Search code examples
javaopenglglsllwjgl

Drawing 2d lights using Shaders?


I was wondering how I could create 2D lights like here:

https://www.youtube.com/watch?v=mVlYsGOkkyM

And here:

https://www.youtube.com/watch?v=nSf1MpsWKig

The shadows aren't currently in my interest. I tried some things but they don't seem to work. So all I currently have is the fragment and the vertex shader with hardly any stuff in it.


Solution

  • Lighting is pretty much the main problem of computer graphics and there are several commonly used ways of achieving lights:

    The simpler but limited way is called "foward shading" and the general idea is that you give all the information about lighting (ambient light, light positions and colors ect.) to the shader that renders your geometry and the lighting is computed directly on each surface you render. The limitation is that you can only pass fixed number of lights to the shader.

    The other way is called "deferred shading" and it is commonly used in modern game engines. Instead of lighting the geometry when you render it you only collect the relevant data for each pixel of the geometry (position, color, normal ect.) and store it in a framebuffer. Then you can use the data to render as many lights as you want. OGLdev has a nice tutorial for deferred shading, but if you are a beginner you probably want to avoid it as it is quite difficult to set up and is slow on old hardware. http://ogldev.atspace.co.uk/www/tutorial35/tutorial35.html

    Also the general lighting formula in GLSL is:

    // Vector from the current pixel to the light
    vec3 toLight = (lightpos - pixelpos);
    
    // This computes how much is the pixel lit based on where it faces
    float brightness = clamp(dot(normalize(toLight), pixelnormal), 0.0, 1.0);
    
    // If it faces towards the light it is lit fully, if it is perpendicular
    // to the direction towards the light then it is not lit at all.
    
    // This reduces the brightness based on the distance form the light and the light's radius
    brightness *= clamp(1.0 - (length(toLight) / lightradius), 0.0, 1.0);
    // The final color of the pixel.
    vec3 finalcolor = pixelcolor * lightcolor * brightness;
    // If you have multiple lights multiply the pixel's color by the combined color of all lights
    // like:
    finalcolor = pixelcolor * (lightcolor1 * brightness1 + lightcolor2 * brightness2);
    
    // Note that some things are clamped to avoid going into negative values