Я хочу использовать изображение глубины для освещения изображения RawColor, но это не кажется хорошим, я хочу знать, что не так с моим кодом, или его полное изображение глубины может сделать: |форма выходного изображения, например, конус, а не круг, и на нем много шума, что я хочу знать, мой код неправильный или неправильный способ сделать это ?!для этого я получаю нормальное значение для каждого пикселя, добавляю его к текстуре и отправляю в пиксельный шейдер для освещения.сюда добавляются изображение и код результата
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Texture2D depth;
Texture2D image;
Texture2D texNormal;
Vector3 cameraPos = new Vector3(0.5f, 0.5f, -0.0999f);
Effect mEffect;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
// TODO: Add your initialization logic here
graphics.PreferredBackBufferWidth = 1000;
graphics.PreferredBackBufferHeight = 1000;
graphics.ApplyChanges();
base.Initialize();
}
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
depth = Content.Load<Texture2D>("depth");
image = Content.Load<Texture2D>("image");
texNormal = getNormalFromDepth(depth);
mEffect = Content.Load<Effect>("depthEffect");
// TODO: use this.Content to load your game content here
}
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
if (Keyboard.GetState().IsKeyDown(Keys.W))
{
cameraPos.Y += 0.01f;
}
if (Keyboard.GetState().IsKeyDown(Keys.S))
{
cameraPos.Y -= 0.01f;
}
if (Keyboard.GetState().IsKeyDown(Keys.A))
{
cameraPos.X -= 0.01f;
}
if (Keyboard.GetState().IsKeyDown(Keys.D))
{
cameraPos.X += 0.01f;
}
if (Keyboard.GetState().IsKeyDown(Keys.Up))
{
cameraPos.Z += 0.01f;
}
if (Keyboard.GetState().IsKeyDown(Keys.Down))
{
cameraPos.Z -= 0.01f;
}
// TODO: Add your update logic here
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
GraphicsDevice.Textures[1] = texNormal;
mEffect.Parameters["LightPos"].SetValue(cameraPos);
// TODO: Add your drawing code here
spriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, null, mEffect);
spriteBatch.Draw(image, new Rectangle(0, 0, 500, 500), Color.White);
spriteBatch.End();
spriteBatch.Begin();
spriteBatch.Draw(texNormal, new Rectangle(500, 0, 500, 500), Color.White);
spriteBatch.Draw(image, new Rectangle(500, 500, 500, 500), Color.White);
spriteBatch.Draw(depth, new Rectangle(0, 500, 500, 500), Color.White);
spriteBatch.End();
base.Draw(gameTime);
}
Texture2D getNormalFromDepth(Texture2D depth)
{
Texture2D output = new Texture2D(GraphicsDevice, depth.Width, depth.Height);
Color[] outbyte = new Color[depth.Width * depth.Height];
Color[] colors1D = new Color[depth.Width * depth.Height];
depth.GetData(colors1D);
Color[,] colors2D = new Color[depth.Width, depth.Height];
for (int x = 0; x < depth.Width; x++)
{
for (int y = 0; y < depth.Height; y++)
{
colors2D[x, y] = colors1D[x + y * depth.Width];
}
}
for (int x = 0; x < depth.Width; x++)
{
for (int y = 0; y < depth.Height; y++)
{
float left = GetHeight(colors2D, ref depth, x - 1, y);
float right = GetHeight(colors2D, ref depth, x + 1, y);
float top = GetHeight(colors2D, ref depth, x, y - 1);
float bottom = GetHeight(colors2D, ref depth, x, y + 1);
// Compute gradient vectors, then cross them to get the normal.
Vector3 dx = new Vector3(1, 0, (right - left) * 1);
Vector3 dy = new Vector3(0, 1, (bottom - top) * 1);
Vector3 normal = Vector3.Cross(dx, dy);
normal.Normalize();
// Store the result.
float alpha = colors2D[x, y].A;
outbyte[y * depth.Width + x] = new Color(new Vector4(normal, alpha));
}
}
output.SetData(outbyte);
return output;
}
float GetHeight(Color[,] depth, ref Texture2D depthImage, int x, int y)
{
if (x < 0)
{
x = 0;
}
else if (x >= depthImage.Width)
{
x = depthImage.Width - 1;
}
if (y < 0)
{
y = 0;
}
else if (y >= depthImage.Height)
{
y = depthImage.Height - 1;
}
Color mColor = (depth[x, y]);
float output = (mColor.R + mColor.G + mColor.B) / 3;
return output;
}
}
и код шейдера здесь
sampler normalSampler : register(s1);
sampler imageSampler : register(s0);
float3 LightPos = (1,0,-0.5);
float3 AmbientColor = (0.1,0.1,0.1);
float3 LightColor = (0.9,0.9,0.9);
float4 main(float4 color : COLOR0 ,float2 texCoord : TEXCOORD0):COLOR0
{
float4 output = float4(1,1,1,1);
float4 normal = tex2D(normalSampler,texCoord);
float4 imageColor = tex2D(imageSampler,texCoord);
float3 tex3DCoord = float3(texCoord.x,texCoord.y,0);
float3 lighting = AmbientColor;
float3 lightDir = (LightPos - tex3DCoord);
lighting += ( LightColor* max(dot(normal.xyz, lightDir), 0));
output = float4 (imageColor*lighting,1);
return output;
}
technique Technique1
{
pass Pass1
{
PixelShader = compile ps_2_0 main();
}
}