Jump to content
  • Advertisement
WhiskyAndCode

OpenGL FrameBuffer / Multi light

Recommended Posts

Advertisement
On 11/26/2018 at 7:50 PM, WhiskyAndCode said:

the author leaves fixed the amount of light (32 lights)

This is just a tutorial, meaning that the purpose is only to show how to do some particular technics.

1 hour ago, WhiskyAndCode said:

Yeah, I've been looking for this for at least 6 months.

Why not sending an uniform to GL that will represent the number of active lights in your current scene ?

Share this post


Link to post
Share on other sites
Just now, _Silence_ said:

 

Why not sending an uniform to GL that will represent the number of active lights in your current scene ?

Hi _Silence_, thank u for reply.

Because my project will have countless sources of lights, the weapons will be laser-type and the players will be able to shoot fire (there's fire light too), put up campfires. That is, I will focus a lot on lighting.

 

Share this post


Link to post
Share on other sites

..You use the G buffers to store normals and all that stuff needed for lighting, then for each light you render either a mesh that represents it (scaled unit sphere for point lights etc), or you can calculate 2d screen coords and render simple quads or something else... But no matter how you do it, the lighting shader reads from the G buffers and outputs using additive blend. Then you can render as many lights as you want to, and I suppose you should output to a 16 bit/channel output buffer and do some HDR/tonemapping to bring it down to 0..1 intensity. You can do a fullscreen quad pass to add ambient light, since that shouldn't be added for each light, but only once.

 

Share this post


Link to post
Share on other sites
3 hours ago, WhiskyAndCode said:

Because my project will have countless sources of lights, the weapons will be laser-type and the players will be able to shoot fire (there's fire light too), put up campfires. That is, I will focus a lot on lighting.

Actually @_Silence_ was giving you a very helpful piece of advice and what you will actually have to do.  Which is send how many lights you have in that scene to the shader for rendering.  Your program (game) will have to know how many lights you are going to render and so will your shader.  They used a fixed amount as he said for the demo, as it is merely that, a demo.  Sounds like you might be better off using an existing engine like Unreal or Unity.

Share this post


Link to post
Share on other sites

What vinterberg told is what should be done when doing deferred rendering with many lights. You'll however have to optimize a lot in order to avoid to compute where a light does not cast and adapt your shader.

Share this post


Link to post
Share on other sites

This is, essentially, what you should be doing! There is no limit to the number of lights you can draw in deferred rendering, but there is a cost to draw them (very cheap shader), the final lighting computation works per pixel on the result of ALL lighting, not per light, so costs for drawing lights are relatively low! We can have hundreds, or thousands of lights, per frame. The next bottleneck is materials.

Share this post


Link to post
Share on other sites
On 11/26/2018 at 10:50 AM, WhiskyAndCode said:

Hey guys, thank u for all reply.

English is not my native language and I find it difficult to express myself.
But come on, following the learnopengl tutorial:
https://learnopengl.com/Advanced-Lighting/Deferred-Shading
the author leaves fixed the amount of light (32 lights) as shown by the GLSL:


#version 330 core
out vec4 FragColor;
  
in vec2 TexCoords;

uniform sampler2D gPosition;
uniform sampler2D gNormal;
uniform sampler2D gAlbedoSpec;

struct Light {
    vec3 Position;
    color;
};
const int NR_LIGHTS = 32;
uniform Light lights [NR_LIGHTS];
uniform vec3 viewPos;

void main ()
{
    // retrieve data from G-buffer
    vec3 FragPos = texture (gPosition, TexCoords) .rgb;
    vec3 Normal = texture (gNormal, TexCoords) .rgb;
    vec3 Albedo = texture (gAlbedoSpec, TexCoords) .rgb;
    float Specular = texture (gAlbedoSpec, TexCoords) .a;
    
    // then calculate lighting as usual
    vec3 lighting = Albedo * 0.1; // hard-coded ambient component
    vec3 viewDir = normalize (viewPos - FragPos);
    for (int i = 0; i <NR_LIGHTS; ++ i)
    {
        // diffuse
        vec3 lightDir = normalize (lights [i] .Position - FragPos);
        vec3 diffuse = max (dot (Normal, lightDir), 0.0) * Albedo * lights [i] .Color;
        lighting + = diffuse;
    }
    
    FragColor = vec4 (lighting, 1.0);
}


And when it comes to applying the lights:


glBindFramebuffer (GL_FRAMEBUFFER, 0);

        // 2. lighting pass: calculate lighting by iterating over screen filled quad pixel-by-pixel using the gbuffer's content.
       
        glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        shaderLightingPass.use ();
        glActiveTexture (GL_TEXTURE0);
        glBindTexture (GL_TEXTURE_2D, gPosition);
        glActiveTexture (GL_TEXTURE1);
        glBindTexture (GL_TEXTURE_2D, gNormal);
        glActiveTexture (GL_TEXTURE2);
        glBindTexture (GL_TEXTURE_2D, gAlbedoSpec);
        // send light relevant uniforms
        for (unsigned int i = 0; i <lightPositions.size (); i ++)
        {
            shaderLightingPass.setVec3 ("lights [" + std :: to_string (i) + "] .Position", lightPositions [i]);
            shaderLightingPass.setVec3 ("lights [" + std :: to_string (i) + "] .Color", lightColors [i]);
            // update attenuation parameters and calculate radius
            const float constant = 1.0; // note that we do not send this to the shader, we assume it is always 1.0 (in our case)
            const float linear = 0.7;
            const float quadratic = 1.8;
            shaderLightingPass.setFloat ("lights [" + std :: to_string (i) + "] .Linear", linear);
            shaderLightingPass.setFloat ("lights [" + std :: to_string (i) + "] .Quadratic", quadratic);
        }
        shaderLightingPass.setVec3 ("viewPos", camera.Position);
        // finally render quad
        renderQuad ();

 

The tutorial can be tweaked to greatly increase the number of lights.
Set NR_LIGHTS to some high value like 512, this is now your "maximum number" of lights on screen.

Then pass in a uniform for the number of active lights, the shader will exit the for loop. There's no need to render geometry per light, that makes it more complicated. This does a single pass that loops over all of your lights per pixel. 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!