clarenx

02-21-2014, 10:58 AM

I have a 2D sprite-based scene and I'm implementing lights that hover just above the 2D plane. Each sprite has a normal map, so I have a fragment shader that shades each sprite according to the lights' position and color.

I pass the lights' coordinates in via a uniform - the coordinates are in exact screen pixel coordinates (e.g. 900, 600), so I apply my ortho matrix to them to get the normalized position. My problem is that the "radius" of the lights is affected by the size of the screen/window, and I'm not sure why. I want the lights to be the same size no matter what.

I have removed all but the necessary code and posted it on an interactive GLSL editor - you can modify the window size to see the undesired effect (sorry, can't post URLs?): glsl.heroku.com/e#14464.0

I'll also post the code here:

uniform vec2 resolution;

void main(void)

{

//orthographic matrix

mat4 ortho_matrix = mat4(

2.0/resolution.x, 0, 0, 0,

0, 2.0/-resolution.y, 0, 0,

0, 0, -1, 0,

-1, 1, 0, 1

);

//surface normal of the 2D plane (looking straight down)

vec3 surface_normal = normalize(mix(vec3(-1), vec3(1), vec3(0.5, 0.5, 1.0)));

//screen position of the light

vec2 light_screen_pos = vec2(650, 150);

//translate light's position to normalized coordinates

//the z value makes sure it is slightly above the 2D plane

vec4 light_ortho_pos = ortho_matrix * vec4(light_screen_pos, -0.03, 1.0);

//calculate the light for this fragment

vec3 light_direction = light_ortho_pos.xyz - vec3(gl_FragCoord.x / resolution.x, gl_FragCoord.y / resolution.y, 0);

float dist = length(light_direction);

light_direction = normalize(light_direction);

vec3 light = clamp(dot(surface_normal, light_direction), 0.0, 1.0) * vec3(0.5, 0.5, 0.5);

vec3 cel_light = step(0.15, (light.r + light.g + light.b) / 3.0) * light;

gl_FragColor = vec4(pow(light + cel_light, vec3(0.4545)), 1.0);

}

Thanks for any advice or insight.

I pass the lights' coordinates in via a uniform - the coordinates are in exact screen pixel coordinates (e.g. 900, 600), so I apply my ortho matrix to them to get the normalized position. My problem is that the "radius" of the lights is affected by the size of the screen/window, and I'm not sure why. I want the lights to be the same size no matter what.

I have removed all but the necessary code and posted it on an interactive GLSL editor - you can modify the window size to see the undesired effect (sorry, can't post URLs?): glsl.heroku.com/e#14464.0

I'll also post the code here:

uniform vec2 resolution;

void main(void)

{

//orthographic matrix

mat4 ortho_matrix = mat4(

2.0/resolution.x, 0, 0, 0,

0, 2.0/-resolution.y, 0, 0,

0, 0, -1, 0,

-1, 1, 0, 1

);

//surface normal of the 2D plane (looking straight down)

vec3 surface_normal = normalize(mix(vec3(-1), vec3(1), vec3(0.5, 0.5, 1.0)));

//screen position of the light

vec2 light_screen_pos = vec2(650, 150);

//translate light's position to normalized coordinates

//the z value makes sure it is slightly above the 2D plane

vec4 light_ortho_pos = ortho_matrix * vec4(light_screen_pos, -0.03, 1.0);

//calculate the light for this fragment

vec3 light_direction = light_ortho_pos.xyz - vec3(gl_FragCoord.x / resolution.x, gl_FragCoord.y / resolution.y, 0);

float dist = length(light_direction);

light_direction = normalize(light_direction);

vec3 light = clamp(dot(surface_normal, light_direction), 0.0, 1.0) * vec3(0.5, 0.5, 0.5);

vec3 cel_light = step(0.15, (light.r + light.g + light.b) / 3.0) * light;

gl_FragColor = vec4(pow(light + cel_light, vec3(0.4545)), 1.0);

}

Thanks for any advice or insight.