Рендеринг круга с помощью вершинного шейдера в DirectX

Я пытаюсь нарисовать простой 2D-круг, манипулируя координатами texcoord внутри вершинного шейдера. Это код:

float2 uv2 = 2.0 * (TextureCoordinate.xy - 0.5);
float tnm = 1.0 - length(uv2);

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

Что происходит внутри вершинного шейдера?

PS. Я должен уточнить, что нет многоугольников, треугольников или круглых объектов/сеток, которые я хочу создать. Я просто передаю texcoord в пиксельный шейдер и возвращаю его. Выполнение 1-texcoord в вершине переворачивает градиент, как и ожидалось, в выводе пикселей. Моя цель состоит в том, чтобы сгенерировать некоторые сферические нормали процедурно.

ППС. Предполагая, что это от [-1,-1] до [1,1] в вершине, я сделал:

(uv + 1) * 0.5;
circle code above which expects [0,1]
(result * 2) - 1;

Но это не сработало.


person vtastek    schedule 11.06.2015    source источник
comment
В Direct3D способ рисования круга заключается либо в точной тесселяции списка соединенных линий, либо в рисовании четырехугольника с текстурой круга на нем. Если ваша цель — рисовать стилизованные линии, окружности, дуги и т. д., вам следует использовать Direct2D.   -  person Chuck Walbourn    schedule 12.06.2015


Ответы (1)


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

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

Что происходит внутри вершинного шейдера?

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

Если вы заполните свои вершины данными круга, эти четыре точки получат сопоставление с кругом и будут линейно интерполированы для других точек между ними, но круг не может быть описан линейным таким образом. Небольшое изображение для пояснения:

введите здесь описание изображения

Как вы видите, координаты текстуры четырех углов сопоставляются с координатами круга. Они лежат снаружи, поэтому их высота по оси Y будет равна нулю. Теперь эти четыре точки интерполируются для пиксельного шейдера, что приводит к еще большей нулевой высоте и отсутствию реального круга. Каждая интерполяция в вершинном шейдере заканчивается чем-то ромбическим, если вы разделите свой четырехугольник один раз, вы получите ромб, если вы будете разбивать его все больше и больше, он будет приближаться к кругу, но никогда не будет идеальным.

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

введите здесь описание изображения

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

Надеюсь, мое объяснение было легко понять :)

person Gnietschow    schedule 12.06.2015
comment
Насколько я понимаю, это так: i.imgur.com/bUOTYpQ.jpg?1 Он пустой, у меня нет градиента. Просто некоторые цифры. Переворот работает, но не код круга, который фактически ожидает градиент. - person vtastek; 13.06.2015
comment
Я обновил свои изображения, потому что ваши еще лучше описывают ситуацию. - person Gnietschow; 13.06.2015