OpenGL ES _ 入门_01
OpenGL ES _ 入门_02
OpenGL ES _ 入门_03
OpenGL ES _ 入门_04
OpenGL ES _ 入门_05
OpenGL ES _ 入门练习_01
OpenGL ES _ 入门练习_02
OpenGL ES _ 入门练习_03
OpenGL ES _ 入门练习_04
OpenGL ES _ 入门练习_05
OpenGL ES _ 入门练习_06
OpenGL ES _ 着色器 _ 介绍
OpenGL ES _ 着色器 _ 程序
OpenGL ES _ 着色器 _ 语法
OpenGL ES_着色器_纹理图像
OpenGL ES_着色器_预处理
OpenGL ES_着色器_顶点着色器详解
OpenGL ES_着色器_片断着色器详解
OpenGL ES_着色器_实战01
OpenGL ES_着色器_实战02
OpenGL ES_着色器_实战03
展示图:
友情提示:
本文重在讲解一些游戏中灯光的类型和作用,明白原理就可以,代码看不懂没关系.之后会用大量时间,剖析OpenGL ES 代码,持续更新!
- 学习目标:
1.理解OpenGL是如何模拟现实世界的光照条件
2.通过定义光源,材料和光照模型属性,渲染光照物体
3.定义光照物体的材料属性
- 任务:
绘制一个被光照射的球体
- 概念解释:
深度缓冲区原理:首先,把一个距离观察平面的深度值(距离) 与窗口中的每个像素相关联,一开始,使用glClear(GL_DEPTH_BUFFER_BIT) 把所有像素的深度值,设置为最大可能的距离,然后,在场景中绘制所有物体,硬件或者软件会把被绘制表面转回为像素集合,在这个时候,不考虑是否被遮挡,OpenGL 此时,还会计算,这些表面和观查着平面的距离,如果启动了深度缓冲区,OpenGL 会把它的深度值和已经存储在缓冲区中的深度值,进行比较,如果新像素比原先的像素更靠近观察平面,这个新像素的颜色和深度会取代原先那个像素,如果新像素的深度值大于原先像素的深度值,新像素就会被遮挡,他的颜色和深度会被丢弃。
如何使用?
首先需要启动它,启动一次即可,每次绘制场景时,需要在绘制之前清除深度缓冲区,然后以任意顺序绘制场景中的物体
glclear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
理解OpenGL是如何模拟现实世界的光照条件
补充知识?
当观察一个物理表面时,眼睛对颜色的感知取决于到达刺激缀细胞的光子和能量分布,这些光子可能来自单个光源,也可能来自多个光源,有些光子被表面吸收,有些被反射出来。不同表面的属性可能存在非常大的区别,有些表面非常光滑,会把光线反射到某个方向,有些表面会把均匀的发散到所有地方,很多表面位于两者之间。
请认真阅读以上的内容,这个将影响到您对本文的理解。
OpenGL是怎么模拟光照的?
首先,假定光可以分解为红,绿,蓝成分,光源的特性是由它发射的红,绿和蓝的数量决定的,表面材料的特性,是由它向不同方向反射光的百分比决定的。OpenGL 有自己的一套光照方程式,计算效率相对来说,也很高,如果想要自己实现这样的一套光照方程式,也可以,可能你需要花费很大的精力,实在是太复杂了。
OpenGL 光照模型中,场景中的灯光,有来自固定方向的和不同方向的,可以单独打开和关闭,这个很简单,想一下我们的生活场景就可以了。
当光照射到物体上,能会体现出光照的意义。
OpenGL 光照模型,把光分为4种独立的成分:环境光,反射光,镜面光,发射光。
下面就来解释一下四种光的含义和作用。
环境光: 在环境中充分的散射,无法辨别其方向的光,似乎来自于所有的方向。当环境光撞击物体表面时,会向各个方向发散。
散射光:来自某个方向,如果它从正面照射,他可能看起来更亮一下,如果他斜着掠过表面,看其他则会暗一些,来自某个特性的位置或者方向的任何光很可能具有散射的成分。
朗伯体光照模型:
Id=kdIi cos(Θ)
ID是漫反射的强度,Ii是光的入射光的强度,和KD的漫反射,是对粗糙松散耦合对象材料。松散的意思是,在许多现实世界的材料,实际表面可能有点抛光,但半透明的,而层立即下执行散射。材料,如这可能有强烈的漫反射和镜面反射成分。此外,每个颜色带可能有自己的K值在现实生活中,所以会有一个红色,绿色和蓝色
镜面光:来自某个方向,如果物体表面光滑,这种光将充分反射,但是一般的物体表面不会绝对的光滑,所有不可能有真正的完美反射.
I =W(q)I cosn Θ
Ilight 入射光的轻度
W(q) 基于光线I的夹角是如何反射的
N是亮度因子
Θ是反射光线,光线射到眼睛的夹交
虽然W(q)是不能直接使用在OpenGL ES 1,它可以用来在一个版本的OpenGL ES 2着色器。它将是特别有用的,在做反射的水,例如。在它的位置是一个常数,是基于从材质设置的高光值。
发射光:材料自身可能具有一种发射颜色,可以模拟那些来自物体的光,它不受任何光源的影响,发射颜色没有作为一种额外的光源。
顶点颜色值:
color=ambientworldmodel +ambientmaterial +emissivematerial +intensitylight
材料颜色:可以给物体设置材料颜色,通俗的解释一下,假设一个物体的材料颜色为红色,那么,用蓝光照射这个物体,我们看到的是一个黑色的球,因为他把蓝光吸收了,如果我们用红光照射他,我们看到的就是一个红球,如果用白光照射他,我们也看到的是红球,因为白光(R=1,G=1,B=1)中 用红光的成分
光照和材料RGB值
如果一束光线的成分为(LR,LG,LB) 一种材料具有的颜色成分为(MR,MG,MB) 那么,进入眼睛的光就是(LR*MR,LG*MG,LB*MB)
两个光源叠加原理(R1,G1,B1) 和 (R2,G2,B2) 叠加后 (R1+R2,G1+G2,B1+B2) 如果相加后任何一个值大于1,则会被截取1(因为设备能后现实的最大颜色亮度)。
提示:
如果使用光照RGBA 颜色索引模式优先选择
为每个物体的每个顶点定义法线向量?
物体的法线向量,决定了它相对于光源的方向,OpenGL 使用法线判断这个顶点从每个光源接受的光线数量,注意,为了正确计算光线,表面法线必须为单位长度,必须保证对物体所进行的模型转换,并没有对表面法线进行缩放,最终的法线仍然为单位长度。
如何创建光源?
glLightfv()函数指定光源的位置,如果使用不同颜色的光,使用glLight*()函数修改
场景中至少可以包含八个光源,除了GL_LIGHT0 之外的其他光源的颜色都为黑色。可以把光源放在很远的地方,模拟阳光,可以对光源进行控制,让它产生狭窄的聚焦光束和角度宽广的光束
如何启用光源?
glEnable() 参数GL_LIGHTING
光源的几个重要属性:颜色,位置,和方向
两个重要函数:
glLight(GLenum light,Glenum pname,TYPE para),
glLightv(GLenum light,Glenum pname,TYPE *param )
参数1 light 指定光源 GL_LIGHT0…GL_LIGHT7
参数2 pname 具体的属性
参数3 para 属性值单值,param属性值,向量 根据属性的不同选择不同的函数
参考下面的表格
参数名称 | 默认值 | 含义 |
---|---|---|
GL_AMBIENT | (0,0,0,1) | 环境光强度 |
GL_DIFFUSE | (1,1,1,1) | 光的散射强度 |
GL_SPECULAR | (1,1,1,1) | 光的镜面强度 |
GL_POSITION | (0,0,1,0) | 光源的位置坐标 |
GL_SPOT_DIRECTION | (0,0,-1,0) | 聚光灯的方向 |
GL_SPOT_EXPONENT | 0.0 | 聚光指数 |
GL_SPOT_CUTOFF | 180 | 聚光灯的切角 |
GL_CONSTANT_ATTENUATION | 1.0 | 常亮衰减因子 |
GL_LINEAR_ATTENUATION | 0.0 | 线性衰减因子 |
GL_QUADRATIC_ATTENUATION | 0.0 | 二次衰减因子 |
提示: 如果想要创建逼真的效果可以将GL_SPECULAR 和 GL_DIFFUSE 的参数值设置相同
选择光照模型我们应该思考的问题?
1.观察者应该在无限远处还是场景本地
2.确定场景中的物体的正面和背面是否应该执行不同的计算
glLightModel*()
为场景中的物体定义材料属性?
物体的材料属性决定他是如何反射光线的,因此也决定了它的颜色。可以指定材料的颜色,散射和镜面颜色以及它的光泽,这个例子只指定了最后两种材料属性,镜面材料颜色和光泽度。
提示: 当光照条件发生变化时,可以使用显示列表实现最大限度的效率
- 光源类型
第一种,光源位于无限远处,这种光源被称为方向性光源,如果光源位于无限远处,当光线到达物体表面时,认为所有的光源都是平行的
第二种,被称为位置性光源,通俗的讲,它的位置决定它对场景产生的效果,具体来说,它决定光线的方向,台灯就是一个位置性光源,通常位置性光源是朝向每个方向发射光线的,但也可以把光源定义为聚光灯,把它的照明范围限制在一个锥体里
- 衰减
随着光源的距离的增加,光的强度也随之衰减,由于方向性光源在无限远处,所以这个原则不适用于方向性光源,但是我们可以对位置性光源进行衰减,OpenGL将光源的强度乘以衰减因子。
衰减因子 = 1/(kc+kl*d+kq*d^2)
d = 光源和顶点的位置
KC = GL_CONSTANT_ATTENUATION
KL = GL_LINEAR_ATTENUATION
KQ = GL_QUADRATIC_ATTENUATION
环境光,散射光,镜面光的强度都进行了衰减,只有发射光和全局环境光没有衰减,由于衰减需要在每种经过计算差生的颜色上再进行一次除法,所以衰减光可能会影响应用程序的性能。
创建聚光灯步骤?
设置光锥切角:
glLightf(GL_LIGHT0,GL_SPOT_CUTOFF,45.0);
设置聚光灯的方向 默认方向为(0,0,-1)
glLightfv(GL_LIGHT0,GL_SPOT_DORECTION,spot_direction);
可以设置衰减因子和光的集中度
GL_SPOT_EXPONENT 参数控制光的集中度
代码部分:
-(void)initLighting
{
// 创建灯光的位置
GLfloat posMain[]={5.0,4.0,6.0,1.0};
GLfloat posFill1[]={-15.0,15.0,0.0,1.0};
GLfloat posFill2[]={-10.0,-4.0,1.0,1.0};
GLfloat white[]={1.0,1.0,1.0,1.0};
// 定义几种颜色值
GLfloat dimblue[]={0.0,0.0,.2,1.0};
GLfloat cyan[]={0.0,1.0,1.0,1.0};
GLfloat yellow[]={1.0,1.0,0.0,1.0};
GLfloat dimmagenta[]={.75,0.0,.25,1.0};
GLfloat dimcyan[]={0.0,.5,.5,1.0};
//设置反射光的位置和颜色
glLightfv(GL_LIGHT0,GL_POSITION,posMain);
glLightfv(GL_LIGHT0,GL_DIFFUSE,white);
// 设置镜面光的颜色,它的光源和反射光是同一个光源
glLightfv(GL_LIGHT0,GL_SPECULAR,yellow);
// 设置光源2的位置和类型
glLightfv(GL_LIGHT1,GL_POSITION,posFill1);
glLightfv(GL_LIGHT1,GL_DIFFUSE,dimblue);
glLightfv(GL_LIGHT1,GL_SPECULAR,dimcyan);
// 设置光源3 的位置和类型以及
glLightfv(GL_LIGHT2,GL_POSITION,posFill2);
glLightfv(GL_LIGHT2,GL_SPECULAR,dimmagenta);
glLightfv(GL_LIGHT2,GL_DIFFUSE,dimblue);
//设置衰减因子
glLightf(GL_LIGHT2,GL_QUADRATIC_ATTENUATION,.005);
//设置材料在反射光下的颜色
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, cyan);
// 设置材料在镜面光下的颜色
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, white);
//
glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS,25);
// 设置光照模式 GL_SMOOTH 代表均匀的颜色涂在表面上
glShadeModel(GL_SMOOTH);
glLightModelf(GL_LIGHT_MODEL_TWO_SIDE,0.0);
// 开启灯光模式
glEnable(GL_LIGHTING);
// 打开灯光123
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);
glEnable(GL_LIGHT2);
}
参考完整代码:
完整代码下载地址:demo