# Basic 2D Lighting Optimization Issue in Fragment Shader with OpenGL (GLSL)

I'm using a fragment shader to implement 2D lighting (code further below). Even though I am satisfied with the visuals of the light i noticed that it has a quite big GPU usage, and when trying to add about 40+ light sources the usage is close to 100% (GTX 1050).

I have a uniform array of structs that contain data about each light source and for loop that goes through all of them.

At first I thought I was pushing too much data to the GPU so I combined the RGB values of the light color in a single 32 bit integer and the two strengths of the light in a single 32 bit integer as well. Then I tried simplifying the formulas I used (using a composed, by composed I'm not referring to the operation, function from multiple linear functions) but it seemed that just made the matters worse.

I think it's worth noting the difference between LightStrength and VisualStrength values that I used in the code, the LightStrength is the strength of the light that lights up the medium around it and the VisualStrength is the strength of the colored hue around the light. And there is also a dark hue variable that is used to make the scene darker as of in the different times of the day.

The code of the fragment shader:

#version 450 core

in vec2 texCoord0;
uniform vec3 CameraPosition;
uniform mat4 Projection;
uniform float DarkHue;

uniform sampler2D u_Texture;
uniform vec2 u_resolution;

struct LightSource {
vec2 Position;
int LightColor;
int ArgumentValue;
};

uniform LightSource LightSources[300];
uniform int LightSourceCount;

float GetLightfactor(float x,float Streght) {
return min(1/(x*(Streght/100.0)+1),1);
}

void main() {
gl_FragColor = texture2D(u_Texture,texCoord0);

vec3 LightSum = vec3(0);
vec4 PCameraPosition = vec4(CameraPosition,0) * Projection;

vec2 NormalizedPosition = gl_FragCoord.xy*2/u_resolution-1;

float LightFactor,VisualFactor,LightStreght,VisualStreght;

for (int i = 0;i < LightSourceCount;++i) {

vec4 Pos = vec4(LightSources[i].Position,0,0) * Projection + PCameraPosition;

vec2 coord = (NormalizedPosition-Pos.xy) * u_resolution;
LightFactor = 0.0;
VisualFactor = 0.0;

LightStreght = LightSources[i].ArgumentValue & 0xffff;
VisualStreght = (LightSources[i].ArgumentValue >> 16) & 0xffff;

float lng = length(coord);

LightFactor = GetLightfactor(lng,LightStreght);
VisualFactor = GetLightfactor(lng,VisualStreght);

LightSum = mix(LightSum,vec3(1),gl_FragColor.rgb * LightFactor * (1-DarkHue)) + vec3(((LightSources[i].LightColor >> 16)&0xff)/255.0,((LightSources[i].LightColor >> 8)&0xff)/255.0,(LightSources[i].LightColor&0xff)/255.0) * VisualFactor;

}

gl_FragColor.rgb *= DarkHue;
gl_FragColor.rgb += LightSum;

}


The code of the c++ function that adds a light source. (Yes when setting uniforms caching is used)

static void AddLightSource(Vec2 Position, uint8_t R, uint8_t B, uint8_t G, uint16_t LightStrenght,uint16_t VisualStrenght) {
std::string access = "LightSources[" + std::to_string(ActiveLightSources) + "]";
int Value = (VisualStrenght << 16) | LightStrenght;
int Color = (R << 16) | (G << 8) | B;
Vec3 Translated = VertexArrayManager::TranslateValue;
shader->setUniform2f(access + ".Position", glm::vec2(Position.x+Translated.x,Position.y + Translated.y));
$$$$
`