フラグメントシェーダーは、ピクセルの色に使用する変数をどのように認識しますか?


82

さまざまなフラグメントシェーダーがたくさんありますが、

#version 130

out vec4 flatColor;

void main(void)
{
    flatColor = vec4(0.0,1.0,0.0,0.5);
}

そして、それらはすべて「アウトカラー」(この場合flatColor)に異なる変数を使用します。では、OpenGLはあなたが何をしようとしているのかをどうやって知るのでしょうか?

flatColorとして定義されている唯一の変数であるため、これは機能するとout思いますが、さらにout変数を追加することは許可されていますね。それともクラッシュするだけでしょうか?


実際、テストとして、私はこれを実行しました:

#version 330

in vec2 TexCoord0;

uniform sampler2D TexSampler;

out vec4 x;
out vec4 y;

void main()
{
    y = texture2D(TexSampler, TexCoord0.xy);
}

それは私が使用したかどううまく働きましたxy


さらに、事前定義されたがありgl_FragColorます。違いは何ですか、そしてなぜ人々は通常自分の変数を使用することを主張するのですか?

回答:


142

さらに、事前定義されたgl_FragColorがあります。

これから始めましょう。いいえ、事前定義されたありませんgl_FragColor。これはコアOpenGL3.1以降から削除されました。互換性を使用している場合を除いて(この場合、3.30シェーダーは#version 330 compatibility上部に表示されます)、これを使用しないでください。

ここで、ユーザー定義のフラグメントシェーダー出力に戻ります。しかし、最初に、簡単な例えです。

頂点シェーダーで入力があることを覚えていますか?そして、これらの入力は、頂点属性のインデックス、あなたがに渡す番号を表すglVertexAttribPointerglEnableVertexAttribArrayなどとは?どの入力がどの属性からプルするかを設定します。GLSL 3.30では、次の構文を使用します。

layout(location = 2) in color;

これにより、color頂点シェーダー入力が属性の場所2から取得されるように設定されます。3.30より前(またはARB_explicit_attrib_locationなし)では、glBindAttrbLocationリンクする前にこれを明示的に設定するか、プログラムに属性インデックスをクエリする必要がありますglGetAttribLocation。属性の場所を明示的に指定しない場合、GLSLは場所を任意に割り当てます(つまり、実装で定義された方法で)。

シェーダーで設定することは、ほとんどの場合、より良いオプションです。

いずれの場合も、フラグメントシェーダーの出力はほぼ同じように機能します。フラグメントシェーダーは複数の出力カラーに書き込むことができ、それら自体がフレームバッファー内の複数のバッファーにマップされます。。したがって、どの出力がどのフラグメント出力カラーに送られるかを示す必要があります。

このプロセスは、フラグメント出力ロケーション値から始まります。これは、頂点シェーダーの入力位置と非常によく似ています。

layout(location = 1) out secColor;

API関数もありますglBindFragDataLocationし、glGetFragDataLocationに類似しており、glBindAttribLocationかつglGetAttribLocation

明示的な割り当てを行わない場合、実装は通常、出力変数の1つを場所0に割り当てます。ただし、OpenGL標準では必要ありません。あなたはどちらかそれに依存するべきではありませんので、この動作を。

公平を期すために、異なる出力位置を取得しなかった2つの出力を使用した場合、プログラムはリンクに失敗するはずです。おそらく起こったことは、あなたのコンパイラがあなたが書き出さなかったものを最適化したことでした、それでリンカーエラーをチェックする時が来たときそれはちょっとそれを忘れていました。


4
+1以上あげられたらいいのに。壮大な答え。フラグメントの出力場所がどのように機能するのか疑問に思いました。:)
kevintodisco 2012

ああ..それで、gl_FragColorどのバッファに書き込むかをより柔軟に選択できるようにするために、非推奨になりましたか?理にかなっています。再度、感謝します!
mpen 2012

3
@Mark:「非推奨」とは、「引き続き使用できますが、今後のバージョンで削除される可能性がある」という意味です。「削除済み」とは、削除済みを意味します。違いがあります。GL 3.0で非推奨とマークされたものは、3.1で削除されました(いくつかのことを除いて)。
ニコルボーラス2012

3
@NicolBolas: "GL 3.3以降(以前のバージョンからの変更)は、それらすべてをロケーション0"に割り当てます。これは仕様によってどこで保証されているのだろうか。3.3は、「プログラムがリンクされている場合、バインドが指定されていない、またはシェーダーテキスト内で明示的に設定されている変数を変更すると、GLによってフラグメントの色とインデックスに自動的にバインドされます。このような割り当てはすべて、次のカラーインデックスを使用します。ゼロ。"。最後の文は3.2にはありません。ただし、インデックスは色を参照していません番号で、デュアルソースブレンディングインデックス(3.3で追加された)のみをます。
derhass 2013

1
ありがとう@NicolBolas、素晴らしい答え!ですから、まだ完全には理解しておらず、「問題なく」作りたいと思っています。シェーダーでlayout (location = 0) out vec4 outColorは、バインドされているもの(ほとんどの場合、FBOではなく「画面」)に描画するときに常に指定します。したがって、デフォルトでは、glDrawBuffersを使用してFBO(または他のバッファー)をバインドしておらず、を指定するとlocation = 0、常に画面に正しく描画されますか?
azP 2016年

9

GLSL_ES_3.10リンクを使用するOpenGLES3.1にこれを指定したいと思います。

§4.4.2

[フラグメントシェーダーに]出力が1つしかない場合は、場所を指定する必要はありません。その場合、デフォルトでゼロになります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.