openGL 中使用三角形的天空盒
我正在尝试在 openGL 中实现一个天空盒,但由于某种原因,除非我关闭背面剔除,否则它无法正确绘制,即使如此,它也会显示 3 个搞砸的三角形。玛比,我没有画对三角形,但我不确定。
bool Skybox::onInitialize()
{
myRadius = 100;
setPosition(Vector3(0.0f, 0.0f, 0.0f));
//Initialize color matrix
myColors.push_back(Color(1.0f, 0.0f, 0.0f, 1.0f));
myColors.push_back(Color(1.0f, 1.0f, 0.0f, 1.0f));
myColors.push_back(Color(1.0f, 0.5f, 0.0f, 1.0f));
myColors.push_back(Color(0.5f, 0.5f, 0.5f, 1.0f));
//Position the key points of the cube
myVertices.push_back(Vertex(-myRadius, -myRadius, myRadius));//0
myVertices.push_back(Vertex(-myRadius, -myRadius, -myRadius));//1
myVertices.push_back(Vertex(myRadius, -myRadius, -myRadius));//2
myVertices.push_back(Vertex(myRadius, -myRadius, myRadius));//3
myVertices.push_back(Vertex(-myRadius, myRadius, myRadius));//4
myVertices.push_back(Vertex(-myRadius, myRadius, -myRadius));//5
myVertices.push_back(Vertex( myRadius, myRadius, -myRadius));//6
myVertices.push_back(Vertex( myRadius, myRadius, myRadius));//7
//Push back the indices that make up the triangles for each face.
//Bottom
myIndices.push_back(0);
myIndices.push_back(1);
myIndices.push_back(2);
myIndices.push_back(2);
myIndices.push_back(1);
myIndices.push_back(0);
//Top
myIndices.push_back(7);
myIndices.push_back(6);
myIndices.push_back(4);
myIndices.push_back(6);
myIndices.push_back(5);
myIndices.push_back(4);
//Left
myIndices.push_back(0);
myIndices.push_back(4);
myIndices.push_back(1);
myIndices.push_back(4);
myIndices.push_back(5);
myIndices.push_back(1);
//Right
myIndices.push_back(2);
myIndices.push_back(6);
myIndices.push_back(3);
myIndices.push_back(6);
myIndices.push_back(7);
myIndices.push_back(3);
//Back
myIndices.push_back(6);
myIndices.push_back(1);
myIndices.push_back(5);
myIndices.push_back(6);
myIndices.push_back(2);
myIndices.push_back(1);
//Front
myIndices.push_back(0);
myIndices.push_back(7);
myIndices.push_back(4);
myIndices.push_back(0);
myIndices.push_back(3);
myIndices.push_back(7);
//Generate Texture Coordinates
//Bottom
myTexCoords.push_back(TexCoord(0.25, 0));
myTexCoords.push_back(TexCoord(0.25, 0.375));
myTexCoords.push_back(TexCoord(0.5, 0.375));
myTexCoords.push_back(TexCoord(0.5, 0));
//Top
myTexCoords.push_back(TexCoord(0.25, 1));
myTexCoords.push_back(TexCoord(0.25, 0.625));
myTexCoords.push_back(TexCoord(0.5, 0.625));
myTexCoords.push_back(TexCoord(0.5, 1));
//Left
myTexCoords.push_back(TexCoord(0, 0.625));
myTexCoords.push_back(TexCoord(0.25, 0.625));
myTexCoords.push_back(TexCoord(0.25, 0.375));
myTexCoords.push_back(TexCoord(0, 0.375));
//Right
myTexCoords.push_back(TexCoord(0.5, 0.625));
myTexCoords.push_back(TexCoord(0.75, 0.625));
myTexCoords.push_back(TexCoord(0.75, 0.375));
myTexCoords.push_back(TexCoord(0.5, 0.375));
//Back
myTexCoords.push_back(TexCoord(0.75, 0.625));
myTexCoords.push_back(TexCoord(1.0, 0.625));
myTexCoords.push_back(TexCoord(1.0, 0.375));
myTexCoords.push_back(TexCoord(0.75, 0.375));
const string vertexShader = (GLSLProgram::glsl130Supported()) ? VERTEX_SHADER_130 : VERTEX_SHADER_120;
const string fragmentShader = (GLSLProgram::glsl130Supported()) ? FRAGMENT_SHADER_130 : FRAGMENT_SHADER_120;
if (!myTexture.load(SKY_TEXTURE))
{
std::cerr << "Could not load the particle texture" << std::endl;
return false;
}
glGenTextures(1, &myTexID);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, myTexID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, myTexture.getWidth(),
myTexture.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
myTexture.getImageData());
m_shaderProgram = std::auto_ptr<GLSLProgram>(new GLSLProgram(vertexShader, fragmentShader));
if (!m_shaderProgram->initialize())
{
std::cerr << "Could not load the skybox shaders" << std::endl;
return false;
}
m_shaderProgram->bindAttrib(0, "a_Vertex");
m_shaderProgram->bindAttrib(1, "a_Color");
m_shaderProgram->bindAttrib(2, "a_TexCoord0");
m_shaderProgram->linkProgram();
m_shaderProgram->sendUniform("texture0", 0);
glGenBuffers(1, &myVertexBuffer); //Generate a buffer for the vertices
glBindBuffer(GL_ARRAY_BUFFER, myVertexBuffer); //Bind the vertex buffer
glBufferData(GL_ARRAY_BUFFER, sizeof(Vector3) * myVertices.size(), &myVertices[0], GL_STATIC_DRAW); //Send the data to OpenGL
glGenBuffers(1, &myColorBuffer);
glBindBuffer(GL_ARRAY_BUFFER, myColorBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(Color) * myColors.size(), &myColors[0], GL_STATIC_DRAW); //Send the data to OpenGL
glGenBuffers(1, &myTexCoordBuffer);
glBindBuffer(GL_ARRAY_BUFFER, myTexCoordBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(TexCoord) * myTexCoords.size(), &myTexCoords[0], GL_STATIC_DRAW); //Send the data to OpenGL
glGenBuffers(1, &myIndexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, myIndexBuffer); //Bind the vertex buffer
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * myIndices.size(), &myIndices[0], GL_STATIC_DRAW); //Send the data to OpenGL
return true;
}
void Skybox::onRender() const
{
//glDisable(GL_DEPTH_TEST);
//glPushMatrix();
glTranslatef(0.0f, 0.0f, 0.0f);
static float modelviewMatrix[16];
static float projectionMatrix[16];
m_shaderProgram->bindShader();
//Get the current matrices from OpenGL
glGetFloatv(GL_MODELVIEW_MATRIX, modelviewMatrix);
glGetFloatv(GL_PROJECTION_MATRIX, projectionMatrix);
//Enable the point sprite and the automatic texture coordinates
glBindTexture(GL_TEXTURE_2D, myTexID);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
//Send the modelview and projection matrices to the shaders
m_shaderProgram->sendUniform4x4("modelview_matrix", modelviewMatrix);
m_shaderProgram->sendUniform4x4("projection_matrix", projectionMatrix);
m_shaderProgram->sendUniform("texture0", 0);
//Bind the vertex array and set the vertex pointer to point at it
glBindBuffer(GL_ARRAY_BUFFER, myVertexBuffer);
glVertexAttribPointer((GLint)0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, myColorBuffer);
glVertexAttribPointer((GLint)1, 4, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, myTexCoordBuffer);
glVertexAttribPointer((GLint)2, 2, GL_FLOAT, GL_FALSE, 0, 0);
//Bind the index array
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, myIndexBuffer);
//glDrawElements(GL_TRIANGLES, myIndices.size(), GL_UNSIGNED_INT, 0);
glPointSize(5.0f);
glDrawArrays(GL_TRIANGLES, 0, myIndices.size());
glDisableVertexAttribArray(2);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(0);
// glPopMatrix();
}
I'm trying to implement a skybox in openGL but for some reason its not being drawn properly unless I turn off back face culling and even then it shows 3 triangles that are screwed up. Maby I'm not drawing the triangles right but I'm not sure.
bool Skybox::onInitialize()
{
myRadius = 100;
setPosition(Vector3(0.0f, 0.0f, 0.0f));
//Initialize color matrix
myColors.push_back(Color(1.0f, 0.0f, 0.0f, 1.0f));
myColors.push_back(Color(1.0f, 1.0f, 0.0f, 1.0f));
myColors.push_back(Color(1.0f, 0.5f, 0.0f, 1.0f));
myColors.push_back(Color(0.5f, 0.5f, 0.5f, 1.0f));
//Position the key points of the cube
myVertices.push_back(Vertex(-myRadius, -myRadius, myRadius));//0
myVertices.push_back(Vertex(-myRadius, -myRadius, -myRadius));//1
myVertices.push_back(Vertex(myRadius, -myRadius, -myRadius));//2
myVertices.push_back(Vertex(myRadius, -myRadius, myRadius));//3
myVertices.push_back(Vertex(-myRadius, myRadius, myRadius));//4
myVertices.push_back(Vertex(-myRadius, myRadius, -myRadius));//5
myVertices.push_back(Vertex( myRadius, myRadius, -myRadius));//6
myVertices.push_back(Vertex( myRadius, myRadius, myRadius));//7
//Push back the indices that make up the triangles for each face.
//Bottom
myIndices.push_back(0);
myIndices.push_back(1);
myIndices.push_back(2);
myIndices.push_back(2);
myIndices.push_back(1);
myIndices.push_back(0);
//Top
myIndices.push_back(7);
myIndices.push_back(6);
myIndices.push_back(4);
myIndices.push_back(6);
myIndices.push_back(5);
myIndices.push_back(4);
//Left
myIndices.push_back(0);
myIndices.push_back(4);
myIndices.push_back(1);
myIndices.push_back(4);
myIndices.push_back(5);
myIndices.push_back(1);
//Right
myIndices.push_back(2);
myIndices.push_back(6);
myIndices.push_back(3);
myIndices.push_back(6);
myIndices.push_back(7);
myIndices.push_back(3);
//Back
myIndices.push_back(6);
myIndices.push_back(1);
myIndices.push_back(5);
myIndices.push_back(6);
myIndices.push_back(2);
myIndices.push_back(1);
//Front
myIndices.push_back(0);
myIndices.push_back(7);
myIndices.push_back(4);
myIndices.push_back(0);
myIndices.push_back(3);
myIndices.push_back(7);
//Generate Texture Coordinates
//Bottom
myTexCoords.push_back(TexCoord(0.25, 0));
myTexCoords.push_back(TexCoord(0.25, 0.375));
myTexCoords.push_back(TexCoord(0.5, 0.375));
myTexCoords.push_back(TexCoord(0.5, 0));
//Top
myTexCoords.push_back(TexCoord(0.25, 1));
myTexCoords.push_back(TexCoord(0.25, 0.625));
myTexCoords.push_back(TexCoord(0.5, 0.625));
myTexCoords.push_back(TexCoord(0.5, 1));
//Left
myTexCoords.push_back(TexCoord(0, 0.625));
myTexCoords.push_back(TexCoord(0.25, 0.625));
myTexCoords.push_back(TexCoord(0.25, 0.375));
myTexCoords.push_back(TexCoord(0, 0.375));
//Right
myTexCoords.push_back(TexCoord(0.5, 0.625));
myTexCoords.push_back(TexCoord(0.75, 0.625));
myTexCoords.push_back(TexCoord(0.75, 0.375));
myTexCoords.push_back(TexCoord(0.5, 0.375));
//Back
myTexCoords.push_back(TexCoord(0.75, 0.625));
myTexCoords.push_back(TexCoord(1.0, 0.625));
myTexCoords.push_back(TexCoord(1.0, 0.375));
myTexCoords.push_back(TexCoord(0.75, 0.375));
const string vertexShader = (GLSLProgram::glsl130Supported()) ? VERTEX_SHADER_130 : VERTEX_SHADER_120;
const string fragmentShader = (GLSLProgram::glsl130Supported()) ? FRAGMENT_SHADER_130 : FRAGMENT_SHADER_120;
if (!myTexture.load(SKY_TEXTURE))
{
std::cerr << "Could not load the particle texture" << std::endl;
return false;
}
glGenTextures(1, &myTexID);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, myTexID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, myTexture.getWidth(),
myTexture.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
myTexture.getImageData());
m_shaderProgram = std::auto_ptr<GLSLProgram>(new GLSLProgram(vertexShader, fragmentShader));
if (!m_shaderProgram->initialize())
{
std::cerr << "Could not load the skybox shaders" << std::endl;
return false;
}
m_shaderProgram->bindAttrib(0, "a_Vertex");
m_shaderProgram->bindAttrib(1, "a_Color");
m_shaderProgram->bindAttrib(2, "a_TexCoord0");
m_shaderProgram->linkProgram();
m_shaderProgram->sendUniform("texture0", 0);
glGenBuffers(1, &myVertexBuffer); //Generate a buffer for the vertices
glBindBuffer(GL_ARRAY_BUFFER, myVertexBuffer); //Bind the vertex buffer
glBufferData(GL_ARRAY_BUFFER, sizeof(Vector3) * myVertices.size(), &myVertices[0], GL_STATIC_DRAW); //Send the data to OpenGL
glGenBuffers(1, &myColorBuffer);
glBindBuffer(GL_ARRAY_BUFFER, myColorBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(Color) * myColors.size(), &myColors[0], GL_STATIC_DRAW); //Send the data to OpenGL
glGenBuffers(1, &myTexCoordBuffer);
glBindBuffer(GL_ARRAY_BUFFER, myTexCoordBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(TexCoord) * myTexCoords.size(), &myTexCoords[0], GL_STATIC_DRAW); //Send the data to OpenGL
glGenBuffers(1, &myIndexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, myIndexBuffer); //Bind the vertex buffer
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * myIndices.size(), &myIndices[0], GL_STATIC_DRAW); //Send the data to OpenGL
return true;
}
void Skybox::onRender() const
{
//glDisable(GL_DEPTH_TEST);
//glPushMatrix();
glTranslatef(0.0f, 0.0f, 0.0f);
static float modelviewMatrix[16];
static float projectionMatrix[16];
m_shaderProgram->bindShader();
//Get the current matrices from OpenGL
glGetFloatv(GL_MODELVIEW_MATRIX, modelviewMatrix);
glGetFloatv(GL_PROJECTION_MATRIX, projectionMatrix);
//Enable the point sprite and the automatic texture coordinates
glBindTexture(GL_TEXTURE_2D, myTexID);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
//Send the modelview and projection matrices to the shaders
m_shaderProgram->sendUniform4x4("modelview_matrix", modelviewMatrix);
m_shaderProgram->sendUniform4x4("projection_matrix", projectionMatrix);
m_shaderProgram->sendUniform("texture0", 0);
//Bind the vertex array and set the vertex pointer to point at it
glBindBuffer(GL_ARRAY_BUFFER, myVertexBuffer);
glVertexAttribPointer((GLint)0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, myColorBuffer);
glVertexAttribPointer((GLint)1, 4, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, myTexCoordBuffer);
glVertexAttribPointer((GLint)2, 2, GL_FLOAT, GL_FALSE, 0, 0);
//Bind the index array
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, myIndexBuffer);
//glDrawElements(GL_TRIANGLES, myIndices.size(), GL_UNSIGNED_INT, 0);
glPointSize(5.0f);
glDrawArrays(GL_TRIANGLES, 0, myIndices.size());
glDisableVertexAttribArray(2);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(0);
// glPopMatrix();
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
你的绘图代码非常混乱。它有很多问题,但它们都源于一个根本性的误解。
您有 4 种颜色、8 个位置和 24 个纹理坐标。 OpenGL 不知道该怎么办。
OpenGL 只能使用唯一的顶点属性组。因此,如果您有位置和纹理坐标,这些数组的长度必须相等。对于每个纹理坐标,都有一个与其配对的特定位置,反之亦然。对于每个位置,都有与其配对的特定颜色,反之亦然。
是的,一个立方体只有 8 个不同的位置。但您没有绘制 8 个顶点(顶点是属性数据的集合,如果您愿意,其中可能包含一个位置)。您正在绘制 12 个三角形。每个三角形有 3 个顶点。
仅当三角形共享该顶点的所有顶点属性时,三角形才能共享该顶点。因此,立方体的一个面可以由四个角顶点表示,因为两个三角形(沿着主对角线)对于两个共享顶点共享相同的位置/颜色/texCoord。
但不同面的三角形只有使用相同位置/颜色/texCoord 三元组才能共享顶点数据。在大多数情况下,你的不会。
因此,你必须大量复制你的位置和颜色。立方体的每个面都有独立的位置和颜色(即使它们可能使用与其他面相同的值)。
另外,请考虑完全避免纹理坐标。显然您正在使用着色器,因此只需将您的环境放入立方体贴图中即可。您可以在立方体贴图向外指向的 8 个角处传递“法线”。将它们作为标准进行插值,然后使用它们访问立方体贴图纹理。
Your drawing code is very confused. There are a lot of things wrong with it, but they all stem from one fundamental misunderstanding.
You have 4 colors, 8 positions, and 24 texture coordinates. OpenGL doesn't know what to do with that.
OpenGL can only work with unique groups of vertex attributes. So if you have positions and texture coordinates, the lengths of these arrays must be equal. For each texture coordinate, there is a specific position that pairs with it, and vice-versa. And for each position, there is a specific color that pairs with it, and vice-versa.
Yes, a cube only has 8 different positions. But you're not drawing 8 vertices (a vertex is a collection of attribute data, which may include a position, if you so desire). You are drawing 12 triangles. Each triangle has 3 vertices.
Triangles can only share vertices if they share all of the vertex attributes of that vertex. So one face of a cube can be represented by the four corner vertices, since the two triangles (along the main diagonal) share the same position/color/texCoord for the two shared vertices.
But the triangles of different faces can only share vertex data if they use the same position/color/texCoord triplet. In most cases, yours don't.
Therefore, you must replicate your positions and colors alot. Each face of the cube will have separate positions and colors (even though they may use the same values from others).
Also, consider avoiding the texture coordinate altogether. You're obviously using a shader, so just put your environment in a cubemap. You can pass "normals" at the 8 corners that point outwards from the cubemap. Interpolate them as standard and then access the cubemap texture with them.