Как создать эффект тени на моих текстурах в XNA для Windows Phone? - PullRequest
0 голосов
/ 12 января 2012

Я пишу простую 2D-игру для Windows Phone 7 с использованием XNA Framework.

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

Фрагмент кода

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 и некоторые другие вещи.)

Я бы хотел создать эффект тени на фоне этих текстур. Я хотел бы нарисовать тень на цели рендера.

К сожалению, Windows Phone 7 не поддерживает пользовательские эффекты шейдеров, поэтому я не могу использовать примеры из Интернета. Поэтому я решил попробовать реализовать это в программном обеспечении. Но я совершенно неопытен в таких вещах, поэтому результат был медленным и безобразным.

То, что я делал в программном обеспечении, было так:

  • Создал обводку вокруг текстуры маски и нарисовал ее с низкой непрозрачностью
  • Создает обводку вокруг предыдущего обводки и рисует ее с низкой непрозрачностью
  • ... Этот шаг повторялся столько же раз, сколько и размер тени

Однако это было ОЧЕНЬ медленно и в основном недопустимо медленно.

Так что вопрос

Можно ли создать эффект капли или тени, используя встроенные эффекты в XNA? Кроме того, если нет, есть ли алгоритм, который может создать красивую тень в программном обеспечении?

Заранее спасибо за ваши ответы! :)

EDIT:

Я расскажу о такой тени:
Drop shadow effect

Очевидно, это всего лишь иллюстрация, я не хочу, чтобы он был именно такого размера. :)

Ответы [ 3 ]

1 голос
/ 27 мая 2015

Я позволил себе скорректировать ваше решение, @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;
    }

То, что он делает, создает копии текстуры и добавляет непрозрачность при каждом рисовании, когда идет к центру. После этого вы можете сместить его и увеличить его размер, чтобы создать больший эффект тени. Это должно выполнить задачу в зависимости от вашей текстуры.

0 голосов
/ 12 июля 2013

Это то, что я придумал, в конце концов.
Конечно, это немного глупо, но когда я задаю вопрос, это делает то, что мне нужно.

    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;
    }
0 голосов
/ 12 января 2012

Чтобы нарисовать тень, нарисуйте исходную цель рендеринга в чистом черном цвете, возможно, с некоторой прозрачностью, немного сместив ее от исходной позиции.
Далее просто нарисуйте, как вы делали ранее, чтобы визуализировать текстуру над тенью.*


Что касается редактирования, создайте текстуру для края и текстуру для угла, затем нарисуйте тень в виде 4 ребер и 4 углов.

...