当前位置:网站首页>OpenGL glLightfv 函数的应用以及光源的相关知识
OpenGL glLightfv 函数的应用以及光源的相关知识
2022-07-07 08:15:00 【my_angle2016】
首先介绍OpenGL的简单光照模型,它的反射光可以分为三个分量:环境反射光,漫反射光,镜面反射光。就是你要实现一个光照效果,需要设置这三个分量,三者之和达到你想要的光照效果。
1.环境光,简单来说就是环境中的光,似乎来自于各个方向
2.漫反射,来自一个方向,光它照射到物体上,则在各个方向上均匀地发散出去,不管视点在哪,物体都是一样亮。
3.镜面光,来自特定方向,并沿着另一方向反射出去。
glLightfv函数原型:void glLightfv(光源名, 类型, 赋值);
类型主要有四类:光源颜色---AMBIENT、DIFFUSE、SPECULAR和光源位置---POSITION
其中DIFFUSE的参数与光源颜色紧密,一般简单的光照模型只设置DIFFUSE就足够用了
GLfloat light0_diffuse[]= { 1.0, 0.0, 0, 1.0};
glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);下面是赋值的代码:
GLfloat light0_ambient[]= { 0.2, 0.2, 0.2, 1.0 };
GLfloat light0_diffuse[]= { 1.0, 0.0, 0, 1.0};
GLfloat light0_specular[] = { 1.0, 0, 0, 1.0 };
glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR,light0_specular);设置光源位置
GLfloat light0_position[] = { 1.0, 1.0, 1.0, 0.0 };
glLightfv(GL_LIGHT0, GL_POSITION,light0_position);开启光源
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);glEnable(GL_LIGHTING);表示启动光照的总开关 glEnable(GL_LIGHT0);//打开0号光源
glEnable(GL_DEPTH_TEST);//打开深度缓冲区,绘制3D图像时候使用
完整代码
#include "stdafx.h"
#include <GL/glut.h>
#include "math.h"
void reshape(int w,int h)
{
glViewport(0,0,(GLsizei)w,(GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if(w<h)
glOrtho(-1.5, 1.5, -1.5,1.5 * (GLfloat)h / (GLfloat)w, -1.5,1.5);
else
glOrtho(-1.5* (GLfloat)w / (GLfloat)h, 1.5, -1.5,1.5, -1.5,1.5 );
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void init ()
{
glClearColor(1.0,1.0,1.0,0.0);
glColor3f(1.0,1.0,0.0);
GLfloat light0_ambient[]= { 0.2, 0.2, 0.2, 1.0 };
GLfloat light0_diffuse[]= { 1.0, 0.0, 0, 1.0};//红色点光源
GLfloat light0_specular[] = { 1.0, 0, 0, 1.0 };
GLfloat light0_position[] = { 1.0, 1.0, 1.0, 0.0 };
glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR,light0_specular);
glLightfv(GL_LIGHT0, GL_POSITION,light0_position);
glShadeModel(GL_SMOOTH);//光滑着色,过渡色效果
glEnable(GL_LIGHTING);//启动光照,总开关
glEnable(GL_LIGHT0);//打开0号光源
glEnable(GL_DEPTH_TEST);
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glutSolidTeapot(0.5);
glFlush();
}
int main(int argc, char* argv[])
{
glutInit(&argc,argv);
glutInitWindowPosition(200,200);
glutInitWindowSize(500,500);
glutCreateWindow("001");
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
运行结果

我们发现茶壶的颜色被设置的光照给覆盖了,本身的颜色(黄色)并没有显示出来。这里引入一个新的函数---颜色材质函数glEnable(GL_COLOR_MATERIAL); 它确保了打开灯光效果之后还能保留图形颜色。使用时候放在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))。参数数据格式要求为数组形式,即数学上的向量形式。
下面一段代码,我们将一个光源的性质进行完整设置:
GLfloat Va[]={0.4,0.4,0.4,1}; //光源环境光强度数组
GLfloat Vd[]={0.6,0.6,0.6,1}; //光源散射光强度数组
GLfloat Vs[]={0.6,0.6,0.6,1}; //光源镜面反射光强度数组
GLfloat Vp[]={1,1,1,1}; //光源位置数组
glLightfv(GL_LIGHT0,GL_AMBIENT,Va); //设置0号光源的环境光属性
glLightfv(GL_LIGHT0,GL_DIFFUSE,Vd); //设置0号光源的散射光属性
glLightfv(GL_LIGHT0,GL_SPECULAR,Vs); //设置0号光源的镜面反射光属性
glLightfv(GL_LIGHT0,GL_POSITION,Vp); //设置0号光源的位置属性 光源的性质设置完毕,还要调用glEnable(GL_LIGHT0)来打开光源。就相当于你买回手电筒、装好电池(设置光源),但如果不打开开关(打开电源),手电筒是不起作用的。
另外,对于GL_POSITION,其位置数组(x,y,z,w)定义了光源在空间中的位置。但三维空间为什么需要4个量呢?事实上这里采用的是齐次坐标,当w≠0时,它表示光源处于空间中(x,y,z)处,这时的光源称为定点光源;当w=0时,根据齐次坐标的性质,它表示光源位于无穷远处,此时光源称为定向光源,其所有光线几乎是相互平等的,如太阳。其光线方向由点(x,y,z)指向(0,0,0)。
将第2章中的正方体的例子做以下修改。修改后的void __fastcall TForm1::OpenGL1 GLPaint(TObject *Sender)处的代码如下(其余位置不变):
void __fastcall TForm1::OpenGL1GLPaint(TObject *Sender)
{
glEnable(GL_DEPTH_TEST); //隐藏表面消除
glClear(GL_DEPTH_BUFFER_BIT); //清除窗口颜色
const GLfloat glfLightAmbient1[4] = {0.1, 0.1, 0.1, 1.0};
const GLfloat glfLightAmbient2[4] = {0.4, 0.4, 0.4, 1.0};
const GLfloat glfLightDiffuse1[4] = {0, 0.8, 0.8, 1.0};
const GLfloat glfLightDiffuse2[4] = {0.8, 0.8, 0.8, 1.0};
const GLfloat glfLightSpecular1[4] = {0, 0.8, 0.8, 1.0};
const GLfloat glfLightSpecular2[4] = {0.8, 0.8, 0.8, 1.0};
const GLfloat glPosition1[4]={0,0,1,0};
const GLfloat glPosition2[4]={0.6,0.6,-0.6,1};
glLightfv(GL_LIGHT0, GL_AMBIENT, glfLightAmbient1);
glLightfv(GL_LIGHT0, GL_DIFFUSE, glfLightDiffuse1);
glLightfv(GL_LIGHT0, GL_SPECULAR, glfLightSpecular1);
glLightfv(GL_LIGHT0,GL_POSITION,glPosition1);
glLightfv(GL_LIGHT1, GL_AMBIENT, glfLightAmbient2);
glLightfv(GL_LIGHT1, GL_DIFFUSE, glfLightDiffuse2);
glLightfv(GL_LIGHT1, GL_SPECULAR, glfLightSpecular2);
glLightfv(GL_LIGHT1,GL_POSITION,glPosition2);
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE);//两面照亮
glEnable(GL_LIGHTING);//启用光照
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);//打开光源
glEnable(GL_COLOR_MATERIAL);//启用颜色追踪
glColorMaterial(GL_FRONT,GL_AMBIENT_AND_DIFFUSE);
//物体正面的材料环境颜色和散射颜色,追踪glColor所设置的颜色(比较拗口,
事实上就是让OpenGL根据glColor所设置的颜色自动设置物体的反射强度)
glShadeModel(GL_FLAT);//设置颜色填充模式
glBegin(GL_QUAD_STRIP) ;
glVertex3f(i,-i,i);
glVertex3f(i,-i,-i);
glColor3f(1,0,0);
glVertex3f(-i,-i,i);
glVertex3f(-i,-i,-i);
glColor3f(0,1,0);
glVertex3f(-i,i,i);
glVertex3f(-i,i,-i);
glColor3f(0,0,1);
glVertex3f(i,i,i);
glVertex3f(i,i,-i);
glColor3f(1,1,0);
glVertex3f(i,-i,i);
glVertex3f(i,-i,-i);
glEnd();
glBegin(GL_QUADS);
glVertex3f(i,-i,i);
glVertex3f(-i,-i,i);
glVertex3f(-i,i,i);
glColor3f(1,0,1);
glVertex3f(i,i,i);
glVertex3f(i,-i,-i);
glVertex3f(-i,-i,-i);
glVertex3f(-i,i,-i);
glColor3f(0,1,1);
glVertex3f(i,i,-i);
glEnd();
glDisable(GL_LIGHTING);//关闭光照
glDisable(GL_LIGHT0);//关闭0号光源
glDisable(GL_LIGHT1); //关闭1号光源
} 边栏推荐
- 【华为机试真题详解】高矮个子排队
- How to cancel automatic saving of changes in sqlyog database
- STM32基础知识—内存映射
- Programming features of ISP, IAP, ICP, JTAG and SWD
- UnityWebRequest基础使用之下载文本、图片、AB包
- Download Text, pictures and ab packages used by unitywebrequest Foundation
- ORM model -- associated fields, abstract model classes
- Slurm资源管理与作业调度系统安装配置
- ArcGIS operation: converting DWG data to SHP data
- Experience sharing of software designers preparing for exams
猜你喜欢

嵌入式背景知识-芯片

HAL库配置通用定时器TIM触发ADC采样,然后DMA搬运到内存空间。

【acwing】789. 数的范围(二分基础)

ORM -- logical relation and & or; Sort operation, update record operation, delete record operation

一文讲解单片机、ARM、MUC、DSP、FPGA、嵌入式错综复杂的关系

Fiddler break point

ISP、IAP、ICP、JTAG、SWD的编程特点

Methods of adding centerlines and centerlines in SolidWorks drawings

【HigherHRNet】 HigherHRNet 详解之 HigherHRNet的热图回归代码

Appx代码签名指南
随机推荐
浅谈日志中的返回格式封装格式处理,异常处理
【剑指Offer】42. 栈的压入、弹出序列
Apprentissage avancé des fonctions en es6
IPv4 socket address structure
High number_ Chapter 1 space analytic geometry and vector algebra_ Quantity product of vectors
C logging method
HAL库配置通用定时器TIM触发ADC采样,然后DMA搬运到内存空间。
2022.7.4DAY596
BigDecimal数值比较
Some properties of leetcode139 Yang Hui triangle
. Net configuration system
【acwing】789. Range of numbers (binary basis)
Programming features of ISP, IAP, ICP, JTAG and SWD
AHB bus in stm32_ Apb2 bus_ Apb1 bus what are these
【HigherHRNet】 HigherHRNet 详解之 HigherHRNet的热图回归代码
Several schemes of building hardware communication technology of Internet of things
Differences between MCU and MPU
ORM model -- associated fields, abstract model classes
一文讲解单片机、ARM、MUC、DSP、FPGA、嵌入式错综复杂的关系
Serial communication relay Modbus communication host computer debugging software tool project development case