我正在尝试在OpenGL中绘制一个框(顶部是打开的)。我给它纹理,但它们似乎非常古怪。当我旋转盒子时,侧面纹理似乎在底部,而不是。
这是前视图:
旋转一下后:
显然,这里出了点问题。蓝色的是侧面板的纹理,但是当它旋转时,它似乎在地板上。灰色的是前面板的纹理。因此,在前视图中,后面板根本不应该是可见的。但是,可以看出它。
代码段:
绘制容器的方法(不包括盖子):
void box::drawContainer() {
GLuint tex = loadTexture("wood.bmp");
glPushMatrix();
glBindTexture(GL_TEXTURE_2D, tex);
drawBlock(vertex(0, 0, 0), length + 0.2, length + 0.2, thickness); // bottom
tex = loadTexture("tiles.bmp");
glBindTexture(GL_TEXTURE_2D, tex);
drawBlock(
vertex((length - thickness) / 2.0,
(containerHeight + thickness) / 2.0, 0), thickness, breadth,
containerHeight); // right
tex = loadTexture("ocean.bmp");
glBindTexture(GL_TEXTURE_2D, tex);
drawBlock(
vertex((thickness - length) / 2.0,
(containerHeight + thickness) / 2.0, 0), thickness, breadth,
containerHeight); // left
tex = loadTexture("smoke.bmp");
glBindTexture(GL_TEXTURE_2D, tex);
drawBlock(
vertex(0, (containerHeight + thickness) / 2.0,
(breadth - thickness) / 2.0), (length - 2.0 * thickness),
thickness, containerHeight); // front
tex = loadTexture("lightning.bmp");
glBindTexture(GL_TEXTURE_2D, tex);
drawBlock(
vertex(0, (containerHeight + thickness) / 2.0,
(thickness - breadth) / 2.0), (length - 2.0 * thickness),
thickness, containerHeight); // back
glPopMatrix();
}
drawBlock方法:
void object::drawBlock(vertex center, float length, float breadth,
float height) {
glPushMatrix();
glTranslatef(center.x, center.y, center.z);
glScalef(length, height, breadth);
glBegin(GL_QUADS);
drawPrimitive(vertex(-0.5, 0.5, 0.5), vertex(-0.5, -0.5, 0.5),
vertex(0.5, -0.5, 0.5), vertex(0.5, 0.5, 0.5),
vertex(-0.5, 0.5, -0.5), vertex(-0.5, -0.5, -0.5),
vertex(0.5, -0.5, -0.5), vertex(0.5, 0.5, -0.5));
glEnd();
glPopMatrix();
}
drawPrimitive方法:
void object::drawPrimitive(vertex v1, vertex v2, vertex v3, vertex v4,
vertex v5, vertex v6, vertex v7, vertex v8) {
drawFace(v1, v2, v3, v4);
drawFace(v5, v6, v7, v8);
drawFace(v1, v5, v6, v2);
drawFace(v4, v3, v7, v8);
drawFace(v1, v4, v8, v5);
drawFace(v2, v6, v7, v3);
}
并且,drawFace方法:
void object::drawFace(vertex v1, vertex v2, vertex v3, vertex v4) {
glTexCoord2f(0, 1);
glVertex3f(v1.x, v1.y, v1.z);
glTexCoord2f(0, 0);
glVertex3f(v2.x, v2.y, v2.z);
glTexCoord2f(1, 0);
glVertex3f(v3.x, v3.y, v3.z);
glTexCoord2f(1, 1);
glVertex3f(v4.x, v4.y, v4.z);
}
主要功能:
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGBA);
glutInitWindowSize(640, 480);
glutInitWindowPosition(50, 50);
glutCreateWindow(title);
glutDisplayFunc(display);
glutKeyboardFunc(processKey);
glutReshapeFunc(reshape);
initGL();
glutMainLoop();
return 0;
}
initGL方法:
void initGL() {
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set background color to black and opaque
glClearDepth(1.0f); // Set background depth to farthest
glEnable(GL_DEPTH_TEST); // Enable depth testing for z-culling
glDepthFunc(GL_LEQUAL); // Set the type of depth-test
glShadeModel(GL_FLAT);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Nice perspective corrections
}
loadTexture方法:
GLuint inline loadTexture(const char* fName) {
// Data read from the header of the BMP file
unsigned char header[54]; // Each BMP file begins by a 54-bytes header
unsigned int dataPos; // Position in the file where the actual data begins
unsigned char * data;
unsigned int imageSize;
unsigned int width, height;
// Actual RGB data
// Open the file
FILE * file = fopen(fName, "rb");
if (!file) {
printf("Image could not be opened\n");
}
if (fread(header, 1, 54, file) != 54) { // If not 54 bytes read : problem
printf("Not a correct BMP file\n");
return 0;
}
if (header[0] != 'B' || header[1] != 'M') {
printf("Not a correct BMP file\n");
return 0;
}
// Read ints from the byte array
dataPos = *(int*) &(header[0x0A]);
imageSize = *(int*) &(header[0x22]);
width = *(int*) &(header[0x12]);
height = *(int*) &(header[0x16]);
// Some BMP files are misformatted, guess missing information
if (imageSize == 0)
imageSize = width * height * 3; // 3 : one byte for each Red, Green and Blue component
if (dataPos == 0)
dataPos = 54;
// Create a buffer
data = new unsigned char[imageSize];
// Read the actual data from the file into the buffer
fread(data, 1, imageSize, file);
//Everything is in memory now, the file can be closed
fclose(file);
// Create one OpenGL texture
GLuint textureID;
glGenTextures(1, &textureID);
// "Bind" the newly created texture : all future texture functions will modify this texture
glBindTexture(GL_TEXTURE_2D, textureID);
// Give the image to OpenGL
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;
}
调用drawContainer的draw方法:
void box::draw()
{
glEnable(GL_TEXTURE_2D);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
drawContainer();
glDisable(GL_TEXTURE_2D);
}
请告诉我是否需要插入更多代码或需要删除任何内容。
答案 0 :(得分:2)
在其他答案中已经说过了,虽然我认为GL_DEPTH_TEST
未启用会出现问题。
但是,我确实看到您的代码包含以下内容:
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
我认为问题在于你实际上没有为深度缓冲区分配/给出任何内存。因此,GL_DEPTH_TEST
无法执行。
虽然我可以看到你实际上说:
glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGBA);
请记住:您需要传递GLUT_DEPTH
而不是GL_DEPTH
等等。(我这样说,以防其他任何人面临同样的问题你,这通常是一个常见的错误)
您是否尝试过使用:
glutInitDisplayMode(GLUT_DEPTH | GLUT_SINGLE | GLUT_RGBA);
问题可能还在于您在计算机上使用的硬件,某些硬件不支持32位深度缓冲区,因此您可以使用24位等深度缓冲区。
我没有在您的代码中看到实际设置透视图的任何位置,这也可能是深度测试混乱的原因。因为如果你在透视投影矩阵中使用0.0
作为近平面,那么它可能会破坏深度测试。
我为这个公开的答案道歉,但我现在无法对此进行测试。此外,如果由于您的硬件而发生,那么我/我们无法测试它。
答案 1 :(得分:0)
你似乎错过了
glEnable(GL_DEPTH_TEST);
另外,请确保您的OpenGL上下文具有深度缓冲区(这取决于平台;因为您没有显示如何创建上下文窗口,所以我无法向您展示如何执行此操作)。
最后,请务必将GL_DEPTH_BUFFER_BIT
传递给glClear
,无论您在何处召唤它。
答案 2 :(得分:0)
您的代码不完整,所以这只是猜测。 (你没有显示loadTexture)
我没有看到你启用和禁用纹理的位置,因此最后一个活动纹理将用于渲染的其余部分,可能会导致问题。
使用纹理的正确顺序是启用它,绑定到纹理,渲染,然后禁用纹理。像这样:
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, textureID);
// render here
glDisable(GL_TEXTURE_2D);
OpenGL common mistakes可以帮助您解决问题。
如果你使用box::drawContainer()
来渲染图像,那么你就是错误地做了,因为每次渲染窗口时你都要创建新的纹理。你需要做一次,然后只使用纹理。当不需要纹理时,您可以释放它们。
答案 3 :(得分:0)
您似乎永远不会清除颜色/深度缓冲区。你需要在每一帧之前完成它。此外,请确保在跟踪容器时仍然启用了深度测试:
glIsEnabled( GL_DEPTH_TEST );
如果没有,请查看您尚未发布的代码。
希望这有帮助
答案 4 :(得分:0)
原来我给了z-perspective错误。感谢所有帮助