如何创建2D聚光灯?怎样修改现有全方向光照算法实现该效果?
2D聚光灯效果修改方案
完全可以实现,只需要在原有全向光照逻辑基础上增加聚光角度校验逻辑即可,具体修改如下:
第一步:扩展Light结构体参数
在现有Light结构体中新增3个聚光灯专属参数:
uniform struct Light { vec4 colour; vec3 position; vec2 radius; float intensity; // 新增聚光灯参数 vec2 direction; // 聚光灯朝向,需要提前归一化 float cutoffHalfAngle; // 聚光灯半开角,单位为弧度 float edgeSoftness; // 聚光灯边缘软过渡系数,取值0~1 } allLights[MAX_LIGHTS];
第二步:修改calculateLight计算逻辑
在原有距离衰减逻辑之前,新增片段是否在聚光范围内的判断:
vec4 calculateLight(Light light) { float aspectRatio = resolution.x / resolution.y; // 注:你原有代码里两个分支逻辑一致,属于逻辑bug,可根据需求调整成正确的宽高比适配逻辑 if (aspectRatio > 1.0) light.radius.x /= aspectRatio; else light.radius.y *= aspectRatio; vec2 lightDir = fragmentPosition.xy - light.position.xy; float lightDistance = length(lightDir); if (length(lightDir / light.radius) >= 1.0) return vec4(0, 0, 0, 1); // 新增聚光灯角度判断逻辑 vec2 normalizedLightDir = normalize(lightDir); // 计算片段方向和聚光朝向的点积,等于夹角的余弦值 float angleCos = dot(normalizedLightDir, normalize(light.direction)); float cutoffCos = cos(light.cutoffHalfAngle); float minCutoffCos = cutoffCos * (1.0 - light.edgeSoftness); // 角度超出聚光范围直接返回黑色 if(angleCos < minCutoffCos) return vec4(0, 0, 0, 1); // 计算边缘软过渡系数 float angleAttenuation = smoothstep(minCutoffCos, cutoffCos, angleCos); return light.intensity * angleAttenuation * (1 - length(lightDir / light.radius)) * light.colour; }
参数调整说明
cutoffHalfAngle为聚光灯的半开角,例如要实现总开角60度的聚光灯,传入π/6即可edgeSoftness控制边缘过渡效果,设为0时是完全硬边的聚光效果,数值越大边缘越柔和,建议取值范围0~0.5
内容的提问来源于stack exchange,提问作者tomatto
相关产品推荐
相关产品推荐

