#include <windows.h>
#include <gl/gl.h>
#include <gl/glut.h>
#include<stdio.h>
// 旋转参数
static GLfloat xRot = 0.0f;
static GLfloat yRot = 0.0f;
//颜色跟踪模式
BOOL bColorMaterial = FALSE;
//初始化窗口
void SetupRC(void)
{
// 窗口颜色黑色
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glShadeModel(GL_FLAT);
}
void ChangeSize(int w, int h)
{
if (h == 0) h = 1;
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h)
glOrtho(-100.0f, 100.0f, -100.0f * h / w, 100.0f * h / w, -100.0f, 100.0f);
else
glOrtho(-100.0f * w / h, 100.0f * w / h, -100.0f, 100.0f, -100.0f, 100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
// 窗口内绘图
void RenderScene(void)
{
GLfloat ambient[] = { 0.8f, 0.8f, 0.8f, 1.0f }; //环境光RGBA
GLfloat material_ambient[] = { 0.75f, 0.0f, 0.0f, 1.0f };
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
//1.设置光照
glEnable(GL_LIGHTING); //启动光照
//glDisable(GL_LIGHTING);//关闭光照
//2.设置全局环境光
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
/*
GL_LIGHT_MODEL_AMBIENT:指定该参数后,其参数值包含四个整数或浮点数,这些参数值指定了场景中RGBA值。参数值在(-1.0,1.0)之间。默认参数值为(0.2,0.2,0.2,1.0),光线相当暗淡。
GL_LIGHT_MODEL_LOCAL_VIEWER:其参数值包含一个整数或浮点数,指定了镜面反射角度。默认是为0,表示视线方向与z轴负方向平行。否则表示坐标原点到Z轴负方向的镜面反射角度。
GL_LIGHT_MODEL_TWO_SIDE:其参数值包含一个整数或浮点数,表示对多边形进行单面还是双面的光照计算。默认值为0,表示单面光照计算,并使用front材质参数,否则为双面光照,使用back材质参数。
例如:glLightModeli(LIGHT_MODEL_TWO_SIDE,GL_TRUE);启动双面光照。如果将GL_TRUE改为GL_FALSE关闭双面光照。
*/
//3.设置材质属性
if (bColorMaterial)
{
glEnable(GL_COLOR_MATERIAL); //启动颜色跟踪
//指定多边形正面使用颜色跟踪
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
/*
void glColorMaterial(GLenum face, GLenum mode);
参数face: 同glMaterial*函数的face参数
参数mode: 同glMaterial*函数的pname参数
*/
}
else
{
glDisable(GL_COLOR_MATERIAL); //关闭颜色跟踪
//指定多边形正面的环境反射和漫反射值
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, material_ambient);
/*
void glMaterial{f,i,fv,iv}(GLenum face, GLenum pname, GLfloat param/*param);
参数face:指定需要更改材质的表面,值为以下三个取值其中之一。
GL_FRONT, GL_BACK, GL_FRONT_AND_BACK
参数pname:指定需要更改的表面的材质参数,取值有:
GL_AMBIENT: 环境光的RGBA值,参数值在(-1.0, 1.0)之间。默认值为(0.2, 0.2, 0.2, 1.0)。
GL_DIFFUSE: 漫反射光的RGBA值,参数值在(-1.0, 1.0)之间,默认值为(0.8, 0.8, 0.8, 1.0)。
GL_SPECULAR: 镜面光的RGBA值,参数值在(-1.0, 1.0)之间,默认值为(0.0, 0.0, 0.0, 1.0)。
GL_AMBIENT_AND_DIFFUSE: 同时设置GL_AMBIENT和GL_DIFFUSE属性,相当于分别使用这两个参数调用两次该函数。
通常,GL_AMBIENT和GL_DIFFUSE取相同的值,可以达到比较真实的效果。
GL_SHININESS: 该属性称为“镜面指数”,取值范围是0到128,该值说明如何确定镜面光亮斑的大小和聚光程度。
该值越小,表示材质越粗糙,点光源发射的光线照射到上面,产生较大的亮点;
该值越大,表示材质越光滑,点光源照射到上面后,产生较小的亮点。
GL_EMISSION: 散射光照(辐射光)的RGBA值,该材质本身微微地向外发射光线,以至于眼睛可以感觉到有这样的颜色,但光线又比较弱,不会影响到其他物体的颜色。
参数值在(-1.0, 1.0)之间,默认值为(0.0, 0.0, 0.0, 1.0)。
*/
}
//4. 定义光源,它是一种白色的光源
GLfloat sun_light_position[] = { 0.0f, 0.0f, 0.0f, 1.0f };
GLfloat sun_light_ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f };
GLfloat sun_light_diffuse[] = { 0.0f, 0.0f, 0.0f, 1.0f };
GLfloat sun_light_specular[] = { 0.0f, 0.0f, 0.0f, 1.0f };
glLightfv(GL_LIGHT0, GL_POSITION, sun_light_position);
glLightfv(GL_LIGHT0, GL_AMBIENT, sun_light_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, sun_light_diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, sun_light_specular);
/*
void glLight{f,i,fv,iv}(GLenum light, GLenum pname, GLfloat param/*param);
参数light: 指定光源,OpenGL支持至少8种光照,值为GL_LIGHT0, GL_LIGHT1,......,GL_LIGHT7。
参数pname: 指定对光源设置何种属性,取值如下:
GL_AMBIENT: 设置环境光分量强度,默认值为(0.0,0.0,0.0,1.0)。
GL_DIFFUSE: 设置漫反射光分量强度,默认值为(1.0,1.0,1.0,1.0)。
GL_SPECULAR: 设置折射光分量强度,默认值为(1.0,1.0,1.0,1.0)。
GL_POSITION: 设置光源位置,默认值为(0.0,0.0,0.0,0.0)。
值由4个分量组成(x,y,z,w),若第4个分量w取值为0,表示该光源位于无限远处,前3个值表示它所在的方向,此时,光源称为方向光源,发出平行光;
若第4个分量w取值为1,表示指定的是离场景较近的光源,前3个值指定了光源的位置,这种光称为定位光源;
若第4个分量w取非零值,但不为1,则光源的位置为(x/w,y/w,z/w)。
GL_SPOT_DIRECTION: 用于设置聚光灯(聚光灯只能作为定位光源),设置聚光灯光锥轴线的方向,默认值为(0.0,0.0,-1.0),即光线指向z轴负向。
GL_SPOT_EXPONENT: 用于设置聚光灯,设置聚光程度。
默认值为0,表示光照范围内向各方向发射的光线强度相同;
为正数时,表示光照向中央集中,正对发射方向的位置受到更多光照,其它位置受到较少光照,数值越大,聚光效果就越明显。
GL_SPOT_CUTOFF: 用于设置聚光灯,设置聚光灯的最大散布角度,即顶角值的一半,默认值为180,即沿所有方向发射光线,还有一种默认值的取法为(0.0,90.0)。
GL_CONSTANT_ATTENUATION: 设置光的常数衰减因子,默认值为1.0。
GL_LINER_ATTENUATION: 设置光的线性衰减因子,默认值为0.0。
GL_QUADRATIC_ATTENUATION: 设置光的二次衰减因子,默认值为0.0。
参数param或*param: 指定pname的设置值或指针
*/
glEnable(GL_LIGHT0);//启用光源
// 旋转图形
glPushMatrix();
glRotatef(xRot, 1.0f, 0.0f, 0.0f);
glRotatef(yRot, 0.0f, 1.0f, 0.0f);
glFrontFace(GL_CW);
//绘制三菱锥
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0.0, 0.0, 80.0);
glVertex3f(0.0, 50.0, 0.0);
glColor3f(1.0, 0.0, 0.0);//红色
glVertex3f(50.0, -50.0, 0.0);
glColor3f(0.0, 1.0, 0.0);//绿色
glVertex3f(-50.0, -50.0, 0.0);
glColor3f(0.0, 0.0, 1.0);//蓝色
glVertex3f(0.0, 50.0, 0.0);
glEnd();
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0.0, 50.0, 0.0);
glVertex3f(50.0, -50.0, 0.0);
glColor3f(1.0, 1.0, 0.0);//黄色
glVertex3f(-50.0, -50.0, 0.0);
glEnd();
glPopMatrix();
glutSwapBuffers();
}
void SpecialKeys(int key, int x, int y)
{
if (key == GLUT_KEY_UP) xRot -= 5.0f;
if (key == GLUT_KEY_DOWN) xRot += 5.0f;
if (key == GLUT_KEY_LEFT) yRot -= 5.0f;
if (key == GLUT_KEY_RIGHT) yRot += 5.0f;
if (xRot > 356.0f) xRot = 0.0f;
if (xRot < -1.0f) xRot = 355.0f;
if (yRot > 356.0f) yRot = 0.0f;
if (yRot < -1.0f) yRot = 355.0f;
// 刷新窗口
glutPostRedisplay();
}
void ProcessMenu(int value)
{
switch (value)
{
case 1:
printf("普通材质");
bColorMaterial = FALSE;
break;
case 2:
printf("颜色跟踪材质");
bColorMaterial = TRUE;
break;
default:
break;
}
glutPostRedisplay();
}
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutCreateWindow("加光照的三菱锥图形");
glutReshapeFunc(ChangeSize);
glutSpecialFunc(SpecialKeys);//对键盘上特殊的4个方向按键的响应函数
glutDisplayFunc(RenderScene);
// 创建右键菜单
glutCreateMenu(ProcessMenu);
glutAddMenuEntry("普通材质", 1);
glutAddMenuEntry("颜色跟踪材质", 2);
glutAttachMenu(GLUT_RIGHT_BUTTON);
SetupRC();
glutMainLoop();
return 0;
}