本文在上一篇(OpenGL ES 光照模型之——环境光照(RenderMonkey测试))环境光基础上,增长漫反射光照。咱们主要使用漫反射光模拟太阳光,实现以下两种效果:函数
一、地球自传,太阳光固定的日出效果;测试
二、地球静止,太阳光围绕地球旋转的效果。spa
本文主要包括以下方面内容:code
一、漫反射光模型简介;orm
漫反射光的定义网上有各类说法,在此就不描述了,下面经过两个图形来表示:it
(平行光)io
(“散”射光)编译
如上两个图中,有人把第一个图的平行光当作漫反射光,也有人把第二个图的模型当作慢反射光。是的,若是第二个图中光远点T无限远,那么两个光照模型的效果实际上是同样的,但模型2更像是没有衰减系数的点光源。
模型公式以下:
其中:
IDifuse为漫反射光照强度;
Id为光源颜色;
Kd能够理解为漫反射光照输入强度;
cosθ为光线与发现的夹角;
咱们下面经过介绍的是使用第一种模型实现的效果。
本段内容咱们先来看下利用RenderMonkey实现的OpenGL ES Shader日出模型的最终效果图,以下图所示:
(日出模型效果图)
OK,咱们如今来具体看看如何使用RenderMonkey实现如上的效果。
咱们在上一篇(OpenGL ES 光照模型之——环境光照(RenderMonkey测试))的基础上,在RenderMonkey工程中加入三个变量:gDiffStrength、time和angles。具体操做以下:
其中:
gDiffStrength为模型公式中的Kd,是一个float类型的数据;
time和angles均为RenderMonkey与设置的float类型数据,且数据会在每一帧中会随时间从0至2π变化。
GPU的Vertex Shader代码实现以下:
//漫反射光照模型vertex shader示例代码 1.0 http://www.cnblogs.com/feng-sc/ uniform mat4 matViewProjection; attribute vec4 rm_Vertex; attribute vec2 rm_TexCoord0; attribute vec3 rm_Normal; //法线输入
varying vec2 rm_Texcoord; varying vec3 fNormal; uniform float angles; mat4 rotate(mat4 matrix, float a,vec3 v ) //矩阵旋转函数shader实现 { float c = cos(a); float s = sin(a); vec3 axis = normalize(v); vec3 temp = (1.0 - c) * axis; matrix[0][0] = c + temp[0] * axis[0]; matrix[0][1] = temp[0] * axis[1] + s * axis[2]; matrix[0][2] = temp[0] * axis[2] - s * axis[1]; matrix[0][3] = 0.0; matrix[1][0] = temp[1] * axis[0] - s * axis[2]; matrix[1][1] = c + temp[1] * axis[1]; matrix[1][2] = temp[1] * axis[2] + s * axis[0]; matrix[1][3] = 0.0; matrix[2][0] = temp[2] * axis[0] + s * axis[1]; matrix[2][1] = temp[2] * axis[1] - s * axis[0]; matrix[2][2] = c + temp[2] * axis[2]; matrix[2][3] = 0.0; matrix[3][0] = 0.0; matrix[3][1] = 0.0; matrix[3][2] = 0.0; matrix[3][3] = 1.0; return matrix; } void main( void ) { mat4 maxtrixWorld = mat4(1.0); maxtrixWorld = rotate(maxtrixWorld,angles * 10.0 ,vec3(0.0,1.0,0.0)); //定义模型矩阵,并使其围绕y轴旋转 gl_Position = (matViewProjection * maxtrixWorld * rm_Vertex); rm_Texcoord = rm_TexCoord0.xy; fNormal = (maxtrixWorld * vec4(rm_Normal,1.0)).xyz; //法线输出,必须与定点同样,通过模型矩阵变化 }
GPU的Fragment Shader实现代码以下:
//漫反射光照模型fragment shader示例代码 1.0 http://www.cnblogs.com/feng-sc/ #ifdef GL_FRAGMENT_PRECISION_HIGH // Default precision precision highp float; #else precision mediump float; #endif uniform sampler2D baseMap; uniform vec4 gAnbientColor; uniform float gAmbientStrength; uniform float gDiffStrength; uniform float time; varying vec2 rm_Texcoord; varying vec3 fNormal; vec4 AmbientColor() //计算环境光 { return gAnbientColor * gAmbientStrength; } vec4 DiffuseColor() //计算漫反射光 { //float diffFactor = max(dot(normalize(fNormal),normalize(vec3(sin(time * 10.0),0.0,cos(time * 10.0))) - vec3(0,0,0)),0.0); float diffFactor = max(dot(normalize(fNormal),vec3(0.0,0.0,1.0)),0.0); //定义光照方向为vec3(0.0,0.0,1.0),与法线求点积 return gAnbientColor * diffFactor * gDiffStrength; } void main( void ) { vec4 color = texture2D(baseMap,rm_Texcoord); vec4 ambientcolor = AmbientColor(); vec4 diffusecolor = DiffuseColor(); gl_FragColor = color * (ambientcolor + diffusecolor); //最后输出颜色为环境光颜色和漫反射光颜色相加,在与文理颜色作乘法混合 }
编译如上两段shader代码后,RenderMonkey场景中最终能够获得咱们刚开始是的显示效果图。
一样,本段内容咱们先来看下利用RenderMonkey实现的OpenGL ES Shader太阳围绕地球旋转的效果图:
(太阳围绕地球旋转的效果图)
GPU的Vertex Shader实现代码以下,与上一段落 (地球自转日出效果Shader实现)的Vertex Shader区别在于屏蔽掉了以下第8行地球自转的代码:
1 //漫反射光照模型,太阳围绕地球转 vertex shader示例代码 1.0 http://www.cnblogs.com/feng-sc/ 2 …… 3 …… 4 …… 5 void main( void ) 6 { 7 mat4 maxtrixWorld = mat4(1.0); 8 // maxtrixWorld = rotate(maxtrixWorld,angles * 10.0 ,vec3(0.0,1.0,0.0)); //定义模型矩阵,并使其围绕y轴旋转 9 gl_Position = (matViewProjection * maxtrixWorld * rm_Vertex); 10 rm_Texcoord = rm_TexCoord0.xy; 11 fNormal = (maxtrixWorld * vec4(rm_Normal,1.0)).xyz; //法线输出,必须与定点同样,通过模型矩阵变化 12 }
GPU的Fragment Shader实现代码以下,与上一段落 (地球自转日出效果Shader实现)的Fragment Shader区别在于屏蔽掉了以下第8行漫反射光照代码,而增长第7行。
第7行中的vec3(sin(time * 10.0),0.0,cos(time * 10.0)),根据time计算光源方向,time的变化范围为0至2π,所以,让光源方向围绕xz平面旋转,得:
x = sin(time)
y = 0
z = cos(time)
注:代码中的time*10中10没有特别意义,只是让光源方向移动得更快。
1 //漫反射光照模型,太阳围绕地球转 fragment shader示例代码 1.0 http://www.cnblogs.com/feng-sc/ 2 …… 3 …… 4 …… 5 vec4 DiffuseColor() //计算漫反射光 6 { 7 float diffFactor = max(dot(normalize(fNormal),normalize(vec3(sin(time * 10.0),0.0,cos(time * 10.0))) - vec3(0,0,0)),0.0); 8 //float diffFactor = max(dot(normalize(fNormal),vec3(0.0,0.0,1.0)),0.0); //定义光照方向为vec3(0.0,0.0,1.0),与法线求点积 9 return gAnbientColor * diffFactor * gDiffStrength; 10 } 11 12 …… 13 …… 14 ……