2017-10-16 4 views
1

C++ OpengLプログラムとGLSL Vertex and Fragmentシェーダを使用しています。GLSLを使用してシェーダ内の位置から直接変換マトリックスを計算する

私は同じオブジェクトのいくつかのインスタンスを作成しています。私はインスタンス間のオブジェクトの位置を変更する必要があります。

これは私がやったことです:私は変換行列の配列である統一変数を​​使って作業しています。各マトリックスはオブジェクトインスタンスを表します。

MVPも変換行列ですが、MVPはカメラの位置、向き、およびプロパティによって設定されます。ここで

は、私の頂点シェーダである:ここで

#version 330 core 
    layout(location = 0) in vec3 vertex_position; 
    layout(location = 1) in vec3 vertex_color; 

    uniform mat4 object_positions[20]; 
    out vec3 fragment_color; 
    uniform mat4 MVP; 

    void main() 
    { 
     gl_Position = object_positions[gl_InstanceID] * MVP * vec4(vertex_position,1.0); 
     fragment_color = vertex_color; 
    } 

は、私はC++でオブジェクトの位置を設定するためのプログラムを実行するために持っているものです。

glm::mat4 object_positions[20]; 
    object_positions[0] = glm::translate(glm::mat4(1), glm::vec3(0.4f,0.2f,0.0f)); 
    object_positions[1] = glm::translate(glm::mat4(1), glm::vec3(0.5f,1.4f,0.0f)); 
    ... 
    object_positions[19] = glm::translate(glm::mat4(1), glm::vec3(-10.6f,0.2f,0.0f)); 
    GLuint object_positions_id = glGetUniformLocation(program_id, "object_positions"); 
    ... 
    glUniformMatrix4fv(object_positions_id, 7, GL_FALSE, glm::value_ptr(object_positions[0])); 

あなたはGLMの2番目の引数として参照vec3 :: translateには各オブジェクトの位置が含まれます。 この時点ですべてのことがうまく動作します。

私がしたいことは、shaderのglm :: translteを計算することです。私が実際に望むのは、それぞれのポジションにマット4の代わりにvec3を送ることです。私はGPUにCPUの代わりに変換行列を計算させたい。私が試したものはすべて動作しません。 OpenGLの変換行列について

おかげ

+0

にノーをしない理由はありません。それは全く同じ結果です。 object_positionsは、この場合は変換行列でなければなりません。 – Bob5421

+1

オフセットを追加するだけの方がはるかに簡単で高速なのはなぜですか? –

+0

はい、これは素晴らしいアイデアですが、私は何をwに入れるべきですか? – Bob5421

答えて

0

投影行列が適用された後にそれが翻訳されるのであなたは絶対に(object_positionsが行列であったとしても)object_positions[gl_InstanceID] * MVP * vec4(vertex_position,1.0);を行うことはできません。

あなたはインスタンスの任意の回転を行っていない場合は、ちょうどそれが動作しません。この

gl_Position = MVP * vec4(vertex_position + object_positions[gl_InstanceID],1.0); 
1

は16個のエントリ(4×4行列といえば)のほんの一次元アレイです。このマトリックスでは、13番目、14番目、15番目のエントリが翻訳コンポーネントを定義します。したがって、行列を第4行第0行に格納する場合、1番目と2番目のエントリは、シェーダに送るベクトルx、y、z成分でなければなりません。このようにシェーダで翻訳マトリックスを構築することができます。行のメジャーマトリックスを持っている場合は、変換の効果を見るためにマトリクスで事前に頂点を変換することを忘れないでください。

gl_Position = Translation Matrix * gl_Vertex; 

あなたの行列が列メジャーの場合、乗算をポストします。

3

4 * 4行列は次のようになります。GLSLで

c0 c1 c2 c3   c0 c1 c2 c3 
[ Xx Yx Zx Tx ]  [ 0 4 8 12 ]  
[ Xy Yy Zy Ty ]  [ 1 5 9 13 ]  
[ Xz Yz Zz Tz ]  [ 2 6 10 14 ]  
[ 0 0 0 1 ]  [ 3 7 11 15 ] 

mat4 m;の列は次のように対処されています

vec4 c0 = m[0].xyzw; 
vec4 c1 = m[1].xyzw; 
vec4 c2 = m[2].xyzw; 
vec4 c3 = m[3].xyzw; 

あなたが好き頂点シェーダでmat4を設定することができますこれは:

#version 330 core 
layout(location = 0) in vec3 vertex_position; 
layout(location = 1) in vec3 vertex_color; 

out vec3 fragment_color; 
uniform mat4 MVP; 

uniform vec3 object_positions[20]; 

void main() 
{ 
    mat4 posMat = mat4(
     vec4(1.0, 0.0, 0.0, 0.0), 
     vec4(0.0, 1.0, 0.0, 0.0), 
     vec4(0.0, 0.0, 1.0, 0.0), 
     vec4(object_positions[gl_InstanceID], 1.0)); 

    gl_Position = MVP * posMat * vec4(vertex_position,1.0); 
    fragment_color = vertex_color; 
} 


しかし、オフセットによって頂点の位置を操作したい場合は、変換行列は必要ありません。

void main() 
{ 
    gl_Position = MVP * vec4(object_positions[gl_InstanceID] + vertex_position, 1.0); 
    fragment_color = vertex_color; 
} 


そして、あなたが設定する必要があります:あなたは、単には(が均質で、あなたの場合のように、座標デカルト座標とではありませんオフセット提供)頂点位置にを相殺追加することができますこのような均一:

glm::vec3 object_positions[20]; 
object_positions[0] = glm::vec3(0.4f,0.2f,0.0f); 
object_positions[1] = glm::vec3(0.5f,1.4f,0.0f); 
... 
object_positions[19] = glm::vec3(-10.6f,0.2f,0.0f); 
GLuint object_positions_id = glGetUniformLocation(program_id, "object_positions"); 
... 
glUniform3fv(object_positions_id, 20, glm::value_ptr(object_positions[0])); 


はさらに参照:

+1

は 'vec4(object_position [gl_InstanceID] + vertex_position、1.0)'と全く同じ 'posMat * vec4(vertex_position、1.0)'ではありません? – Jherico

関連する問題