cocos2D-X源码分析之从cocos2D-X学习OpenGL(17)----发光体

      cocos引擎支持四种发光体:环境光,方向光,点光源和聚光灯,上一篇已经介绍了基本光照模型,其中也介绍了环境光的算法,下面就介绍另外三种光源。


       当一个光源很远的时候,来自光源的每条光线接近于平行,这看起来像是来自于同一个方向,比如太阳由于离我们无限远,所以太阳光被定义为平行光,因为所有的光线都是平行的,对场景中每个物体的光都保持一致,光照计算会和场景中的其他物体相似。

       点光是一个有位置的光源,它向所有方向发光,光线随着距离增加逐渐变暗。灯泡和火炬就是这样的点光。


     点光源的计算方式和之前的方向光使用同一个函数,只是加入了一个调整的参数,代码如下:

vec3 computeLighting(vec3 normalVector, vec3 lightDirection, vec3 lightColor, float attenuation)
{
    float diffuse = max(dot(normalVector, lightDirection), 0.0);
    vec3 diffuseColor = lightColor  * diffuse * attenuation;
    
    return diffuseColor;
}
for (int i = 0; i < MAX_POINT_LIGHT_NUM; ++i)

{
    vec3 ldir = v_vertexToPointLightDirection[i] * u_PointLightSourceRangeInverse[i];
    float attenuation = clamp(1.0 - dot(ldir, ldir), 0.0, 1.0);
    combinedColor.xyz += computeLighting(normal, normalize(v_vertexToPointLightDirection[i]), u_PointLightSourceColor[i], attenuation);
}
       添加的这个attenuation参数使用的是点光的位置乘以点光源范围的倒数,然后用1减去这个值得平方,最后获得0到1之间的attenuation参数,最后在computeLighting函数中传入这个attenuation参数,这个值其实是点光源在它的范围内的衰减值。

auto pointLight = static_cast<PointLight *>(light);
Mat4 mat= pointLight->getNodeToWorldTransform();
const Color3B &col = pointLight->getDisplayedColor();
//光的颜色
_pointLightUniformColorValues[enabledPointLightNum].set(col.r / 255.0f * intensity, col.g / 255.0f * intensity, col.b / 255.0f * intensity);
//光的位置
_pointLightUniformPositionValues[enabledPointLightNum].set(mat.m[12], mat.m[13], mat.m[14]);
//光范围的倒数
_pointLightUniformRangeInverseValues[enabledPointLightNum] = 1.0f / pointLight->getRange();
++enabledPointLightNum;
       聚光灯是一种位于环境某处的光源,不是向所有方向,只有某个方向会被照亮,如图所示,聚光灯通过切光角表示:



       由于如果我们在聚光灯的边界“一刀切”的话,这种转变过于强烈,所以聚光灯一般用两个角度表示,一个是内角一个外角,在这两个角度之间是线性逐步减小,cocos2d也采用这种方式处理聚光灯

//计算范围精度值
vec3 ldir = v_vertexToSpotLightDirection[i] * u_SpotLightSourceRangeInverse[i];
float attenuation = clamp(1.0 - dot(ldir, ldir), 0.0, 1.0);
vec3 vertexToSpotLightDirection = normalize(v_vertexToSpotLightDirection[i]);

vec3 spotLightDirection = normalize(u_SpotLightSourceDirection[i] * 2.0);

//计算光线方向和点方向之间的夹角
float spotCurrentAngleCos = dot(spotLightDirection, -vertexToSpotLightDirection);

//在内角外角之间
attenuation *= smoothstep(u_SpotLightSourceOuterAngleCos[i], u_SpotLightSourceInnerAngleCos[i], spotCurrentAngleCos);
attenuation = clamp(attenuation, 0.0, 1.0);
combinedColor.xyz += computeLighting(normal, vertexToSpotLightDirection, u_SpotLightSourceColor[i], attenuation);
       聚光灯的attenuation精度值包括点光源的范围精度值以及在内外角之间的衰减值,两个值相乘,在固定在0到1的范围之间就得到聚光灯的精度值,最后在传入到计算光照的函数里得到聚光灯对于光照的影响值


        能力不足,水平有限,如有错误,欢迎指出。


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值