سؤال

I have a shader which adds lighting to an otherwise 2D scene (lights are slightly above the 2D plane). In my fragment shader, I loop through each light to calculate the direction and distance by applying my ortho matrix to the light's pos.

The problem is, the light's "radius" is affected by the size and aspect ratio of my window. I thought that translating the coordinates using the ortho matrix would ensure that the screen size wouldn't matter, but a wide window produces an oval light, and smaller windows produce smaller ovals than larger windows. Should I be using another matrix of some sort?

Full shader here (change window size to see the unwanted effect): http://glsl.heroku.com/e#14464.0

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 = vec3(0.0, 0.0, 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);
}

Note: I know it's not optimal to make this calculation for each light, each pixel - I should be passing the light's position in another uniform probably.

هل كانت مفيدة؟

المحلول

The light direction needs to be scaled according to screen resolution. I ended up adding the following code to make it work, with an arbitrary brightness of 500 or so:

light_direction *= vec3(resolution.x / brightness, resolution.y / brightness, 1.0);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top