【发布时间】:2018-07-02 10:56:40
【问题描述】:
我的爱好 OpenGL4.1 引擎中的统一缓冲区出现了一些奇怪的行为。
在 Windows 上一切正常(英特尔和 Nvidia GPU),但在我的 MacBook(也是英特尔)上,这不起作用。
所以解释一下 OSX 上发生了什么:如果我在实际的片段着色器代码中硬编码我所有的统一缓冲区变量,那么我可以完美地渲染,但如果我将它们设置回变量 - 我什么也得不到。
使用 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
【问题讨论】:
-
我注意到的另一件事......如果我改变统一缓冲区中变量的顺序,我可以得到截然不同的结果。这告诉我这可能是缓冲区本身的字节偏移问题。
-
我认为对齐没有问题。但在着色器中,生成的颜色仅受
albedo影响,并且不使用统一缓冲区。我用FinalColour.rgb = albedo * directionLightFactor;运行你的着色器,它工作正常。 -
请附上填写UBO和绑定UBO的代码。有几个潜在的问题。
-
@Asaq 抱歉,我似乎在示例中复制了错误的着色器代码 - 我已修复它。
-
@derhass 我添加了更新 UBO 的 OpenGL 调用。