着色器中的多个[in]属性 - OpenGL

时间:2015-05-03 17:11:02

标签: c++ opengl textures shader

我要学习OpenGL 4,现在我正在使用纹理。我想将纹理应用于球体,我的顶点着色器看起来像这样:

#version 410

in vec4 vPosition;
in vec2 texCoord;

uniform mat4 mvpMatrix;
uniform mat4 mvMatrix;
uniform mat3 normalMatrix;
uniform vec3 vLightPosition;

smooth out vec3 vVaryingNormal;
smooth out vec3 vVaryingLightDir;
smooth out vec2 uvCoord;

void main (void)
{
    uvCoord = texCoord;
    vec3 vNormal = vPosition.xyz / vPosition.w;
    vVaryingNormal = normalMatrix * vNormal;
    vec4 vPosition4 = mvMatrix * vPosition;
    vec3 vPosition3 = vPosition4.xyz / vPosition4.w;
    vVaryingLightDir = normalize(vLightPosition - vPosition3);
    gl_Position = mvpMatrix * vPosition;
}

在定义球体的坐标和三角测量索引之后,我使用以下代码构建VAO:

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

    // Generate and bind the vertex buffer object
    glGenBuffers(1, &_vbo);
    glBindBuffer(GL_ARRAY_BUFFER, _vbo);
    glBufferData(GL_ARRAY_BUFFER, _sphereCoordinates.size() * sizeof(float), &_sphereCoordinates[0], GL_STATIC_DRAW);

    // Generate and bind the index buffer object
    glGenBuffers(1, &_ibo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ibo);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, _sphereIndexes.size() * sizeof(unsigned int), &_sphereIndexes[0], GL_STATIC_DRAW);

    // Generate and bind texture
    _texture = LoadTexture("ball.bmp");

    LoadAttributeVariables();

    glBindVertexArray(0);
}

GLuint ProgramManager::LoadTexture(const char* imagepath)
{    
    unsigned int width, height;
    unsigned char * data = LoadBMP(imagepath, &width, &height);

    GLuint textureID;
    glGenTextures(1, &textureID);
    glBindTexture(GL_TEXTURE_2D, textureID);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, data);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

    return textureID;
}

要加载属性,我执行了以下操作(在使用纹理之前):

void SphereShaderProgram::LoadAttributeVariables()
{
    // Vertex Attributes
    GLuint VertexPosition_location = glGetAttribLocation(GetProgramID(), "vPosition");
    glEnableVertexAttribArray(VertexPosition_location);
    glVertexAttribPointer(VertexPosition_location, 3, GL_FLOAT, GL_FALSE, 0, 0);
}

然而,现在,我有一个包含纹理坐标的数组(_sphereTexCoords),我不知道如何在顶点坐标传递时将其传递给顶点着色器。我是否必须创建另一个VBO?我做了类似的事情:

GLuint TextureCoord_Location = glGetAttribLocation(GetProgramID(), "texCoord");
glEnableVertexAttribArray(TextureCoord_Location);
glVertexAttribPointer(TextureCoord_Location, 2, GL_FLOAT, GL_FALSE, 0, 0);

但我真的不知道如何指定这与_sphereTexCoords数组有关。

修改

我尝试了这个,但它没有用。

void SphereShaderProgram::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, _sphereCoordinates.size() * sizeof(float), &_sphereCoordinates[0], GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, _vbo[1]);
    glBufferData(GL_ARRAY_BUFFER, _textureCoordinates.size() * sizeof(float), &_textureCoordinates[0], GL_STATIC_DRAW);

    // Generate and bind the index buffer object
    glGenBuffers(1, &_ibo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ibo);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, _sphereIndexes.size() * sizeof(unsigned int), &_sphereIndexes[0], GL_STATIC_DRAW);

    // Generate and bind texture
    _texture = LoadTexture("ball.bmp");

    LoadAttributeVariables();

    glBindVertexArray(0);
}

void SphereShaderProgram::LoadAttributeVariables()
{
    // Vertex Attributes
    GLuint VertexPosition_location = glGetAttribLocation(GetProgramID(), "vPosition");
    glEnableVertexAttribArray(VertexPosition_location);
    glVertexAttribPointer(VertexPosition_location, 3, GL_FLOAT, GL_FALSE, 0, 0);

    GLuint TextureCoord_Location = glGetAttribLocation(GetProgramID(), "texCoord");
    glEnableVertexAttribArray(TextureCoord_Location);
    glVertexAttribPointer(TextureCoord_Location, 2, GL_FLOAT, GL_FALSE, 0, 0);
}

绑定程序时出错。

1 个答案:

答案 0 :(得分:2)

你非常接近。我唯一看到的缺点是你在调用glVertexAttribPointer()之前没有绑定正确的缓冲区。当您致电glVertexAttribPointer()时,您指定将从当前绑定到GL_ARRAY_BUFFER的缓冲区中提取该属性的数据。

因此,您的LoadAttributeVariables()方法应为:

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(), "texCoord");
glEnableVertexAttribArray(TextureCoord_Location);
glBindBuffer(GL_ARRAY_BUFFER, _vbo[1]);
glVertexAttribPointer(TextureCoord_Location, 2, GL_FLOAT, GL_FALSE, 0, 0);