主函数
int main(int argc, char** argv)
{
printf("按键’1’,’2’为整体旋转\n");
printf("按键’3’为头部旋转\n");
printf("按键’4’,’5’,’6’,’7’为手臂旋转\n");
printf("按键’8’,’9’,’a’,’b’为腿部旋转\n");
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RED);
glutInitWindowSize(600, 600);
glutInitWindowPosition(100, 100);
glutCreateWindow(argv[0]);
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutMainLoop();
return 0;
}
init()函数前面的部分都是流程化的内容,执行到init()部分,主要是光照的设置。
光照的设置
OpenGL中我们可以设置8个光源,其编号分别为GL_LIGHT0、GL_LIGHT1、……、GL_LIGHT7。就相当于现实生活中有8个太阳,但每个太阳的位置、方向及它发出的光线可以完全不同。OpenGL中我们设置光源时,主要就是设置其颜色、位置、方向等性质。另外,OpenGL中任何一个光源都可以发出不同强度的环境光、散射光、镜面反射光,这几个方面综合起来就决定了光源的颜色。
我们通过glLightfv(光源编号,光源特性,参数数据)来设置光源。其中,光源编号可取GL_LIGHT0、GL_LIGHT1、……、GL_LIGHT7共8个值。光源特性主要可取GL_AMBIENT(设置光源的环境光属性,默认值(0,0,0,1))、GL_DIFFUSE(设置光源的散射光属性,默认值(1,1,1,1))、GL_SPECULAR(设置光源的镜面反射光属性,默认值(1,1,1,1))、GL_POSITION(设置光源的位置,默认值(0,0,1,0))。
主函数中还使用了void glLightModelfv。
void glLightModelfv(GLenum pname, const GLfloat * params);
函数参数:
pname 指定一个单值光照模型参数。必须是GL_LIGHT_MODEL_TWO_SIDE或者GL_LIGHT_MODEL_AMBIENT。
params 指定要设置的参数指针。
GL_LIGHT_MODEL_AMBIENT:params包含四个定点或浮点值来指定整个场景的环境光强度。初始值是(0.2,0.2,0.2,1.0)。
void init(void)
{
GLfloat ambient[] = { 0.0, 0.0, 0.0, 1.0 };
GLfloat diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat position[] = { 0.0, 5.0, 10.0, 0.0 };
GLfloat lmodel_ambient[] = { 0.4, 0.4, 0.4, 1.0 };
GLfloat local_view[] = { 0.0 };
glClearColor(0, 0, 0, 0);
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
glLightfv(GL_LIGHT0, GL_POSITION, position);
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, local_view);
glShadeModel(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
}
光源的性质设置完毕,还要调用glEnable(GL_LIGHT0)来打开光源。就相当于买回手电筒、装好电池(设置光源),但如果不打开开关(打开电源),手电筒是不起作用的。另外,对于GL_POSITION,其位置数组(x,y,z,w)定义了光源在空间中的位置。但三维空间为什么需要4个量呢?事实上这里采用的是齐次坐标,当w≠0时,它表示光源处于空间中(x,y,z)处,这时的光源称为定点光源;当w=0时,根据齐次坐标的性质,它表示光源位于无穷远处,此时光源称为定向光源,其所有光线几乎是相互平等的,如太阳。其光线方向由点(x,y,z)指向(0,0,0)。
glEnable(GL_DEPTH_TEST): 用来开启更新深度缓冲区的功能,也就是,如果通过比较后深度值发生变化了,会进行更新深度缓冲区的操作。启动它,OpenGL就可以跟踪再Z轴上的像素,这样,它只会再那个像素前方没有东西时,才会绘画这个像素。
**glEnable(GL_LIGHTING):**这个函数调用告诉OpenGL使用材料属性和光照参数去决定每个顶点的颜色值。如果没有开启这个函数,则看到的物体是昏暗的。开启光照后会根据你的材料属性和光照参数计算顶点的颜色值。
glutReshapeFunc(reshape)函数是当窗口尺寸改变时,图形比例不发生变化。
步骤:
1.创建、定位和启用光源
(1)定义光源的颜色和位置
GLfloat ambient[] = { 0.0, 0.0, 0.0, 1.0 };
GLfloat diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat position[] = { 0.0, 3.0, 2.0, 0.0 };
(2)创建光源
glLightfv(GL_LIGHT1, GL_AMBIENT, ambient); // Setup The Ambient Light设置环境光
glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse); // Setup The Diffuse Light设置漫射光
glLightfv(GL_LIGHT1, GL_POSITION,position); // Position The Light设置光源位置
(3)启动光照和光源
glEnable(GL_LIGHTING); // 启动光照
glEnable(GL_LIGHT1); // Enable Light One启用一号光源
2.选择光照模型
GLfloat lmodel_ambient[] = { 0.4, 0.4, 0.4, 1.0 };
GLfloat local_view[] = { 0.0 };
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, local_view);
3.定义材质
(1)材料属性
GLfloat no_mat[] = { 0.0, 0.0, 0.0, 1.0 };
GLfloat mat_ambient[] = { 0.7, 0.7, 0.7, 1.0 };
GLfloat mat_ambient_color[] = { 0.8, 0.8, 0.2, 1.0 };
GLfloat mat_diffuse[] = { 0.1, 0.5, 0.8, 1.0 };
GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat no_shininess[] = { 0.0 };
GLfloat low_shininess[] = { 5.0 };
GLfloat high_shininess[] = { 100.0 };
GLfloat mat_emission[] = {0.3, 0.2, 0.2, 0.0};
(2)指定材料属性
glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, no_mat);
glMaterialfv(GL_FRONT, GL_SHININESS, no_shininess);
glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);
4.绘制物体
glutSolidSphere(1.0, 16, 16);
display函数
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glRotatef(angle, 0, 1, 0);
glTranslatef(0, 4, 0);
draw_body();
draw_head();
draw_leftshoulder();
draw_rightshoulder();
draw_leftfoot();
draw_rightfoot();
glPopMatrix();
glutSwapBuffers();
}
关于 glRotatef(angle, 0, 1, 0);函数的解释请点击这里
void draw_body(void)
{
glPushMatrix();
glTranslatef(0, 1.5, 0);
glScalef(0.5, 1, 0.4);
glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient_color);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, high_shininess);
glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);
glutSolidCube(4); ;
glPopMatrix();
}
glMaterialfv()函数里参数的意义:
void draw_head(void)
{
glPushMatrix();
glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, low_shininess);
glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);
glTranslatef(0, 3.5, 0);
glRotatef(neck, 0, 0, 1);
glTranslatef(0, 1, 0);
glutWireSphere(1, 200, 500);
glPopMatrix();
}
void draw_leftshoulder(void)
{
glPushMatrix();
glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, no_mat);
glMaterialfv(GL_FRONT, GL_SHININESS, no_shininess);
glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);
glTranslatef(1.5, 3, 0);
glRotatef(lshoulder, 1, 0, 0);
glTranslatef(0, -0.5, 0);
glScalef(0.4, 1, 0.5);
glutSolidCube(2);
glScalef(1 / 0.4, 1 / 1, 1 / 0.5);
glTranslatef(0, -1.4, 0);
glRotatef(lelbow, 1, 0, 0);
glutWireSphere(0.4, 200, 500);
glScalef(0.4, 1, 0.5);
glTranslatef(0, -1.4, 0);
glutSolidCube(2);
glPopMatrix();
}
void draw_rightshoulder(void)
{
glPushMatrix();
glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, no_mat);
glMaterialfv(GL_FRONT, GL_SHININESS, no_shininess);
glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);
glTranslatef(-1.5, 3, 0);
glRotatef(rshoulder, 1, 0, 0);
glTranslatef(0, -0.5, 0);
glScalef(0.4, 1, 0.5);
glutSolidCube(2);
glScalef(1 / 0.4, 1 / 1, 1 / 0.5);
glTranslatef(0, -1.4, 0);
glRotatef(relbow, 1, 0, 0);
glutWireSphere(0.4, 200, 500);
glScalef(0.4, 1, 0.5);
glTranslatef(0, -1.4, 0);
glutSolidCube(2);
glPopMatrix();
}
void draw_leftfoot(void)
{
glPushMatrix();
glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, no_mat);
glMaterialfv(GL_FRONT, GL_SHININESS, no_shininess);
glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);
glTranslatef(-0.6, -0.6, 0);
glRotatef(lfoot, 1, 0, 0);
glTranslatef(0, -1, 0);
glScalef(0.4, 1, 0.5);
glutSolidCube(2);
glScalef(1 / 0.4, 1 / 1, 1 / 0.5);
glTranslatef(0, -1.4, 0);
glRotatef(lhips, 1, 0, 0);
glutWireSphere(0.4, 200, 500);
glScalef(0.4, 1, 0.5);
glTranslatef(0, -1.4, 0);
glutSolidCube(2);
glPopMatrix();
}
void draw_rightfoot(void)
{
glPushMatrix();
glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, no_mat);
glMaterialfv(GL_FRONT, GL_SHININESS, no_shininess);
glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);
glTranslatef(0.6, -0.6, 0);
glRotatef(rfoot, 1, 0, 0);
glTranslatef(0, -1, 0);
glScalef(0.4, 1, 0.5);
glutSolidCube(2);
glScalef(1 / 0.4, 1 / 1, 1 / 0.5);
glTranslatef(0, -1.4, 0);
glRotatef(rhips, 1, 0, 0);
glutWireSphere(0.4, 200, 500);
glScalef(0.4, 1, 0.5);
glTranslatef(0, -1.4, 0);
glutSolidCube(2);
glPopMatrix();
}
源代码
#include<windows.h>
#include<gl/glut.h>
#pragma comment(lib, "glut32.lib")
#include <iostream>
using namespace std;
GLfloat no_mat[] = { 0.0, 0.0, 0.0, 1.0 };
GLfloat mat_ambient[] = { 0.8, 0.8, 0.8, 1.0 };
GLfloat mat_ambient_color[] = { 0.8, 0.8, 0.2, 1.0 };
GLfloat mat_diffuse[] = { 0.5, 0.8, 0.0, 1.0 };
GLfloat mat_specular[] = { 1.0, 0.0, 0.5, 1.0 };
GLfloat no_shininess[] = { 0.5 };
GLfloat low_shininess[] = { 5.0 };
GLfloat high_shininess[] = { 100.0 };
GLfloat mat_emission[] = { 0.3, 0.2, 0.2, 0.0 };
static int angle = 0, neck = 0, lshoulder = 0, lelbow = 0, rshoulder = 0, relbow = 0,
lhips = 0, rhips = 0, lfoot = 0, rfoot = 0, flagneck = 0, flaglshoulder = 0,
flaglelbow = 0, flagrshoulder = 0, flagrelbow = 0, flaglhips = 0,
flagrhips = 0, flaglfoot = 0, flagrfoot = 0;
void init(void)
{
GLfloat ambient[] = { 0.0, 0.0, 0.0, 1.0 };
GLfloat diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat position[] = { 0.0, 5.0, 10.0, 0.0 };
GLfloat lmodel_ambient[] = { 0.4, 0.4, 0.4, 1.0 };
GLfloat local_view[] = { 0.0 };
glClearColor(0, 0, 0, 0);
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
glLightfv(GL_LIGHT0, GL_POSITION, position);
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, local_view);
glShadeModel(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
}
void draw_body(void)
{
glPushMatrix();
glTranslatef(0, 1.5, 0);
glScalef(0.5, 1, 0.4);
glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient_color);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, high_shininess);
glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);
glutSolidCube(4); ;
glPopMatrix();
}
void draw_leftshoulder(void)
{
glPushMatrix();
glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, no_mat);
glMaterialfv(GL_FRONT, GL_SHININESS, no_shininess);
glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);
glTranslatef(1.5, 3, 0);
glRotatef(lshoulder, 1, 0, 0);
glTranslatef(0, -0.5, 0);
glScalef(0.4, 1, 0.5);
glutSolidCube(2);
glScalef(1 / 0.4, 1 / 1, 1 / 0.5);
glTranslatef(0, -1.4, 0);
glRotatef(lelbow, 1, 0, 0);
glutWireSphere(0.4, 200, 500);
glScalef(0.4, 1, 0.5);
glTranslatef(0, -1.4, 0);
glutSolidCube(2);
glPopMatrix();
}
void draw_rightshoulder(void)
{
glPushMatrix();
glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, no_mat);
glMaterialfv(GL_FRONT, GL_SHININESS, no_shininess);
glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);
glTranslatef(-1.5, 3, 0);
glRotatef(rshoulder, 1, 0, 0);
glTranslatef(0, -0.5, 0);
glScalef(0.4, 1, 0.5);
glutSolidCube(2);
glScalef(1 / 0.4, 1 / 1, 1 / 0.5);
glTranslatef(0, -1.4, 0);
glRotatef(relbow, 1, 0, 0);
glutWireSphere(0.4, 200, 500);
glScalef(0.4, 1, 0.5);
glTranslatef(0, -1.4, 0);
glutSolidCube(2);
glPopMatrix();
}
void draw_head(void)
{
glPushMatrix();
glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, low_shininess);
glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);
glTranslatef(0, 3.5, 0);
glRotatef(neck, 0, 0, 1);
glTranslatef(0, 1, 0);
glutWireSphere(1, 200, 500);
glPopMatrix();
}
void draw_leftfoot(void)
{
glPushMatrix();
glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, no_mat);
glMaterialfv(GL_FRONT, GL_SHININESS, no_shininess);
glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);
glTranslatef(-0.6, -0.6, 0);
glRotatef(lfoot, 1, 0, 0);
glTranslatef(0, -1, 0);
glScalef(0.4, 1, 0.5);
glutSolidCube(2);
glScalef(1 / 0.4, 1 / 1, 1 / 0.5);
glTranslatef(0, -1.4, 0);
glRotatef(lhips, 1, 0, 0);
glutWireSphere(0.4, 200, 500);
glScalef(0.4, 1, 0.5);
glTranslatef(0, -1.4, 0);
glutSolidCube(2);
glPopMatrix();
}
void draw_rightfoot(void)
{
glPushMatrix();
glMaterialfv(GL_FRONT, GL_AMBIENT, no_mat);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, no_mat);
glMaterialfv(GL_FRONT, GL_SHININESS, no_shininess);
glMaterialfv(GL_FRONT, GL_EMISSION, no_mat);
glTranslatef(0.6, -0.6, 0);
glRotatef(rfoot, 1, 0, 0);
glTranslatef(0, -1, 0);
glScalef(0.4, 1, 0.5);
glutSolidCube(2);
glScalef(1 / 0.4, 1 / 1, 1 / 0.5);
glTranslatef(0, -1.4, 0);
glRotatef(rhips, 1, 0, 0);
glutWireSphere(0.4, 200, 500);
glScalef(0.4, 1, 0.5);
glTranslatef(0, -1.4, 0);
glutSolidCube(2);
glPopMatrix();
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glRotatef(angle, 0, 1, 0);
glTranslatef(0, 4, 0);
draw_body();
draw_head();
draw_leftshoulder();
draw_rightshoulder();
draw_leftfoot();
draw_rightfoot();
glPopMatrix();
glutSwapBuffers();
}
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-8, 8, -8, 8, -10, 10);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0, 4.0, 10, 0.0, 4, 0.0, 0.0, 1.0, 0.0);
}
void keyboard(unsigned char key, int x, int y)
{
switch (key)
{
case '1':
angle = (angle + 5) % 360;
glutPostRedisplay();
break;
case '2':
angle = (angle - 5) % 360;
glutPostRedisplay();
break;
case '3':
if (flagneck)
{
neck = neck + 5;
if (neck >= 30)flagneck = 0;
}
else {
neck = neck - 5;
if (neck <= -30)flagneck = 1;
}
glutPostRedisplay();
break;
case '4':
if (flaglshoulder)
{
lshoulder += 5;
if (lshoulder >= 60)flaglshoulder = 0;
}
else
{
lshoulder -= 5;
if (lshoulder <= -60)flaglshoulder = 1;
}
glutPostRedisplay();
break;
case '5':
if (flagrshoulder)
{
rshoulder += 5;
if (rshoulder >= 60)flagrshoulder = 0;
}
else
{
rshoulder -= 5;
if (rshoulder <= -60)flagrshoulder = 1;
}
glutPostRedisplay();
break;
case '6':
if (flaglelbow)
{
lelbow += 5;
if (lelbow >= 60)flaglelbow = 0;
}
else
{
lelbow -= 5;
if (lelbow <= -60)flaglelbow = 1;
}
glutPostRedisplay();
break;
case '7':
if (flagrelbow)
{
relbow += 5;
if (relbow >= 60)flagrelbow = 0;
}
else
{
relbow -= 5;
if (relbow <= -60)flagrelbow = 1;
}
glutPostRedisplay();
break;
case '8':
if (flaglhips)
{
lhips += 5;
if (lhips >= 60)flaglhips = 0;
}
else
{
lhips -= 5;
if (lhips <= -60)flaglhips = 1;
}
glutPostRedisplay();
break;
case '9':
if (flagrhips)
{
rhips += 5;
if (rhips >= 60)flagrhips = 0;
}
else
{
rhips -= 5;
if (rhips <= -60)flagrhips = 1;
}
glutPostRedisplay();
break;
case 'a':
if (flaglfoot)
{
lfoot += 5;
if (lfoot >= 60)flaglfoot = 0;
}
else
{
lfoot -= 5;
if (lfoot <= -60)flaglfoot = 1;
}
glutPostRedisplay();
break;
case 'b':
if (flagrfoot)
{
rfoot += 5;
if (rfoot >= 60)flagrfoot = 0;
}
else
{
rfoot -= 5;
if (rfoot <= -60)flagrfoot = 1;
}
glutPostRedisplay();
break;
default:
break;
}
}
int main(int argc, char** argv)
{
printf("按键’1’,’2’为整体旋转\n");
printf("按键’3’为头部旋转\n");
printf("按键’4’,’5’,’6’,’7’为手臂旋转\n");
printf("按键’8’,’9’,’a’,’b’为腿部旋转\n");
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RED);
glutInitWindowSize(600, 600);
glutInitWindowPosition(100, 100);
glutCreateWindow(argv[0]);
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutMainLoop();
return 0;
}