• Ei tuloksia

CG – C för Grafik

N/A
N/A
Info
Lataa
Protected

Academic year: 2022

Jaa "CG – C för Grafik"

Copied!
26
0
0

Kokoteksti

(1)

CG – C för Grafik

Fredrik Bärg

Institutionen för Informationsbehandling Åbo Akademi, FIN-20520 Åbo, Finland E-post: fbarg@abo.fi

(2)

Abstrakt

Nvidia Corporation har nyligen släppt ett nytt språk för att förflytta vertex- och pixelprogrammering till en högre nivå. Det enda sätt som funnits om man velat programmera vertex- eller pixelshaders har varit att programmera i krånglig assemblerkod. Cg är ett språk som underlättar programmeringen av shaders. Artikeln kommer att innehålla information om språket i sig och lite beskrivningar av dess struktur.

ACM – Klassificering

I.3.3 Picture/Image generation, I.3.4 Graphics Utilities,

I.3.7 Three-Dimensional Graphics and Realism

Innehållsförteckning Sid

1 Inledning

1

2 Programmerbarhet i grafikprosessorer

2

3 Shaders

3

3.1 Vertex shaders

3

3.2 Pixel shaders

4

4 CG – C for graphics

5

4.1 Definition

5

4.2 Programmeringsmodell

5

4.3 Programinput och –output

6

4.3.1 Programinput 6

4.3.2 Varierande input till ett vertexprogram 7 4.3.3 Varierande output till och från vertexprogram 7

4.3.4 Varierande output från fragmentprogram 8

4.3.5 Uniforma input 8

4.4 Datatyper

8

4.4.1 Standard datatyper 8

4.4.2 Typkonverteringar 9

4.4.3 Strukturer 10

4.4.4 Räckor 10

4.5 Uttryck och operatorer

10

(3)

4.5.1 Kontrollflöde 11 4.5.2 Funktionsdefinitioner och funktionsöverladdning 11

4.5.3 Aritmetiska funktioner från C 11

4.5.4 Multipliceringsfunktionen 12

4.5.5 Vektorkonstruktor 12

4.5.6 Boolska operationer och jämförelseoperationer 12

4.5.7 Swizzle operator 13

4.5.8 Skrivmaskoperator 13

4.5.9 Konditionell operator 13

4.6 Standard biblioteksfunktioner

14

4.6.1 Structs som använder bindande semantik 14

4.6.2 Matematiska funktioner 15

4.6.3 Geometriska funktioner 18

4.6.4 Texture map funktioner 18

4.6.5 Derivatafunktioner 20

4.7 Cg run-time bibliotek

20

5 Sammanfattning

21

(4)

1 Inledning

Vi lever i en värld där informationsteknologi har fått allt större betydelse i samhället.

Med denna betydelse har det också blivit viktigt att effektivt kunna använda sig av denna teknologi och att kunna interagera med den. Flera olika sätt finns i nuläget för att göra just detta. Det vanligaste och kanske viktigaste sättet att förmedla information åt användare av informationsteknologi är genom bilder som ses på t.ex. en dataskärm.

Eftersom stor vikt sätts vid just bildpresentation har också tekniken för att generera dessa bilder haft ett behov av att förbättras och utvecklas.

Utvecklingen av grafikhårdvaran har gått med rask takt. Det är inte så många år sedan som man bara i sina vildaste fantasier kunde föreställa sig de bilder som grafikkort av idag lyckas framställa. Fotorealismen börjar så småningom vara verklighet, dvs. att man inte mera lyckas avgöra om en bild som man ser är dataanimerad eller ett foto taget i verkligheten. I en vanlig bordsdator finns i dagens läge grafikkort som kan åstadkomma samma saker som endast en dedikerad arbetsstation för ungefär hundratusen euro skulle ha kunnat göra för bara några år sedan. Utvecklingen har också gått mer och mer mot 3D-grafik och man ser hela tiden nya program där den tredje dimensionen utnyttjas effektivt för att bättre visualisera den information som programmet erbjuder. Den typ av program där det används överlägset mest 3d är nog ändå i speltillverkningen där utvecklingen håller ganska jämna steg med den nya grafikhårdvara som kommer ut.

Det enda sättet som har funnits för att kunna dra nytta av de krafter som en GPU har att erbjuda har varit genom s.k. API:n (Application Program Interface). Det finns idag två stora API:n som i huvudsak används, DirectX som styrs av Microsoft och OpenGL, som är en öppen standard. Den snabba utvecklingen av GPU:n har också inneburit att dessa API:n inte alltid hänger med. De stora tillverkarna av GPU:n (ATI Technologies Inc. och Nvidia Corporation) kommer hela tiden fram med nya teknologier och nya effekter i sina prosessorer. Allt eftersom API:na och deras underliggande teknologier förändras, hamnar programmerare, grafiker och programvaruutgivare att adaptera till nya förhållandena. En inte alltid lätt uppgift.

(5)

Att grafikhårdvaran har blivit programmerbar har också inneburit en större utmaning för programmerare som vill förverkliga några av de effekter som GPU:na erbjuder.

Tidigare har de som velat använda någon speciell effekt på GPU:n varit tvungna att skriva anrop direkt till grafikkortet via ett lågnivåspråk, en ytterst tidsödande och krävande uppgift där det är lätt att göra små fel. Med alltmer komplexa GPU:n, som har ännu mera programmerbarhet, kommer detta att bli en otroligt komplicerad uppgift. Ett högnivåspråk behövs för att effektivt kunna accessera den komplexa GPU:n.

2 Programmering av grafikprosessorer

Förmågan att programmera grafikpipelinen är relativt ny. Det är först de senaste två åren som det blivit möjligt att direkt programmera olika steg i grafikkortspipelinen.

Nya GPU:n (Graphics Processing Unit) har kommit ut med ungefär ett halvt års mellanrum och varje ny generation fördubblar prestandan. När det gäller mikroprosessorer så har Moores lag varit gällande ett antal år redan. Men när det gäller grafikkort och grafikprocessorer så har moores lag satts ur spel.

Utvecklingstakten är så pass stor för tillfället att den motsvarar tre gånger den utvecklingstakt som moores lag säger. Denna kraft och prestanda har också möjliggjort skapandet av 3D-miljöer som på ett naturtroget sätt kan efterlikna den verkliga världen. Men för att kunna utnyttja kraften måste man kunna komma åt hårdvaran på ett så effektivt sätt som möjligt.

Grafikkortspipelinen kan delas upp i tre distinkta delar. Primitivprocessering, vertexprocessering och fragmentprocessering. Det första steget i pipelinen tar spel- eller programspecifik data och datastrukturer och producerar flera vertex för vertexprosessorn att prosessera. Det andra skedet prosesserar alla uträkningar som har med vertex att göra och det sista skedet beslutar slutligen vad enskilda pixlar skall ha för färg.[2]

(6)

3 Shaders

En shader kontrollerar hur en triangel i en 3D-scen är belyst och färgad. Detta inkluderar hur den svarar mot diffus, reflektiv, ambient samt ljusalstrande belysning.

Vertex shaders ersätter det normala transformations och belysningssteget av grafikkortspipelinen, medan pixel shaders, fungerande på rasteriseringssteget, inverkar på hur den slutgiltiga skärmfärgen bestäms. Det finns stöd för shaders i DirectX 8 och senare versioner och i OpenGL genom extensioner (och som en del av den föreslagna OpenGL 2.0 standarden).

3.1 Vertex shaders

De punkter som tillsammans bildar en triangel, polygon eller liknande kallas med en gemensam benämning för en vertex. En vertex shader ersätter som tidigare sagts transformations och belysningssteget i grafikkortpipelinen. Det går att dela in vertexprocesseringen i ett antal olika steg nämligen: transformationer, ljussättning och i viss mån textur-kordinat transformationer.[2]

Transformationer innebär att man tar positionsdata såsom det är sparat i vertexen och transformerar det till en skärmrymdposition. Skärmrymden refererar till det tvådimensionella plan som representerar betraktarens fönster in i världen, dvs bilden som ses på en monitor är en representation av betraktarens position i spelvärlden. Vid traditionell vertexprocessering så förmedlas positionsdata från den otransformerade vertexen till den transformerade utan att göra någonting åt datat eller så förmedlar den vertexarna genom en världstransformationsmatris, följt av en vymatris och slutligen en projektionsmatris.[2]

Det har blivit allt vanligare i nyare spel att använda sig av dynamisk ljussättning. Till skillnad från statisk ljussättning, som är uträknad i förväg och sparad som en textur eller ljuskarta (eng. lightmap), räknas dynamisk ljussättning ut per vertex. I framtiden kommer säkert den dynamiska ljussättningen att mer och mer göras i pixelprocesseringslagret även om vertexprosessorn fortfarande kommer att förbereda datat för pixelprocessorn.[2]

(7)

Texturtransformationer involverar att förmedla texturkordinaterna inuti vertexformatet till pixelrasteriseringsblocket. För det mesta gör detta processeringsblock inget annat än att skicka vidare texturkordinaterna. Men i det fallet att animerade texturer används så är det möjligt att göra en matristransformation på texturkordinaterna för att åstadkomma texturanimation utan att ändra på vertexarna, vilket annars skulle innebära att vertexarna skulle modifieras i videobussen och senare behöva skickas över AGP(Advanced Graphics Port)-bussen, vilket är en väldigt dyr operation i nuläget. Texturtransformationsblocket kan också användas för att räkna ut texturkordinater för sfärisk- och kubreflektionskartläggning.[2]

En vertex shader tillåter en programmerare att specificera ända upp till 128 instruktioner som grafikkortet skall utföra på varje vertex. Om grafikkortet själv inte stöder vertex shaders kan de fortfarande processeras på CPU:n. Med äldre TnL (Transform & Lighting) grafikkort är det ofta möjligt att utföra enkel processering mycket snabbare genom att använda de fixerade funktioner som dessa kort har. Alltså utan att använda vertexshaders.[1]

3.2 Pixel shaders

En pixel shader eller pixelrasteriserare tar den information som den får från vertexprosessorn och räknar ut en slutlig pixelfärg baserat på denna. Ett exempel av dess användning kan vara att ta en diffuserad färg och multiplicera den med texturfärgen (genom att använda texturkordinaterna för att hämta en färg från texturen). En annan metod kunde vara att addera till en färg från en reflektionstextur genom att använda sig av ett annat set med texturkordinater.[2]

Pixelshaderinterfacet är mera förvillande än vertexshaderinterfacet och har många restriktioner. Den viktigaste är att pixelshaders endast kan processeras på grafikkort som stöder dem, så för äldre hårdvara måste programutvecklaren utveckla både pixelshaderteknologi och sådan teknologi som saknar pixelshaders. Detta har också inneburit att pixelshaders används mer som extra features och därför läggs inte så mycket tid på dessa. Mer tid läggs i stället på programmering av kärngrafiken.[1]

(8)

4 CG – C for Graphics

Nvidia Corporation introducerade den 13:e juni 2002 en specifikation för CG – C for Graphics. Ett högnivåspråk med aspiration till att bli en standard för shaderprogrammering. Det är det första initiativet som tagits i denhär riktningen och de preliminära reaktionerna har varit positiva bland spel- och programutvecklare. Cg är ett funktionellt språk som inte är implementationsspecifikt när det gäller hårdvara.

Det går alltså att använda sig av Cg även för GPU:n av andra fabrikat än Nvidia, vilket är en förutsättning för att språket skall ha någon chans att bli en standard.

Språket är plattformsoberoende och går således att kompilera och köra på vilket operativsystem och vilken grafikhårdvara som helst (en förutsättning för detta är dock att det är någon typ av GPU som kan programmeras). Det är också relativt framtidssäkert, eftersom Cg går att anpassa till ny teknik då den kommer. Kompilern kan t.ex. optimisera för en ny GPU som kanske inte ens existerade när det ursprungliga programmet skrevs.

Cg är ett HLSL (High Level Shader Language) som utvecklats med syftet att göra livet enklare för programmerare som vill använda sig av vertex- och pixelshaders.

4.1 Definition

Cg är baserat på programmeringsspråket C och delar därför många karakteristika med det. Cg har samma syntax för deklarationer, funktionsanrop och de flesta datatyper som C men innehåller vissa förbättringar och ändringar som gör det enkelt att skriva program som kan kompileras om till väldigt optimiserad GPU-kod.[3]

4.2 Programmeringsmodell

CPU:n har normalt endast en programmerbar prosessor. Det är då att jämföra med en GPU som har åtminstone två programmerbara prosessorer, en vertexprocessor och en fragmentprocessor, och andra icke programmerbara delar. Prosessorerna, de icke programmerbara delarna och applikationen är alla sammanlänkade genom dataflöden.

Figur 1 visar Cg:s modell av GPU:n i ett dataflödesdiagram.

(9)

Figur 1 CG:s modell av GPU:n

Med Cg kan man skriva program till både vertexprocessorn, så kallade vertexprogram eller vertex shaders, och fragmentprocessorn, kallade pixelprogram eller pixel shaders.[3]

4.3 Programinput och –output

De programmerbara prosessorerna i en GPU opererar på strömmar av data.

Vertexprocessorn opererar t.ex. på en ström av vertexar och fragmentprosessorn opererar på en ström av fragment

I en vanlig CPU exekveras ett program endast en gång medan det i en GPU exekveras upprepade gånger, en gång för varje dataelement i en ström. Vertexprogrammet körs en gång för varje vertex, medan fragmentprogram körs en gång för varje fragment.

Cg har inbyggt stöd för denna ström-baserade programmeringsmodell.[3]

4.3.1 Programinput

Ett Cg-program kan behandla två olika typer av input, variabla och uniforma inputs.

Variabla inputs används för data som är specificerad för varje element av inputdataströmmen. Till exempel är variabla inputs till ett vertexprogram de per-

(10)

vertex värden som är specificerade i vertexräckor. I ett fragmentprogram är interpolanterna såsom texturkordinater varierande input.

Uniforma inputs används för värden som är specificerade separat från huvudströmmen av inputdata och som inte ändrar för varje element i strömmen. Ett vertexprogram behöver t.ex. en transformationsmatris som uniformt input. Uniforma inputs ses ofta som grafiktillstånd.[3]

4.3.2 Varierande input till ett vertexprogram

Ett vertexprogram kan vanligtvis ta emot flera olika varierande inputs. Till exempel så kan ett vertexprogram behöva få specifikationer från applikationen för följande inputs: modellens rymdposition för varje vertex, modellens rymdnormalvektor för varje vertex och texturkordinaten för varje vertex.

I en programmerbar grafikpipeline finns det inga predefinierade inputs. Det är helt resonabelt för en programutvecklare att skriva ett vertexprogram som använder sig av ett per vertex refraktivt indexvärde så länge som applikationen tillhandahåller detta värde för varje vertex.

Cg stöder två olika mekanismer för att specificera dessa flexibla per-vertex inputs.

Första mekanismen använder sig av bindande semantik, dvs fördefinierade namn. Det är också möjligt att skippa den bindande semantiken, men då måste applikationen istället referera till varje parameter med dess namn istället för dess bindande semantik. Om bindande semantik inte används måste alla de varierande programparametrarna finnas i en enda struct som måste annoteras för att indikera att den representerar data som överförs från applikationen till vertexprogrammet.[3]

4.3.3 Varierande output till och från vertexprogram

Output:en från ett vertexprogram passerar genom en rasteriserare och görs sedan tillgänglig åt ett fragmentprogram i formen av varierande input. För att ett vertexprogram och ett fragmentprogram skall kunna operera tillsammans måste de samsas om det data som passerar mellan dem.[3]

(11)

Så som var fallet med dataflödet mellan applikationen och vertexprogrammet stöder Cg två olika mekanismer för att specificera dataflödet mellan vertex- och fragmentprogrammen. Den första mekanismen använder bindande semantik, medan den andra tillåter att bindande semantik bortlämnas.[3]

Cg tillåter att det mesta av den bindande semantiken bortlämnas, men för att säkerställa att vertex- och fragmentprogrammen kan fungera tillsammans måste båda använda sig av samma struct för deras respektive output och input.[3]

4.3.4 Varierande output från fragmentprogram

Bindande semantik krävs alltid för output:en från fragmentprogram.Följande bindande semantik finns tillgängliga i alla Cg fragmentprofiler: color och depth. Av bekvämlighetsskäl finns det en fragout struct fördefinierad i Cg:s standardbibliotek som alltid är tillgänglig fast man inte explicit har definierat den.[3]

4.3.5 Uniforma input

Vertex- och fragmentprogram i Cg kan också acceptera uniforma input. Ett Cg vertexprogram tar t.ex. vanligtvis en modellvy eller projektionsmatris som en av dess uniforma inputs. Ett uniformt input specificeras genom att använda uniform nyckelordet.

4.4 Datatyper

Cg stöder flera olika features som skapar och manipulerar data. T.ex. standard datatyper, strukturer, räckor och typ-omändringar.

4.4.1 Standard datatyper

Cg har stöd för fem olika datatyper: float, half, fixed, bool och sampler*, varav sampler finns i fem olika varianter: sampler1D, sampler2D, sampler3D, samplerCUBE och samplerRECT.[3]

(12)

Cg innehåller också inbyggda vektordatatyper som är baserade på de primära datatyperna. Exempel på några av dess är float4, float3, float2 och float1 samt bool4, bool3, bool2 och bool1.[3]

Stöd finns också för matriser som är ända upp till 4x4 element. Ett exempel på hur en sådan deklaration skrivs är följande: float4x2 matrix1; vilket skapar en 4x2 matris.[3]

En sak som man bör observera är att Cg inte innehåller någon int datatyp. De flesta grafikhårdvarorna stöder inte en int datatyp, därför är den heller inte inkluderad i språket. I vanliga fall går float och bool typerna att använda istället för int.[3]

4.4.2 Typkonverteringar

Typkonverteringar i Cg fungerar ungefär som de gör i C. Typkonverteringar kan explicit specifieras genom att använda C:s (newtype) typecast operator.[3]

Cg utför automatiskt typbefordringar då man utför operationer med två olika typer av data. T.ex. så blir uttrycket

floatvar * halfvar automatiskt kompilerat som

floatvar * (float) halfvar

Cg använder sig av andra regler vid automatisk typbefordring än i C endast i ett fall.

En konstant utan någon explicit typsuffix orsakar inte någon typbefordring. T.ex. så blir uttrycket

halfvar * 2.0 kompilerat som

halfvar * (half) 2.0 [3]

Som jämförelse kan nämnas att C i ovanstående fall skulle ha kompilerat det som ((double) halfvar) * 2.0. Cg använder sig av andra regler här för att minimera uträkningar som kanske är oavsiktliga men som orsakar uträkningarna att göras i en långsammare högprecisionsaritmetik.[3]

(13)

Om man vill ha tillbaka C:s uppträdande i sådana här fall så måste man skriva konstanten så att man explicit visar vilken typ den är. För detta ändamål så kan man efter konstanten lägga antingen ett f som står för float, ett h som står för half eller ett x som står för fixed. Exempelvis så blir:

halfvar * 2.0f kompilerat som

((float) halfvar) * 2.0f.[3]

4.4.3 Strukturer

Cg stöder strukturer på samma sätt som C. Cg använder sig av C++ konventionen som implicit kör en typedef baserat på namnet när en struktur är deklarerad.

struct mystruct { ... };

mystruct s; // Definierar s som mystruct [3]

4.4.4 Räckor

Det finns stöd för räckor i Cg och de deklareras precis som i C. Eftersom Cg inte stöder användandet av pekare måste räckor alltid definieras användande räck-syntax istället för pekar-syntax.[3]

4.5 Uttryck och operatorer

Cg stöder uttryck och operatorer för att åstadkomma något av följande:

- kontrollflöde

- funktionsdefinitioner och funktionsöverladdningar - aritmetiska operatorer från C

- multipliceringsfunktionen - vektorkonstruktion

- boolska operatorer och jämförelseoperatorer - swizzle operator

- skrivmaskoperator - konditionell operator [3]

(14)

4.5.1 Kontrollflöde

Cg använder sig av följande C kontrollkonstruktorer:

- funktionsanrop och return uttrycket - if/else

- while - for

Dessa kontrollkonstruktorer kräver att deras konditionella uttryck är av typen bool.

Eftersom Cg-uttryck såsom i <= 3 är av typen bool, märks denna ändring från C inte så bra.

Funktionsrekursion är förbjuden i Cg.[3]

4.5.2 Funktionsdefinitioner och funktionsöverladdning

Cg överför modifierbara funktionsparametrar per värde eller resultat istället per referens eftersom vertex- och fragmenthårdvaran på GPU:n inte stöder användandet av pekare.

Cg stöder funktionsöverladdning per antalet operander och per operandtyp. Valet av en funktion sker genom att matcha varje operand för sig, börjande från den första operanden.[3]

4.5.3 Aritmetiska operatorer från C

Cg inkluderar alla standard aritmetikoperatorer från C och låter dem användas på såväl vektorer som skalärer. Vektoroperationerna sker alltid per element. T.ex.

float3 (a,b,c) * float3 (A,B,C) blir float3 (a*A,b*B,c*C) Operationerna kan också göras i en blandad skalär-/vektorform, dvs.

a * float3 (A,B,C) blir float3 (a*A,b*B,c*C).[3]

(15)

4.5.4 Multipliceringsfunktionen

Cg:s mul() funktion används för att multiplicera matriser med vektorer och för att multiplicera matriser med matriser.[3]

4.5.5 Vektorkonstruktor

Cg tillåter vektorer som är ända upp till storlek 4, att bli konstruerade genom följande notation. Vektorkonstruktorn kan vara var som helst i uttrycket:

y = x * float4 (3.0, 2.0, 1.0, -1.0);[3]

4.5.6 Boolska operatorer och jämförelseoperatorer Cg inkluderar tre standard boolska operatorer från C:

- &&

- ||

- !

I C tar dessa operatorer in och ut int-värden men i Cg tar de in och producerar bool- värden. Cg stöder också C:s jämförelseoperatorer som producerar värden av typen bool:

- <

- <=

- !=

- ==

- >=

- >

Till skillnad från C tillåter Cg alla boolska operatorer att operera på vektorer i vilket fall den boolska operationen utförs per element.[3]

(16)

4.5.7 Swizzle operator

Cg har en så kallad swizzle-operator, ., som låter komponenterna av en vektor byta plats för att åstadkomma en ny vektor. Den nya vektorn behöver inte vara av samma storlek som den ursprungliga, element kan upprepas eller lämnas bort fullständigt.

Bokstäverna x, y, z, och w representerar den första, andra, tredje och fjärde komponenten av orginalvektorn. Bokstäverna r, g, b, och a kan användas för samma ändamål. Eftersom swizzle-operatorn är effektivt implementerad i hårdvaran är den oftast gratis att använda.

Ett exempel på dess användning:

float3 (a,b,c).zyx blir float3 (c,b,a)

Swizzle operatorn kan också användas för att skapa en vektor av en skalär:

a.xxxx blir float4 (a,a,a,a)[3]

4.5.8 Skrivmaskoperator

När den är placerad på vänstra sidan om en uppgift, är . operatorn använd för skrivmaskning. Den kan användas för att selektivt skriva över komponenterna i en vektor. Det är förbjudet att specificera en särskild komponent fler än en gång i en skrivmask.[3]

4.5.9 Konditionell operator

I Cg finns inkluderat C:s if/else funktionalitet, likaså ? : konstruktet. Med ? : konstruktet så kan kontrollvariabeln vara en boolsk vektor. I detta fall så måste den andra och tredje operanden vara likaledes stora vektorer och urval sker på elementbasis. Cg förbjuder den andra och tredje operanden från att producera sidoeffekter. Specifikt så kan inte den andra och tredje operanden vara uttryck som kallar på en funktion med en out parameter.[3]

(17)

4.6 Standard biblioteksfunktioner

CG tillhandahåller ett antal inbyggda funktioner och fördefinierade strukturer med bindande semantik för att förenkla GPU-programmering. Dessa funktioner är liknande till standard biblioteksfunktioner i C på så sätt att de ger ett bekvämt set med vanliga funktioner. I de flesta fall kartläggs funktionerna till en enkel inbyggd GPU- instruktion vilket betyder att de utförs väldigt snabbt.

Specifika funktioner kan ändras om det av prestanda eller kvalitetsskäl är nödvändigt, men oftast så är det bättre att använda sig av standardbiblioteket eftersom dess funktioner är optimiserade för framtida GPU:n. Detta betyder att en shader som skrivs idag inte är föråldrad då nyare arkitekturer av hårdvara kommer i framtiden. En fördel med standardbiblioteket är också att det tillhandahåller ett bekvämt ihopsatt interface för vertex- och fragmentprogram.[3]

4.6.1 Structs som använder bindande semantik

Flera structer som använder bindande semantik är fördefinierade i standardbiblioteket beroende på vilken profil som används.Det finns tre färdigdefinierade structer, av20, vf20 och fragout.

Av20 structen kopplar ihop en applikation med ett vertexprogram och innehåller den konventionella listan över parametrar som förs över från applikationer till vertexprogram.

Vf20 är en vertex till fragment kopplande struct. Det som den gör är att den definierar ett standardset av parametrar som förs över från vertexprocessering till fragmentprocessering

Den tredje structen med bindande semantik som definieras i standarbiblioteket är fragment till skärmbuffert kopplande och kallas fragout.[3]

(18)

4.6.2 Matematiska funktioner

Cg har stöd för en mängd matematiska funktioner inom trigonometri, exponering, avrundning och vektor- och matrismanipulationer bland annat. Alla funktioner fungerar på skalärer och vektorer av alla möjliga storlekar förutom i vissa enskilda fall där specialregler finns. Följande tabell visar vilka funktioner som är möjliga med Cg.[3]

Tabell 1 Cg:s matematiska funktioner (C) Nvidia Corporation

(19)
(20)
(21)

4.6.3 Geometriska funktioner

Cg stöder ett mindre antal geometriska funktioner i standardbiblioteket vilka kan ses i tabell 2.

Tabell 2 Cg:s geometriska funktioner (C) Nvidia Corporation

4.6.4 Texture map funktioner

Tabell 3 visar de texturfunktioner som tillhandahålls av Cg:s standardbibliotek. För tillfället stöds dessa funktioner endast av Nvidia:s fp30-profil (denna profil innehåller de funktioner som Nvidia:s nya grafikkort, som kommer ut i februari 2003, stöder),

(22)

men dessa funktioner kommer också att stödas av alla framtida profiler som har texturekartläggningsfunktionalitet.

I tabellen så kan istället för t stå f, h eller x för att indikera returneringstypen float, half eller fixed. På samma vis så står n istället för 1, 2, 3 eller 4 för att indikera en returneringstyp som är en skalär, två vektorer, tre vektorer eller fyra vektorer.

Tabell 3 Cg:s texture map funktioner (C) Nvidia Corporation

(23)

4.6.5 Derivata-funktioner

Tabell 4 visar de derivatafunktioner som Cg stöder i sitt standardbibliotek. Dessa funktioner stöds endast i fp30 profilen.

Tabell 4 Cg:s derivatafunktioner (C) Nvidia Corporation

4.7 Cg run-time biblioteket

Cg kompilern kan användas på två olika sätt, antingen för off-line kompilering eller för run-time kompilering.

Off-line kompilering innebär att Cg kompilern används av applikationsutvecklaren som ett command-line verktyg under applikationsutvecklingen för att kompilera Cg-

(24)

kod så att den omvandlas till GPU assemblerspråk. Applikationen är ansvarig för att använda denna assemblerkod på samma vis som den skulle vara ansvarig för att använda ett handskrivet vertex- eller fragmentprogram.

Run-time kompilering innebär att Cg-kompilern anropas av applikationen vid körtid, genom en run-time API. Run-time API:n levererar ytterligare egenskaper bortom kompileringen. Det viktigaste är att den låter applikationen manipulera inputs till ett Cg-program genom att använda samma parameternamn som uppkommer i prototypen av Cg-programmet. Utan denna förmåga, måste input:en till ett GPU-program manipuleras med hjälp av hårdvaruregistren. Run-time API:n är det enklaste sättet att använda Cg i en applikation.

4.7.1 Egenskaper levererade av run-time API:n

Cg run-time:n levererar alla de egenskaper som finns tillgängliga åt en applikation. På grund av skillnaderna mellan OpenGL och Direct3D är några av dessa egenskaper implementerade genom att använda olika rutiner för OpenGL och Direct3D versionerna av run-time:n. En [*] indikerar sådana egenskaper i listan här nere.

- Kompilera ett Cg-program levererat via en string eller en fil.

- Sända den kompilergenererade assemblerkoden till den underliggande API.n (OpenGL eller Direct3D). [*]

- Binda till ett Cg-program i förberedelse för renderingen (alltså välja tidigare kompilerade Cg vertex- och fragmentprogram för att rendera en hop med geometri). [*]

- Göra en förfrågan för att få reda på listan över uniforma och varierande (per vertex) parametrar som behövs av ett program.

- Göra en förfrågan om typen av en särskild parameter.

- Sätta värdet av en uniform parameter till ett program. [*]

- Göra ändringar i en av texturdelarna/samplers som används av ett program. [*]

- Specificera en vertex-räcka som kan användas för varierande parametrar till ett program. [*]

- Göra en förfrågan om vilket hårdvaruregister en viss parameter använder.

(25)

5 Sammanfattning

Nvidias satsning på Cg kan ses som ett steg i rätt riktning. Ingen programmerare vill hålla på och skriva jobbig assemblerkod när det finns alternativ som är lättare. Cg har lyckats i det hänseendet att det har gjort vertex- och pixelshaderprogrammering mera överskådlig. Likheten till C gör att kodningen känns mera familjär för programmerare som vill lära sig språket. Det blir således lättare för nya programmera att greppa tag i språket och börja använda sig av shaders i sina program.

Det finns fortfarande många frågetecken vad gäller accepterandet av Cg som standard.

Det som kan förorsaka lite försiktighet är att endast Nvidia själv har rättigheterna att ändra på specifikationerna till språket. Detta ger Nvidia en något ojust fördel eftersom de skulle kunna ändra specifikationerna på Cg när de vill för att bättre kunna matcha det med sin nya hårdvara, således skulle det alltid vara deras egna grafikkort som skulle vara bäst lämpade.

Just nu för tillfället så är Cg det bästa (och enda) programmerinsspråket för att skriva vertex och pixelshaders, men hur kommer situationen att se ut om ett år? DirectX 9.0 kommer att ha ett inbyggt HLSL och ingen vet ännu hur enkelt eller svårt det är att använda. Om man ser åt andra hållet så kommer även OpenGL i sin 2.0-version att innehålla möjlighet att programmera vertex- och pixelshaders. Det är tiden som får utvisa om Nvidias satsning bär frukt.

Personligen tror jag att Nvidia kan få det lite svårt att nå sitt mål att göra Cg till en standard. Allt hänger väl egentligen på om Nvidia kan tänka sig att lägga in stöd för funktioner som endast deras konkurrenter har. Om de skulle utveckla språket på det viset så tror jag faktiskt att deras drömmar om att få det till en standard kan gå i uppfyllelse. Men eftersom Nvidia är ett kommersiellt företag som måste gå på vinst så kan det bra vara så att de inte vill slå benen under sig och stöda sådana funktioner i Cg som skulle kunna gynna konkurrenterna.

(26)

Referenser

[1] HLSL's, Cg and the RenderMonkey (Tom’s Hardware Guide) [www]

http://www6.tomshardware.com/graphic/02q4/021004/index.html, hämtat 20.11.2002

[2] Vertex shaders and pixel shaders (Tom’s Hardware Guide) [www]

http://www6.tomshardware.com/graphic/02q1/020116/index.html, hämtat 20.11.2002

[3] CG Toolkit User’s Manual (Nvidia Corporation) [www]

http://download.nvidia.com/developer/cg/Cg_Users_Manual.pdf, hämtat 20.10.2002

Viittaukset

LIITTYVÄT TIEDOSTOT

Om jag skulle utskilja den specifika princip som ligger till grund för alla emotioner, går den för Mishnas del ut på, att känslor måste hållas under kont-

För att decentraliserad reglering skall fungera (tillräckligt bra) måste det finnas naturliga par av in- och utsignaler som står för den dominerande dynamiken i systemet. Om in-

För att dimensioneringen av vården inte ska sänkas, måste övergångsbestämmelsen fortfarande föreskriva att den vård och omsorg som tillhandahålls vid verksamhetsenheten ska

Utskottet anser det i vilket fall som helst vara viktigt att lagen om utkomststöd ses över i sin.. En översyn måste fokuseras på att stärka utkomststödets roll för

Vi måste naturligtvis stärka vårt utbildnings- system i detta hänseende, men i den globala världen behöver vi en strategi för att locka de toppförmågor som redan finns till

Och sedan alla idéer om att vi ska vara företagsaktiga inom universiteten – det måste också fi nnas plats för röster som inte tycker vi ska vara företagsaktiga utan att

För att bereda plats för denna måste man nämligen riva den svensk-finska församlingens enda kyrka i Helsingfors, den snart hundraåriga Ulrika Eleonora kyrkan som uppfördes efter

Som en klar fördel för samarbetet mel- lan de finlandssvenska journalisterna och språkvårdarna måste ses det faktum att fle- ra av språkvårdarna har haft tillfälle att inte