我的朋友,教我如何使用着色器制作一个简单的2d点灯,所以我按照他的步骤完成了它!
但有些事情发生了,光的形状就像一个椭圆形而不像一个圆圈,我的朋友们无法解释我为什么,
你能帮我解决一下吗?并解释一下为什么会发生这种情况?
这是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();
答案 0 :(得分:1)
U-V坐标各自为0f至1f。这意味着U-V空间中的1f,1f在屏幕空间中可能是800,600。这意味着纵横比在UV空间中被“拉伸”......并且由于你的纵横比将是4:3或16:9(宽度:高度),你得到的是椭圆形而不是圆形。
答案 1 :(得分:1)
我认为实现目标的简便方法是在屏幕空间中工作。
因此,如果您的屏幕空间大小为(800,600)且背景纹理大小为(800,600),则只需将纹理坐标乘以(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计算需要更多的数学运算。