2012-02-25 9 views
0

私の友人は、シェーダでシンプルな2次元点光源を作る方法を教えてくれました。2D Point Light XNA、なぜポイントライトの半径が楕円ですか?

が、何かが光形状が楕円形のようなもので、円を好きではない、起こった、私の友人は、なぜ、

あなたはそれを修正する方法を、私を助けて、そしてそれが起こった理由を私に説明することができ、私を説明couldntの?ここ

は、それが

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

答えて

1

私はあなたがそれを達成するための簡単な方法は、スクリーンスペースで働いていると思います。

スクリーンスペースのサイズが(800,600)、背景テクスチャサイズが(800,600)の場合、テクスチャ座標por(800,600)を掛けるだけです。

float ScreenWidth = 800; 
float ScreenHeight = 600; 

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 = 200; // Pixeles in screen space 
    float lightIntensity = 15.0f; 
    float4 lightColor = float4(0, 0, 1, 1); 
    float2 lightPos = float2(ScreenWidth/2, ScreenHeight/2); // Center of the screen 
    float2 pixelPos = input.TexCoord.xy * float2(ScreenWidth, ScreenHeight);  

    dist = distance(lightPos, pixelPos); 

    float distanceFactor = (lightRadius-dist)/lightRadius; 

    color += saturate(distanceFactor *lightIntensity)*lightColor; 

    texCol = saturate(color) *texCol; 

    return texCol; 
} 

注:異なるサイズ、その画面でテクスチャとしていない位置(0,0)で作業する場合は、pixelPos計算は、より多くの数学を必要とします。

+0

それは完全に動作します!ありがとうございました!しかし、唯一のことは今は "勾配"ではなく、フラットです、どうすればこの問題を解決できますか? PLZも説明すると、私はできるだけ多くのことを学びたい –

+1

申し訳ありませんが、わかりませんでしたが、因子の値を[0..1]の範囲に保つために半径で割ります。私はコードを修正しました。 – Blau

+0

は素晴らしい作品です!どうもありがとう! –

1

U-V座標をどのように見えるかである各1Fに0Fからです。これは、U-V空間内の1f、1fがスクリーンスペースで800,600である可能性があることを意味します。これは、アスペクト比がU-V空間で「伸ばされる」ということです。縦横比が4:3または16:9(幅:高さ)になるため、円の代わりに楕円形が得られます。

+0

私はテクスチャを正方形に変更してサークルを描画しますが、正方形以外のイメージを使用してこれを修正する方法はありますか? –

関連する問題