Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Determining world position of the current fragment in a shader  (Read 3657 times)

0 Members and 1 Guest are viewing this topic.

Blasphemer

  • Newbie
  • *
  • Posts: 3
    • View Profile
    • Email
Determining world position of the current fragment in a shader
« on: January 22, 2015, 12:59:12 pm »
I am trying to make a lighting fragment shader. For that, I need to know the world position of the fragment in order to determine its distance to the light source (in world units). Should I do it by setting up a varying world coordinates variable in a vertex shader? If so, can SFML provide the model matrix needed to compute the vertex world position like this?:

vec2 world_coords = gl_Vertex * gl_ModelMatrix

Or should I compute the vertex world positions in SFML - getting the entity transform, applying it to local vertex coords then passing the results to the vertex shader?

Is this even the correct way to make a per-pixel lighting shader with SFML that would not change output with view/screen transformations?
« Last Edit: January 22, 2015, 01:09:50 pm by Blasphemer »

TheNess

  • Newbie
  • *
  • Posts: 17
    • View Profile
    • Email
Re: Determining world position of the current fragment in a shader
« Reply #1 on: January 27, 2015, 11:24:31 am »
are you talking 2d or 3d?

I implemented a 2d lighting shader with normal maps and I sent the light position to the shader already converted to screen coords. I even asked this somewhat similar question:
http://en.sfml-dev.org/forums/index.php?topic=17352.0

so if you are talking 2d I can give you more info.

Blasphemer

  • Newbie
  • *
  • Posts: 3
    • View Profile
    • Email
Re: Determining world position of the current fragment in a shader
« Reply #2 on: January 31, 2015, 02:18:01 pm »
are you talking 2d or 3d?

I implemented a 2d lighting shader with normal maps and I sent the light position to the shader already converted to screen coords. I even asked this somewhat similar question:
http://en.sfml-dev.org/forums/index.php?topic=17352.0

so if you are talking 2d I can give you more info.

Yes I am talking about 2D. I have already implemented the shader with the approach outlined in the OP. The code is here:

uniform sampler2D texture;

uniform vec2 light_position;
uniform vec4 light_color;
uniform float light_intensity;

uniform vec2 topleft;
uniform vec2 topright;
uniform vec2 bottomright;
uniform vec2 bottomleft;

vec2 resize_vect(vec2 vect, float lenght)
{
        float vect_lenght = sqrt(vect.x * vect.x + vect.y * vect.y); //get vector's lenght

        vect.x = vect.x / vect_lenght; //normalize vector
        vect.y = vect.y / vect_lenght;

        vect.x = vect.x * lenght; //multiply it by lenght
        vect.y = vect.y * lenght;

        return vect;
}

void main()
{
       
       
        vec2 fragment_position_x = topleft + resize_vect(topright - topleft, gl_TexCoord[0].x*3 * distance(topleft, topright));
        vec2 fragment_position_y = topleft + resize_vect(bottomleft - topleft, gl_TexCoord[0].y * distance(topleft, bottomleft));
        vec2 fragment_position = fragment_position_x + (fragment_position_y - topleft);
       
        vec4 pixel = texture2D(texture, gl_TexCoord[0].xy);
       
        float intensity = (light_intensity/5) / clamp(distance(fragment_position, light_position), 0.001, 4000000.0);
       
        vec4 light = vec4(pixel.r*light_color.r*intensity, pixel.g*light_color.g*intensity, pixel.b*light_color.b*intensity, pixel.a);

        gl_FragColor = light;

(I have to multiply gl_TexCoord[0].x by 3 because I am also storing glow map and environment map in the same texture so the end of the first texture is at x = 1/3)
« Last Edit: January 31, 2015, 02:20:06 pm by Blasphemer »

TheNess

  • Newbie
  • *
  • Posts: 17
    • View Profile
    • Email
Re: Determining world position of the current fragment in a shader
« Reply #3 on: January 31, 2015, 10:21:35 pm »
to be honest I didn't fully understand what you are doing in the shader with the fragment_position calculation (maybe its because of the time :)), but if its 2d, why not calculating the distance in screen position? i.e. using the gl_FragCoord varying you already have built-in. or are you doing anything special in the vertex shader?

read more here: https://www.opengl.org/sdk/docs/man/html/gl_FragCoord.xhtml

also two tips about your code:

instead of this:
float vect_lenght = sqrt(vect.x * vect.x + vect.y * vect.y); //get vector's lenght

    vect.x = vect.x / vect_lenght; //normalize vector
    vect.y = vect.y / vect_lenght;
 

you can use normalize() to normal the vector and length() to get vector length (if you need it).

and instead of this:
vec4 light = vec4(pixel.r*light_color.r*intensity, pixel.g*light_color.g*intensity, pixel.b*light_color.b*intensity, pixel.a);
 

you can do something like this:
vec4 light = pixel;
light.rgb *= light_color.rgb * intensity;
 



I don't know if it helps but this is how I wrote my normal maps shader (rgb is normals, a is depth):
(click to show/hide)
« Last Edit: January 31, 2015, 10:25:43 pm by TheNess »