我正在尝试在我的OpenGL程序中实现实例化。我让它工作,然后决定通过将模型 - 视图 - 投影乘法矩阵作为GLSL程序的输入来使我的GLSL代码更有效,以便CPU为每个实例计算它,而不是GPU。这是我的顶点着色器代码(大部分与我的问题无关):
#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;
}
以上代码有效,但仅仅因为我没有使用最后输入的modelsVP来计算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交换为10而不是14,我可以使用它,但不能使用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);
}
答案 0 :(得分:11)
OpenGL强制实现提供至少16个4分量顶点属性。因此,并不保证所有实现都支持16的索引;有关详细信息,请参阅GL_MAX_VERTEX_ATTRIBS
。
您的mat4顶点属性计为4个4组件属性,因此在仅支持16个4组件顶点属性的实现上,索引14超出范围。
答案 1 :(得分: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;
}
请参阅?这不是那么简单吗?顶点着色器中的制服更少,片段着色器的输出更少,数学计算更少,顶点属性更少。
您需要做的就是更改片段着色器以使用相机空间位置,而不是世界空间位置。这应该是一个相当容易的变化。