OpenGL ES 学习教程(10.1):Directional Light(平行光)
发表于2017-11-22
前面我们学习光照的时候,指定了灯光的所在位置。根据灯光的位置与Fragment的位置算出向量A,然后与Fragment 的法线进行计算,得到夹角,然后计算出 Fragment 受光照的强弱大小。
指定灯光位置的方式常见于室内的灯泡、手电筒等环境。
对于太阳及其它类似的发光体,我们可以作为平行光(Directional Light) 来处理。
我们拿上篇OpenGL ES 学习教程(9):油腻的效果Lighting Maps高光贴图的工程来进行修改。
在上一节 高光贴图 中,是指定了光源的位置,现在修改成 直接指定 光线方向。
修改 GLProgram_Cube.h Line115 ,去掉 position ,添加 direction 。
"struct Light" //替换光的RGB分量强度 "{" //" vec3 position;" " vec3 direction;" " vec3 ambient;" " vec3 diffuse;" " vec3 specular;" "};" "uniform Light m_light;"
然后 原来的计算 由 Fragment 指向 灯光位置的向量,也不必进行了。
修改 GLProgram_Cube.h Line127 。
" vec3 normal=normalize(out_normal);" //法线向量 A //" vec3 lightdir=normalize(m_light.position-out_fragpos);" //物体指向灯光 向量 B " vec3 lightdir=normalize(-m_light.direction);" " float cosvalue=max( dot(normal,lightdir),0.0);" //点乘A B 计算角度cos值,角度越大 cos越小,90度的时候法线和光垂直,最小值。 " vec3 diffuse=(cosvalue* vec3(texture2D(m_diffusetexture,m_outUV))*m_light.diffuse);" //漫反射光 " vec3 cameraDir=normalize(m_camerapos-out_fragpos);" //计算顶点片段指向观察者的向量 " vec3 reflectDir=reflect(-lightdir,normal);" //计算光的反射 R reflect第一个参数是光源指向片段的向量 " float spec=pow(max(dot(cameraDir,reflectDir),0.0),m_material.shininess);" //计算镜面亮度,32是高光的发光值 Shininess,发光值越高,反射光越强,散射越小,高光点越集中。 " vec3 specular=(spec * vec3(texture2D(m_speculartexture,m_outUV))*m_light.specular);" " vec3 result=ambient +diffuse+specular;" //(环境光+漫反射光) * 物体本身的颜色
然后传入 direction 的值。
修改 GLProgram_Cube.h Line161。
m_lightDirection = glGetUniformLocation(m_programId, "m_light.direction");
修改 MyApp.h Line143
glUniform3f(m_programCube.m_lightDirection, 0.0f, 0.0f, -1.0f);//传入光的方向.照向屏幕里面,照亮正面;
运行效果图:
可以看到,每个箱子上面受到的光照都是相同的!!
实例工程下载:http://pan.baidu.com/s/1i4bfphb