如何在片段着色器中将圆形点光源调整为椭圆形/椭圆?
实现椭圆形点光源的修改方案
结论
完全可以基于你现有的代码实现,仅需要调整距离判断的计算逻辑即可。
原代码问题
你当前的逻辑仅使用了radius参数的x分量,相当于y方向作用半径和x方向完全一致,最终呈现正圆形的光源范围,没有用到vec2类型radius的y分量能力。
实现原理
正圆形的距离判断是基于标准欧氏距离:$\sqrt{(x-x_0)^2 + (y-y_0)^2} \leq r$
而轴对齐的椭圆形距离判断只需要把两个方向的偏移量分别除以对应方向的半径,再计算长度即可:$\sqrt{(\frac{x-x_0}{r_x})^2 + (\frac{y-y_0}{r_y})^2} \leq 1$,满足该条件的点就在椭圆范围内。
修改后的代码
uniform struct Light { vec4 colour; vec3 position; vec2 radius; float intensity; } allLights[MAX_LIGHTS]; vec4 calculateLight(Light light) { vec2 lightDir = fragmentPosition.xy - light.position.xy; // 对xy方向分别按对应半径做归一化 vec2 scaledDir = lightDir / light.radius; float normalizedDistance = length(scaledDir); if (normalizedDistance >= 1.0) { return vec4(0, 0, 0, 1); // 超出椭圆范围返回黑色 } // 衰减逻辑直接使用归一化后的距离计算即可 return light.intensity * (1.0 - normalizedDistance) * light.colour; }
拓展说明
- 如果你需要实现任意角度旋转的椭圆形光源,只需要在计算
scaledDir之前,先对lightDir应用对应角度的二维旋转矩阵即可 - 该方案的性能开销和原代码几乎一致,没有增加过多的计算量
内容的提问来源于stack exchange,提问作者tomatto
相关产品推荐
相关产品推荐

