内容简介:OpenGL(十二) 光源类型 平行光 、 点光源 、 聚光灯 的实现
常规的 光源类型 有三种。最简单的自然是平行光。稍复杂些的为点光源,最复杂的为聚光灯。总体说来,在可编程管线中原理是一样的。在OpenGL代码中传入必要的参数,在shader中进行相关的计算绘制出效果。本文分别介绍三种效果的shader实现。
平行光
平行光我们已经写的轻车熟路了。它只需要一个光源方向就够了。通常我们会定义一个光源点,它与坐标轴原点的连线就是光线方向。
//GL Code float lightPos[] = { 0.0f,1.5f,0.0f,0.0f }; float diffuseLightColor[] = { 1.0f,1.0f,1.0f,1.0f }; glUniformMatrix4fv(gpuProgram.GetLocation("M"), 1,GL_FALSE, glm::value_ptr(model)); glUniformMatrix4fv(gpuProgram.GetLocation("V"), 1, GL_FALSE, identity); glUniformMatrix4fv(gpuProgram.GetLocation("P"), 1, GL_FALSE, glm::value_ptr(projectionMatrix)); glUniformMatrix4fv(gpuProgram.GetLocation("NM"), 1, GL_FALSE, glm::value_ptr(normalMatrix)); glUniform4fv(gpuProgram.GetLocation("U_LightPos"), 1, lightPos); glUniform4fv(gpuProgram.GetLocation("U_DiffuseLightColor"), 1, diffuseLightColor); //fs void main(){ //... vec3 n = normalize(V_Normal); vec3 L = U_LightPos.xyz; float diffuseIntensity=max(0.0,dot(L,n)); vec4 diffuseColor=U_DiffuseLightColor*diffuseIntensity; //... gl_FragColor=ambientColor+diffuseColor; }
获取的光线方向直接与法线点乘,即为光照强度。
点光源
在平行光的基础上,根据模型与光源之间的距离进行衰减。衰减为与距离相关的二次函数。因此需要加入三个因数,分别为 expFactor
、 linearFactor
、 constantFactor
。
//GL Code float constantFactor = 1.0; float linearFactor = 0.2; float expFactor=0.0; glUniform1f(gpuProgram.GetLocation("U_ConstantFactorn"), 1, constantFactor); glUniform1f(gpuProgram.GetLocation("U_LinearFactor"), 1, linearFactor); glUniform1f(gpuProgram.GetLocation("U_ExpFactor"), 1, expFactor); //fs float attenuation = 1.0; void main(){ //... vec3 n = normalize(V_Normal); vec3 L = U_LightPos.xyz - V_WorldPos; float distance = length(L); attenuation = 1.0/(U_ExpFactor*distance*distance + U_LinearFactor*distance + U_ConstantFactor); float diffuseIntensity = max(0.0,dot(L,n)); vec4 diffuseColor = U_DiffuseLightColor*attenuation*diffuseIntensity; //... gl_FragColor=ambientColor+diffuseColor; }
聚光灯
在点光源的基础上,添加一个带角度的锥形区域的检测。只有在区域内的部分才有照亮处理。因此需要传入shader两个参数,分别为光照方向和范围角度。
//GL Code //... float spotLightDirection[] = { 0.0f,-1.0f,0.0f,128.0f }; float spotLightCutoff = 15.0f; glUniform1f(gpuProgram.GetLocation("U_Cutoff"), spotLightCutoff); glUniform4fv(gpuProgram.GetLocation("U_LightDirection"), 1, spotLightDirection); //... //fs float attenuation = 1.0; void main(){ //... float radianCutoff = U_Cutoff*3.14/180; float cosThta = cos(radianCutoff); vec3 spotLightDirection = normalize(U_LightDirection.xyz); vec3 n = normalize(V_Normal); vec3 L = U_LightPos.xyz - V_WorldPos; float distance = length(L); attenuation = 1.0/(U_ExpFactor*distance*distance + U_LinearFactor*distance + U_ConstantFactor); float currentCosThta=max(0.0,dot(-L,spotLightDirection)); float diffuseIntensity = 0.0; if(currentCosThta > cosThta) { if(dot(L,n) >0.0) { diffuseIntensity = pow(currentCosThta,U_LightDirection.w); } } vec4 diffuseColor = U_DiffuseLightColor*attenuation*diffuseIntensity; //... gl_FragColor=ambientColor+diffuseColor; }
总结
以上为三种光源的OpenGL实现,可以看出,计算量最大的为聚光灯效果,而且为了让边缘柔和,需要pow的大量计算。移动端跑实时运算估计要优化算法了。
本文出自松阳论道 转载必须注明出处
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
推荐系统与深度学习
黄昕、赵伟、王本友、吕慧伟、杨敏 / 清华大学出版社 / 2019-1-1 / 65.00元
本书的内容设置由浅入深,从传统的推荐算法过渡到近年兴起的深度学习技术。不管是初学者,还是有一定经验的从业人员,相信都能从本书的不同章节中有所收获。 区别于其他推荐算法书籍,本书引入了已被实践证明效果较好的深度学习推荐技术,包括Word2Vec、Wide & Deep、DeepFM、GAN 等技术应用,并给出了相关的实践代码;除了在算法层面讲解推荐系统的实现,还从工程层面详细阐述推荐系统如何搭建.一起来看看 《推荐系统与深度学习》 这本书的介绍吧!