цель рендеринга xna 4 с альфа-каналом

Я хотел бы сделать простую вещь: отрендерить 2d текстуру в цель 2d рендеринга с альфа-наложением каналов.

Итак, я создаю свою цель рендеринга:

renderTarget = new RenderTarget2D(m_graphicsDevice, 200, 200);

затем я создаю свою текстуру:

texture = new Texture2D(_device, 1, 1, false, SurfaceFormat.Color);
Color clr = Color.Red;
// set half transparency on my texture
clr.A = 128;
Color[] bitmap = new Color[1] {clr};
texture.SetData(bitmap);

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

graphicsDevice.SetRenderTarget(renderTarget);
graphicsDevice.Clear(Color.White);

BlendState myState = new BlendState();
// multiplicative blending on color
myState.ColorSourceBlend = Blend.Zero;
myState.ColorDestinationBlend = Blend.SourceColor;
// multiplicative blending on alpha
myState.AlphaSourceBlend = Blend.Zero;
myState.AlphaDestinationBlend = Blend.SourceAlpha;

spriteBatch.Begin(SpriteSortMode.Immediate, myState);
// draw my texture twice, with an overlaping part
spriteBatch.Draw(texture, new Vector2(0, 0), null, Color.White, 0, Vector2.Zero, 100, SpriteEffects.None, 0);
spriteBatch.Draw(texture, new Vector2(50, 50), null, Color.White, 0, Vector2.Zero, 100, SpriteEffects.None, 0);
spriteBatch.End();
graphicsDevice.SetRenderTarget(null);

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

graphicsDevice.Clear(Color.Green);
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.NonPremultiplied);
spriteBatch.Draw(renderTarget, Vector2.zero, Color.White);
spriteBatch.End();

результат такой, как ожидалось:

  • в цели рендеринга только для пикселей, принадлежащих одной текстуре:

    • red chanel = texture red chanel (1) * render target red chanel (1) = 1
    • зеленый и синий chanel = текстура chanel (0) * render target chanel = 0
    • альфа канал = текстура альфа (0,5) * цель рендеринга альфа (1) = 0,5
    • и эта текстура, нарисованная над зеленым фоном, дает коричневый цвет благодаря альфа-прозрачности, установленной на 0,5 (1/2 красного + 1/2 зеленого)
  • в цели рендеринга для перекрывающихся пикселей (таким образом, вышеуказанное вычисление применяется дважды)

    • red chanel = texture red chanel (1) * texture red chanel (1) * render target red chanel (1) = 1
    • зеленый и синий канал = канал текстуры (0) * канал текстуры (0) * целевой канал рендеринга = 0
    • альфа-канал = альфа текстуры (0,5) * альфа текстуры (0,5) * альфа целевой рендеринга (1) = 0,25
    • и эта текстура, нарисованная над зеленым фоном, дает почти зеленый цвет благодаря альфа-значению 0,25 (1/4 красного + 3/4 зеленого)

теперь, если я изменю состояние рендеринга, чтобы просто позволить применить альфа-канал текстуры и не допустить умножения цветов:

BlendState myState = new BlendState();
// texture color is ignored, dest color remain unchanged
myState.ColorSourceBlend = Blend.Zero;
myState.ColorDestinationBlend = Blend.One;
// alpha chanel are still multiplied
myState.AlphaSourceBlend = Blend.Zero;
myState.AlphaDestinationBlend = Blend.SourceAlpha;

что я должен получить:

  • в цели рендеринга только для пикселей, принадлежащих одной текстуре:

    • red chanel = 0 * texture red chanel (1) + 1 * render target red chanel (1) = 1
    • зеленый и синий chanel = 0 * текстура chanel (0) + 1 * render target chanel (1) = 1
    • альфа канал = текстура альфа (0,5) * цель рендеринга альфа (1) = 0,5
    • и эта текстура, нарисованная над зеленым фоном, должна дать светло-зеленый цвет (1/2 белого + 1/2 зеленого).
  • в цели рендеринга для перекрывающихся пикселей (таким образом, вышеуказанное вычисление применяется дважды)

    • red chanel = 1
    • зеленый и синий Шанель = 1
    • альфа-канал = альфа текстуры (0,5) * альфа текстуры (0,5) * альфа целевой рендеринга (1) = 0,25
    • и эта текстура, нарисованная над зеленым фоном, должна давать более интенсивный зеленый цвет (0,25 * белый + 0,75 * зеленый).

и я получаю простую белую текстуру ...

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

Благодарность


person fbf    schedule 17.03.2014    source источник


Ответы (1)


Вы сказали (и я получаю простую белую текстуру ...), но я получаю: введите описание изображения здесь

person Wallstrider    schedule 18.03.2014
comment
Я просто переписал весь приведенный выше код в функции «Рисование» и попробовал: у меня все еще остается пустая текстура во втором случае (и правильное поведение в первом случае). Вы сделали что-то особенное? Я использую XNA 4.0 внутри среды Monogame - person fbf; 18.03.2014
comment
Хорошо, посмотрите на ширину и высоту вашего renderTarget. Это 200 x 200. А затем посмотрите, где вы рисуете текстуры, новые позиции Vector2 (200, 200) и Vector2 (250, 250). Итак, текстуры, нарисованные за пределами renderTarget, не отображались в текстуре renderTarget. Вместо этого установите новый Vector2 (0, 0) и новый Vector2 (50, 50). : D - person Wallstrider; 18.03.2014
comment
Я использовал простой XNA 4.0, просто скопировал и вставил ваш код, затем изменил положение текстур, вот и все. Я могу поделиться проектом, изображение которого приведено выше. - person Wallstrider; 18.03.2014
comment
Вот ссылка на проект - person Wallstrider; 18.03.2014
comment
спасибо wallstrider, ваш код работает. Я сравнил каждую строчку со своей, они одинаковые, но мой код НЕ работает. Единственное объяснение, которое я вижу, это то, что я не использую сборки XNA 4.0, но я использую Xna 4.0 через моноигру ... похоже, проблема в моноигре, а не в моем коде ... Я исследую этот путь. (а для размера и положения текстуры это ошибки в моем сообщении, проблема не в этом. Я исправил код в своем сообщении) - person fbf; 19.03.2014
comment
Это моно приложение для Android? Имейте в виду, что при использовании шейдеров они также могут приводить к разным результатам. - person Wallstrider; 19.03.2014
comment
Я запускаю этот тест в приложении windowsGl с моноигрой 3.01 - person fbf; 20.03.2014
comment
@ user3348323 Я не понимаю, что вы имеете в виду, почему вы используете сборки XNA в Monogame? - person jgallant; 21.10.2014
comment
Проблема исправлена ​​после обновления до последней версии моноигры. Проблема действительно в моноигре, а не в xna. - person fbf; 22.10.2014
comment
Пожалуйста, опубликуйте это принятый ответ на ваш вопрос. Я просто потратил 20 минут, пытаясь разобраться в проблеме. - person James; 10.01.2015