代码之家  ›  专栏  ›  技术社区  ›  tuket

GLT带输出接口块的反馈变量

  •  0
  • tuket  · 技术社区  · 4 年前

    我在我的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();
    }
    

    变量内容:

    blockIndex: 0 //OK
    blockSize: 48 //OK
    Indices: {1, 2, 3, 78} //OK
    Offset: {0, 16, 32, 44} //OK
    

    片段着色器代码:

    #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;
    }
    

    这段代码工作得很好。输出如下:

    enter image description here

    但我知道,可以将实例名(如C/C++中的结构)与统一块一起使用,如下所示:

     uniform MaterialBlock
     {
        vec3 Ka, Kd, Ks;
        float Shininess;
    
     } MaterialInfos;
    

    当然,着色器中使用的所有变量,如“Ka”、“Kd”、“Ks”和“shinity”,都会变成“materialinfo”。《物质信息》。Kd’,“材料信息”。“Ks”和“MaterialInfo”。“光亮”。

    但不幸的是,程序执行失败,因为在客户机代码中,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错误),但我找不到解决方案。

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

    0 回复  |  直到 11 年前
        1
  •  3
  •   Nicol Bolas    10 年前

    使用实例化均匀块时,将 OpenGL application uses the block name (in this case MaterialBlock ) before the dot ,而不是当前代码中的实例名称。实例名称仅由GLSL着色器看到。

    所以你 names 变量的定义和初始化应如下所示:

    const GLchar *names[4] = {"MaterialBlock.Ka", "MaterialBlock.Kd", "MaterialBlock.Ks", "MaterialBlock.Shininess" };
    
        2
  •  0
  •   foundry    11 年前

        struct MaterialData
        {
            vec3 kAmbient;
            vec3 kDiffuse;
            vec3 kSpecular;
            float shininess;
        };
    
        uniform MaterialData material;
    

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

    然后,您可以将制服称为(例如) "material.kAmbient" material.kAmbient 在gpu方面。