Hello. I have a problem I've been trying to fix for about 2 weeks but couldn't find anything that would help me.
Everything started when I stumbled upon a 2D light shader that works flawlessly and does everything I want it to (which is basically creating these cool point lights):
#version 450
uniform vec2 lightPos;
uniform vec3 lightColor;
uniform float intensity;
out vec4 color;
void main()
{
vec3 lAtt = vec3(0.01, 0.1, 0.00001);
float dist = distance(gl_FragCoord.xy, lightPos.xy);
float att = 1.0 / (lAtt.x + lAtt.y * dist + lAtt.z * dist * dist);
vec4 finLight = vec4(vec3(att) * lightColor, 1.0) * intensity;
color = finLight;
}
How I drew these lights was pretty simple: I rendered every single object in the scene and used this shader on a render texture, which I found out to be very efficient because I'm applying the light only once for each frame and not for every object for each frame.
However, that was not something I wanted in the long run due to the fact that it only worked for ONE light but since I'm in development of a game that obviously requires more than one light (particles, lights around objects, etc.) and so I started to look for a better solution than this.
The first thing I came up with is a buffed version of this shader which allowed me to render up to 256 lights and which worked pretty well (and was WAY more efficient with rendering a hundred lights in comparison to the next version of it which I'll explain in a moment):
#version 450
struct Light
{
vec2 position;
vec3 color;
float intensity;
};
uniform int lightCount;
uniform Light lights[256];
uniform sampler2D texture;
uniform vec2 size;
out vec4 clr;
void main()
{
vec3 lAtt = vec3(0.0001, 0.0001, 0.001);
vec2 uv = gl_FragCoord.xy;
vec4 outc = vec4(0.0);
for (int i = 0; i < lightCount; i++)
{
float dist = distance(lights[i].position, uv);
float att = 1.0 / (lAtt.x + lAtt.y * dist + lAtt.z * dist * dist);
outc += vec4(vec3(att), 1.0) * lights[i].intensity * vec4(lights[i].color, 1.0);
}
vec4 pixel = texture2D(texture, uv / size);
clr = pixel * outc;
}
So everything was fun and all, but this solution seems to be hated all over the internet since I'm passing HUGE amounts of data to the shader (which I heard is not recommended) and it still had a light limit which I did not like because it's obvious that for many particles or huge maps this is a real pain in the .... .
So I kept looking for solutions, and found one that, yes, allowed me to draw as many lights as I wanted, but on the other hand used a TON of resources of my GPU (GTX 1070).
How it worked was simple: I used the first version of the lighting shader, but used this shader multiple times in this manner:
pseudocode:
for each object:
draw every object to a rendertexture
for each light:
draw each light to another render texture with the lighting shader and add up the results with additive blending
multiply the lights' and the scene's texture to achieve a lit scene
draw the lit scene
So, now, here's my question: what did I do wrong? How can I improve this so it can render even 10,000 lights?
Any help is appreciated!