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