Posts tagged ‘shaders’

Trudny wybór: sprawa materiałów

2007-10-21 14:48

W programowaniu też trzeba często podejmować różne trudne decyzje; zwykle dotyczą one kwestii projektowych. Szczególnie złożone robią się one tam, gdzie idee OOPu muszą się spotkać ze sprowadzeniem na ziemię przez wymagania wydajnościowe obecne w programowaniu grafiki i interfejs graficznych API takich jak DirectX.
Na co więc tak narzekam? Otóż chodzi o odpowiednie opakowanie systemu materiałów. Jak wiadomo, materiał to jest taka cecha geometrii, która nie jest zapisana w danych o wierzchołkach – czyli właściwie wszystko, co może być w geometrii interesujące :) Materiał określa więc cechy powierzchni (gładka, bump-mapowana), właściwości świetlne albo nawet tak fundamentalne cechy jak półprzezroczystość lub renderowanie jako siatki (wireframe).

Zakodowanie takiego systemu materiałów zgodnie z regułami programowania obiektowego oznaczałoby przede wszystkim to, że część potoku odpowiedzialna za rysowanie nie musiałaby nawet wiedzieć, z jakiego dokładnie materiału korzysta dany fragment geometrii. Za pomocą metod wirtualnych można by bowiem albo pobrać odpowiednie ustawienia stanów renderowania, albo wręcz kazać materiałowi, aby sam je ustawił.
To da się zrobić. Sęk w tym, że wszystkie te dane trzeba przekazać do shadera, który już taki sprytny nie jest. W rzeczy samej, dopiero od niezbyt w sumie długiego czasu shadery można pisać w czymś, co przypomina język wysokiego poziomu, a o OOPie czy tym bardziej polimorfizmie nawet nie ma co marzyć. Chociaż… w HLSL już teraz do ewentualnego przyszłego użycia zarezerwowano słowo kluczowe class :)

Na teraz trzeba jednak zdecydować się na rozwiązanie pośrednie, które mniej więcej zadowoli obie strony – elastyczną obiektowość i “sztywny” shader. Osobiście widzę trzy rozwiązania dla organizacji klas(y) materiałów w silniku:

  • Jedna duża klasa materiału, zawierająca pola z wartościami wszystkich możliwych ustawień. Jest więc flaga półprzezroczystości, wskaźnik na ewentualną normal-mapę, wskaźnik na tekstury powierzchni i tym podobne. Zaletą tego rozwiązania jest prostota (chociaż wynikowa klasa byłaby dość duża) i w łatwość “wyciągania” danych potrzebnych do sortowania fragmentów geometrii.
  • Kilka klas ułożonych w nieskomplikowaną hierarchię dziedziczenia. Jej ‘rozpiętość pionowa’ (możliwość dodawania kolejnych klas pochodnych) byłaby aczkolwiek pozorna, bo cała ta hierarchia musiałaby znaleźć odbicie w shaderze.
  • Jedna klasa materiału, składającego się z abstrakcyjnych “klocków” definiujących poszczególne jego cechy. To właśnie według nich odbywałoby się sortowanie geometrii. Konsekwencją jest jednak to, że w podobny (addytywny) sposób musiałby też być (s)konstruowany shader.

Zapewne to ostatnie rozwiązanie jest najbardziej elastyczne, rzeźnickie i w ogóle “naj” – tyle że jest też najbardziej skomplikowane i zdecydowanie nie chciałbym się za nie zabierać już za pierwszym razem. Dlatego, jak sądzę, powinienem wybrać coś między opcją pierwsza a drugą. Obie są właściwie pewnymi odcieniami tego samego wariantu, w którym możliwe cechy materiału są po prostu wpisane na sztywno w kodzie – zarówno samej aplikacji, jak i shaderów.
W przypadku drugiej opcji istnieje naturalnie tradycyjny dylemat: czy dana cecha zasługuje tylko na osobne pole, czy może wymaga już nowej klasy pochodnej. Myślę jednak, że tutaj można zastosować dość prostą zasadę związania klasy z shaderem. Jeśli więc dwa materiały należą do tej samej klasy, to różnią się tylko wartościami stanów renderowania. Natomiast materiały z różnych klas różnią się samym zestawem stanów, jakie można dla nich ustawiać; potrzebują zatem innych shaderów.

Tags: , , ,
Author: Xion, posted under Programming » Comments Off on Trudny wybór: sprawa materiałów

Pomocna małpa

2007-10-04 16:56

Eksperymentując z grafiką 3D bardzo często zachodzi potrzeba napisania i przetestowania programu testującego jakąś konkretną technikę zrobienia czegoś – na przykład powierzchni odbijającej światło czy rzucania cieni. Można w tym celu stworzyć jakiś szablon przykładowego programu, który będziemy odpowiednio modyfikować. Nie będzie to zwykle wygodne, chyba że naprawdę się postaramy (czytaj: poświęcimy dużo czasu na rzecz nie do końca potrzebną).

Logo RenderMonkeyIstnieje aczkolwiek inne rozwiązanie i jest nim skorzystanie z wyspecjalizowanej aplikacji, jak na przykład RenderMonkey stworzonej przez ATI i dostępnej za darmo. Jest to coś w rodzaju wirtualnego środowiska dla programowania grafiki (czyli shaderów) działającego jednak na zupełnie realnym urządzeniu – przy użyciu DirectX lub OpenGL.
Ma ono całkiem spore możliwości oraz udostępnia sporą wygodę w testowaniu różnych efektów opierających się na ustalonych parametrach. O ile w kodzie zmiana jakiejś wartości wymagałaby zwykle rekompilacji, o tyle tutaj można taką wartość (zmienną) odpowiednio oznaczyć i modyfikować jej wartość przy pomocy graficznego interfejsu, natychmiast podglądając rezultat.

Screen z RenderMonkey Screen z RenderMonkey

Rzeczone zmienne ostatecznie mają po prostu odpowiedniki w rejestrach shaderów (pisanych dla DX w HLSL). Oprócz edytowania ich RenderMonkey umożliwia też dodawanie do projektów różnego rodzaju zasobów (modeli, tekstur, itp.) oraz ustawianie ich różnych stanów. Na dodatek w pakiecie z programem jest całkiem sporo takich właśnie przykładowych zasobów.

A wady? Cóż… Mogę wspomnieć o tym, że obecnie program wykorzystuje tylko DX9, czyli niestety nie pobawimy się tymi jakże użytecznymi geometry shaderami (oczywiście przy założeniu, że nasza karta potrafi się nimi bawić :)) Ale jest i dobra strona – nie trzeba instalować Visty ;P

 


© 2023 Karol Kuczmarski "Xion". Layout by Urszulka. Powered by WordPress with QuickLaTeX.com.