使用 SDL 加载 OpenGL 纹理
OpenGL texture loading with SDL
我开始使用NeHe教程学习OpenGL已经有一段时间了。这是课程的代码 6.It 应该加载一个 bmp 图像并将其用作我正在绘制的立方体的纹理。但它不能正常工作,立方体根本不是白色的。加载图像的函数是"loadGLTextures"。谁能帮忙?我的图像位深度是 24.我正在使用 Visual Studio 2010。
#include <Windows.h>
#include <stdio.h>
#include <glGL.h>
#include <glGLU.h>
#include <SDLSDL.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 : %sn" , SDL_GetError());
Quit(1);
}
//Fetch the video info.
videoInfo = SDL_GetVideoInfo();
if(!videoInfo)
{
fprintf(stderr , "Video query failed : %sn" , 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 : %sn" , 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 : %sn" , 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();
}
}
这是我尝试加载的图像。
我使用土壤库,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 };
我能够通过更改以下内容让您的程序产生纹理(尽管它是镜像的):
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。
一切都取决于您的图像格式。正如迈克尔所说SDL_LoadBMP
不会转换图像数据。所以你无法确定你应该通过哪个标志。
我建议您使用SDL_Image
库。它将所有图像格式转换为一种特定格式。然后,您可以使用(例如)GL_RGBA
标志并确保一切正常!
相关文章:
- OpenGL大的3D纹理(>2GB)非常慢
- OpenGL将纹理四边形渲染为(0,0)
- OpenGL 4.3 错误地将第 4 个纹理坐标映射到与第 3 个纹理坐标相同的位置
- Qt OpenGL 渲染到纹理性能问题
- 使用 C++在 OpenGL 中对 3D 多边形进行纹理处理
- 无法获取要在 OpenGL ES2 中显示的 RGB 纹理
- 在 OpenGL 中加载纹理C++
- 添加新纹理OpenGL时,模型消失了
- 初始化多个纹理 OpenGL、SDL C++ 时出现问题
- 将多个纹理 OpenGL 绑定到不同的四边形
- 如何加载纹理Opengl
- 读写一个纹理(OpenGL)
- 渲染时加载纹理 (OpenGL)
- 如何绑定纹理openGL的一部分
- 将两个图像堆栈的非电源加载到 3D 纹理 OpenGL C++
- 我的精灵在纹理opengl之间切换
- 使用深度纹理OpenGL/GLSL的深度遮挡(3.3/330)
- 加载多纹理opengl 2.0
- 将位置写入纹理OpenGL/GLSL
- 为纹理OpenGL C++加载多个.bmp文件时出现问题