OpenGL(十二) 光源类型 平行光 、 点光源 、 聚光灯 的实现

栏目: 编程工具 · 发布时间: 7年前

内容简介: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;
}
 
 

获取的光线方向直接与法线点乘,即为光照强度。

点光源

在平行光的基础上,根据模型与光源之间的距离进行衰减。衰减为与距离相关的二次函数。因此需要加入三个因数,分别为 expFactorlinearFactorconstantFactor

//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的大量计算。移动端跑实时运算估计要优化算法了。

OpenGL(十二) 光源类型 平行光 、 点光源 、 聚光灯 的实现

本文出自松阳论道 转载必须注明出处


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

UML基础、案例与应用

UML基础、案例与应用

施穆勒 / 李虎、赵龙刚 / 人民邮电出版社 / 2004-7-1 / 42.00元

本书教读者循序渐进地、系统地学习UML基础知识和应用技术。和前一版相比,本书内容根据UML 2.0进行了补充和更新,随书光盘包含了建模工具Poseidon的试用版。 全书分为三部分24章。第一部分“基础知识”包括第1章到第15章,主要是介绍UML语言的基础知识以及面向对象的概念和思想,还简单介绍了UML在开发过程的应用方法。第二部分“学习案例”包括第16章到第22章,结合实例详细分析了UML的应用......一起来看看 《UML基础、案例与应用》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

MD5 加密
MD5 加密

MD5 加密工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具