You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 00:27:04