opengl光照之镜面光逐顶点渲染与逐像素渲染

镜面光逐顶点渲染效果
opengl光照之镜面光逐顶点渲染与逐像素渲染
文章图片


顶点shader

attribute vec3 pos; //顶点坐标 attribute vec2 texcoord; //纹理坐标 attribute vec3 normal; //法线uniform mat4 M; //模型矩阵 uniform mat4 P; //投影矩阵 uniform mat4 V; //摄像机观察矩阵 uniform mat4 NM; //将法线变换到世界坐标系或视口坐标系的矩阵uniform vec3 U_LightPos; //光源位置 uniform vec3 U_EyePos; //眼睛的位置 uniform vec4 U_DiffuseLightColor; //漫反射光颜色 uniform vec4 U_DiffuseMaterial; //漫反射光的材质 uniform vec4 U_SpecularLightColor; //镜面光颜色 uniform vec4 U_SpecularMaterial; //镜面光材质varying vec4 V_DiffuseColor; varying vec4 V_SpecularColor; void main() { vec3 L=U_LightPos; //由物体表面指向光源的向量 L=normalize(L); //归一化 //获取转换到世界空间或者视口空间的法线向量 vec3 n=normalize(mat3(NM)*normal); //计算漫反射光强度 float diffuseIntensity=max(0.0,dot(L,n)); //漫反射光照最终颜色 V_DiffuseColor=U_DiffuseLightColor*U_DiffuseMaterial*diffuseIntensity; //镜面光产生的原因:当照射在物体上的光源产生的反射光和人眼看物体的方向一致时 //此时,物体表面就会产生最亮的光斑,也就是镜面光 //计算镜面反射反射光 vec3 reflectDir=reflect(-L,n); reflectDir=normalize(reflectDir); //将模型上的点变化到世界空间 vec4 worldPos=M*vec4(pos,1.0); //视线方向 vec3 viewDir=U_EyePos-worldPos.xyz; viewDir=normalize(viewDir); //计算最终镜面光 V_SpecularColor=U_SpecularLightColor*U_SpecularMaterial*pow(max(0.0,dot(viewDir,reflectDir)),8.0); gl_Position=P*V*worldPos; }


镜面光逐顶点渲染片元shader
uniform vec4 U_AmbientLightColor; uniform vec4 U_AmbientMaterial; varying vec4 V_DiffuseColor; varying vec4 V_SpecularColor; void main() { vec4 ambientColor=U_AmbientLightColor*U_AmbientMaterial; gl_FragColor=ambientColor+V_DiffuseColor+V_SpecularColor; }


镜面光逐像素渲染效果 opengl光照之镜面光逐顶点渲染与逐像素渲染
文章图片


可以发现 逐像素的渲染效果比逐顶点好很多,因为逐顶点渲染顶点之间的片元是插值出来的效果。
逐像素渲染顶点shader

attribute vec3 pos; attribute vec2 texcoord; attribute vec3 normal; uniform mat4 M; uniform mat4 P; uniform mat4 V; uniform mat4 NM; varying vec3 V_Normal; varying vec3 V_WorldPos; void main() { V_Normal=mat3(NM)*normal; vec4 worldPos=M*vec4(pos,1.0); V_WorldPos=worldPos.xyz; gl_Position=P*V*worldPos; }

逐像素渲染片段shader
uniform vec3 U_LightPos; uniform vec3 U_EyePos; uniform vec4 U_AmbientLightColor; uniform vec4 U_AmbientMaterial; uniform vec4 U_DiffuseLightColor; uniform vec4 U_DiffuseMaterial; uniform vec4 U_SpecularLightColor; uniform vec4 U_SpecularMaterial; varying vec3 V_Normal; varying vec3 V_WorldPos; void main() { //ambient vec4 ambientColor=U_AmbientLightColor*U_AmbientMaterial; //diffuse //L vector vec3 L=U_LightPos; L=normalize(L); //N vector vec3 n=normalize(V_Normal); float diffuseIntensity=max(0.0,dot(L,n)); vec4 diffuseColor=U_DiffuseLightColor*U_DiffuseMaterial*diffuseIntensity; //specular //reflection vec3 reflectDir=reflect(-L,n); reflectDir=normalize(reflectDir); //inverse view direction : object->eye vec3 viewDir=U_EyePos-V_WorldPos; viewDir=normalize(viewDir); vec4 specularColor=U_SpecularLightColor*U_SpecularMaterial*pow(max(0.0,dot(viewDir,reflectDir)),8.0); gl_FragColor=ambientColor+diffuseColor+specularColor; }


normalMatrix 法线矩阵的计算 【opengl光照之镜面光逐顶点渲染与逐像素渲染】
glm::mat4 modelMatrix = glm::translate(0.0f,0.0f,-3.0f); glm::mat4 projectionMatrix = glm::perspective(50.0f, 800.0f / 600.0f, 0.1f, 1000.0f); glm::mat4 normalMatrix = glm::inverseTranspose(modelMatrix);




    推荐阅读