【问题标题】:Weird behaviour with OpenGL Uniform Buffers on OSXOSX 上 OpenGL 统一缓冲区的奇怪行为
【发布时间】: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 调用。

标签: macos opengl


【解决方案1】:

我认为当您使用 std140 布局时,您的数据成员应该是字节对齐的,因此您不能混合 vec4 和 vec3 或浮动保留所有变量 mat4 和 vec4 否则 dnt 使用 std140 布局并在应用程序端计算 ubo 对齐和变量的偏移量在 ubo 上并设置值。请参阅 GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 的用法。 随着实验将所有变量更改为 mat4 和 vec4 并看到您的问题应该消失了。

如果您没有对块使用 std140 布局,则需要查询块内每个制服的字节偏移量。 OpenGL 规范解释了每种基本类型的存储,但没有解释类型之间的对齐方式。结构成员,就像常规制服一样,每个都有一个单独的偏移量,必须单独查询。

【讨论】:

  • 这可能是问题所在。在 Windows 上 GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 是 16。在我的 MacBook 上是 256。
  • 是的,您可以进行快速实验,我告诉过您只需将 UBO 的所有成员更改为 vec4 或 mat4,基本上与您的偏移量对齐,它应该可以正常工作。
  • 已将所有 vec3 和 float 更改为 vec4,但仍然无法正常工作。奇怪的是在 ApiTrace 中,它显示了所有正确的值,所以它应该可以工作。
  • 你能只用 vec4 发布更新的代码吗?也不要使用创建单独的 DirectionalLightData 只是为了简化直接在此处使用数据。
【解决方案2】:

经过几天的挖掘,我似乎找到了问题所在。

绑定不同的着色器程序后,我没有调用 glBindBufferBase()。

这么愚蠢的错误让我很伤心。

感谢大家的帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多