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

发布于 2024-12-11 11:59:57 字数 6152 浏览 0 评论 0原文

我想使用深度图像来照亮 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();
    }
}

I want use a depth image to lighting a RawColor image but it not seems good
i want know whats wrong with my code , or its all depth image can do :|
the output image shape like Cone instead of circle and there are many noise on it , what i want to know is my code wrong or its not right way to do this?!
for that i get normal for each pixel and add it to a texture and send it to pixel shader to use for lighting. result image and code are added here

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



}

and shader Code is here

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文