OpenGL 中的天空盒

4

我正在为OpenGL中的天空盒制作环境贴图,但是遇到了纹理问题。我的代码产生了一些我试图映射的纹理瓷砖,而不是一个大的纹理。这些瓷砖也丢失了大部分分辨率,并且非常小。

这里是我的代码:

#include <windows.h>
#include <stdio.h>
#include <glew.h>
#include <glut.h>
#include "Camera.h"

Camera cam;
GLuint texture [6]; //the array for our texture

GLfloat angle = 0.0;

GLuint LoadTexture( const char * filename, int width, int height) {
    GLuint texture;
    unsigned char * data;
    FILE* file;

    file = fopen( filename, "rb" );
    if ( file == NULL ) return 0;
    data = (unsigned char *)malloc( width * height * 3 );
    fread( data, width * height * 3, 1, file );
    fclose( file );

    glGenTextures( 1, &texture ); 
    glBindTexture( GL_TEXTURE_2D, texture ); 
    glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); 

    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR );

    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );

    gluBuild2DMipmaps( GL_TEXTURE_2D, 3, width, height, GL_RGB, GL_UNSIGNED_BYTE, data );    
    free(data);
    return texture; 
}    

void FreeTexture( GLuint texture )
{
    glDeleteTextures( 1, &texture );
}

void skybox (void) {
float x = 0;
float y = 0;
float z = 0;
float width  = 100;
float height = 100;
float length = 100;
// Bind the BACK texture of the sky map to the BACK side of the cube
glBindTexture(GL_TEXTURE_2D, texture[0]);
// Center the skybox
x = x - width  / 2;
y = y - height / 2;
z = z - length / 2;
glBegin(GL_QUADS);      
    glTexCoord2f(1.0f, 0.0f); glVertex3f(x + width, y,  z);
    glTexCoord2f(1.0f, 1.0f); glVertex3f(x + width, y + height, z); 
    glTexCoord2f(0.0f, 1.0f); glVertex3f(x, y + height, z);
    glTexCoord2f(0.0f, 0.0f); glVertex3f(x, y,  z);
glEnd();
glBindTexture(GL_TEXTURE_2D, texture[1]);
glBegin(GL_QUADS);  
    glTexCoord2f(1.0f, 0.0f); glVertex3f(x, y,  z + length);
    glTexCoord2f(1.0f, 1.0f); glVertex3f(x, y + height, z + length);
    glTexCoord2f(0.0f, 1.0f); glVertex3f(x + width, y + height, z + length); 
    glTexCoord2f(0.0f, 0.0f); glVertex3f(x + width, y,  z + length);
glEnd();

glBindTexture(GL_TEXTURE_2D, texture[4]);
glBegin(GL_QUADS);      

    glTexCoord2f(1.0f, 0.0f); glVertex3f(x, y,  z);
    glTexCoord2f(1.0f, 1.0f); glVertex3f(x, y,  z + length);
    glTexCoord2f(0.0f, 1.0f); glVertex3f(x + width, y,  z + length); 
    glTexCoord2f(0.0f, 0.0f); glVertex3f(x + width, y,  z);
glEnd();
glBindTexture(GL_TEXTURE_2D, texture[5]);
glBegin(GL_QUADS);      
    glTexCoord2f(0.0f, 0.0f); glVertex3f(x + width, y + height, z);
    glTexCoord2f(1.0f, 0.0f); glVertex3f(x + width, y + height, z + length); 
    glTexCoord2f(1.0f, 1.0f); glVertex3f(x, y + height, z + length);
    glTexCoord2f(0.0f, 1.0f); glVertex3f(x, y + height, z);
glEnd();
glBindTexture(GL_TEXTURE_2D, texture[2]);
glBegin(GL_QUADS);      
    glTexCoord2f(1.0f, 1.0f); glVertex3f(x, y + height, z); 
    glTexCoord2f(0.0f, 1.0f); glVertex3f(x, y + height, z + length); 
    glTexCoord2f(0.0f, 0.0f); glVertex3f(x, y,  z + length);
    glTexCoord2f(1.0f, 0.0f); glVertex3f(x, y,  z);     

glEnd();
glBindTexture(GL_TEXTURE_2D, texture[3]);
glBegin(GL_QUADS);  
    glTexCoord2f(0.0f, 0.0f); glVertex3f(x + width, y,  z);
    glTexCoord2f(1.0f, 0.0f); glVertex3f(x + width, y,  z + length);
    glTexCoord2f(1.0f, 1.0f); glVertex3f(x + width, y + height, z + length); 
    glTexCoord2f(0.0f, 1.0f); glVertex3f(x + width, y + height, z);
glEnd();
//glBindTexture( GL_TEXTURE_CUBE_MAP, texture[0] ); //bind the texture
//glRotatef( angle, 1.0f, 1.0f, 1.0f );
//glutSolidSphere(2, 40, 40);
}

void display (void) {
glClearColor (0.0,0.0,0.0,1.0);
glClear (GL_COLOR_BUFFER_BIT);
glLoadIdentity();
cam.camera();
//gluLookAt (20.0, 20.0, 20.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
texture[0] = LoadTexture( "Back.bmp", 256, 256 ); //load the texture
texture[1] = LoadTexture( "Front.bmp", 256, 256 ); //load the texture
texture[2] = LoadTexture( "Left.bmp", 256, 256 ); //load the texture
texture[3] = LoadTexture( "Right.bmp", 256, 256 ); //load the texture
texture[4] = LoadTexture( "Bottom.bmp", 256, 256 ); //load the texture
texture[5] = LoadTexture( "Top.bmp", 256, 256 ); //load the texture
glEnable(GL_TEXTURE_2D); //enable 2D texturing
glEnable(GL_TEXTURE_GEN_S); //enable texture coordinate generation
glEnable(GL_TEXTURE_GEN_T);
skybox();
for (int i = 0; i < 6; i++) {
    FreeTexture( texture[i] );
}
glutSwapBuffers();
angle = angle + 0.5;
cam.incAngle();
}

void keyboard (unsigned char key, int x, int y) {
switch (key) {
case 'q': cam.lookUpwards(); break;
case 'z': cam.lookDownwards(); break;
case 'w': cam.slideForward(); break;
case 's': cam.slideBackward(); break;
case 'a': cam.strafeLeft(); break;
case 'd': cam.strafeRight(); break;
case 'e': exit(0); break;
default: break;
}
}

void reshape(int x, int y) {
cam.reshape(x, y);
}

void mouseMovement(int x, int y) {
cam.mouseMovement(x, y);
}

int main (int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
glutCreateWindow("A basic OpenGL Window");
glutDisplayFunc(display);
glutIdleFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutPassiveMotionFunc(mouseMovement);
glutMainLoop();
}

这是固定功能的OpenGL,已经相当过时了。请考虑使用可编程管线和着色器。 - Stephan van den Heuvel
11
请考虑回答实际问题,而不是建议OP不需要的东西。无论日期是否过时,固定功能即使在今天仍有很多用途。为了绘制天空盒而制作GL4着色器是过度设计了。 - SigTerm
1
@StephanvandenHeuvel:我回复你的评论是因为我认为它是有害的。在我的理解中,你提出了增加不必要的复杂性。这违反了KISS原则,引入了YAGNI功能,并将导致额外的错误和浪费的开发时间。如果一项技术是较新的,这并不意味着你应该在你的程序中使用它。如果一项技术比较老旧,这也不意味着你应该避免使用它。我们今天仍然使用TCP/IP,对吧?车轮呢?代码不会腐烂,最好的想法是为问题使用最合适的工具,即使这个工具不是昨天发明的。(续) - SigTerm
@StephanvandenHeuvel:关于OpenGL,着色器并不是很容易理解的,而且在你建议使用的OpenGL 2.0中,与固定功能管线相比,在这个特定的任务(天空盒)中没有任何收益。 - SigTerm
嘿,这与主题无关。但是,在显示函数中不要加载纹理。它会减慢您的程序。 - shan
显示剩余2条评论
2个回答

2

因为您正在手动指定纹理坐标,所以应删除/禁用以下自动生成的内容:

glEnable(GL_TEXTURE_GEN_S); //enable texture coordinate generation
glEnable(GL_TEXTURE_GEN_T);

此外,你正在将 .bmp 文件作为纯粹的 RGB 数据加载似乎有些可疑。

1
如果我们在“glew.h”中使用GL_BGR来替换GL_RGB,颜色就会恢复正常。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接