6

OpenGL プログラムにインスタンス化を実装しようとしています。私はそれを機能させ、モデル ビュー プロジェクション乗算行列を GLSL プログラムへの入力として送信して、GPU ではなくインスタンスごとに CPU が計算するようにすることで、GLSL コードをより効率的にすることにしました。これが私の頂点シェーダーコードです(ほとんどは私の質問とは関係ありません):

#version 330 core

// Input vertex data, different for all executions of this shader.
layout(location = 0) in vec3 vertexPosition_modelspace;
layout(location = 2) in vec3 vertexColor;
layout(location = 3) in vec3 vertexNormal_modelspace;
layout(location = 6) in mat4 models;
layout(location = 10) in mat4 modelsV;
layout(location = 14) in mat4 modelsVP;

// Output data ; will be interpolated for each fragment.
out vec3 newColor;

out vec3 Position_worldspace;

out vec3 Normal_cameraspace;
out vec3 EyeDirection_cameraspace;

// Values that stay constant for the whole mesh.
uniform mat4 MVP;
uniform mat4 MV;
uniform mat4 P;
uniform mat4 V;
uniform mat4 M;
uniform int num_lights;
uniform vec3 Lights[256];

void main(){

// Output position of the vertex, in clip space : MVP * position
gl_Position =  P * modelsV * vec4(vertexPosition_modelspace,1);

// Position of the vertex, in worldspace : M * position
Position_worldspace = (models * vec4(vertexPosition_modelspace,1)).xyz;

// Vector that goes from the vertex to the camera, in camera space.
// In camera space, the camera is at the origin (0,0,0).
vec3 vertexPosition_cameraspace = ( modelsV * vec4(vertexPosition_modelspace,1)).xyz;
EyeDirection_cameraspace = vec3(0,0,0) - vertexPosition_cameraspace;    

// Normal of the the vertex, in camera space
Normal_cameraspace = ( modelsV * vec4(vertexNormal_modelspace,0)).xyz;

// UV of the vertex. No special space for this one.
newColor = vertexColor;

}

上記のコードは機能しますが、最後の入力モデル VP を使用して gl_position を計算していないためです。(P*modelsV を計算する代わりに) それを使用すると、インスタンスが描画されず、次のエラーが発生します。

Linking program
Compiling shader : GLSL/meshColor.vertexshader
Compiling shader : GLSL/meshColor.fragmentshader
Linking program
Vertex info
0(10) : error C5102: input semantic attribute "ATTR" has too big of a numeric index (16)
0(10) : error C5102: input semantic attribute "ATTR" has too big of a numeric index (16)
0(10) : error C5041: cannot locate suitable resource to bind variable "modelsVP". Possibly large array.

OpenGLコードで正しくリンクしていると確信しています。入力場所modelsVPをmodelsVと交換して、14ではなく10にすると、それを使用できますが、modelsVは使用できません。頂点シェーダーに使用できる入力の最大数はありますか? 他になぜこのエラーが発生するのか、他の考えは本当に思いつきません...

ここに関連する OpenGL コードをさらに含めますが、それが正しいと確信しています (すべてが同じクラスまたはメソッドにあるわけではありません)。

// Buffer data for VBO. The numbers must match the layout in the GLSL code.
#define position 0 
#define uv 1
#define color 2
#define normal 3 
#define tangent 4
#define bitangent 5
#define model 6      // 4x4 matrices take 4 positions
#define modelV 10
#define modelVP 14
#define num_buffers 18

GLuint VBO[num_buffers];
glGenBuffers(num_buffers, VBO);

for( int i=0; i<ModelMatrices.size(); i++ )
{
mvp.push_back( projection * view * ModelMatrices.at(i) );
mv.push_back( view * ModelMatrices.at(i) );
}

glBindBuffer(GL_ARRAY_BUFFER, VBO[model]);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::mat4) * ModelMatrices.size(), &ModelMatrices[0], GL_DYNAMIC_DRAW);
for (unsigned int i = 0; i < 4 ; i++) {

glEnableVertexAttribArray(model + i);
glVertexAttribPointer(model + i, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), 
(const GLvoid*)(sizeof(GLfloat) * i * 4));
glVertexAttribDivisor(model + i, 1);
}

glBindBuffer(GL_ARRAY_BUFFER, VBO[modelV]);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::mat4) * mv.size(), &mv[0], GL_DYNAMIC_DRAW);
for (unsigned int i = 0; i < 4 ; i++) {

glEnableVertexAttribArray(modelV + i);
glVertexAttribPointer(modelV + i, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), 
(const GLvoid*)(sizeof(GLfloat) * i * 4));
glVertexAttribDivisor(modelV + i, 1);
}

glBindBuffer(GL_ARRAY_BUFFER, VBO[modelVP]);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::mat4) * mvp.size(), &mvp[0], GL_DYNAMIC_DRAW);
for (unsigned int i = 0; i < 4 ; i++) {

glEnableVertexAttribArray(modelVP + i);
glVertexAttribPointer(modelVP + i, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (const GLvoid*)(sizeof(GLfloat) * i * 4));
glVertexAttribDivisor(modelVP + i, 1);
}
4

2 に答える 2

7

使用している頂点属性が多すぎます。コードをあまり変更せずに属性の数を減らす方法を次に示します (機能的な変更は改善です)。models以下は、が「モデルからワールドへ」のマトリックスでmodelsVあり、 が「モデルからカメラへ」のマトリックスであり、それmodelsVPが「モデルからプロジェクションへ」のマトリックスであると仮定しています。

#version 330 core

// Input vertex data, different for all executions of this shader.
layout(location = 0) in vec3 vertexPosition_modelspace;
layout(location = 2) in vec3 vertexColor;
layout(location = 3) in vec3 vertexNormal_modelspace;
layout(location = 6) in mat4 modelsV;

// Output data ; will be interpolated for each fragment.
out vec3 newColor;

//The fragment shader should work in *camera* space, not world space.
out vec4 Position_cameraspace;

out vec3 Normal_cameraspace;
//out vec3 EyeDirection_cameraspace; Can be computed from Position_cameraspace in the FS.

// Values that stay constant for the whole mesh.
uniform mat4 P;

void main()
{
  Position_cameraspace = modelsV * vec4(vertexPosition_modelspace, 1.0);

  gl_Position = P * Position_cameraspace;

  Normal_cameraspace = ( modelsV * vec4(vertexNormal_modelspace,0)).xyz;

  newColor = vertexColor;
}

見る?それははるかに簡単ではありませんか?頂点シェーダーでの均一化、フラグメント シェーダーへの出力、数学計算、および頂点属性が少なくなります。

必要なのは、ワールド空間の位置ではなく、カメラ空間の位置を使用するようにフラグメント シェーダーを変更することだけです。これはかなり簡単な変更です。

于 2013-08-31T03:33:43.200 に答える