opengl光照效果的三棱锥+键盘上下左右控制旋转(学习笔记-仅供参考)

#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;
}

在这里插入图片描述

OpenGL中,绘制一个动态颜色变化的椎体通常需要结合顶点着色器(Vertex Shader)、片段着色器(Fragment Shader)以及基本的三维变换知识。首先,你需要创建一个椎体几何模型,并且为每个面分配一个初始颜色。然后,你可以通过设置颜色作为顶点属性的一部分,或者在着色器中计算颜色来实现实时颜色变化。 步骤大致如下: 1. **创建模型**: - 使用OpenGL库提供的函数如glGenBuffers、glGenVertexArrays等生成缓冲区和VAO(Vertex Array Object),用于存储顶点数据和索引。 2. **设置顶点数据**: - 定义一个包含位置、法线、纹理坐标和初始颜色的结构体或向量数组。 - 将这些数据填充到缓冲区中,例如,对于每个椎体顶点,可以是一个包含XYZ位置、RGB颜色的四元组。 3. **着色器编写**: - 编写顶点着色器(VS),将位置、颜色作为输入传入并可能包含一个时间变量,用于动画效果。 - 写一个片段着色器(FS),接收顶点着色器传递的颜色,并可以根据需要进行处理,比如基于时间的变化。 4. **设置颜色和动画**: - 在顶点着色器中,可以用当前的时间或其他动画信号更新每个多边形的颜色。 - 需要在主渲染循环中提供实时的时间值给着色器。 5. **绘制**: - 绑定VAO和VBO(Buffer Object),启用着色器,设置投影矩阵、视图矩阵和模型矩阵。 - 调用glDrawArrays或glDrawElements绘制椎体。 ```sh // 示例代码(伪代码) glUseProgram(shaderProgram); time = ... // 获取当前时间 glUniform1f(colorUniform, time); // 更新颜色 uniforms glBindVertexArray(vao); glDrawArrays(GL_TRIANGLES, 0, numVertices); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值