Изобразяване на кръг с Vertex shader в DirectX

Опитвам се да начертая прост 2D кръг, като манипулирам координатите на texcoord вътре в шейдър на върха. Това е кодът:

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

В пикселния шейдър това рисува кръг. Същият код вътре в върховия шейдър ще нарисува чисто бяло. Мога да получа някакъв диагонален градиент в най-добрия случай, ако играя с числа, но без кръгове.

Какво се случва във вертекс шейдъра?

PS. Трябва да изясня, че няма многоъгълници, триъгълници или кръгли обекти/мрежи, които искам да създам. Просто предавам texcoord на пикселния шейдър и го връщам. Извършването на 1-texcoord във връх обръща градиента, както се очаква в пикселния изход. Целта ми е процедурно да генерирам някои сферични нормали.

PPS. Ако приемем, че е [-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)


На първо място, бих искал да ви предложа да разгледате по-задълбочено конвейера за рендиране и значението на вертексните шейдъри и пикселните шейдъри. Не ми се сърдете, но изглежда, че трябва малко по-основно разбиране за тази тема.

Ще се опитам да дам бърз преглед на вашия проблем: няма да постигнете добър кръг в шейдъра на върховете, освен че ще направите много теселна геометрия. Имате нужда от пикселния шейдър, за да получите вашата сфера с нормали.

Какво се случва във вертекс шейдъра?

Това е основният проблем тук: Vertex Shader трансформира вашата дадена геометрия, така че може да бъде растеризирана, за да рендира пиксели на вашия екран. Растеризаторът ще вземе получените триъгълници и ще генерира пиксел за всеки пиксел, който триъгълникът обхваща на екрана. Този пиксел ще бъде обработен от pixelshader и полученият цвят ще бъде показан. За данните, които всеки пиксел носи, растеризаторът интерполира данните за върха на трите ъгъла, така че всеки пиксел има свои собствени позиционно зависими данни. Това си е твой проблем.

Ако попълните вашите върхове с данните за окръжността, тези четири точки получават там картографиране към окръжността и ще бъдат линейно интерполирани за другите точки между тях, но една окръжност не може да бъде описана линейно по този начин. Малко изображение за пояснение:

въведете описание на изображението тук

Както виждате, координатите на четирите ъгъла на текстурата са нанесени на координати на кръг. Те лежат отвън, така че тяхната y-височина ще бъде нанесена на нула. Сега тези четири точки са интерполирани за пикселния шейдър, което води до още по-нулева височина и липса на реален кръг. Всяка интерполация във vertexshader завършва с нещо ромбично, ако разделите своя квадрат веднъж, ще получите ромб, ако го разделяте все повече и повече, той ще се доближи до кръг, но никога няма да бъде перфектен.

Следователно имате нужда от пикселен шейдър. Така че всеки пиксел получава своята интерполирана позиция, за да определи правилната норма на сферата вместо грешни интерполирани нормали.

въведете описание на изображението тук

Поради този проблем най-модерните изчисления за осветление се правят в пикселния шейдър. Особено за огледалното осветление е от съществено значение да се получат фини и прецизни акценти.

Надявам се, че обяснението ми беше лесно за разбиране :)

person Gnietschow    schedule 12.06.2015
comment
Ако разбирам, така става: i.imgur.com/bUOTYpQ.jpg?1 Празно е, нямам градиент. Само малко числа. Обръщането работи, но не и кръговият код, който всъщност очаква градиент. - person vtastek; 13.06.2015
comment
Актуализирах снимките си, защото вашите описват ситуацията още по-добре. - person Gnietschow; 13.06.2015