openGL繪製正方體分別實現簡單顏色繪製、紋理繪製、光照繪製
阿新 • • 發佈:2019-01-25
使用openGL繪製正方體;
面1:使用簡單顏色繪製,顏色為綠色;
面2:使用簡單顏色繪製,顏色為漸變色;
面3:繪製一維紋理;
面4:繪製二維紋理;
面5:光照繪製,黃色;
面6:光照繪製,橘色;
繪製效果如下:
需要注意的問題:
1、 在繪製紋理和光照的時候,要正確設定每個面的法線方向;使用函式glNormal3f( )進行設定;
2、 使用光照的時候,如果只是區域性光照,要在區域性光照結束之後,關閉光源,否則別的面也被光照;使用函式glDisable(GL_LIGHTING)實現;
3、 使用png圖片作為二維紋理的時候需要將原始圖片進行上下翻轉,因為OpenGL以左下角為影象原點;自定義函式void upsidedown32(unsigned char *pImage, unsigned width, unsignedheight)實現影象上下翻轉;
#include <GL/glut.h> #include "lodepng.h" void init(void); void reshape(int w, int h); void mouse(int button, int state, int x, int y); void motion(int x, int y); void display(void); void drawCoordinates(void); void drawTetrahedron(void); int mx,my; //position of mouse int m_state=0; //mouse usage float x_angle=20.0f, y_angle=20.0f; //angle of eye float dist=10.0f; //distance from the eye GLuint texDog, tex1D; void upsidedown32(unsigned char *pImage, unsigned width, unsigned height) //Upside down the image { unsigned i; unsigned char *pLine; pLine = (unsigned char *)malloc(4*width); if(pLine == NULL) { printf("No memory left!"); exit(0); } for(i=0; i<height/2; i++) { memcpy(pLine, &pImage[i*4*width], 4*width); memcpy(&pImage[i*4*width], &pImage[(height-1-i)*4*width], 4*width); memcpy(&pImage[(height-1-i)*4*width], pLine, 4*width); } free(pLine); } void init(void) { int i; unsigned error; unsigned width, height; unsigned char *pDogImg; unsigned char img1D[16][3]; error = lodepng_decode32_file(&pDogImg, &width, &height, "dog.png"); if(error) { printf("error %u: %s\n", error, lodepng_error_text(error)); exit(0); } upsidedown32(pDogImg, width, height); //Upside down the image glGenTextures(1, &texDog); //生成紋理號 glBindTexture(GL_TEXTURE_2D, texDog); //紋理繫結 glTexImage2D(GL_TEXTURE_2D, 0, 4, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pDogImg); //定義紋理資料 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); //設定紋理目標引數 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); free(pDogImg); for(i=0; i<16; i++) //構造一維紋理 if(i%4) img1D[i][0] = img1D[i][1] = img1D[i][2] = 255; else img1D[i][0] = img1D[i][1] = img1D[i][2] = 0; glGenTextures(1, &tex1D); glBindTexture(GL_TEXTURE_1D, tex1D); glTexImage1D(GL_TEXTURE_1D, 0, 3, 16, 0, GL_RGB, GL_UNSIGNED_BYTE, img1D); glTexParameteri(GL_TEXTURE_1D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_1D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); //設定紋理環境引數 glEnable(GL_DEPTH_TEST); } void reshape(int w, int h) { glViewport(0, 0, w, h); } void mouse(int button, int state, int x, int y) { if(button==GLUT_LEFT_BUTTON && state == GLUT_DOWN) { mx = x; my = y; m_state = 0; } if(button==GLUT_RIGHT_BUTTON && state == GLUT_DOWN) { mx = x; my = y; m_state = 1; } } void motion(int x, int y) { int dx,dy; //offset of mouse; dx = x-mx; dy = y-my; if(m_state == 0) { y_angle += dx*0.1f; x_angle += dy*0.1f; } else if(m_state == 1) dist += (dx+dy)*0.05f; mx = x; my = y; glutPostRedisplay(); } void display(void) { int rect[4]; float w, h; //float lit_position[] = {0.0f, 0.0f, 1.0f, 0.0f}; //float mat_yellow[] = {1.0f, 1.0f, 0.0f, 1.0f}; glGetIntegerv(GL_VIEWPORT, rect); w = rect[2]; h = rect[3]; glClearColor(1.0f,1.0f,1.0f,0.0f); glClearDepth(1.0); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); //對應單位陣I if(h < 1) h=1; gluPerspective(30.0, w/h, 0.1, 20.0); //對應變換陣T0 glMatrixMode(GL_MODELVIEW); glLoadIdentity(); //對應單位陣I glTranslated(0.0, 0.0, -dist); //對應變換陣T1 glRotatef(x_angle, 1.0f, 0.0f, 0.0f); //對應變換陣T2 glRotatef(y_angle, 0.0f, 1.0f, 0.0f); //對應變換陣T3 glPushMatrix(); glScalef(1.5f, 1.5f, 1.5f); //對應變換陣T6 drawCoordinates(); drawTetrahedron(); glPopMatrix(); glFlush(); glutSwapBuffers(); } void drawTetrahedron(void) { float pnt[8][3] = {{0.0,0.0,0.0}, {0.0,1.0,0.0}, {1.0,1.0,0.0}, {1.0,0.0,0.0},{0.0,0.0,1.0},{0.0,1.0,1.0},{1.0,1.0,1.0},{1.0,0.0,1.0}}; int tetra[6][4] = {{0,1,2,3}, {1,5,6,2}, {0,3,7,4}, {2,6,7,3},{0,4,5,1},{4,7,6,5}}; float lit_position1[] = {1.0f, 0.0f, 0.0f, 0.0f}; float lit_position2[] = {-1.0f, 0.0f, 0.0f, 0.0f}; float yellow[] = {1.0f, 1.0f, 0.0f, 1.0f}; float orange[] = {1.0f, 0.5f, 0.0f, 1.0f}; //glNormal3f(0.0f, 0.0f, -1.0f); glBegin(GL_QUADS); //簡單顏色繪兩個面,一個單一色,一個漸變色 glColor3f(0.0f,1.0f,0.0f); //綠色 glVertex3fv(pnt[tetra[0][0]]); //glVertex3fv(pnt[0]); glVertex3f(0.0f, 0.0f, 0.0f); glVertex3fv(pnt[tetra[0][1]]); //glVertex3fv(pnt[2]); glVertex3f(0.0f, 1.0f, 0.0f); glVertex3fv(pnt[tetra[0][2]]); //glVertex3fv(pnt[1]); glVertex3f(1.0f, 0.0f, 0.0f); glVertex3fv(pnt[tetra[0][3]]); glEnd(); //glNormal3f(0.0f, 1.0f, 0.0f); glBegin(GL_QUADS); glColor3f(0.0f,1.0f,1.0f); glVertex3fv(pnt[tetra[1][0]]); glColor3f(1.0f,0.0f,1.0f); glVertex3fv(pnt[tetra[1][1]]); glColor3f(1.0f,1.0f,0.0f); glVertex3fv(pnt[tetra[1][2]]); glColor3f(1.0f,1.0f,1.0f); glVertex3fv(pnt[tetra[1][3]]); glEnd(); /* 繪製紋理圖案 */ glNormal3f(0.0f, -1.0f, 0.0f);//一維紋理繪製 glDisable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_1D); glBegin(GL_POLYGON); glTexCoord1f(0.0f); glVertex3fv(pnt[tetra[2][0]]); //設定紋理座標 glTexCoord1f(0.0f); glVertex3fv(pnt[tetra[2][1]]); glTexCoord1f(1.0f); glVertex3fv(pnt[tetra[2][2]]); glTexCoord1f(1.0f); glVertex3fv(pnt[tetra[2][3]]); glEnd(); glNormal3f(0.0f, 0.0f, 1.0f); //二維紋理的繪製 glDisable(GL_TEXTURE_1D); glEnable(GL_TEXTURE_2D); glBegin(GL_POLYGON); // 正對面 glTexCoord2f(0.0f, 0.0f); glVertex3fv(pnt[tetra[5][0]]); glTexCoord2f(1.0f, 0.0f); glVertex3fv(pnt[tetra[5][1]]); glTexCoord2f(1.0f, 1.0f); glVertex3fv(pnt[tetra[5][2]]); glTexCoord2f(0.0f, 1.0f); glVertex3fv(pnt[tetra[5][3]]); glEnd(); glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_1D); /* 兩個光照面 */ glLightfv(GL_LIGHT0, GL_POSITION, lit_position2); //光源位置 glEnable(GL_LIGHT0); glEnable(GL_LIGHTING); //之後使用光照模型計算頂點顏色 glMaterialfv(GL_FRONT, GL_DIFFUSE, yellow); glNormal3f(-1.0f,0.0f,0.0f); glBegin(GL_QUADS); glVertex3fv(pnt[tetra[4][0]]); glVertex3fv(pnt[tetra[4][1]]); glVertex3fv(pnt[tetra[4][2]]); glVertex3fv(pnt[tetra[4][3]]); glEnd(); glDisable(GL_LIGHTING); //(不能省略)之後頂點顏色為當前顏色,當前顏色可以通過glColor*函式指定。 glLightfv(GL_LIGHT0, GL_POSITION, lit_position1); //普通光照(橘色) glEnable(GL_LIGHT0); glEnable(GL_LIGHTING); glMaterialfv(GL_FRONT, GL_DIFFUSE, orange); glNormal3f(1.0f,0.0f,0.0f); glBegin(GL_QUADS); glVertex3fv(pnt[tetra[3][0]]); glVertex3fv(pnt[tetra[3][1]]); glVertex3fv(pnt[tetra[3][2]]); glVertex3fv(pnt[tetra[3][3]]); glEnd(); glDisable(GL_LIGHTING); } void drawCoordinates(void) { glColor3f(1.0f,0.0f,0.0f); //畫紅色的x軸 glBegin(GL_LINES); glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(2.0f, 0.0f, 0.0f); glEnd(); glColor3f(0.0,1.0,0.0); //畫綠色的y軸 glBegin(GL_LINES); glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(0.0f, 2.0f, 0.0f); glEnd(); glColor3f(0.0,0.0,1.0); //畫藍色的z軸 glBegin(GL_LINES); glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(0.0f, 0.0f, 2.0f); glEnd(); } int main(int argc,char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(500,500); glutInitWindowPosition(0,0); glutCreateWindow("model & zbuffer"); init(); glutDisplayFunc(display); glutReshapeFunc(reshape); glutMouseFunc(mouse); glutMotionFunc(motion); glutMainLoop(); glDeleteTextures(1, &texDog); //刪除紋理 glDeleteTextures(1, &tex1D); //刪除紋理 return 0; }