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

时间:2023-02-07 23:33:56

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

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

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

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

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

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

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-X源码分析之从cocos2D-X学习OpenGL(17)----发光体

       由于如果我们在聚光灯的边界“一刀切”的话,这种转变过于强烈,所以聚光灯一般用两个角度表示,一个是内角一个外角,在这两个角度之间是线性逐步减小,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的范围之间就得到聚光灯的精度值,最后在传入到计算光照的函数里得到聚光灯对于光照的影响值


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