opengl紋理示例
一 一個簡單例子
首先做一個簡單例子;繪製一個簡單的二維紋理圖,並將該影象對映到一個四邊形上;程式碼;
#include <stdlib.h> #include <GL/glut.h> #define imageWidth 64 #define imageHeight 64 GLubyte image[imageWidth][imageHeight][3]; /*繪製一個簡單的二維紋理圖*/ void makeImage(void) { int i,j,r,g,b; /*根據點的位置設定不同的顏色*/ for(i = 0;i < imageWidth;i++) { for(j = 0;j <imageHeight;j++) { r = (i*j)%255; g = (i*i)%255; b = (j*j)%255; image[i][j][0] = (GLubyte)b; image[i][j][1] = (GLubyte)g; image[i][j][2] = (GLubyte)r; } } } void myInit(void) { glClearColor(0.0,0.0,0.0,0.0); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); makeImage(); glPixelStorei(GL_UNPACK_ALIGNMENT,1); /*指定二維紋理對映*/ glTexImage2D(GL_TEXTURE_2D,0,3,imageWidth,imageHeight,0,GL_RGB,GL_UNSIGNED_BYTE,&image[0][0][0]); /*設定紋理引數*/ glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); /*設定紋理環境引數*/ glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL); glEnable(GL_TEXTURE_2D); glShadeModel(GL_FLAT); } void myDisplay(void) { glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); /*將紋理對映到四邊形上*/ glBegin(GL_QUADS); /*紋理的座標和四邊形頂點的對應*/ glTexCoord2f(0.0,0.0); glVertex3f(-1.0,1.0,0.0); glTexCoord2f(0.0,1.0); glVertex3f(-1.0,-1.0,0.0); glTexCoord2f(1.0,1.0); glVertex3f(1.0,-1.0,0.0); glTexCoord2f(1.0,0.0); glVertex3f(1.0,1.0,0.0); glEnd(); glFlush(); } void myReshape(int w,int h) { glViewport(0,0,(GLsizei)w,(GLsizei)h); glMatrixMode(GL_PROJECTION); //glMatrixMode(GL_TEXTURE); glLoadIdentity(); gluPerspective(80.0,1.0-(GLfloat)w/(GLfloat)h,1.0,30.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } int main(int argc,char **argv) { /*初始化*/ glutInit(&argc,argv); glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB); glutInitWindowSize(300,300); glutInitWindowPosition(200,200); /*建立視窗*/ glutCreateWindow(" Texture "); /*繪製與顯示*/ myInit(); glutReshapeFunc(myReshape); glutDisplayFunc(myDisplay); glutMainLoop(); return 0; }
效果:
二 示例2
編譯如下一個例子;需要用到《OpenGL超級寶典》中的一些庫和標頭檔案;未編譯成功;不過過程和用到的一些資源比較有用;記錄一下;
1 程式碼
#include "gltools.h" //#include "math3d.h" #include <GL/glut.h> #include <stdio.h> // Define targa header. #pragma pack(1) typedef struct { GLbyte identsize; // Size of ID field that follows header (0) GLbyte colorMapType; // 0 = None, 1 = paletted GLbyte imageType; // 0 = none, 1 = indexed, 2 = rgb, 3 = grey, +8=rle unsigned short colorMapStart; // First colour map entry unsigned short colorMapLength; // Number of colors unsigned char colorMapBits; // bits per palette entry unsigned short xstart; // image x origin unsigned short ystart; // image y origin unsigned short width; // width in pixels unsigned short height; // height in pixels GLbyte bits; // bits per pixel (8 16, 24, 32) GLbyte descriptor; // image descriptor } TGAHEADER; #pragma pack(8) GLbyte *gltLoadTGA(const char *szFileName, GLint *iWidth, GLint *iHeight, GLint *iComponents, GLenum *eFormat) { FILE *pFile; // File pointer TGAHEADER tgaHeader; // TGA file header unsigned long lImageSize; // Size in bytes of image short sDepth; // Pixel depth; GLbyte *pBits = NULL; // Pointer to bits // Default/Failed values *iWidth = 0; *iHeight = 0; *eFormat = GL_BGR_EXT; *iComponents = GL_RGB8; // Attempt to open the fil pFile = fopen(szFileName, "rb"); if(pFile == NULL) return NULL; // Read in header (binary) fread(&tgaHeader, 18/* sizeof(TGAHEADER)*/, 1, pFile); // Do byte swap for big vs little endian #ifdef __APPLE__ BYTE_SWAP(tgaHeader.colorMapStart); BYTE_SWAP(tgaHeader.colorMapLength); BYTE_SWAP(tgaHeader.xstart); BYTE_SWAP(tgaHeader.ystart); BYTE_SWAP(tgaHeader.width); BYTE_SWAP(tgaHeader.height); #endif // Get width, height, and depth of texture *iWidth = tgaHeader.width; *iHeight = tgaHeader.height; sDepth = tgaHeader.bits / 8; // Put some validity checks here. Very simply, I only understand // or care about 8, 24, or 32 bit targa's. if(tgaHeader.bits != 8 && tgaHeader.bits != 24 && tgaHeader.bits != 32) return NULL; // Calculate size of image buffer lImageSize = tgaHeader.width * tgaHeader.height * sDepth; // Allocate memory and check for success pBits = (signed char *)malloc(lImageSize * sizeof(GLbyte)); if(pBits == NULL) return NULL; // Read in the bits // Check for read error. This should catch RLE or other // weird formats that I don't want to recognize if(fread(pBits, lImageSize, 1, pFile) != 1) { free(pBits); return NULL; } // Set OpenGL format expected switch(sDepth) { case 3: // Most likely case *eFormat = GL_BGR_EXT; *iComponents = GL_RGB8; break; case 4: *eFormat = GL_BGRA_EXT; *iComponents = GL_RGBA8; break; case 1: *eFormat = GL_LUMINANCE; *iComponents = GL_LUMINANCE8; break; }; // Done with File fclose(pFile); // Return pointer to image data return pBits; } static GLint iWidth, iHeight, iComponents; static GLenum eFormat; static GLfloat xRot, yRot; static GLfloat noLight[4] = {0.0f, 0.0f, 0.0f, 1.0f}; static GLfloat ambientLight[4] = {0.3f, 0.3f, 0.3f, 1.0f}; static GLfloat diffuseLight[4] = {0.7f, 0.7f, 0.7f, 1.0f}; static GLfloat brightLight[4] = {1.0f, 1.0f, 1.0f, 1.0f}; //光的位置在右上角 static GLfloat lightPos[] = { 5.0f, 5.0f, 5.0f, 1.0f}; void SetupRC() { glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glCullFace(GL_BACK); glFrontFace(GL_CCW); glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); //設定光照環境 glEnable(GL_LIGHTING); glLightModelfv(GL_LIGHT_MODEL_AMBIENT, noLight); glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight); glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight); glLightfv(GL_LIGHT0, GL_SPECULAR, brightLight); glLightfv(GL_LIGHT0, GL_POSITION, lightPos); glEnable(GL_LIGHT0); //開啟顏色追蹤 glEnable(GL_COLOR_MATERIAL); glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); glMaterialfv(GL_FRONT, GL_SPECULAR, brightLight); //鏡面光加亮的範圍設定大一點 glMateriali(GL_FRONT, GL_SHININESS, 30); //讀取影象檔案 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); void *pImage = NULL; pImage = gltLoadTGA("..\\stone.tga", &iWidth, &iHeight, &iComponents, &eFormat); if (pImage) { //載入紋理,然後釋放臨時的記憶體 glTexImage2D(GL_TEXTURE_2D, 0, iComponents, iWidth, iHeight, 0, eFormat, GL_UNSIGNED_BYTE, pImage); free(pImage); pImage = NULL; } //設定紋理過濾 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); //設定紋理環境 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glEnable(GL_TEXTURE_2D); } void RenderScene() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* 金字塔頂點下標為0,底部座標如下 1______2 | | |______| 3 4 */ //金字塔頂點陣列 M3DVector3f vertices[5] = {{0.0f, 0.8f, 0.0f}, {-.50f, 0.0f, -.50f}, {.50f, 0.0f, -.50f}, {-.50f, 0.0f, .50f}, {.50f, 0.0f, .50f}}; //表面法線向量 M3DVector3f normal; glPushMatrix(); //先往裡和往下平移一點 glTranslatef(0.0f, -0.3f, -4.0f); if (xRot > 360.5f) { xRot = 0.0f; } if (yRot > 360.5f) { yRot = 0.0f; } //進行旋轉 glRotatef(xRot, 1.0f, 0.0f, 0.0f); glRotatef(yRot, 0.0f, 1.0f, 0.0f); xRot += 0.5f; yRot += 0.5f; glBegin(GL_TRIANGLES); //底面的四方形由兩個三角形組成 glColor3f(1.0f, 0.0f, 0.0f); //注意法線和紋理都要在頂點之前設定 glNormal3f(0.0f, -1.0f, 0.0f); glTexCoord2f(0.0f, 1.0f); glVertex3fv(vertices[1]); glTexCoord2f(1.0f, 1.0f); glVertex3fv(vertices[2]); glTexCoord2f(1.0f, 0.0f); glVertex3fv(vertices[4]); glTexCoord2f(1.0f, 0.0f); glVertex3fv(vertices[4]); glTexCoord2f(0.0f, 0.0f); glVertex3fv(vertices[3]); glTexCoord2f(0.0f, 1.0f); glVertex3fv(vertices[1]); //前面 glColor3f(0.0f, 1.0f, 0.0f); m3dFindNormal(normal, vertices[0], vertices[3], vertices[4]); glNormal3fv(normal); glTexCoord2f(0.5f, 0.5f); glVertex3fv(vertices[0]); glTexCoord2f(0.0f, 0.0f); glVertex3fv(vertices[3]); glTexCoord2f(1.0f, 0.0f); glVertex3fv(vertices[4]); //左側面 glColor3f(0.0f, 0.0f, 1.0f); m3dFindNormal(normal, vertices[1], vertices[3], vertices[0]); glNormal3fv(normal); glTexCoord2f(0.0f, 0.0f); glVertex3fv(vertices[1]); glTexCoord2f(1.0f, 0.0f); glVertex3fv(vertices[3]); glTexCoord2f(0.5f, 0.5f); glVertex3fv(vertices[0]); //右側面 glColor3f(0.0f, 1.0f, 1.0f); m3dFindNormal(normal, vertices[0], vertices[4], vertices[2]); glNormal3fv(normal); glTexCoord2f(0.5f, 0.5f); glVertex3fv(vertices[0]); glTexCoord2f(0.0f, 0.0f); glVertex3fv(vertices[4]); glTexCoord2f(1.0f, 0.0f); glVertex3fv(vertices[2]); //後面 glColor3f(1.0f, 0.0f, 1.0f); m3dFindNormal(normal, vertices[0], vertices[2], vertices[1]); glNormal3fv(normal); glTexCoord2f(0.5f, 0.5f); glVertex3fv(vertices[0]); glTexCoord2f(0.0f, 0.0f); glVertex3fv(vertices[2]); glTexCoord2f(1.0f, 0.0f); glVertex3fv(vertices[1]); glEnd(); glPopMatrix(); glutSwapBuffers(); } void ChangeSize(GLsizei w, GLsizei h) { if (h == 0) h = 1; glViewport(0, 0, w, h); float fAspect = (GLfloat)w/(GLfloat)h; glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(35.0, fAspect, 1.0, 100.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glutPostRedisplay(); } void TimerFunc(int value) { glutPostRedisplay(); glutTimerFunc(60, TimerFunc, 1); } int main(int args, char *arv[]) { glutInit(&args, arv); glutInitDisplayMode(GL_RGB | GL_DOUBLE | GL_DEPTH); glutInitWindowSize(800, 600); glutCreateWindow("pyramid"); glutDisplayFunc(RenderScene); glutReshapeFunc(ChangeSize); SetupRC(); glutTimerFunc(50, TimerFunc, 1); glutMainLoop(); return 0; }
2 LNK 1103錯誤
Linking...
LINK : warning LNK4098: defaultlib "LIBCMT" conflicts with use of other libs; use /NODEFAULTLIB:library
gltools.lib(math3d.obj) : fatal error LNK1103: debugging information corrupt; recompile module
執行 link.exe 時出錯.
在VC6下選中上圖的 忽略全部預設庫後;不再出現此錯誤;我用的VC6,估計在VS2008以上不會出現此錯誤;
3 關於gltLoadTGA
參閱此文
http://larrycheung.blog.163.com/blog/static/13172966120129284281428/
另外還需要一個輔助函式gltLoadTGA;
我已經加入到上面程式碼中;
另外還有一個opengl讀取tga檔案的類,在此處;
http://download.csdn.net/detail/jiangcaiyang123/4823365
如果出現下述錯誤,
wenli2.cpp(69) : error C2440: '=' : cannot convert from 'void *' to 'signed char *'
把
pBits = malloc(lImageSize * sizeof(GLbyte));
改為
pBits = (signed char *)malloc(lImageSize * sizeof(GLbyte));
4 用到的庫
gltools.h, gltools.lib,OpenGL超級寶典完整原始碼 中附帶;
glew庫;偶又額外下了一個glew-1.9.0;
在後面連結中有;
另外還有一個
http://blog.csdn.net/van_2013/article/details/47165953
5 LNK 2001錯誤
弄好上面;再編譯,還有下述錯誤;
Linking...
wenli2.obj : error LNK2001: unresolved external symbol _fclose
wenli2.obj : error LNK2001: unresolved external symbol _free
wenli2.obj : error LNK2001: unresolved external symbol _malloc
wenli2.obj : error LNK2001: unresolved external symbol _fread
wenli2.obj : error LNK2001: unresolved external symbol _fopen
wenli2.obj : error LNK2001: unresolved external symbol __chkesp
wenli2.obj : error LNK2001: unresolved external symbol __fltused
gltools.lib(math3d.obj) : error LNK2001: unresolved external symbol __fltused
LINK : error LNK2001: unresolved external symbol _mainCRTStartup
gltools.lib(math3d.obj) : error LNK2001: unresolved external symbol __CIcos
gltools.lib(math3d.obj) : error LNK2001: unresolved external symbol __CIsin
gltools.lib(math3d.obj) : error LNK2001: unresolved external symbol __CIsqrt
gltools.lib(math3d.obj) : error LNK2001: unresolved external symbol __CItan
Debug/wenli2.exe : fatal error LNK1120: 12 unresolved externals
執行 link.exe 時出錯.
CIcos、CIsin等這些都是3d的數學計算函式;看樣子需要把 OpenGL超級寶典完整原始碼 中相關工程編譯;除了gltools.lib外,再獲得math3d的lib和dll,才可以;
目前只有VC6;先到這裡吧;
6 資源下載
上面兩個工程;glew庫1.9.0, gltools庫,OpenGL超級寶典完整原始碼(第五版);包含在下面;
http://pan.baidu.com/s/1eRF0LTS