“This is the 23rd day of my participation in the First Challenge 2022. For details: First Challenge 2022”

Principle of internal luminescence

The simple principle of internal luminescence is as follows: sampling the alpha of surrounding pixels and taking the average stacking effect. It may seem very simple in summary, but it requires a certain amount of understanding and digestion. The luminous object can be regarded as a circular object to collect the pixel value around the circular object. For example, given that the radius of the circle is R and the Angle is Angle, the current pixel coordinate position is deduced according to the radius and Angle, and the transparency is obtained by the current pixel coordinate position before calculation.

But it seems to have been introduced in the shadow mask effect that can also pass. The difference is that shadow shading uses the circle drawing to render outwards while the inner glow effect works inwards.

Luminator implementation

First, RGB overlay is realized by drawing a circle. You can see that the center is darker where the circle is drawn, and the color is dimming as it spreads out. It’s not going to work but we know what to do next.

void main() {
    vec2 uv = gl_FragCoord.xy / iResolution.xy;
    uv -= 0.5;
    uv.x *= iResolution.x/iResolution.y; 
    vec3 color = vec3(0.);
    float glow = length(uv);
    color += glow;
    gl_FragColor = vec4(color,1.);
}
Copy the code

By taking the opposite operation, you can divide by a numberlength(uv)Let’s multiply by a decimal to reduce the value a little bit. The desired effect can be seen in the final result. The comparison of the previous effect shows that division is equivalent to taking the reverse of the original result. The original internal value is the minimum, and the internal value becomes the maximum after division.

void main() {
    vec2 uv = gl_FragCoord.xy / iResolution.xy;
    uv -= 0.5;
    uv.x *= iResolution.x/iResolution.y; 
    vec3 color = vec3(0.);
    float glow = 0.05 * 3./length(uv);
    color += glow;
    gl_FragColor = vec4(color,1.);
}
Copy the code

However, the transition effect whitening range seems to be too large to continue to optimize the original algorithm. increasepowThe method makes the number smaller.

float getGlow(float dist, float radius, float intensity){
    return pow(radius/dist, intensity);
}

void main() {
    vec2 uv = gl_FragCoord.xy / iResolution.xy;
    uv -= 0.5;
    uv.x *= iResolution.x/iResolution.y; 
    vec3 color = vec3(0.);
    float glow = 0.05 * getGlow(length(uv), 1..2.);
    color += glow;
    gl_FragColor = vec4(color,1.);
}
Copy the code

Extension effect

Small sun

Change the luminous position and luminous color to simulate the effect of solar illumination.

float getGlow(float dist, float radius, float intensity){
    return radius/dist;
}

void main() {
    vec2 uv = gl_FragCoord.xy / iResolution.xy;
    vec3 color = vec3(0.);

    vec2 uv2 = uv;
    uv2 -=1.0;
    float glow = 0.09 * 3./length(uv2);
    color += (5.0 * vec3(0.02 * glow) + vec3(0.9686.0.6941.0.0) * glow);
    gl_FragColor = vec4(color,1.);
}
Copy the code

Light moving effect

float getGlow(float dist, float radius, float intensity){
    return radius/dist;
}

void main() {
    vec2 uv = gl_FragCoord.xy / iResolution.xy;
    vec3 color = texture(iChannel1,uv).rgb;

    float position = sin(iTime) / 2.;
    vec2 uv2 = uv;
    uv2 -=0.5;
    uv2.x *= iResolution.x/iResolution.y; 
    uv2 += position;
    float glow = 0.09 * 3./length(uv2);
    color += (5.0 * vec3(0.02 * glow));
    gl_FragColor = vec4(color,1.);
}
Copy the code