2012-11-25 39 views
0

我試圖加載六張圖片作爲紋理並繪製天空盒,但結果很奇怪,每張圖片在其相應的矩形上以灰色映射三次。問題是什麼?我的代碼無法正確加載圖片到opengl

#include <stdlib.h> 
#include <stdio.h> 

#include <glut.h> 
#include <gl.h> 
#include <glu.h> 

#include <math.h> 
#include <windows.h> 

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

void init(void) 
{ 

glClearColor (0.0, 0.0, 0.0, 1.0); 
glShadeModel (GL_SMOOTH); 
glEnable(GL_LIGHTING); 
glEnable(GL_LIGHT0); 
glEnable(GL_DEPTH_TEST); 
glEnable(GL_NORMALIZE); 
glEnable(GL_TEXTURE_2D); 
} 

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

file = fopen(filename, "r"); 
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); 

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_DECAL); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_DECAL); 
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); 
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // texture should tile 
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; 
glPushAttrib(GL_ENABLE_BIT); 
glEnable(GL_TEXTURE_2D); 
glDisable(GL_DEPTH_TEST); 
glDisable(GL_LIGHTING); 
glDisable(GL_BLEND); 
// 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 | GL_DEPTH_BUFFER_BIT); 
GLfloat light_ambient[] = { 1.0, 1.0, 1.0, 1.0 }; 
GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 }; 
GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 }; 
GLfloat light_position[] = { 0.0, 0.0, 30.0, 0.0 }; 


glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient); 
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); 
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular); 
glLightfv(GL_LIGHT0, GL_POSITION, light_position); 

glLoadIdentity(); 
glPushMatrix(); 
gluLookAt (20.0, 20.0, 20.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); 
glPushMatrix(); 
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 
glPopMatrix(); 
glPopMatrix(); 

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


} 


void reshape (int w, int h) 
{ 
glViewport (0, 0, (GLsizei) w, (GLsizei) h); 
glMatrixMode (GL_PROJECTION); 
glLoadIdentity(); 
glOrtho(-100.0, 100.0, -100.0, 100.0,-100.0,100.0); 
glMatrixMode(GL_MODELVIEW); 
glLoadIdentity(); 

} 

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

glutMainLoop(); 
} 

回答

1

所以,你要加載DIB/BMP圖片文件:

>  texture[0] = LoadTexture("back.bmp", 256, 256); //load the texture 
>         ^^^^ 
> 

閱讀的內容文件

> GLuint LoadTexture(const char * filename, int width, int height) { 
> GLuint texture; unsigned char * data; FILE* file; 
> 
> file = fopen(filename, "r"); 
> if (file == NULL) return 0; 
> data = (unsigned char *)malloc(width * height * 3); 
> fread(data, width * height * 3, 1, file); 

這對BMP,BTW來說太短了。

> fclose(file); 

那麼,您的DIB解析器代碼在哪裏?

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

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_DECAL); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_DECAL); 
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); 
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // texture should tile 
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; 
} 

你只是通過非解析DIB/BMP文件內容的OpenGL。你期望OpenGL如何處理這個問題? OpenGL不知道文件格式,不知道如何處理DIB文件。你需要一個DIB解析器。

+0

你是對的,datenwolf,我也嘗試nehe的代碼,它使用AUX_RGBImageRec,我的編譯器說'無法打開DIB文件'。但我是初學者,我不知道DIB解析器,有沒有例子? – phil

+0

嘗試使用類似['stb_image.c'](http://nothings.org/stb_image.c)。 – genpfault

+0

@ phil:好的,有兩種方法可以解決您的問題。你自己編寫一個DIB解析器,遵循DIB文件格式規範http://en.wikipedia.org/wiki/BMP_file_format - 或者你可以使用一個圖像閱讀器庫(它也可以支持多種文件格式)。我個人很喜歡Imlib2 http://docs.enlightenment.org/api/imlib2/html/ – datenwolf

0

既然你加載RGB數據確保GL_UNPACK_ALIGNMENT is set to 1

glPixelStorei(GL_UNPACK_ALIGNMENT, 1)​. 
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, width, height, GL_RGB, GL_UNSIGNED_BYTE,data); 
+1

OP正試圖將DIB文件直接轉儲到OpenGL而不解析它。我很確定,那是他的主要問題。 True Color DIB文件總是將它們的行對齊到4個字節的邊界,所以這是設置對齊無關緊要的情況之一:) – datenwolf

+0

我不知道,也許OP將一些'raw'文件改名爲'BMP' :) – genpfault

0

我使用ImageMagick開放庫來輕鬆加載任何圖像以用於OpenGL。