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

时间:2022-03-15 04:32:42

I'm to learn OpenGL 4 and now I working with textures. I would like to apply a texture to a sphere, and my vertex shader looks like this:

我要学习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;
}

After defining the coordinates and triangulation indexes of a sphere, I build a VAO with the following code:

在定义球体的坐标和三角测量索引之后,我使用以下代码构建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;
}

To load the attributes, I did the following (before using texture):

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

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

Now, however, I have an array (_sphereTexCoords) which contains the texture coordinates and I don't really know how to pass it to the vertex shader as the vertex coordinates are passed. Do I have to create another VBO? I though of doing something like this:

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

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

But I don't really know how to specify that this is related to the _sphereTexCoords array.

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

EDIT

I tried this, but it didn't work.

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

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

I get an error when binding the program.

绑定程序时出错。

1 个解决方案

#1


You're very close. The only thing I see missing is that you do not bind the correct buffer before calling glVertexAttribPointer(). When you call glVertexAttribPointer(), you specify that the data for the attribute will be pulled from the buffer that is currently bound to GL_ARRAY_BUFFER.

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

Your LoadAttributeVariables() method should therefore be:

因此,您的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);

#1


You're very close. The only thing I see missing is that you do not bind the correct buffer before calling glVertexAttribPointer(). When you call glVertexAttribPointer(), you specify that the data for the attribute will be pulled from the buffer that is currently bound to GL_ARRAY_BUFFER.

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

Your LoadAttributeVariables() method should therefore be:

因此,您的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);