如何使用从 fragcoord 到灯光位置的距离在 GLSL 中制作自定义灯光形状

How to make custom light shape in GLSL using distance from fragcoord to light postion

我在 shader toy 中阅读了一个 2d light shader,它可以用来创建 2d(点)光。 https://www.shadertoy.com/view/4dfXDn

vec4 drawLight(vec2 p, vec2 pos, vec4 color, float range)
    {
        float ld = length(p - pos);  
        if (ld > range) return vec4(0.0);
        float fall = (range - ld)/range;
        fall *= fall;
        return (fall) * color;
    }

void main() {
    vec2 p = gl_FragCoord.xy;
    vec2 c = u_resolution.xy / 2.0;

    vec4 col = vec4(0.0);

    vec2 lightPos = vec2(c);
    vec4 lightCol = vec4(1.000,0.25,0.000,1.000);

    col += drawLight(p, lightPos, lightCol, 400.0);

    gl_FragColor = col;
}

但是,我不知道如何使用它制作另一个 "shape" 光? 如何修改 drawLight 函数使其具有另一个参数来修改原始光,例如 1.0 是整圈光,0.25 是四边形光?

在您的代码中

float ld = length(p - pos);

在所有方向上均匀地计算您与光的距离(欧氏距离)。如果你想要不同的阴影改变等式...

例如,您可以像这样计算到多边形光的最小垂直距离:

顶点:

// Vertex
#version 420 core
layout(location=0) in vec2 pos;     // glVertex2f <-1,+1>
layout(location=8) in vec2 txr;     // glTexCoord2f  Unit0 <0,1>
out smooth vec2 t1;                 // fragment position <0,1>
void main()
    {
    t1=txr;
    gl_Position=vec4(pos,0.0,1.0);
    }

片段:

// Fragment
#version 420 core
uniform sampler2D txrmap;   // texture unit
uniform vec2 t0;            // mouse position <0,1>
in smooth vec2 t1;          // fragment position <0,1>
out vec4 col;

// light shape
const int n=3;
const float ldepth=0.25;    // distance to full disipation of light
const vec2 lpolygon[n]=     // vertexes CCW
    {
    vec2(-0.05,-0.05),
    vec2(+0.05,-0.05),
    vec2( 0.00,+0.05),
    };
void main()
    {
    int i;
    float l;
    vec2 p0,p1,p,n01;
    // compute perpendicular distance to edges of polygon
    for (p1=vec2(lpolygon[n-1]),l=0.0,i=0;i<n;i++)
        {
        p0=p1; p1=lpolygon[i];          // p0,p1 = edge of polygon
        p=p1-p0;                        // edge direction
        n01=normalize(vec2(+p.y,-p.x)); // edge normal CCW
//      n01=normalize(vec2(-p.y,+p.x)); // edge normal CW
        l=max(dot(n01,t1-t0-p0),l);
        }
    // convert to light strength
    l = max(ldepth-l,0.0)/ldepth;
    l=l*l*l;
    // render
//  col=l*texture2D(txrmap,t1);
    col = l*vec4(1.0,1.0,1.0,0.0);
    }

我使用类似的代码 作为起点,因此变量名称略有不同。

这个想法是计算片段到你的光形状所有边缘的垂直距离,并选择最大的一个,因为其他的都面向错误的一侧。

lpolygon[n] 是光相对于光位置的形状 t0t1 是片段位置。它必须是逆时针绕组,否则你需要 否定正常计算(我的视图被翻转所以它可能看起来是 CW 但不是)。我使用范围 <0,1> 因为你可以直接使用它作为纹理坐标...

此处截图:

这里有一些解释:

对于分析形状,您需要使用分析距离计算...