niedziela, 23 stycznia 2011

Programowanie karty graficznej - shadery

Początkowo w tytuł miał brzmieć tylko "Programowanie karty graficznej" jednak od jakiegoś czasu (kilku lat właściwie) taki tytuł jest niejednoznaczny. Pod terminem programowanie karty graficznej kryje się zarówno pisanie shaderów w ramach programowalnego potoku renderingu jak i użycie technologii takich jak CUDA, OpenCL i DirectCompute (czyli wykorzystanie mocy obliczeniowej karty graficznej do dowolnego zadania). Tym razem zajmę się pierwszym zagadnieniem czyli tym do czego karty graficzne powstały.

 Aktualnie najbardziej popularne API graficzne to OpenGL i Direct3D (wchodzące w skład "bezpośredniego X" :)). Obie biblioteki obsługują programowalny potok renderingu i mają własne wysokopoziomowe języki do pisania shaderów. Własne jest tutaj słowem kluczowym ponieważ oba języki są inne i niekompatybilne. Dlatego jest też trzecia droga :) opracowany przez NVIDIA (we współpracy z Microsoft dlatego jest podobny do HLSL) język Cg.

Na co komu trzecie rozwiązanie? Odpowiedź jest oczywista - aby mieć jeden by wszystkimi rządzić - niebywałą zaletą Cg jest to że współpracuje z obiema bibliotekami.
Jak to działa? Najpierw potrzebujemy Cg Toolkit (dostępny za darmo) z którym są dwie możliwości.
  1. Dodajemy biblioteki do obsługi Cg i w ten sposób importujemy i obsługujemy shadery. Ten sposób ma tę zaletę, że każdy shader będzie kompilowany przy uruchomieniu aplikacji i będzie optymalizowany pod obecną kartę graficzną (przynajmniej tak chwalą się twórcy w dokumentacji)
  2. Możemy też skompilować shader do użycia z wybraną przez nas biblioteką i pod wybraną wersję Pixel i Vertex Shadera i używać go jakby został napisany w języku natywnym dla wybranej biblioteki.

Jednak najbardziej w wykorzystaniu Cg podobają mi się pliki efektów CgFX. Czym jest efekt? Jest to zbiór technik pozwalających uzyskać jakiś efekt. Dzięki temu można w jednym pliku zdefiniować kilka technik kompatybilnych z różnymi wersjami shaderów i wybrać najnowszą obsługiwaną wersję.

Pojedyncze technika natomiast może zawierać kilka przejść (z ang. pass) co w połączeniu z prostym API pozwala na tworzenie złożonych efektów bez potrzeby specjalnego budowania kodu w celu ich uzyskania (trzeba tylko dodawać odpowiednie zmienne, jednak plik efektu pozwala na zastosowanie domyślnej wartości). Tak wygląda najprostszy efekt (niestety nie ma kolorowania składni):
float4x4 ModelViewProj : ModelViewProjection;

void PassThru_vs(float4 position : POSITION,
             float4 color : COLOR,
             
         out float4 oPosition : POSITION,
         out float4 oColor : COLOR,
         
     uniform float4x4 modelViewProj)
{
    oPosition = mul(modelViewProj, position);
    oColor = color;
}

float4 PassThru_ps(float4 color : COLOR) : COLOR
{
    return color;
}

Technique PassThru
{
    pass PassThru_0
    {
        VertexProgram = compile vp20 PassThru_vs(ModelViewProj);
        FragmentProgram = compile fp20 PassThru_ps();
    }
}

Wszystko fajnie ale za Cg stoi NVIDIA więc co z kartami innych producentów? Nie ma problemu, shader kompilowany jest pod konkretne profile które odpowiadają odpowiednim wersją shaderów więc każda karta która trzyma się standardów będzie poprawnie obsługiwać tak napisany program.

Brak komentarzy: