web-dev-qa-db-ja.com

GLSL:ピクセルのx、y、zワールド位置を取得する方法?

世界でのxyzの位置に応じて色を調整したいと思います。

私は私のフラグメントシェーダーでこれを試しました:

varying vec4 verpos;

void main(){
    vec4 c;
    c.x = verpos.x;
    c.y = verpos.y;
    c.z = verpos.z;
    c.w = 1.0;

    gl_FragColor = c;
}

カメラの角度/位置によって色が変化するようですが、座標をカメラの位置/角度から独立させるにはどうすればよいですか?

ここに私の頂点シェーダーがあります:

varying vec4 verpos;

void main(){
    gl_Position = ftransform();
    verpos = gl_ModelViewMatrix*gl_Vertex;
}

Edit2:タイトルを変更したので、画面の座標ではなく、世界の座標が必要です!

Edit3:完全なコードを追加

25
Rookie

頂点シェーダーには、モデル座標での頂点の位置であるgl_Vertex(または固定パイプラインを使用しない場合は何か)があります。モデル行列にgl_Vertexを乗算すると、ワールド座標での頂点の位置が得られます。これをvarying変数に割り当て、その値をフラグメントシェーダーで読み取ると、フラグメントの位置が世界座標で取得されます。

ここでの問題は、モデルとビューマトリックスの両方の組み合わせであるOpenGLのデフォルトのモデルビューマトリックスを使用する場合、必ずしもモデルマトリックスが存在しないことです。私は通常、この問題を、1つのモデルビュー行列ではなく、2つの別々の行列を持つことで解決します。

  1. モデルマトリックス(モデル座標を世界座標にマップ)、および
  2. ビューマトリックス(世界座標をカメラ座標にマップ)。

したがって、2つの異なる行列を別々に頂点シェーダーに渡すだけです。これを定義するには、次のようにします。

uniform mat4 view_matrix;
uniform mat4 model_matrix;

頂点シェーダーの最初。そして、ftransform()の代わりに、

gl_Position = gl_ProjectionMatrix * view_matrix * model_matrix * gl_Vertex;

メインプログラムでは、これらの新しい行列の両方に値を書き込む必要があります。最初に、ビューマトリックスを取得するには、glLoadIdentity()、glTranslate()、glRotate()またはgluLookAt()または通常の方法でカメラ変換を行いますが、次にglGetFloatv(GL_MODELVIEW_MATRIX、&array);を呼び出します。行列データを配列に取得するため。次に、同様に、モデルマトリックスを取得するには、glLoadIdentity();も呼び出します。そして、glTranslate()、glRotate()、glScale()などでオブジェクト変換を行い、最後にglGetFloatv(GL_MODELVIEW_MATRIX、&array);を呼び出します。 OpenGLからマトリックスデータを取得し、頂点シェーダーに送信できるようにします。特に、オブジェクトの変換を開始する前に、glLoadIdentity()を呼び出す必要があることに注意してください。通常、最初にカメラを変換し、次にオブジェクトを変換します。これにより、ビューとモデルの両方の機能を実行する1つの行列が生成されます。ただし、個別のマトリックスを使用しているため、カメラをglLoadIdentity()で変換した後にマトリックスをリセットする必要があります。

gl_FragCoordはピクセル座標であり、世界座標ではありません。

31
kynnysmatto

または、z座標をw座標で除算することもできます。これにより、透視投影が本質的に行われなくなります。あなたにあなたの元の世界座標を与えます。

すなわち。

depth = gl_FragCoord.z / gl_FragCoord.w;

もちろん、これはクリップされていない座標に対してのみ機能します。

しかし、とにかくクリップされたものを気にする人はいますか?

11
uofc

ワールド/モデルマトリックスをユニフォームとして頂点シェーダーに渡し、それを頂点位置で乗算して、変動としてフラグメントシェーダーに送信する必要があります。

/*Vertex Shader*/

layout (location = 0) in vec3 Position

uniform mat4 World;
uniform mat4 WVP;

//World FragPos
out vec4 FragPos;

void main()
{
 FragPos = World * vec4(Position, 1.0);
 gl_Position = WVP * vec4(Position, 1.0);
}

/*Fragment Shader*/

layout (location = 0) out vec4 Color;

... 

in vec4 FragPos

void main()
{
 Color = FragPos;
}
2
Gerard097