我已经开始使用NeHe教程学习OpenGL了一会儿。这是第6课的代码。它应该加载bmp图像并将其用作我正在绘制的立方体的纹理。但它无法正常工作并且立方体保持白色。加载图像的功能是“loadGLTextures”。任何人都可以帮忙吗? 我的图像位深度为24.我正在使用Visual Studio 2010。
#include <Windows.h>
#include <stdio.h>
#include <gl\GL.h>
#include <gl\GLU.h>
#include <SDL\SDL.h>
#pragma comment(lib , "SDL.lib")
#pragma comment(lib , "SDLmain.lib")
#pragma comment(lib , "OPENGL32.lib")
#pragma comment(lib , "glu32.lib")
//height , width and bit depth
#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 600
#define SCREEN_BPP 16
//SDL surface
SDL_Surface* surface;
//Texture storage.
GLuint texture[1];
//Quit func.
void Quit(int returnCode)
{
SDL_Quit();
exit(returnCode);
}
//This function will load a bitmap image.
bool loadGLTextures(void)
{
SDL_Surface* textureImage;
textureImage = SDL_LoadBMP("123.bmp");
if(!textureImage)
{
fprintf(stderr , "Couldn't load %s.\n" , "123.bmp");
return false;
}
else
{
//Create the texture.
glGenTextures(1 , &texture[0]);
//Typical texture generation using data from the bitmap.
glBindTexture(GL_TEXTURE_2D , texture[0]);
//Generate the texture.
glTexImage2D(GL_TEXTURE_2D , 0 , 3 , textureImage->w ,
textureImage->h , 0 , GL_RGB , GL_UNSIGNED_BYTE ,
textureImage->pixels);
//Linear filtering.
glTexParameteri(GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR);
//Free up the memory.
if(textureImage)
SDL_FreeSurface(textureImage);
return true;
}
}
//All of the drawing goes throw this.
int drawGLScene(void)
{
static float xrot = 0 , yrot = 0 , zrot = 0;
//Clear screen and depth buffer.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0f , 0.0f , -5.0f);
glRotatef(xrot , 1.0f , 0.0f , 0.0f);
glRotatef(yrot , 0.0f , 1.0f , 0.0f);
glRotatef(zrot , 0.0f , 0.0f ,1.0f);
//Select the texture.
glBindTexture(GL_TEXTURE_2D , texture[0]);
glBegin(GL_QUADS);
//Front:
//Bottom left of the texture and quad.
glTexCoord2f(0.0f , 0.0f); glVertex3f(-1.0f , -1.0f , 1.0f);
//Bottom right fo the texture and quad.
glTexCoord2f(1.0f , 0.0f); glVertex3f(1.0f , -1.0f , 1.0f);
//Top right of the texture and quad.
glTexCoord2f(1.0f , 1.0f); glVertex3f(1.0f , 1.0f , 1.0f);
//Top left of the texture and quad.
glTexCoord2f(0.0f , 1.0f); glVertex3f(-1.0f , 1.0f , 1.0f);
//Back:
//Bottom left of the texture and quad.
glTexCoord2f(0.0f , 0.0f); glVertex3f(1.0f , -1.0f , -1.0f);
//Bottom right of the texture and quad.
glTexCoord2f(1.0f , 0.0f); glVertex3f(-1.0f , -1.0f , -1.0f);
//Top right of the texture and the quad.
glTexCoord2f(1.0f , 1.0f); glVertex3f(-1.0f , 1.0f , -1.0f);
//Top left of the texture and the quad.
glTexCoord2f(0.0f , 1.0f); glVertex3f(1.0f , 1.0f , -1.0f);
//Top:
//Top right of the texture and quad.
glTexCoord2f(1.0f , 1.0f); glVertex3f(1.0f , 1.0f , -1.0f);
//Top left of the texture and quad.
glTexCoord2f(0.0f , 1.0f); glVertex3f(-1.0f , 1.0f , -1.0f);
//Bottom left of the texture and quad.
glTexCoord2f(0.0f , 0.0f); glVertex3f(-1.0f , 1.0f , 1.0f);
//Bottom right of the texture and quad.
glTexCoord2f(0.0f , 1.0f); glVertex3f(1.0f , 1.0f , 1.0f);
//Bottom:
//Top left of the texture and quad.
glTexCoord2f(0.0f , 1.0f); glVertex3f(-1.0f , -1.0f , 1.0f);
//Bottom left of the texture and quad.
glTexCoord2f(0.0f , 0.0f); glVertex3f(-1.0f , -1.0f , -1.0f);
//Bottom right of the texture and quad.
glTexCoord2f(1.0f , 0.0f); glVertex3f(1.0f , -1.0f , -1.0f);
//Top right of the texture and quad.
glTexCoord2f(1.0f , 1.0f); glVertex3f(1.0f , -1.0f , 1.0f);
//Right:
//Bottom right of the texture and quad.
glTexCoord2f(1.0f , 0.0f); glVertex3f(1.0f , -1.0f , -1.0f);
//Top right of the texture and quad.
glTexCoord2f(1.0f , 1.0f); glVertex3f(1.0f , 1.0f , -1.0f);
//Top left of the texture and quad.
glTexCoord2f(0.0f , 1.0f); glVertex3f(1.0f , 1.0f , 1.0f);
//Bottom left of the texture and quad.
glTexCoord2f(0.0f , 0.0f); glVertex3f(1.0f , -1.0f , 1.0f);
//Left:
//Bottom left of the texture and quad.
glTexCoord2f(0.0f , 0.0f); glVertex3f(-1.0f , -1.0f , -1.0f);
//Bottom right of the texture and quad.
glTexCoord2f(1.0f , 0.0f); glVertex3f(-1.0f , -1.0f , 1.0f);
//Top right of the texture and quad.
glTexCoord2f(1.0f , 1.0f); glVertex3f(-1.0f , 1.0f , 1.0f);
//Top left of the texture and quad.
glTexCoord2f(0.0f , 1.0f); glVertex3f(-1.0f , 1.0f , -1.0f);
glEnd();
SDL_GL_SwapBuffers();
xrot += 0.1;
yrot += 0.1;
zrot += 0.1;
return true;
}
//This function will reset our viewport after a windows resize.
int resizeWindow(int width , int height)
{
//Height / width ration.
float ratio;
//Protect against a division by zero.
if(height == 0)
height = 1;
ratio = width / height;
//Setup viewport
glViewport(0 , 0 , width , height);
//Change to the projection matrix and reset it.
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//set perspective.
gluPerspective(45.0f , ratio , 0.1f , 100.0f);
//Change to model view matrix and reset it.
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
return true;
}
//Toggle fullScreen.
void toggleFullscreen(SDL_Surface* screen)
{
int videoFlags = screen->flags;
(videoFlags & SDL_FULLSCREEN) == SDL_FULLSCREEN ? videoFlags ^= SDL_FULLSCREEN : videoFlags |= SDL_FULLSCREEN;//NICE!!
screen = SDL_SetVideoMode(SCREEN_WIDTH , SCREEN_HEIGHT , SCREEN_BPP , videoFlags);
resizeWindow(surface->w , surface->h);
drawGLScene();
}
//OpenGL initialization.
int initGL(void)
{
if(!loadGLTextures())
return false;
glShadeModel(GL_SMOOTH);
glEnable(GL_TEXTURE_2D); //Enable texture mapping.
glClearColor(0.0f , 0.0f , 0.0f , 0.5f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
//Nice perspective.
glHint(GL_PERSPECTIVE_CORRECTION_HINT , GL_NICEST);
return true;
}
//This func will handle any key inputs.
void handleKeyPress(SDL_keysym* keysym)
{
switch(keysym->sym)
{
case SDLK_ESCAPE:
Quit(0);
break;
case SDLK_F1:
toggleFullscreen(surface);
break;
case SDLK_r:
drawGLScene();
break;
default:
break;
}
return;
}
int main(int argc , char* argv[])
{
//Flags to pass to SDL_SetVideoMode : awsome!! ints can be compiled.
int videoFlags;
//Event
SDL_Event event;
//Holds information about display.
const SDL_VideoInfo* videoInfo;
//Is window active?
bool isActive = true;
//SDL initialization.
if(SDL_Init(SDL_INIT_VIDEO) < 0)
{
fprintf(stderr , "SDL video initialization failed : %s\n" , SDL_GetError());
Quit(1);
}
//Fetch the video info.
videoInfo = SDL_GetVideoInfo();
if(!videoInfo)
{
fprintf(stderr , "Video query failed : %s\n" , SDL_GetError());
Quit(1);
}
//Add flags to pass to SDL_SetVideoMode.
videoFlags = SDL_OPENGL; //Enable OpenGL in SDL.
videoFlags |= SDL_GL_DOUBLEBUFFER; //Enable double buffering.
videoFlags |= SDL_HWPALETTE; //Store the palette in hardware.
videoFlags |= SDL_RESIZABLE; //Enable window resizing.
//This checks to see if surfaces can be stored in hardware.
videoInfo->hw_available ? videoFlags |= SDL_HWSURFACE : SDL_SWSURFACE;
//This checks if harware blits can be done.
if(videoInfo->blit_hw)
videoFlags |= SDL_HWACCEL;
//Set OpenGL double buffering.
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER , 1);
surface = SDL_SetVideoMode(SCREEN_WIDTH , SCREEN_HEIGHT , 16 , videoFlags);
//verify the surface.
if(!surface)
{
fprintf(stderr , "Video mode set failed : %s\n" , SDL_GetError());
Quit(1);
}
SDL_WM_SetCaption("OpenGL-Sample" , 0);
//initialize OpenGL
if(initGL() == false)
{
fprintf(stderr , "Could not initialize OpenGL.\n");
Quit(1);
}
//Main loop
while(1)
{
//Handle the events in the queue.
if(SDL_PollEvent(&event))
{
switch(event.type)
{
case SDL_ACTIVEEVENT:
if(event.active.gain == 0)
isActive = false;
else
isActive = true;
break;
case SDL_VIDEORESIZE:
//Handle resize event.
surface = SDL_SetVideoMode(event.resize.w , event.resize.h , SCREEN_BPP , videoFlags);
if(!surface)
{
fprintf(stderr , "Could not get a surface after resize : %s\n" , SDL_GetError());
Quit(1);
}
resizeWindow(event.resize.w , event.resize.h);
break;
case SDL_KEYDOWN:
handleKeyPress(&event.key.keysym);
break;
case SDL_QUIT:
Quit(0);
default:
break;
}
}
if(isActive)
drawGLScene();
}
}
这是我正在尝试加载的image。
答案 0 :(得分:1)
我使用SOIL库http://www.lonesock.net/soil.html,
这是一个非常容易使用的OpenGL纹理加载器库,您不必这样做 担心图像格式或自己制作任何加载代码,它会为您完成所有操作。
加载纹理就像这样简单:
int textureID = SOIL_load_OGL_texture("img.png", SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID, SOIL_FLAG_MIPMAPS);
if(textureID == 0) { cout << "Failed to load texture!" << endl };
答案 1 :(得分:0)
通过更改:
,我能够让你的程序产生一个纹理(虽然它是镜像的) textureImage->h , 0 , GL_RGB , GL_UNSIGNED_BYTE ,
为:
textureImage->h , 0 , GL_RGBA , GL_UNSIGNED_BYTE ,
遗憾的是,错误地获取该字段不会产生任何错误。如果你试图告诉GL图像数据比实际大,那么它可能会导致你的程序崩溃,但是传递GL_RGB而不是GL_RGBA就会说它比它实际上要小。
请记住,SDL_LoadBMP()
并未尝试转换图像数据,因此您必须确保BMP文件的格式符合程序所需的格式。你可能需要使用GL_RGBA或GL_RGB。
答案 2 :(得分:0)
一切都取决于图像的格式。正如Michael所说,SDL_LoadBMP
不会转换图像数据。因此,您无法确定应该通过哪个标志
我建议你使用SDL_Image
库。将所有图像格式转换为一种特定格式。然后你可以使用(例如)GL_RGBA
标志并确保一切正常!