Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

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

ShaderCode

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();
    }
}

XNA CODE

    GraphicsDevice.SetRenderTarget(normalRender);
    GraphicsDevice.Clear(Color.Black);
    spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, null, null, null, effectLight);
      spriteBatch.Draw(background, Vector2.Zero, Color.White);
    spriteBatch.End();

    normalRenderTexture = normalRender;

    GraphicsDevice.SetRenderTarget(null);
    GraphicsDevice.Clear(Color.Black);
    spriteBatch.Begin();
       spriteBatch.Draw(normalRenderTexture, Vector2.Zero, Color.White);
    spriteBatch.End();
share|improve this question
    
Could you zip the visual studio project and put it on your dropbox? I would like to download it and help you out. –  Luis Estrada Feb 26 '12 at 0:02
    
@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 –  Joyal Feb 26 '12 at 0:21
2  
for a quick fix please change the size of your image to be a square. I will explain why soon. –  Luis Estrada Feb 26 '12 at 0:50
1  
@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? –  Joyal Feb 26 '12 at 1:21
    
I modified your code a bit to get a simple solution. See attached: dl.dropbox.com/u/29838828/PointLightXNA.zip –  Luis Estrada Feb 27 '12 at 4:38
show 1 more comment

1 Answer 1

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.

share|improve this answer
    
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? –  Joyal Feb 26 '12 at 13:23
    
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. –  Luis Estrada Feb 27 '12 at 3:35
    
@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. –  Daniel Carlsson Feb 27 '12 at 11:51
    
@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 –  Daniel Carlsson Feb 27 '12 at 11:53
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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