Как связаны между собой вершинный и пиксельный шейдеры? - PullRequest
0 голосов
/ 15 октября 2019

Я знаю, что об этом спрашивали миллион раз, но я просто не получаю некоторые детали.

В качестве примера, скажем, у меня создана цепочка обмена и одна стадия ID3D11Texture2D.

Что я могу с этим сделать, это загрузить растровое изображение в эту 2D-текстуру и затем скопировать его в цель рендеринга (при условии, что размер и формат обоих ресурсов совпадают).

Теперь я хотел быхотел бы показать спрайт над этим. Одним из решений является использование вершинных и пиксельных шейдеров. Моя проблема понимания начинается здесь.

Вершинный шейдер:
Полагаю, мне нужно нарисовать 2 треугольника (2 треугольника составляют прямоугольник или квад). DirectX использует левостороннюю систему координат, но я думаю, что здесь это не имеет значения, потому что я имею дело с 2D-спрайтами, верно? По той же причине я предполагаю, что могу игнорировать преобразования world->view->projection, верно? На самом деле, мне нужен только перевод здесь, чтобы разместить спрайт в нужном месте на экране, верно?

Должны ли координаты этих двух треугольников соответствовать размерам спрайта плюс перевод? В каком порядке я должен предоставить эти вершины? Должно ли начало системы координат находиться в центре спрайта или начало в верхнем левом углу спрайта?

Например, если у меня есть спрайт 80x70, какими будут значения вершин?

Реальные вершины: (X, Y, Z - без применения перевода)

1. -40, -35, 0
2. -40,  35, 0
3.  40, -35, 0
4.  40,  35, 0
5. -40,  35, 0
6.  40, -35, 0

Это правильно?

Шаг растеризации должен вызывать пиксельный шейдер один раз для каждого пикселя в спрайте. Вывод вершинного шейдера будет вводиться для пиксельного шейдера. Означает ли это, что пиксельный шейдер должен иметь доступ к спрайту, чтобы возвращать правильное значение пикселя при вызове?

1 Ответ

0 голосов
/ 16 октября 2019

Для 2D-рисования вы обычно используете world-> view-> projection, которое преобразует классическое «пиксельное пространство» в пространство клипа (-1..1).

float xScale = 2.0f / ViewPortWidth;
float yScale = 2.0f / ViewPortHeight;

[ xScale, 0        0, 0, ]
[ 0,      -yScale, 0, 0, ]
[ 0,      0,       1, 0, ]
[ -1,     1,       0, 1  ]

Значения -1 и -yScale сводятся на нет, так что 0,0 находится в верхнем левом углу.

Vertex Shader выполняет преобразование в пространство клипа:

void SpriteVertexShader(inout float4 color    : COLOR0,
                        inout float2 texCoord : TEXCOORD0,
                        inout float4 position : SV_Position)
{
    position = mul(position, MatrixTransform);
}

затем точки квадратора растеризуются, затем вызывается пиксельный шейдер:

Texture2D<float4> Texture : register(t0);
sampler TextureSampler : register(s0);

float4 SpritePixelShader(float4 color    : COLOR0,
                         float2 texCoord : TEXCOORD0) : SV_Target0
{
    return Texture.Sample(TextureSampler, texCoord) * color;
}

См. SpriteBatch в наборе инструментов DirectX .

...