web-dev-qa-db-ja.com

頂点シェーダーはどのようにして色情報をフラグメントシェーダーに渡しますか?

ウィンドウに静的な三角形を描画する単純なhello-world OpenGLプログラムで、三角形の3つの頂点を赤、緑、青の色に設定すると、三角形はグラデーションで塗りつぶされます。

しかし、次のようなシェーダーを使用すると:

頂点シェーダー:

attribute vec4 aVertex;
attribute vec4 aColor;

varying vec4 vColor;

void main(void) {
    gl_Position = gl_ModelViewMatrix * gl_ProjectionMatrix * aVertex;
    vColor = aColor;
}

ここで、属性aVertexおよびaColorは、glVertexAttribPointerの呼び出しを通じて渡された頂点バッファーからのものです。

フラグメントシェーダー:

varying vec4 vColor;
void main(void) {
    gl_FragColor = vColor;
}

三角形はまだグラデーションで満たされていますが、ここに質問があります:

頂点シェーダーが頂点ごとに計算される場合、vColorの各インスタンスに頂点の色を割り当てる必要があります。頂点カラーは、頂点バッファで設定されているように、赤、緑、または青のいずれかである必要があります。

それで、勾配はどこから来たのですか?

または、別のWordで、フラグシェーダーでvColorが頂点の色ではなく補間された色であることが判明したのはいつですか。

21
RnMss

フラグメントシェーダーの「変化する」変数には、頂点シェーダーステージで指定された値の間を線形補間した結果があります(頂点間のフラグメントの相対位置に基づく)。

つまり、ラスタライザがピクセルでフラグメントを吐き出すとき、その位置も重心座標の三角形の頂点に対して相対的に与えられます。これらの座標は、頂点シェーダーからのすべての変数を補間するために使用されます。ほとんどの場合、これはあなたが望んでいることであり、最近では補間しないことで得られる速度はかなり重要ではありません。

キーワード「フラット」を使用すると、補間が無効になり、代わりに最初の頂点の値が使用されます(「フラット」は、 GLSLの新しいバージョン )。

余談ですが、フラグメントが各頂点からのいくつかの値を必要とする場合、これが特に役立つことがわかりました。この場合、私はflat out myVertexValue[3]ジオメトリシェーダー内( 例:here )。

17
jozxyqk

グラデーションは、 fragment シェーダーへの可変パスで発生する頂点カラー間の補間に由来します。補間したくない場合は、可変の最初に "flat"キーワードを使用してください。あなたの誤解はおそらく、頂点とフラグメントの段階がどのように機能するかについての知識の欠如に起因します。それらは異なる動作をします。フラグメントシェーダーはフラグメントごとに呼び出されますが、フラグメントごとに呼び出されます。ラスタライズ中に生成されたフラグメントをカバーする必要があるため、補間はデフォルトで行われますプリミティブアセンブリによって定義された領域のステージ。そして先ほど述べたように、「フラット」による補間を無効にすることができます。そのような場合、最初の頂点属性の色が形状の全体的な色を定義します。

2
Michael IV