【问题标题】:How can I create a drop shadow effect on my textures in XNA for Windows Phone?如何在 XNA for Windows Phone 中为我的纹理创建投影效果?
【发布时间】:2012-01-12 12:37:22
【问题描述】:

我正在使用 XNA 框架为 Windows Phone 7 编写一个简单的 2D 游戏。

基本上用户可以拖动多个项目。我通过在RenderTarget2D 上绘制东西来动态创建它们的纹理,然后再绘制RenderTarget2D。我使用 模板缓冲区 将较大纹理的一部分绘制到渲染目标上。

代码 sn-p

util.GraphicsDevice.SetRenderTarget(result);
util.GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.Stencil | ClearOptions.DepthBuffer, Color.Transparent, 0, 0);

// The "mask"

spriteBatch.Begin(SpriteSortMode.Deferred, util.DontWriteColorsState, null, util.StencilAlways, null, alphaTestEffect);
spriteBatch.Draw(maskTexture, destination, Color.White);
spriteBatch.End();

// The actual texture

spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, null, util.StencilKeepWhere1, null, alphaTestEffect);
spriteBatch.Draw(bigTexture, destination, source, Color.White);
spriteBatch.End();

util.GraphicsDevice.SetRenderTarget(null);

util 只是一个帮助器类的实例,我使用它是为了不必在任何地方复制粘贴相同的代码,它包含 DepthStencilState 对象和其他一些东西。) em>

我想在这些纹理后面创建一个阴影效果。我想在渲染目标上绘制阴影。

不幸的是,Windows Phone 7 不支持自定义着色器效果,因此我无法使用互联网上的任何示例。所以我决定尝试在软件中实现它。但是我对这种东西完全没有经验,所以结果既慢又丑。

我在软件中所做的是:

  • 围绕蒙版纹理创建了一个笔触,并以低不透明度进行绘制
  • 围绕前一个笔画创建一个笔画,并以低不透明度进行绘制
  • ...此步骤的重复次数与投影的大小相同

但是,它非常慢,基本上慢得让人无法接受。

所以问题是

是否可以使用 XNA 中的内置效果创建阴影或阴影效果?另外,如果没有,是否有一种算法可以在软件中创建漂亮的投影?

提前感谢您的回答! :)

编辑:

我正在考虑这种阴影:

显然,这只是一个插图,我不希望它完全是这个尺寸。 :)

【问题讨论】:

    标签: c# .net windows-phone-7 xna windows-phone-7.1


    【解决方案1】:

    我冒昧地调整了您的解决方案,@Venemo,这是我想出的一个好的开始:

    public Texture2D CreateBlurredTexture(Texture2D originalTexture, SpriteEffects effects)
        {
            var device = originalTexture.GraphicsDevice;
            var rt = new RenderTarget2D(device, originalTexture.Width/2, originalTexture.Height/2);
            var rt2 = new RenderTarget2D(device, originalTexture.Width, originalTexture.Height);
            Color shadowColor = Color.Lerp(Color.Black, Color.Transparent, 0.9f);
            using (var spriteBatch = new SpriteBatch(device))
            {
                device.SetRenderTarget(rt);
                device.Clear(Color.Transparent);
                spriteBatch.Begin();
                spriteBatch.Draw(originalTexture, new Rectangle(0, 0, rt.Width, rt.Height), null, shadowColor, 0, Vector2.Zero, effects, 0f);
                spriteBatch.Draw(originalTexture, new Rectangle(1, 1, rt.Width - 2, rt.Height - 2), null, shadowColor, 0, Vector2.Zero, effects, 0f);
                spriteBatch.Draw(originalTexture, new Rectangle(2, 2, rt.Width - 4, rt.Height - 4), null, shadowColor, 0, Vector2.Zero, effects, 0f);
                spriteBatch.Draw(originalTexture, new Rectangle(3, 3, rt.Width - 6, rt.Height - 6), null, shadowColor, 0, Vector2.Zero, effects, 0f);
                spriteBatch.Draw(originalTexture, new Rectangle(4, 4, rt.Width - 8, rt.Height - 8), null, shadowColor, 0, Vector2.Zero, effects, 0f);
                spriteBatch.End();
                device.SetRenderTarget(rt2);
                device.Clear(Color.Transparent);
                spriteBatch.Begin();
                spriteBatch.Draw(rt, new Rectangle(0, 0, rt2.Width, rt2.Height), Color.White);
                spriteBatch.End();
                device.SetRenderTarget(null);
            }
    
            return rt2;
        }
    

    它所做的是创建纹理副本并在每次绘制时增加不透明度,同时朝向中心。完成后,您可以偏移它并增加其大小以创建更大的阴影效果。这应该根据您的纹理完成任务。

    【讨论】:

    • 你真是太好了,但这个问题现在已经有好几年了。我不再有 WP7 设备,也没有用于测试它的开发环境。
    【解决方案2】:

    要绘制阴影,以纯黑色绘制原始渲染目标,可能具有一些透明度,稍微偏离原始位置。
    接下来再次绘制,就像之前在阴影上渲染纹理一样。


    关于您的编辑,为边创建纹理,为角创建纹理,然后将投影绘制为 4 个边和 4 个角。

    【讨论】:

    • 我应该更清楚这一点,但不是在谈论这种阴影。
    • 图片模型可能会有所帮助,因为我重新阅读了您的帖子并仍然得出相同的结论。
    • 我希望阴影在其边缘“模糊”,例如。 Photoshop 中的投影效果。
    • 在我的问题中添加了一张图片。
    • 嗯,没有更强大的着色器。可能多次绘制阴影,位置略有不同,大部分是透明的。
    【解决方案3】:

    这就是我最终想出的。
    当然,这有点 hacky,但是当我问这个问题时,它可以满足我的需要。

        public static Texture2D CreateBlurredTexture(Texture2D originalTexture, SpriteEffects effects)
        {
            var device = originalTexture.GraphicsDevice;
            var rt4 = new RenderTarget2D(device, originalTexture.Width / 4, originalTexture.Height / 4);
    
            using (var rt2 = new RenderTarget2D(device, originalTexture.Width * 3 / 2, originalTexture.Height * 3 / 2))
            using (var rt3 = new RenderTarget2D(device, originalTexture.Width / 2, originalTexture.Height / 2))
            using (var spriteBatch = new SpriteBatch(device))
            {
                device.SetRenderTarget(rt2);
                device.Clear(Color.Transparent);
                spriteBatch.Begin();
                spriteBatch.Draw(originalTexture, new Rectangle(0, 0, rt2.Width, rt2.Height), null, Color.White, 0, Vector2.Zero, effects, 0f);
                spriteBatch.End();
                device.SetRenderTarget(rt3);
                device.Clear(Color.Transparent);
                spriteBatch.Begin();
                spriteBatch.Draw(rt2, new Rectangle(0, 0, rt3.Width, rt3.Height), Color.White);
                spriteBatch.End();
                device.SetRenderTarget(rt4);
                device.Clear(Color.Transparent);
                spriteBatch.Begin();
                spriteBatch.Draw(rt3, new Rectangle(0, 0, rt4.Width, rt4.Height), Color.White);
                spriteBatch.End();
                device.SetRenderTarget(null);
            }
    
            return rt4;
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-09-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-06
      相关资源
      最近更新 更多