加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-14 17:05:38 所属栏目:百科 来源:网络整理
导读:cocos引擎支持四种发光体:环境光,方向光,点光源和聚光灯,上一篇已经介绍了基本光照模型,其中也介绍了环境光的算法,下面就介绍另外三种光源。 当一个光源很远的时候,来自光源的每条光线接近于平行,这看起来像是来自于同一个方向,比如太阳由于离我们

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


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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读