OpenGL在光照模拟中将光线分为辐射光、环境 光、漫反射光和镜面反射光 4 种独立的成分。
辐射光emissive light:源自发光体,并且不受其他光源的影响。
环境光Ambient:是由光源发出经环境多次散射而无法确定其入射方向的光,即似乎来自所有方向。其特征是入射方向和出射方向均为任意方向。
漫射光Diffuse:来自特定方向,它垂直于物体时比倾斜时更明亮。一旦它照射到物体上,则在各个方向上均匀地发散出去,效果为无论视点在哪里它都一样亮,其特征是入射方向唯一、出射方向为任意方向。
镜面光Specular:来自特定方向并沿另一方向反射出去,一个平行激光束在高质量的镜面上产生100%的镜面反射,其特征是入射方向和出射方向均唯一。
在OpenGL中加入光照的步骤:
1.设置光源参数: 需要多次调用带有不同参数的glLightfv函数,设置环境光(Ambient Light)、漫射光(Diffuse Light)、镜面光(Specular Light)和光照位置(Position)等。
2.开启光照,使用glEnable(GL_LIGHTING)和glEnable(GL_LIGHTXX)来开启光照和XX号光源,前者相当于光 源的总开关,后者是对应的开启相应号数的光源。
3.第3步是法线的设置。
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
import numpy as np
def draw():
global angle
glClearColor(0.0, 0.0, 0.0, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); #清理颜色和深度缓存
#创建透视效果视图
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(80.0, 1.0, 1.0, 20.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0, 12.0, 10.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
#定义环境光源,它是一种白色的光源
glLightfv(GL_LIGHT0, GL_POSITION,(0.0,0.0,0.0,1.0) );
glLightfv(GL_LIGHT0, GL_AMBIENT,(0.0,0.0,0.0,1.0) );
glLightfv(GL_LIGHT0, GL_DIFFUSE, (1.0,1.0,1.0,1.0) );
glLightfv(GL_LIGHT0, GL_SPECULAR,(1.0,1.0,1.0,1.0) );
#开启灯光
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);
glEnable(GL_DEPTH_TEST);
#定义太阳的材质并绘制太阳
glMaterialfv(GL_FRONT, GL_AMBIENT, (0.0, 0.0, 0.0, 1.0));
glMaterialfv(GL_FRONT, GL_DIFFUSE, (0.0, 0.0, 0.0, 0.0));
glMaterialfv(GL_FRONT, GL_SPECULAR, (0.0, 0.0, 0.0, 0.0));
glMaterialfv(GL_FRONT, GL_EMISSION, (1.0, 1.0, 1.0, 1.0));
glMaterialf(GL_FRONT, GL_SHININESS, 0.0);
glutSolidSphere(3.0, 40, 32);
#定义地球的材质并绘制地球
#环境光蓝灰色
glMaterialfv(GL_FRONT, GL_AMBIENT, (0.0, 0.0, 1.0, 1.0));
#漫射光红色
glMaterialfv(GL_FRONT, GL_DIFFUSE, (1.0, 0.0, 0.0, 1.0));
#镜面光白色
glMaterialfv(GL_FRONT, GL_SPECULAR,(1.0, 1.0, 1.0, 1.0));
#发光体蓝色
glMaterialfv(GL_FRONT, GL_EMISSION, (0.0, 0.0, 1.0, 1.0));
glMaterialf(GL_FRONT, GL_SHININESS, 30.0);
glRotatef(angle, 0.0, -1.0, 0.0);
glTranslatef(7.0, 0.0, 0.0);
glutSolidSphere(3.0, 40, 32);
#OpenGL缓冲区
glutSwapBuffers();
angle += 0.05
while angle > 360:
angle -= 360
# 刷新缓存
glFlush()
#关闭窗口
def close(key,x,y):
if key==b'\x1b':
glutDestroyWindow(win_id)
if __name__ == "__main__":
angle = 0
# 初始化glut窗口
glutInit()
# 设置窗口显示模式:RGBA四通道|单缓存|深度
glutInitDisplayMode(GLUT_RGBA | GLUT_SINGLE | GLUT_DEPTH)
# 初始化窗口大小
glutInitWindowSize(400, 400)
# 创建窗口
win_id = glutCreateWindow("CUBE")
# 注册键盘事件
glutKeyboardFunc(close)
# 设置渲染函数
glutDisplayFunc(draw)
# 设置窗口空闲时函数
glutIdleFunc(draw)
# 开启深度测试
glEnable(GL_DEPTH_TEST)
# 开启窗口主循环
glutMainLoop()