我一直在尝试使用OpenGL 3.3创建一个创建并允许修改统一缓冲区对象的类。无论统一块定义中的布局限定符(std140,共享或打包),该类都应该可用。它似乎工作正常,直到我重构phong着色器使用统一块而不是制服。从那以后,应用程序无法在phong着色器中找到统一的块,但对所有其他着色器工作得非常好。 这让我相信它一定是我在重新格式化phong着色器时所犯的错误,但我已经无数次地查看它并找不到任何东西。我唯一能想到的是编译器正在从着色器中删除均匀块,因为它认为它们没有被使用,但它们肯定被使用,所以它不可能。 着色器肯定是成功编译的,并在调用glGetUniformBlockIndex()之前链接。
每次创建着色器时,都会查找当前使用的两个统一块,然后绑定到绑定点(如果找到)。
programID = glCreateProgram();
glAttachShader(programID, vertexID);
glAttachShader(programID, fragmentID);
glLinkProgram(programID);
glUseProgram(programID);
GLuint matricesIndex = glGetUniformBlockIndex(programID, "MatrixBlock");
if (matricesIndex == GL_INVALID_INDEX)
cout << "Could not get index for uniform block MatrixBlock in " << name << endl;
glUniformBlockBinding(programID, matricesIndex, 0);
GLuint lightsIndex = glGetUniformBlockIndex(programID, "LightBlock");
if (lightsIndex == GL_INVALID_INDEX)
cout << "Could not get index for uniform block LightBlock in " << name << endl;
glUniformBlockBinding(programID, lightsIndex, 1);
这是我在Phong着色器中找不到两个均匀块的地方。顶点和片段着色器如下: 顶点:
// phong.vert
#version 330
const int maxLights = 30;
layout (std140) uniform MatrixBlock
{
mat4 modelMat;
mat4 viewMat;
mat4 modelViewMat;
mat4 projectionMat;
mat3 normalMat;
};
layout (std140) uniform LightBlock
{
int numLights;
vec4 position[maxLights];
vec4 direction[maxLights];
vec4 ambient[maxLights];
vec4 diffuse[maxLights];
vec4 specular[maxLights];
vec3 attenuation[maxLights];
float cosCutoffAngle[maxLights];
};
layout (location = 0) in vec3 in_Position;
layout (location = 2) in vec3 in_Normal;
layout (location = 3) in vec2 in_TexCoord;
out VS_OUT
{
vec3 vs_normalVec;
vec3 vs_vertexVec;
vec2 vs_texCoord;
vec3 vs_lightVec[maxLights];
float vs_lightVertDistance[maxLights];
float vs_attenuation[maxLights];
} vs_out;
void calculateVectors()
{
//Translate vertex position into view coordinates.
vec4 vertexPosition = modelMat * vec4(in_Position, 1.0);
//Find vertex position in view coordinates. Since the viewer is at the origin, simply negate the position.
vs_out.vs_vertexVec = normalize(-vertexPosition).xyz;
//Translate normal of the vertex to view coordinates. Uses the normal matrix.
vs_out.vs_normalVec = normalize(normalMat * in_Normal);
for(int i=0; i<numLights; ++i)
{
//Calculate the vector from the vertex position to the light source in view coordinates.
vs_out.vs_lightVec[i] = position[i].xyz - vertexPosition.xyz;
//Calculate the distance of the above vector before normalising it.
vs_out.vs_lightVertDistance[i] = length(vs_out.vs_lightVec[i]);
vs_out.vs_lightVec[i] = normalize(vs_out.vs_lightVec[i]);
vs_out.vs_attenuation[i] = 1 /
(attenuation[i].x +
attenuation[i].y*vs_out.vs_lightVertDistance[i] +
attenuation[i].z*vs_out.vs_lightVertDistance[i]*vs_out.vs_lightVertDistance[i]);
}
}
void main(void)
{
calculateVectors();
vs_out.vs_texCoord = in_TexCoord;
gl_Position = projectionMat * modelViewMat * vec4(in_Position, 1.0);
}
和碎片:
//phong.frag
#version 330
// Some drivers require the following
precision highp float;
struct materialStruct
{
vec4 ambient;
vec4 diffuse;
vec4 specular;
float shininess;
};
const int maxLights = 30;
vec3 reflection;
layout (std140) uniform LightBlock
{
int numLights;
vec4 position[maxLights];
vec4 direction[maxLights];
vec4 ambient[maxLights];
vec4 diffuse[maxLights];
vec4 specular[maxLights];
vec3 attenuation[maxLights];
float cosCutoffAngle[maxLights];
};
uniform materialStruct material;
uniform sampler2D textureUnit0;
uniform bool textured = true;
in VS_OUT
{
vec3 vs_normalVec;
vec3 vs_vertexVec;
vec2 vs_texCoord;
vec3 vs_lightVec[maxLights];
float vs_lightVertDistance[maxLights];
float vs_attenuation[maxLights];
} fs_in;
layout (location = 0) out vec4 colour;
vec4 calculateLightColour(int i)
{
//Calculate colour of light and object material.
//Ambient intensity
vec4 ambientI = ambient[i] * material.ambient;
// Diffuse intensity
vec4 diffuseI = diffuse[i] * material.diffuse;
diffuseI = diffuseI * max(dot(fs_in.vs_normalVec, fs_in.vs_lightVec[i]), 0.0) * fs_in.vs_attenuation[i];
// Specular intensity
vec4 specularI = specular[i] * material.specular;
//Specular Intensity = Ks*(R.V)^(alpha)*Is
specularI = specularI * pow( max( dot( reflection, fs_in.vs_vertexVec ), 0 ), material.shininess ) * fs_in.vs_attenuation[i];
return ambientI + diffuseI + specularI;
}
vec4 calculateLight(int i)
{
//Calculate reflection light makes to the surface.
reflection = reflect( -fs_in.vs_lightVec[i], fs_in.vs_normalVec );
if(cosCutoffAngle[i] == 0 && direction[i] == vec4(0.0, 0.0, 0.0, 0.0))
{
return calculateLightColour(i);
}
else
{
//Calculate the direction vector of the light in view space.
vec3 spotDirection = normalize((position[i] - normalize(direction[i])).xyz);
//Get dot product of spotlight direction and vertex vector.
float dotProduct = dot(fs_in.vs_lightVec[i], -normalize(direction[i].xyz));
//float dotProduct = dot(fs_in.vs_lightVec[i], -spotDirection);
if(dotProduct > cosCutoffAngle[i])
{
return calculateLightColour(i);
}
else
return vec4(0.0, 0.0, 0.0, 1.0);
}
}
void main(void)
{
vec4 lightColour = vec4(0.0, 0.0, 0.0, 1.0);
for(int i=0; i<numLights; ++i)
{
lightColour += vec4(calculateLight(i).rgb, 0.0);
}
if(textured)
colour = lightColour * texture(textureUnit0, fs_in.vs_texCoord);
else
colour = lightColour;
}
任何帮助在着色器中找到问题都会有很大帮助。如果没有明显的错误,那么有什么可能是问题的任何建议将不胜感激。
我想知道OpenGL中的统一块的其他内容是Superbible第6版关于统一缓冲区的章节说你需要使用统一块的名称,然后在获得制服的偏移时使用元素的名称。例如
GLchar *names[] = {
"MatrixBlock.modelMat",
...
...
};
然后使用glGetUniformIndices和glGetActiveUniformsiv正确填充缓冲区。但是这种命名元素的方法对我来说不起作用,也没有使用实例名称,我看到它也提到了一些地方。 对我有用的只是使用元素名称,例如:
GLchar *names[] = {
"modelMat",
...
...
};
这些差异是否有任何特殊原因?