在我的爱好OpenGL4.1引擎中,我在使用统一缓冲区时表现出一些奇怪的行为。
在Windows上,一切正常(英特尔和Nvidia GPU),但在我的MacBook(也为英特尔)上,此功能无法正常工作。
所以要解释一下OSX上发生的情况:如果我将所有Uniform Buffer变量硬编码到实际的片段着色器代码中,那么我可以很好地渲染,但是如果将它们重新设置为变量,我什么也没得到。
使用apitrace来查看OpenGL状态,所有变量值都很完美,因此我对这里发生的事情有些困惑。
我希望这只是一个代码错误,而不是驱动程序的一些潜在问题。
下面是片段着色器代码,如果我对所有DirectionLight变量进行硬编码,一切都可以正常工作。
#version 410
struct DirectionalLightData
{
vec4 Colour;
vec3 Direction;
float Intensity;
};
layout(std140) uniform ObjectBuffer
{
mat4 Model;
};
layout(std140) uniform FrameBuffer
{
mat4 Projection;
mat4 View;
DirectionalLightData DirectionalLight;
vec3 ViewPos;
};
uniform sampler2D PositionMap;
uniform sampler2D NormalMap;
uniform sampler2D AlbedoSpecMap;
layout(location = 0) in vec2 TexCoord;
out vec4 FinalColour;
float CalcDiffuseContribution(vec3 lightDir, vec3 normal)
{
return max(dot(normal, -lightDir), 0.0f);
}
float CalcSpecularContribution(vec3 lightDir, vec3 viewDir, vec3 normal, float specularExponent)
{
vec3 reflectDir = reflect(lightDir, normal);
vec3 halfwayDir = normalize(lightDir + viewDir);
return pow(max(dot(normal, halfwayDir), 0.0f), specularExponent);
}
float CalcDirectionLightFactor(vec3 viewDir, vec3 lightDir, vec3 normal)
{
float diffuseFactor = CalcDiffuseContribution(lightDir, normal);
float specularFactor = CalcSpecularContribution(normal, viewDir, normal, 1.0f);
return diffuseFactor * specularFactor;
}
void main()
{
vec3 position = texture(PositionMap, TexCoord).rgb;
vec3 normal = texture(NormalMap, TexCoord).rgb;
vec3 albedo = texture(AlbedoSpecMap, TexCoord).rgb;
vec3 viewDir = normalize(ViewPos - position);
float directionLightFactor = CalcDirectionLightFactor(viewDir, DirectionalLight.Direction, normal) * DirectionalLight.Intensity;
FinalColour.rgb = albedo * directionLightFactor * DirectionalLight.Colour.rgb;
FinalColour.a = 1.0f * DirectionalLight.Colour.a;
}
这是我更新和绑定UBO的顺序(由于有太多代码无法在此处复制粘贴,因此我已将它们从apitrace中拉出):
glGetActiveUniformBlockName(5, 0, 255, NULL, FrameBuffer);
glGetUniformBlockIndex(5, FrameBuffer) = 0;
glGetActiveUniformBlockName(5, 1, 255, NULL, ObjectBuffer);
glGetUniformBlockIndex(5, ObjectBuffer) = 1;
glBindBuffer(GL_UNIFORM_BUFFER, 1);
glMapBufferRange(GL_UNIFORM_BUFFER, 0, 172,GL_MAP_WRITE_BIT);
memcpy(0x10b9f8000, [binary data, size = 172 bytes], 172);
glUnmapBuffer(GL_UNIFORM_BUFFER);
glBindBufferBase(GL_UNIFORM_BUFFER, 0, 2);
glBindBufferBase(GL_UNIFORM_BUFFER, 1, 1);
glBindBuffer(GL_UNIFORM_BUFFER, 2);
glMapBufferRange(GL_UNIFORM_BUFFER, 0, 64, GL_MAP_WRITE_BIT);
memcpy(0x10b9f9000, [binary data, size = 64 bytes], 64);
glUnmapBuffer(GL_UNIFORM_BUFFER);
glUniformBlockBinding(5, 1, 0);
glUniformBlockBinding(5, 0, 1);
glDrawArrays(GL_TRIANGLES, 0, 6);
请注意,FrameBuffer UBO的ID为1,ObjectBuffer UBO的ID为2
答案 0 :(得分:0)
我认为当您使用std140布局时,您的数据成员应按字节对齐,因此您不能混合使用vec4和vec3或浮点数保留所有变量mat4和vec4,否则dnt使用std140布局,并在应用程序端计算ubo对齐和变量的偏移量在ubo上并设置值。查看GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT的用法。 在实验中,将所有变量都更改为mat4和vec4,然后您的问题就会消失。
如果未将std140布局用于块,则需要查询块中每个统一的字节偏移。 OpenGL规范说明了每种基本类型的存储,但没有说明类型之间的对齐方式。与常规制服一样,结构成员每个成员都有一个单独的偏移,必须单独查询。
答案 1 :(得分:0)
经过几天的挖掘,我似乎已经找到了问题。
绑定另一个着色器程序后,我没有调用glBindBufferBase()。
这种愚蠢的错误使我非常悲痛。
感谢大家的帮助。