что не так с использованием глубины изображения для освещения - PullRequest
1 голос
/ 25 октября 2011

Я хочу использовать изображение глубины для освещения изображения RawColor, но это не кажется хорошим, я хочу знать, что не так с моим кодом, или его полное изображение глубины может сделать: |форма выходного изображения, например, конус, а не круг, и на нем много шума, что я хочу знать, мой код неправильный или неправильный способ сделать это ?!для этого я получаю нормальное значение для каждого пикселя, добавляю его к текстуре и отправляю в пиксельный шейдер для освещения.сюда добавляются изображение и код результата

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