使用OpenGL/GLSL时,统一块(UBO)的实例名称不起作用

使用OpenGL/GLSL时,统一块(UBO)的实例名称不起作用,opengl,glsl,opengl-3,Opengl,Glsl,Opengl 3,我在我的OpenGL/GLSL应用程序中实现了一个统一块,用于管理网格材质数据(环境光、漫反射光和镜面反射光以及反光) 在我的第一次尝试中,我实现了以下统一块语法: uniform MaterialBlock { vec3 Ka, Kd, Ks; float Shininess; }; 以下是客户端代码: scene::MaterialPtr pMaterial = this->FindMaterialByName(name); GLuint bindingPoint =

我在我的OpenGL/GLSL应用程序中实现了一个统一块,用于管理网格材质数据(环境光、漫反射光和镜面反射光以及反光)

在我的第一次尝试中,我实现了以下统一块语法:

uniform MaterialBlock
{
   vec3 Ka, Kd, Ks;
   float Shininess;
};
以下是客户端代码:

scene::MaterialPtr pMaterial = this->FindMaterialByName(name);

GLuint bindingPoint = 0, bufferIndex = 0;
GLint blockSize = 0;
GLuint indices[4];
GLint offset[4];

const GLchar *names[4] = {"Ka", "Kd", "Ks", "Shininess" };

GLuint blockIndex = glGetUniformBlockIndex(this->m_Handle, "MaterialBlock");

glGetActiveUniformBlockiv(this->m_Handle, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &blockSize);
glGetUniformIndices(this->m_Handle, 4, names, indices);
glGetActiveUniformsiv(this->m_Handle, 4, indices, GL_UNIFORM_OFFSET, offset);

char *pBuffer = new char[blockSize];

memset(pBuffer, '\0', blockSize);

glm::vec3 ambient = pMaterial->GetAmbient();
glm::vec3 diffuse = pMaterial->GetDiffuse();
glm::vec3 specular = pMaterial->GetSpecular();

float shininess = pMaterial->GetShininess();

std::copy(reinterpret_cast<char*>(&ambient[0]),
    reinterpret_cast<char*>(&ambient[0]) + sizeof(glm::vec4), pBuffer + offset[0]);
std::copy(reinterpret_cast<char*>(&diffuse[0]), reinterpret_cast<char*>(
    &diffuse[0]) + sizeof(glm::vec4), pBuffer + offset[1]);
std::copy(reinterpret_cast<char*>(&specular[0]),
    reinterpret_cast<char*>(&specular[0]) + sizeof(glm::vec3), pBuffer + offset[2]);
std::copy(reinterpret_cast<char*>(&shininess), reinterpret_cast<char*>(
    &shininess) + sizeof(float), pBuffer + offset[3]);

glUniformBlockBinding(this->m_Handle, blockIndex, bindingPoint);
{
    glGenBuffers(1, &bufferIndex);
    glBindBuffer(GL_UNIFORM_BUFFER, bufferIndex);
    {
        glBufferData(GL_UNIFORM_BUFFER, blockSize, NULL, GL_DYNAMIC_DRAW);
        glBufferSubData(GL_UNIFORM_BUFFER, 0, blockSize, (const GLvoid *)pBuffer);
    }
    glBindBuffer(GL_UNIFORM_BUFFER, 0);
}
glBindBufferBase(GL_UNIFORM_BUFFER, bindingPoint, bufferIndex);

//TEXTURE.
{
    this->SetUniform("colorSampler", 0); //THE CHANNEL HAS TO BE CALCULATED! //int

    glActiveTexture(GL_TEXTURE0); //DYNAMICS.
    pMaterial->GetTexture()->Lock();
}
片段着色器代码:

#version 440

#define MAX_LIGHT_COUNT 10

/*
** Output color value.
*/
layout (location = 0) out vec4 FragColor;

/*
** Inputs.
*/
in vec3 Position;
in vec2 TexCoords;
in vec3 Normal;

/*
** Material uniform block.
*/
uniform MaterialBlock
{
    vec3 Ka, Kd, Ks;
    float Shininess;
};

uniform sampler2D ColorSampler;

struct Light
{
    vec4 Position;
    vec3 La, Ld, Ls;
    float Kc, Kl, Kq;
};

uniform struct Light LightInfos[MAX_LIGHT_COUNT];

uniform unsigned int LightCount;

/*
** Light attenuation factor.
*/
float getLightAttenuationFactor(vec3 lightDir, Light light)
{
    float lightAtt = 0.0f;
    float dist = 0.0f;

    dist = length(lightDir);
    lightAtt = 1.0f / (light.Kc + (light.Kl * dist) + (light.Kq * pow(dist, 2)));
    return (lightAtt);
}

/*
** Basic phong shading.
*/
vec3 Basic_Phong_Shading(vec3 normalDir, vec3 lightDir, vec3 viewDir, int idx)
{
    vec3 Specular = vec3(0.0f);

    float lambertTerm = max(dot(lightDir, normalDir), 0.0f);

    vec3 Ambient = LightInfos[idx].La * Ka;
    vec3 Diffuse = LightInfos[idx].Ld * Kd * lambertTerm;

    if (lambertTerm > 0.0f)
    {
        vec3 reflectDir = reflect(-lightDir, normalDir);
        Specular = LightInfos[idx].Ls * Ks * pow(max(dot(reflectDir, viewDir), 0.0f), Shininess);
    }
    return (Ambient + Diffuse + Specular);
}

/*
** Fragment shader entry point.
*/
void main(void)
{
    vec3 LightIntensity = vec3(0.0f);

    vec4 texDiffuseColor = texture2D(ColorSampler, TexCoords);
    vec3 normalDir = (gl_FrontFacing ? -Normal : Normal);

    for (int idx = 0; idx < LightCount; idx++)
    {
        vec3 lightDir = vec3(LightInfos[idx].Position) - Position.xyz;
        vec3 viewDir = -Position.xyz;

        float lightAttenuationFactor = getLightAttenuationFactor(lightDir, LightInfos[idx]);

        LightIntensity += Basic_Phong_Shading(
            -normalize(normalDir), normalize(lightDir), normalize(viewDir), idx
        ) * lightAttenuationFactor;
    }
    FragColor = vec4(LightIntensity, 1.0f) * texDiffuseColor;
}
当然,着色器中使用的所有变量,如“Ka”、“Kd”、“Ks”和“Shininess”,都变成了“materialinfo.Ka”、“materialinfo.Kd”、“materialinfo.Ks”和“materialinfo.Shininess”

但不幸的是,程序执行失败,因为在客户机代码中,varibales的“索引”和“偏移”没有正确填充

这是日志:

blockIndex: 0 //OK
blockSize: 48 //OK
Indices: {4294967295, 4294967295, 4294967295, 4294967295} //NOT OK
Offset: {-858993460, -858993460, -858993460, -858993460} //NOT OK
因此,只有块索引和块大小是正确的。因此,为了解决问题,我尝试更改行:

const GLchar *names[4] = {"Ka", "Kd", "Ks", "Shininess" };
通过以下方式:

const GLchar *names[4] = {"MaterialInfos.Ka", "MaterialInfos.Kd", "MaterialInfos.Ks", "MaterialInfos.Shininess" };
但是对于变量'index'和'offset',我仍然有相同的日志。因此,我的申请仍然失败。我认为这是客户端代码中的语法问题(不是GLSL代码,因为我没有GLSL错误),但我找不到解决方案


你知道我的问题是从哪里来的吗?

试着将你的structType与制服(structType的类型)分开声明

(如果遵循此示例,则MaterialBlock和Light声明都是错误的,原因稍有不同)


然后,您可以通过在cpu端将它们引用为(例如)
“material.kAmbient”
,并在gpu端将它们读取为
material.kAmbient

当使用实例化的统一块时,引用的不是当前代码中的实例名称。实例名称仅由GLSL着色器看到

因此,
名称
变量的定义和初始化如下:

const GLchar *names[4] = {"MaterialBlock.Ka", "MaterialBlock.Kd", "MaterialBlock.Ks", "MaterialBlock.Shininess" };

你好您的解决方案就是我在使用统一块之前使用的解决方案。这个解决方案有效,但是使用glUniformXXX方法,就像我在文章顶部所说的那样。这些信息必须在每一帧发送,这与统一缓冲区对象(在缓存中存储数据)不同。数据不需要每帧发送一次!如果你看我上面的片段着色器源代码,你会发现你的解决方案就是我用于光信息“struct light”的解决方案(此后,该结构将消失,以支持新的统一块,如实际的MaterialBlock)。哦!你的解决方案是我唯一没有测试过的!它工作得很好!非常感谢你。再见。
const GLchar *names[4] = {"MaterialInfos.Ka", "MaterialInfos.Kd", "MaterialInfos.Ks", "MaterialInfos.Shininess" };
    struct MaterialData
    {
        vec3 kAmbient;
        vec3 kDiffuse;
        vec3 kSpecular;
        float shininess;
    };

    uniform MaterialData material;
const GLchar *names[4] = {"MaterialBlock.Ka", "MaterialBlock.Kd", "MaterialBlock.Ks", "MaterialBlock.Shininess" };