您的位置:首页 > 运维架构

OpenGL ES 学习教程(八) 精密控制光照元素的 Material 材质系统

2015-12-15 14:20 453 查看
学习教程(七) 第一篇了解了OpenGL中是如何模拟光照的,后面三篇中简单学习了 Ambient Light(环境光照)、Diffuse Lighting(漫反射光照)、Specular Lighting(镜面高光) 。然后我们可以做一些简单的光照效果,比如不同的高光效果:
文章转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn


但是这个东西是学习的一个例子,和自然世界中的光照效果相比,还是有很大的差距的。即使上面的图中看起来是光照在一块方砖上的效果,但是和真正的砖也是有差别的。

文章转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn
比如一辆跑车,车身上抛光打蜡,很容易就反光发亮,但是轮胎是不容易发亮的。



所以我们要给不同的物体 ,赋予不同的效果,通过使用三种光照元素定义一个材质颜色,为每个元素指定一个颜色,来对物体的颜色输出进行精密控制。

在Fragment Shader 中,我们定义一个 Struct Material (GLProgram_Cube.h Line:102)

struct Material  //替换顶点色
{
vec3 ambient;
vec3 diffuse;
vec3 specular;
float shininess;
};
uniform Material m_material;


在 Material 中,为每一种光照模型的元素都定义了一个颜色向量。文章转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn
ambient 描述环境光照下这个物体反射的是什么颜色,通常和物体颜色相同。

diffuse 描述漫反射光照下物体的颜色,漫反射颜色被设置为和环境光一样,设置为物体的颜色。

specular 描述的是物体受到的镜面光照的影响的颜色。

shininess 影响镜面高光的散射半径。

通过调整不同的光照颜色向量,我们就能模拟不同的材质。

下面来实现这样一个简单的材质系统。

我们已经在 Fragment Shader 中添加了一个 uniform 材质结构体,然后就要修改 Fragment Shader 的代码。(GLProgram_Cube.h Line 90)

void main()
{
vec3 ambient=m_material.ambient*m_lightcolor;//环境光;

vec3 normal=normalize(out_normal); //法线向量 A
vec3 lightdir=normalize(m_lightpos-out_fragpos); //物体指向灯光 向量 B
float cosvalue=max( dot(normal,lightdir),0.0); //点乘A B 计算角度cos值,角度越大 cos越小,90度的时候法线和光垂直,最小值。
vec3 diffuse=(cosvalue* m_material.diffuse) * m_lightcolor; //漫反射光

vec3 cameraDir=normalize(m_camerapos-out_fragpos); //计算顶点片段指向观察者的向量
vec3 reflectDir=reflect(-lightdir,normal); //计算光的反射 R reflect第一个参数是光源指向片段的向量,所以这里使用 -lightdir
float spec=pow(max(dot(cameraDir,reflectDir),0.0),m_material.shininess); //计算镜面亮度,32是高光的发光值 Shininess,发光值越高,反射光越强,散射越小,高光点越集中。
vec3 specular=(spec * m_material.specular) * m_lightcolor;

vec3 result=ambient +diffuse+specular; //(环境光+漫反射光) * 物体本身的颜色

gl_FragColor=vec4(result,1.0);
}

从整体上来看,就是用 Material 里面的三种光照属性 替换了 顶点色

设置三种光照颜色  (MyApp.h Line 95)文章转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn
//传入Material
glUniform3f(m_programCube.m_matAmbient, 1.0f, 0.5f, 0.31f); //环境光颜色
glUniform3f(m_programCube.m_matDiffuse, 1.0f, 0.5f, 0.31f); //漫反射颜色
glUniform3f(m_programCube.m_matSpecular, 0.5f, 0.5f, 0.5f); //高光颜色
glUniform1f(m_programCube.m_matShininess, 32.0f); //聚光值

运行程序,得到下面的结果



文章转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn
看起来是没什么问题,物体是亮着的,说明 Ambient Lighting 生效。背面比正面暗,说明 Diffuse Lighting 生效。也看到了白色的高光,说明 Specular Lighting生效。

但是对比之前的效果,这个图太亮了。

从代码逻辑上来说,缺少了 光照强度控制。

于是我们再定义一个 Struct Light (GLProgram_Cube.h Line 111)

struct Light //替换光的RGB分量强度
{
vec3 position;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
uniform Light m_light;

在给 m_light 赋值的时候,调整三种光照不同的强度,得到不同的效果。
例如我们设置 Ambient Lighting 值小一点,环境光的影响就少一点,就不那么亮。(MyApp.h Line 101)

//传入light;
glUniform3f(m_programCube.m_lightpos, 1.0f, 0.0f, 5.0f);//传入灯光的位置
glUniform3f(m_programCube.m_lightAmbient, 0.2f, 0.2f, 0.2f);
glUniform3f(m_programCube.m_lightDiffuse, 0.5f, 0.5f, 0.5f);
glUniform3f(m_programCube.m_lightSpecular, 1.0f, 1.0f, 1.0f);

运行程序获得下面的效果



文章转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn
如果调整一下 Material 中 Ambient Lighting 分量的值,设置为 (MyApp.h Line 96)

glUniform3f(m_programCube.m_matAmbient, 1.0f, 0.0f, 0.0f);

然后调整 Light 中 Ambient Lighting 的分量,把环境光对Cube的影响值调大 (MyApp.h Line 103)
glUniform3f(m_programCube.m_lightAmbient, 1.0f, 1.0f, 1.0f);

那么会得到下面的结果



现在可以很方便的调整 Material 效果了,而且能精确的模拟自然效果,因为 三种光照都是可控的。

文章转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn
示例工程下载:
http://pan.baidu.com/s/1dDQb69b
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: