[GLSL] Simple Deferred Shader with mult light

Started by
5 comments, last by DavidTheFighter 6 years, 7 months ago

Hello, i would to have a simple deferred shader with many light source code.

I have read many tutorials but I could not understand.

I would like a tutorial that I could use as many lights as I want without declaring a constant with the amount of lights.

without 

I would like this effect (but without physical): 

 

maxresdefault.jpg

 

Thank :D

 

Advertisement
On 06/09/2017 at 10:36 AM, renanrosa said:

Hello, i would to have a simple deferred shader with many light source code.

I have read many tutorials but I could not understand.

I would like a tutorial that I could use as many lights as I want without declaring a constant with the amount of lights.

without 

I would like this effect (but without physical): 

 

maxresdefault.jpg

 

Thank

 

 

up

If you want an unlimited (well, not really, but still a LOT) number of lights, I'd look into shader storage buffers. You can specify an unsized array of light data, and just pass a uniform specifying the number of lights. Such as:


uniform int pointLightNumber;

struct PointLightData
{
	// blah blah blah lighting data
};

layout(std430, binding = 0) buffer pointLightArray
{
	PointLightData pointLights[];
};

It does require OpenGL 4.3, however. Also, if you are using a deferred renderer and really want to squeeze some performance out, I'd recommend also looking into tiled deferred lighting. It essentially splits the screen into a grid of tiles, and each tile does a frustum check to see if a point light is in visible in that portion of the screen. If it is, the shader will do the calculations for it, if not, it'll skip it. This way you don't calculate lighting for every light in the scene, even if it's not visible in that portion of the screen. Although if you're not looking for extreme performance, or just want to start out simple and get a lighting system going, I wouldn't worry about this for now.

Here's an article on storage buffers: https://www.khronos.org/opengl/wiki/Shader_Storage_Buffer_Object

do you have a sample with source code?

On 09/09/2017 at 4:11 PM, DavidTheFighter said:

If you want an unlimited (well, not really, but still a LOT) number of lights, I'd look into shader storage buffers. You can specify an unsized array of light data, and just pass a uniform specifying the number of lights. Such as:



uniform int pointLightNumber;

struct PointLightData
{
	// blah blah blah lighting data
};

layout(std430, binding = 0) buffer pointLightArray
{
	PointLightData pointLights[];
};

It does require OpenGL 4.3, however. Also, if you are using a deferred renderer and really want to squeeze some performance out, I'd recommend also looking into tiled deferred lighting. It essentially splits the screen into a grid of tiles, and each tile does a frustum check to see if a point light is in visible in that portion of the screen. If it is, the shader will do the calculations for it, if not, it'll skip it. This way you don't calculate lighting for every light in the scene, even if it's not visible in that portion of the screen. Although if you're not looking for extreme performance, or just want to start out simple and get a lighting system going, I wouldn't worry about this for now.

Here's an article on storage buffers: https://www.khronos.org/opengl/wiki/Shader_Storage_Buffer_Object

Thank you for your reply.

but using this code, how would you do it in C ++ to set various lights?
I would not want to use an array of lights in GLSL:
PointLightData pointLights [];
it's possible ?

If you're going for an "unlimited" number of lights, I'd set up a vector of point lights in C++. Something like std::vector<PointLightData>, with PointLightData being a struct holding the data for each light. You can add or remove lights from it, and update the contents whenever you want. You'd then pass the data of this vector to the shader storage buffer object each frame, with a glBufferData call. Because the array in GLSL is unsized, there's no hard limit to how many point lights you can add, except for hardware limitations (which I doubt you'll reach). As long as the SSBO is backed by data uploaded in C++ from glBufferData(), it's all valid. Some C++ pseudo-code would go something like this:


struct PointLight
{
	vec3 position;
	// whatever other data you want
};

std::vector<PointLight> scenePointLights;
  
void mainLoop()
{
	updatePointLights(); // do whatever logic like physics
	uploadPointLightData(); // call glBufferData() with the data from scenePointLights
	renderScene();
}

An the GLSL pseudo:


struct PointLight
{
	vec3 position;
	// whatever other data
};

 layout(std430, binding = 0) buffer pointLights
 {
     PointLight pointLightData[]; // scenePointLights.data()
 };

uniform int numPointLights; // scenePointLights.size()

void main()
{
	for (int i = 0; i < numPointLights; i ++)
    {
		PointLight p = pointLights.pointLightData[i];
      
    	// Do whatever lighting code
    }
}

This is obviously a little simplified, but it's the basic idea on how to do it. I'd suggest doing a bit of Googling to figure out exactly how all of these work, though. The link I posted earlier shows a few more examples, too.

This topic is closed to new replies.

Advertisement