OpenGL统一缓冲区?
问题描述:
我试图使用统一的缓冲区,但它不工作。我有两个统一的缓冲区,一个是光照,另一个是材质。问题在于颜色不是它们应该是的,每次移动相机时它们都会发生变化。当我使用正常制服时,这个问题不存在。这里的图片来展示我的意思:When using uniform buffers和when using normal uniforms!OpenGL统一缓冲区?
这是我的片段着色器:
#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,则问题消失。
根据文档,缓冲区0将被glDeleteBuffers默默忽略。我的猜测是AMD驱动程序中存在一个错误。
答
尝试使用glMapBuffer
/glUnmapBuffer
更新缓冲区。
你做了什么来调试呢?你有没有尝试打印出你在着色器中获得的值(通过简单地将它们写为片段着色器输出)?至少在颜色方面,你应该能够看到哪些值不会像你期望的那样出现。 – 2012-02-06 03:29:58
另外,您用来使用值填充这些缓冲区的代码在哪里? – 2012-02-06 03:30:10
@Gigi:我没有在Cat 12.1上看到过这个。它似乎对我来说工作得很好,我在片段着色器中使用了2个块。另外,你是否提交过这方面的错误报告? – 2012-02-06 03:36:49