统一块和缓冲区

时间:2014-11-10 22:27:33

标签: c++ opengl glsl

我一直在尝试使用OpenGL 3.3创建一个创建并允许修改统一缓冲区对象的类。无论统一块定义中的布局限定符(std140,共享或打包),该类都应该可用。它似乎工作正常,直到我重构phong着色器使用统一块而不是制服。从那以后,应用程序无法在phong着色器中找到统一的块,但对所有其他着色器工作得非常好。 这让我相信它一定是我在重新格式化phong着色器时所犯的错误,但我已经无数次地查看它并找不到任何东西。我唯一能想到的是编译器正在从着色器中删除均匀块,因为它认为它们没有被使用,但它们肯定被使用,所以它不可能。 着色器肯定是成功编译的,并在调用glGetUniformBlockIndex()之前链接。

每次创建着色器时,都会查找当前使用的两个统一块,然后绑定到绑定点(如果找到)。

    programID = glCreateProgram();

    glAttachShader(programID, vertexID);
    glAttachShader(programID, fragmentID);

    glLinkProgram(programID);
    glUseProgram(programID);

    GLuint matricesIndex = glGetUniformBlockIndex(programID, "MatrixBlock");
    if (matricesIndex == GL_INVALID_INDEX)
        cout << "Could not get index for uniform block MatrixBlock in " << name << endl;
    glUniformBlockBinding(programID, matricesIndex, 0);

    GLuint lightsIndex = glGetUniformBlockIndex(programID, "LightBlock");
    if (lightsIndex == GL_INVALID_INDEX)
        cout << "Could not get index for uniform block LightBlock in " << name << endl;
    glUniformBlockBinding(programID, lightsIndex, 1);

这是我在Phong着色器中找不到两个均匀块的地方。顶点和片段着色器如下: 顶点:

// phong.vert
#version 330

const int maxLights = 30;

layout (std140) uniform MatrixBlock
{
    mat4 modelMat;
    mat4 viewMat;
    mat4 modelViewMat;
    mat4 projectionMat;
    mat3 normalMat;
};

layout (std140) uniform LightBlock
{
    int numLights;
    vec4 position[maxLights];
    vec4 direction[maxLights];
    vec4 ambient[maxLights];
    vec4 diffuse[maxLights];
    vec4 specular[maxLights];
    vec3 attenuation[maxLights];
    float cosCutoffAngle[maxLights];
};

layout (location = 0) in vec3 in_Position;
layout (location = 2) in vec3 in_Normal;
layout (location = 3) in vec2 in_TexCoord;

out VS_OUT
{
    vec3 vs_normalVec;
    vec3 vs_vertexVec;
    vec2 vs_texCoord;
    vec3 vs_lightVec[maxLights];
    float vs_lightVertDistance[maxLights];
    float vs_attenuation[maxLights];
} vs_out;


void calculateVectors()
{
        //Translate vertex position into view coordinates. 
    vec4 vertexPosition = modelMat * vec4(in_Position, 1.0);

        //Find vertex position in view coordinates. Since the viewer is at the origin, simply negate the position. 
    vs_out.vs_vertexVec = normalize(-vertexPosition).xyz;

        //Translate normal of the vertex to view coordinates. Uses the normal matrix. 
    vs_out.vs_normalVec = normalize(normalMat * in_Normal);

    for(int i=0; i<numLights; ++i)
    {
            //Calculate the vector from the vertex position to the light source in view coordinates. 
        vs_out.vs_lightVec[i] = position[i].xyz - vertexPosition.xyz;
            //Calculate the distance of the above vector before normalising it. 
        vs_out.vs_lightVertDistance[i] = length(vs_out.vs_lightVec[i]);
        vs_out.vs_lightVec[i] = normalize(vs_out.vs_lightVec[i]);

        vs_out.vs_attenuation[i] = 1 / 
            (attenuation[i].x + 
            attenuation[i].y*vs_out.vs_lightVertDistance[i] + 
            attenuation[i].z*vs_out.vs_lightVertDistance[i]*vs_out.vs_lightVertDistance[i]);
    }
}

void main(void) 
{
    calculateVectors();

    vs_out.vs_texCoord = in_TexCoord;

    gl_Position = projectionMat * modelViewMat * vec4(in_Position, 1.0);

}

和碎片:

//phong.frag
#version 330

// Some drivers require the following
precision highp float;

struct materialStruct
{
    vec4 ambient;
    vec4 diffuse;
    vec4 specular;
    float shininess;
};

const int maxLights = 30;

vec3 reflection;

layout (std140) uniform LightBlock
{
    int numLights;
    vec4 position[maxLights];
    vec4 direction[maxLights];
    vec4 ambient[maxLights];
    vec4 diffuse[maxLights];
    vec4 specular[maxLights];
    vec3 attenuation[maxLights];
    float cosCutoffAngle[maxLights];
};

uniform materialStruct material;
uniform sampler2D textureUnit0;
uniform bool textured = true;

in VS_OUT
{
    vec3 vs_normalVec;
    vec3 vs_vertexVec;
    vec2 vs_texCoord;
    vec3 vs_lightVec[maxLights];
    float vs_lightVertDistance[maxLights];
    float vs_attenuation[maxLights];
} fs_in;

layout (location = 0) out vec4 colour;


vec4 calculateLightColour(int i)
{
        //Calculate colour of light and object material.
        //Ambient intensity
    vec4 ambientI = ambient[i] * material.ambient;

        // Diffuse intensity
    vec4 diffuseI =  diffuse[i] * material.diffuse;
    diffuseI = diffuseI * max(dot(fs_in.vs_normalVec, fs_in.vs_lightVec[i]), 0.0) * fs_in.vs_attenuation[i];

        // Specular intensity
    vec4 specularI = specular[i] * material.specular;
        //Specular Intensity = Ks*(R.V)^(alpha)*Is
    specularI = specularI * pow( max( dot( reflection, fs_in.vs_vertexVec ), 0 ), material.shininess ) * fs_in.vs_attenuation[i];

    return ambientI + diffuseI + specularI;
}

vec4 calculateLight(int i)
{
        //Calculate reflection light makes to the surface. 
    reflection = reflect( -fs_in.vs_lightVec[i], fs_in.vs_normalVec );

    if(cosCutoffAngle[i] == 0 && direction[i] == vec4(0.0, 0.0, 0.0, 0.0))
    {
        return calculateLightColour(i);
    }
    else
    {
            //Calculate the direction vector of the light in view space. 
        vec3 spotDirection = normalize((position[i] - normalize(direction[i])).xyz);

            //Get dot product of spotlight direction and vertex vector. 
        float dotProduct = dot(fs_in.vs_lightVec[i], -normalize(direction[i].xyz));
        //float dotProduct = dot(fs_in.vs_lightVec[i], -spotDirection);

        if(dotProduct > cosCutoffAngle[i])
        {
            return calculateLightColour(i);
        }
        else
            return vec4(0.0, 0.0, 0.0, 1.0);
    }
}

void main(void)
{
    vec4 lightColour = vec4(0.0, 0.0, 0.0, 1.0);

    for(int i=0; i<numLights; ++i)
    {
        lightColour += vec4(calculateLight(i).rgb, 0.0);
    }

    if(textured)
        colour = lightColour * texture(textureUnit0, fs_in.vs_texCoord);
    else
        colour = lightColour;
}

任何帮助在着色器中找到问题都会有很大帮助。如果没有明显的错误,那么有什么可能是问题的任何建议将不胜感激。

我想知道OpenGL中的统一块的其他内容是Superbible第6版关于统一缓冲区的章节说你需要使用统一块的名称,然后在获得制服的偏移时使用元素的名称。例如

GLchar *names[] = {
"MatrixBlock.modelMat",
...
...
};

然后使用glGetUniformIndices和glGetActiveUniformsiv正确填充缓冲区。但是这种命名元素的方法对我来说不起作用,也没有使用实例名称,我看到它也提到了一些地方。 对我有用的只是使用元素名称,例如:

GLchar *names[] = {
"modelMat",
...
...
};

这些差异是否有任何特殊原因?

0 个答案:

没有答案