使用深度图像进行照明有什么问题

时间:2011-10-25 08:10:34

标签: c# xna xna-4.0 pixel-shader

我想使用深度图像来照亮RawColor图像但看起来不太好 我想知道我的代码有什么问题,或者它的所有深度图像都可以:| 输出图像的形状像Cone而不是圆圈,它上面有很多噪音,我想知道的是我的代码是错的还是不正确的方法呢?! 为此我得到每个像素的正常值并将其添加到纹理并将其发送到像素着色器以用于照明。结果图像和代码添加到这里

result image

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

0 个答案:

没有答案