I friend of mine , taught me how to make a simple 2d point light with shader, so i follow his steps and finally done it !

but something happend , the light shape is like an oval and not like a circle , my friends couldnt explain me why,

could you help me how to fix it, and explain me why it happend?

here is how it looks like http://dl.dropbox.com/u/2553973/screengrab/PointLight_07.png


Texture InputTexture;

sampler InputTextureSampler = sampler_state {
    texture = <InputTexture>;
    magfilter = LINEAR;
    minfilter = LINEAR;
    mipfilter = LINEAR;
    AddressU = mirror;
    AddressV = mirror;

struct VertexShaderOutput
    float4 Position  : POSITION0;
    float2 TexCoord  : TEXCOORD0;
    float4 Color     : COLOR0;

float4      ambientColor = float4(1.0,1.0,1.0,0.0);
float       ambientIntensity = 0.3f;

float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
    //float4 color = float4(1, 0, 0, 1);
    float4 texCol = tex2D(InputTextureSampler, input.TexCoord);

    float4 color = ambientIntensity*ambientColor;
    float dist;

    //Light 1
    float  lightRadius = 0.2f;
    float  lightIntensity = 15.0f;
    float4 lightPos = float4(0.3f,0.3f,0.0f,0); 
    float4 lightColor =  float4(0, 0, 1, 1);

        dist = distance(lightPos, input.TexCoord);
    color += saturate((lightRadius-dist)*lightIntensity)*lightColor;

    texCol = saturate(color) *texCol;

    return texCol;

technique PointLight
    pass Pass1
        PixelShader = compile ps_2_0 PixelShaderFunction();


    spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, null, null, null, effectLight);
      spriteBatch.Draw(background, Vector2.Zero, Color.White);

    normalRenderTexture = normalRender;

       spriteBatch.Draw(normalRenderTexture, Vector2.Zero, Color.White);
  • \$\begingroup\$ Could you zip the visual studio project and put it on your dropbox? I would like to download it and help you out. \$\endgroup\$ Feb 26 '12 at 0:02
  • \$\begingroup\$ @LuisEstrada dl.dropbox.com/u/2553973/PointLightXNA.zip , here is the project, the light is coded inside the Shader, is just a sample project :D, btw XNA 4.0 \$\endgroup\$
    – Joyal
    Feb 26 '12 at 0:21
  • 2
    \$\begingroup\$ for a quick fix please change the size of your image to be a square. I will explain why soon. \$\endgroup\$ Feb 26 '12 at 0:50
  • 1
    \$\begingroup\$ @LuisEstrada it tottaly worked, i imagine why, because the aspect ratio of the texcoords of the image isnt square, but, is there any solution to keep using non square images? \$\endgroup\$
    – Joyal
    Feb 26 '12 at 1:21
  • \$\begingroup\$ I modified your code a bit to get a simple solution. See attached: dl.dropbox.com/u/29838828/PointLightXNA.zip \$\endgroup\$ Feb 27 '12 at 4:38

You need to take into account the AspectRatio of your viewport (GraphicsDevice.Viewport.AspectRatio), the texture coordinates given to the shader are normalized to a square region so you need to inform the shader of what your AspectRatio is.

In 3D you do this with the Matrix.CreatePerspectiveFieldOfView call, in 2D you simply need to make a float aspectRatio which you initialize in XNA.

  • \$\begingroup\$ oh i see, i understand, but how i inform to the shader of the aspect ratio? , i need multiply this var with something? like the distance? \$\endgroup\$
    – Joyal
    Feb 26 '12 at 13:23
  • \$\begingroup\$ It actually doesn't have to do with the screen size or viewport. If you change the screen size to be a square (AspectRatio = 1.0) you get the same effect. \$\endgroup\$ Feb 27 '12 at 3:35
  • \$\begingroup\$ @Joyal When you map the UV coordinates to your light texture with 800x600, moving to the right 1/800 will swap one pixel to the right, and 1/600 a pixel to the bottom. I don't know if I'm making sense here. Basically you want to divide the U coordinate with the aspectratio (I believe it is, can't look it up right now, if not the U then the V). Setting it in the shader is just a simple matter of doing shader.Parameters["aspectratio"].SetValue I believe, again don't have the doc or ide in front of me. \$\endgroup\$ Feb 27 '12 at 11:51
  • \$\begingroup\$ @LuisEstrada Making the viewport (which is the same as screen size in fullscreen) into 1:1 simply means that modifying the UV coordinates is not necessary since they are already 1:1. 5*1 = 5/1 = 5. But unless your okay with that restriction you need to account for the aspectratio in your shader since it gives fractional coordinates that are mapped to be 1:1 \$\endgroup\$ Feb 27 '12 at 11:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.