使用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;
}