glBufferSubData同样赋值不同的行为

时间:2014-07-03 22:23:13

标签: c++ opengl glsl

我在glBufferSubData尝试更新GL_UNIFORM_BUFFER时发现了一种奇怪的行为。

在我的场景中有3个物体。

我使用以下结构作为我的材质定义

#pragma pack(push, 0)

struct Material
{
    GLfloat diffuse[4];
    GLfloat ambient[4];
    GLfloat specular[4];
    GLint useTex;
    GLfloat shininess;
} material;

#pragma pack(pop)

在向其写入值后,我更新了统一缓冲区:

glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(material), (void*)&material);
std::cout << "out usetex: " << material.useTex << "\n";
/*The terminal shows: 
    out usetex: 0
    out usetex: 7
    out usetex: 7*/

这是我的片段着色器(为调试而简化):

#version 330

layout (location = 0) out vec4 outputF;

layout (std140) uniform Material {
    vec4 diffuse;
    vec4 ambient;
    vec4 specular;
    int useTex;
    float shininess;
};

void main()
{
    if(useTex == 1)
    {
        outputF = vec4(1.0);
    } else
        outputF = vec4(vec3(float(useTex), 0.0, 0.0), 1.0);
}

从之前的测试中我知道diffuseambientspecularshininess已正确更新,并且会呈现正确的信息。

着色器绘制三个完全白色的对象(因此useTex显然为1)。但正如您可能从上面注意到的那样,值应为0,7和7。

由于这没有成功,我尝试手动更新useTex

glBufferSubData(GL_UNIFORM_BUFFER, sizeof(material.diffuse)*3, sizeof(material.useTex), (void*)&material.useTex);

哪个没有改变任何东西。

然后是奇怪的事情。我尝试了以下方法:

GLint gi = *new GLint(0);
std::cout << "out gi: " << gi << "\n";
std::cout << "out usetex: " << material.useTex << "\n";
    /* gives:
       out gi: 0
       out usetex: 0
       out gi: 0
       out usetex: 7
       out gi: 0
       out usetex: 7*/
glBufferSubData(GL_UNIFORM_BUFFER, sizeof(material.diffuse)*3, sizeof(material.useTex), (void*)&gi);

其中呈现三个黑色对象(当您查看着色器时如预期的那样)。

GLint gi = *new GLint(material.useTex);

这个再次呈现三个白色物体......

那么*new GLint(material.useTex)*new GLint(0)之间的区别是什么?两者都应该与1不同,不应该是吗?

我已经使用glGetError()检查了OpenGL错误。没有错误。

您可能需要更多代码。以下几行描述了如何为material指定值。如果您需要更多,我可以添加此信息。但我无法想到任何可能与这个问题有关的事情。

std::map<std::string, Material> materials;
std::vector<Mesh> meshes;
std::vector<Buffer> buffers;
/*... Mesh file loading code ...*/
/*a new material was found (name: matKey):*/
if(...)
{
    materials[matKey].useTex |= DIFFUSE;
}
if(...)
{
    materials[matKey].useTex |= SPECULAR;
}
if(...)
{
    materials[matKey].useTex |= NORMAL;
}
/* for each mesh the following is called (The key exists! I checked that.)*/
meshes[meshIndex].material = materials[/*some key string*/];
/* After all mesh objects are filled with values the following loop copies the data to a Buffer object*/
for(size_t i = 0; i < meshes.size(); i++)
{
    buffers[i].assign(&meshes[i]);
}
/* somewhere in Buffer::assign(Mesh* m) the uniform buffer is generated and the material struct is copied to a internal variable*/
glGenBuffers(1, &materialBuffer);
glBindBuffer(GL_UNIFORM_BUFFER, materialBuffer);
glBufferData(GL_UNIFORM_BUFFER, sizeof(m->material), (void*)&m->material, GL_DYNAMIC_DRAW);
glBindBufferBase(GL_UNIFORM_BUFFER, Shader::MATERIAL_BLOCK_BINDING_POINT, materialBuffer);
material = m->material; //material is an internal variable
/* the class Buffer has also a render() function which starts with the uniform loading code that was described earlier (glBufferSubData() ...).*/

/* The `1` that is outputted in the shader comes from the constructor Mesh::Mesh()*/
Mesh::Mesh()
{
    /* .. some initializing .. */
    material.useTex = 1;
}

如何解决此问题的任何提示?

0 个答案:

没有答案