上篇文章我们讲到了 opengl的 mvp矩阵,以及在三维世界里漫游的方法,与实现,这篇讲解下,opengl的光照模型。
环境光ambient: 就是环境周边物体反射找到物体上的光
漫反射光diffuse: 物体表面漫反射出去的光
镜面反射光specular:光束找到物体表面反射的光
当光照射物体的时候我们需要设置:
物体反射光设置:
物体所处环境光
物体的漫反射光(通常和物体颜色有关)
物体的镜面反射光(与光源有关系)
光源设置:
光源位置
光源环境光
光源漫反射光
光源镜面反射光
当然根据需要,我们可以组建不同的光照模型:
lambient模型 :环境光 和 漫反射光
phong模型:环境光 和 漫反射光 和 镜面反射光
blin-phong: 模型是phong模型的简化版
光源的设置其实很简单,如下:
void model::setLightArgs(glm::vec4 cameraPos){
glUniform4fv(U_LightPosLocation , 1 ,glm::value_ptr(glm::vec4(0.0f,10.0f,10.0f,0.0f) ));
glUniform4fv(U_CameraPosLocation,1,glm::value_ptr(cameraPos));
glUniform4fv(U_LightAmbientLocation , 1 ,glm::value_ptr(glm::vec4(0.4f,0.4f,0.0f,1.0f)) );
glUniform4fv(U_LightDiffuseLocation,1,glm::value_ptr(glm::vec4(0.5f,0.50f,0.0f,1.0f)));
glUniform4fv(U_LightSpecularLocation,1,glm::value_ptr(glm::vec4(1.0f,1.0f,1.0f,1.0f)));
glUniform4fv(U_OptionLocation,1,glm::value_ptr(glm::vec4(1.0f,0.0f,0.0f,0.0f)));
glUniform4fv(U_AmbientMaterialLocation,1,glm::value_ptr(glm::vec4(0.1f,0.1f,0.1f,1.0f)));
glUniform4fv(U_DiffuseMaterialLocation,1,glm::value_ptr(glm::vec4(0.6f,0.6f,0.6f,1.0f)));
glUniform4fv(U_SpecularMaterialLocation,1,glm::value_ptr(glm::vec4(1.0f,1.0f,1.0f,1.0f)));
}
U_OptionLocation 为所选光照模型,在着色器根据这个的值来进行不同的光照运算。
normal法向量的计算,前2篇文章中讲解了,我们在解析模型后右一个atribute属性就是normal,是每个点的法向量,是每个点的切屏幕垂直的向量。光的反射就是靠这个向量来计算的。但随着模型的转动,法向量在三维世界也会改变,因此我们要计算 转动后的 模型在三维世界,或者 屏幕坐标系里的值。
INVERSE_TRANSPOSE_MATRIX 方法
该方法是将法向量normal 旋转后,转化到视觉坐标系中,推到方法这里不讲了,有点繁杂,大家记住结论就可以:
利用glm可以通过下面方法获得:
glm::mat4 it=glm::inverseTranspose(modelMatrix);
glUniformMatrix4fv(IT_ModelMatrixLocation, 1, GL_FALSE, glm::value_ptr(it));
在着色器中使用如下,相乘得到的向量就为旋转后的法向量,当然只用取前面的x、y、z
V_Normal=IT_ModelMatrix*normal;
逐定点渲染:是将光照 和 颜色的计算放在 定点着色器中计算,然后varing 传递到 fragmentshader中去。计算复杂度只跟定点个数有关系,属于轻量级渲染。
逐像素渲染:是在fragmentshader中去做 颜色的渲染工作,算法的计算个数与屏幕的像素大小有关系,因此,它的计算级别比逐顶点渲染高很多,但效果也好。