OpenGL统一缓冲区

OpenGL Uniform buffers?

本文关键字:缓冲区 OpenGL      更新时间:2023-10-16

我正在尝试使用统一缓冲区,但它并没有按预期工作。我有两个统一的缓冲区,一个用于照明,另一个用于材料。问题是,这些颜色并不是它们应该有的样子,每次我移动相机时它们都会改变。当我使用普通制服时,这个问题并不存在。下面的图片展示了我的意思:当使用统一缓冲区时和当使用普通制服时!

这是我的碎片着色器:

#version 400 // Fragment Shader
uniform layout(std140);
in vec3 EyePosition;
in vec3 EyeNormal;
in vec2 TexCoord;
out vec4 FragColor;
uniform sampler2D Texture;
uniform LightBlock
{
    vec4 Position;
    vec4 Intensity;
} Light;
uniform MaterialBlock
{
    vec4 Ambient;
    vec4 Diffuse;
} Material;
vec4 PointLight(in int i, in vec3 ECPosition, in vec3 ECNormal)
{
    vec3 n = normalize(ECNormal);
    vec3 s = normalize(Light.Position.xyz - ECPosition);
    return Light.Intensity * (Material.Ambient + Material.Diffuse * max(dot(s, n), 0.0));
}
void main()
{
    FragColor  = texture(Texture, TexCoord);
    FragColor *= PointLight(0, EyePosition, EyeNormal);
}

我不确定我是否做得很好,但以下是我创建统一缓冲区的方法:

glGenBuffers(1, &light_buffer);
glGenBuffers(1, &material_buffer);
glBindBuffer(GL_UNIFORM_BUFFER, light_buffer);
glBufferData(GL_UNIFORM_BUFFER, sizeof(LightBlock), nullptr, GL_DYNAMIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, material_buffer);
glBufferData(GL_UNIFORM_BUFFER, sizeof(MaterialBlock), nullptr, GL_DYNAMIC_DRAW);
GLuint program = Shaders.GetProgram();
light_index = glGetUniformBlockIndex(program, "LightBlock");
material_index = glGetUniformBlockIndex(program, "MaterialBlock");
glUniformBlockBinding(program, light_index, 0);
glUniformBlockBinding(program, material_index, 1);
glBindBufferBase(GL_UNIFORM_BUFFER, 0, light_buffer);
glBindBufferBase(GL_UNIFORM_BUFFER, 1, material_buffer);

编辑:以下是我如何填充缓冲区:

// Global structures
struct LightBlock
{
    Vector4 Position; // Vector4 is a vector class I made
    Vector4 Intensity;
};
struct MaterialBlock
{
    Vector4 Ambient;
    Vector4 Diffuse;
};
// This is called for every object rendered
LightBlock Light;
Light.Position = Vector3(0.0f, 5.0f, 5.0f) * Camera.GetCameraMatrix();
Light.Intensity = Vector4(1.0f);
glBindBuffer(GL_UNIFORM_BUFFER, light_buffer);
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(LightBlock), &Light);
MaterialBlock Material;
Material.Diffuse = Vector4(1.0f);
Material.Ambient = Material.Diffuse * Vector4(0.3f);
glBindBuffer(GL_UNIFORM_BUFFER, material_buffer);
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(MaterialBlock), &Material);

我遇到了同样的问题,但只是AMD(而不是NVIDIA)。有趣的是,问题只发生在更改视图矩阵时。

由于我有一个可重复的问题,取决于视图矩阵的变化,我能够追溯到根本原因(进行艰苦的尝试和错误)。在应用程序中更改视图时,我会根据需要动态分配和释放一些OpenGL资源。在这个过程中,有一个对缓冲区0的glDeleteBuffers()的调用。如果我使用一个条件语句,以便不对缓冲区0调用glDeleteBuffers,那么问题就消失了。

根据文档,glDeleteBuffers将静默地忽略缓冲区0。我的猜测是AMD驱动程序中有一个错误。

尝试使用glMapBuffer/glUnmapBuffer更新缓冲区。