前面我们学习光照的时候 ,指定了 灯光的所在位置。根据 灯光的位置 与 Fragment 的位置 算出向量A , 然后与 Fragment 的 法线 进行计算 , 得到夹角,然后计算出 Fragment 受光照的强弱 大小。
指定灯光位置的 方式 常见于 室内的灯泡、手电筒 等环境。
对于太阳 及其它类似的发光体,我们可以作为 平行光(Directional Light) 来处理。
我们拿上一节 OpenGL ES 学习教程(九) 油腻的效果 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