在 OpenGL 中找不到属性变量,可能的优化

Attribute Variable not found in OpenGL, possible optimization

我目前在延迟着色中工作,我创建了一个 class 来管理 FBO 并在屏幕上绘制缓冲区。

到目前为止是这样的:

FBORender::FBORender(float screenWidth, float screenHeight) :
    _screenWidth(screenWidth),
    _screenHeight(screenHeight),
    ProgramManager("defVertexShader.txt", "defFragShader.txt")
{
    CreateProgram();
    _vbo[0] = 0;
    _vbo[1] = 0;
    _vao = 0;
    BuildQuad();
    BuildVAO();


    glGenFramebuffers(1, &_fbo);
    glGenRenderbuffers(1, &_depthBuffer);

    // Bind the depth buffer
    glBindRenderbuffer(GL_RENDERBUFFER, _depthBuffer);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, (int)_screenWidth, (int)_screenHeight);

    // Generate and bind the texture for diffuse
    glGenTextures(1, &_diffuseBuffer);
    glBindTexture(GL_TEXTURE_2D, _diffuseBuffer);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (int)_screenWidth, (int)_screenWidth, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    // Generate and bind the texture for positions
    glGenTextures(1, &_positionBuffer);
    glBindTexture(GL_TEXTURE_2D, _positionBuffer);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, (int)_screenWidth, (int)_screenWidth, 0, GL_RGBA, GL_FLOAT, NULL);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    // Generate and bind the texture for normals
    glGenTextures(1, &_normalBuffer);
    glBindTexture(GL_TEXTURE_2D, _normalBuffer);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, (int)_screenWidth, (int)_screenWidth, 0, GL_RGBA, GL_FLOAT, NULL);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    // Bind the FBO so that the next operations will be bound to it.
    glBindFramebuffer(GL_FRAMEBUFFER, _fbo);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthBuffer);
    // Attach the textures to the FBO
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _diffuseBuffer, 0);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, _positionBuffer, 0);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, _normalBuffer, 0);

    GLenum fboStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    if (fboStatus != GL_FRAMEBUFFER_COMPLETE)
    {
        printf("DeferredLighting::Init: FrameBuffer incomplete: 0x%x\n", fboStatus);
        exit(1);
    }
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
}


FBORender::~FBORender()
{
    glDeleteTextures(1, &_normalBuffer);
    glDeleteTextures(1, &_positionBuffer);
    glDeleteTextures(1, &_diffuseBuffer);
    glDeleteFramebuffers(1, &_fbo);

    glDeleteVertexArrays(1, &_vao);
    glDeleteBuffers(2, _vbo);
}


void FBORender::Start()
{
    // Bind the FBO and set the viewport to the proper size
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _fbo);
    glViewport(0, 0, (int)_screenWidth, (int)_screenWidth);

    // Clear the render targets
    GLenum windowBuffClear[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
    glDrawBuffers(3, windowBuffClear);
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    GLenum windowBuffOpaque[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
    glDrawBuffers(3, windowBuffOpaque);
}


void FBORender::Draw(const glm::mat4 &Projection, const glm::mat4 &ModelView)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    _ModelViewProjection = Projection * ModelView;
    _ModelView = ModelView;

    glDisable(GL_DEPTH_TEST);

    Bind();

    glActiveTexture(GL_TEXTURE2);
    glBindTexture(GL_TEXTURE_2D, _normalBuffer);

    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, _positionBuffer);

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, _diffuseBuffer);

    glBindVertexArray(_vao);
    LoadUniformVariables();
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    glBindVertexArray(0);

    UnBind();
}


void FBORender::Stop()
{
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
}


void FBORender::BuildQuad()
{
    _coordinates[0] = 1.0f;
    _coordinates[1] = 1.0f;
    _coordinates[2] = 0.0f;
    _coordinates[3] = -1.0f;
    _coordinates[4] = 1.0f;
    _coordinates[5] = 0.0f;
    _coordinates[6] = 1.0;
    _coordinates[7] = -1.0f;
    _coordinates[8] = 0.0f;
    _coordinates[9] = -1.0f;
    _coordinates[10] = -1.0f;
    _coordinates[11] = 0.0f;

    _uv[0] = 1.0f;
    _uv[1] = 1.0f;
    _uv[2] = 0.0f;
    _uv[3] = 1.0f;
    _uv[4] = 1.0f;
    _uv[5] = 0.0f;
    _uv[6] = 0.0f;
    _uv[7] = 0.0f;
}


void FBORender::BuildVAO()
{
    // Generate and bind the vertex array object
    glGenVertexArrays(1, &_vao);
    glBindVertexArray(_vao);

    // Generate and bind the vertex buffer object
    glGenBuffers(2, _vbo);
    glBindBuffer(GL_ARRAY_BUFFER, _vbo[0]);
    glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(float), _coordinates, GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, _vbo[1]);
    glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(float), _uv, GL_STATIC_DRAW);

    LoadAttributeVariables();

    glBindVertexArray(0);
}


void FBORender::LoadUniformVariables()
{
    // OpenGL Matrices
    GLuint ModelViewProjection_location = glGetUniformLocation(GetProgramID(), "mvMatrix");
    glUniformMatrix4fv(ModelViewProjection_location, 1, GL_FALSE, glm::value_ptr(_ModelView));

    // Texture buffers
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, _diffuseBuffer);
    GLint Diffuse_location = glGetUniformLocation(GetProgramID(), "tDiffuse");
    glUniform1i(Diffuse_location, 0);

    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, _positionBuffer);
    GLint Position_location = glGetUniformLocation(GetProgramID(), "tPosition");
    glUniform1i(Position_location, 0);

    glActiveTexture(GL_TEXTURE2);
    glBindTexture(GL_TEXTURE_2D, _normalBuffer);
    GLint Normal_location = glGetUniformLocation(GetProgramID(), "tNormals");
    glUniform1i(Normal_location, 0);
}


void FBORender::LoadAttributeVariables()
{
    // Vertex Attributes
    GLuint VertexPosition_location = glGetAttribLocation(GetProgramID(), "vPosition");
    glEnableVertexAttribArray(VertexPosition_location);
    glBindBuffer(GL_ARRAY_BUFFER, _vbo[0]);
    glVertexAttribPointer(VertexPosition_location, 3, GL_FLOAT, GL_FALSE, 0, 0);

    GLuint TextureCoord_Location = glGetAttribLocation(GetProgramID(), "uvCoord");
    printf("%d \n", TextureCoord_Location);
    glEnableVertexAttribArray(TextureCoord_Location);
    glBindBuffer(GL_ARRAY_BUFFER, _vbo[1]);
    glVertexAttribPointer(TextureCoord_Location, 2, GL_FLOAT, GL_FALSE, 0, 0);
}

这些是我的着色器:

#version 410 core

uniform mat4 mvMatrix;

in vec4 vPosition;
in vec2 uvCoord;

smooth out vec2 texCoord;

void main(void) 
{
    texCoord = uvCoord;
    gl_Position = vPosition * mvMatrix;
}


#version 410 core

uniform sampler2D tDiffuse; 
uniform sampler2D tPosition;
uniform sampler2D tNormals;

in vec2 texCoord;

out vec4 fragColor;

void main( void )
{
    vec4 image = texture( tDiffuse, texCoord.st );
    vec4 position = texture( tPosition, texCoord.st );
    vec4 normal = texture( tNormals, texCoord.st );

    fragColor.xyz = vec3(0.5f, 0.5f, 0.5f);
}

问题是,当我尝试设置属性变量时,找不到名为 uvCoord 的变量。我认为这可能是由于优化所致,但是,如果是这样,我做错了什么或者我应该怎么做? uvCoord 用于片段着色器。

The uvCoord is used in the fragment shader.

不,不是。您的输出是恒定的颜色。结果,之前的纹理提取都被一个像样的编译器消除了,texCoord 变化也是如此。这最终导致输入属性的消除,这根本不会以任何方式影响程序的输出。这是 GL 规范允许的。您的属性只是不被视为 活动,但只有活动属性才有位置。