OpenGL programmerbare prosessorer

Thu 31 December 2009

Her vil vi gå kort igjennom de to prossesortypene vi har å forholde oss til. Hvilken muligheter og begrensinger disse gir oss. Før du leser videre kan det kanskje være interessant for deg å lese

Programmerbare prosessorer

Vertex prosessor

Vertex prosessoren jobber, som navnet tilsier, med vertex verdier og data.

  • Vertex transformasjon
  • Normal transformasjon og normalisering
  • Texture koordinater generering
  • Lyssetting
  • Color material

Vertex prosessoren er en "general-purpose" unit og kan behandle et stort spekter av kalkuleringer. En shader som er skrevet for vertex prosessoren kalles "Vertex shader". Et viktig poeng når det gjelder vertex shadere er at skal du bruke en shader må den implementere all fixed funksjonalitet som den erstatter.

Implementerer vi en avansert lyssetting må vi også ha med vertex og normal transformasjoner i shaderen. Vi kan ikke gjøre litt i fixed og resten i programmerbar shader.

Variabler

Vi har to typer variabler inn til en vertex shader.

Attributer (glsl: ATTRIBUTE VARIABLES) er typisk verdier som ofte sendes mellom programmet og vertex prosessoren. Vi har to typer attribute variabler, innebygde og brukerdefinerte.

Innebygde attribute variabler Brukerdefinerte attribute variabler
  • gl_Color
  • gl_Normal
  • gl_Vertex
  • gl_MultiTexCoord0
  • ...osv...
  • StartColor
  • Velocity
  • Elevation
  • Tangent
  • ...osv...

Attribute variabler blir satt mellom glBegin og glEnd og er den eneste måten vi kan definere variabler på pr.vertex basis. Attribute variabler kan leses, men ikke skrives i vertex shadere. Attribute variabler er ikke tilgjengelig for fragment shadere.

Uniformer (glsl: UNIFORM VARIABLES) er verdier som går fra programmet til vertex eller fragment prosessoren, og er typisk statisk over en frame/primitive/scene. Vi har to typer uniforme variabler, innebygde og brukerdefinerte.

Innebygde uniforme variabler Brukerdefinerte uniforme variabler
  • gl_ModelViewMatrix
  • gl_FrontMaterial
  • gl_LightSource[0]
  • gl_Fog
  • ...osv...
  • ModelScaleFactor
  • EyePos
  • Epsilon
  • LightPosition
  • ...osv...

Uniforme variabler kan kun settes av primitiver og kan derfor ikke brukes pr. vertex. Uniforme variabler kan leses, men ikke skrives i vertex og fragment shadere.

lighting-phong

Per Fragment Lighting using phong shading model (phong fragment shader)

author

Vi har to typer variabler ut fra en vertex shader.

Varierende (glsl: VARYING VARIABLES) er data som blir sendt mellom vertex og fragment prosessor. Brukes for data som skal interpoleres som f.eks farger, normaler, tekstur koordinater med mer. Vi har to typer varierende variabler, innebygde og brukerdefinerte variabler.

Innebygde varierende variabler Egendefinerte varierende variabler
  • gl_FrontColor
  • gl_BackColor
  • gl_FogFragCoord
  • ...osv...
  • Normal
  • ModelCoord
  • RefractionIndex
  • ...osv...

Varierende variabler kan skrives i vertex shader, men kun leses i fragment shader. Vi må og deklarere varierende variabler både i vertex shader og fragment shader.

Eks: For pr.fragment kalkulering av lys (f.eks i phong fragment shader vist i bildet over) trenger vi Normalen til fragmentet. Men i OpenGL defineres Normaler kun pr.vertex, og er dermed kun tilgjengelig for vertex shaderen (via Attributet: gl_Normal). Vi må derfor lese Normalen av i vertex shaderen og sende den til fragment shaderen som en varierende variabel.

Spesielle (glsl: N/A) er vertexens homogoene posisjonkoordinat i clip space. Koordinaten lagres i variablen gl_Position. Vi har i tillegg to spesial variabler gl_ClipVertex og gl_PointSize som kan brukes til å lagre informasjon som trengs under clipping og rasterisering.

Innebygde spesial variabler
  • gl_Position
  • gl_PointSize
  • gl_ClipVertex

Annet

- Vertex prosessoren kan lese fra teksturminnet. Dette gjør at vi kan implementere f.eks displacement mapping i vertex shader.

- Teoretisk sett vil vertex prosessoren behandler en vertex om gangen, og vertex shaderen blir utført en gang pr. vertex. I praksis vil hardwaren kunne utføre operasjoner i paralell dersom det finnes flere vertex prosessorer i systemet.

Fragment prosessor

Jobber, ikke overraskende, med fragment verdier og tilhørende data.

  • Operasjoner på interpolerte verdier
  • Teksturer
  • Fog
  • Color sum

En shader skrevet for fragment prosessoren kalles en fragment shader. Akkurat som vertex shadere, så må fragment shadere implementere all fixed funksjonalitet som den erstatter.

Vi kan ikke bruke fixed line til å generere fog, og fragment shader til teksturer. Vi må gjøre alt i fragment shader eller med fixed funksjoanlitet. Vi kan heller ikke bruke en fragment shader dersom vi trenger å vite noe om flere fragmenter samtidig.

Fragment shaderen kan lese av pikselkoordinater, men ikke endre. Dette er motsatt av vertex shaderen som har tilgang til modelview og projection matrisene, og dermed anledning til å flytte vertexene.

Fragment prosessoren kan jobbe på fragmenter generert fra rasterisering av punkter, linjer, polygoner, piksel rektangler og bitmaps. Dersom en først laster bilder inn i teksturminnet kan fragment prosessoren også gjøre jobber som krever tilgant til et bestemt piksel og dets naboer.

  • Pixel zoom
  • Skalering og bias
  • Color table lookup
  • Convolution
  • Farge matrise

Variabler

Hoveddataene inn til fragment prosessoren kommer fra innebygde og brukerdefinerte varierende variabler. Brukerdefinerte varierende variabler må defineres i fragment shader og stemme overens med definisjonene i vertex shaderen. I tillegg har fragment prosessoren tilgang til data fra fixed funksjon operasjonene mellom vertex og fragment prosessorene. Disse kan vi nå v.h.a spesielle variabler (glsl: special input variables).

Innebygde varierende variabler Spesielle variabler Brukerdefinerte varierende variabler
  • gl_Color
  • gl_SecondaryColor
  • gl_TexCoord[0...n]
  • gl_FogFragCoord
  • gl_FragCoord
  • gl_FrontFacing
  • Normal
  • ModelCoord
  • RefractionIndex
  • Density

Akkurat som vertex shader har fragment shader tilgang til OpenGL tilstander gjennom innebygde uniformer. Ved å definere brukerdefinerte uniformer både i vertex og fragment shader kan disse brukes til å sende data til fragment shader.

En av de største fordelene med fragment prosessoren er at den kan lese teksturminnet. Vi kan lese flere verdier fra en tekstur, eller flere verdier fra mange teksturer.

For hvert fragment som blir prosessert har vi to valg:

  • Gi ut fragmentets farge (gl_FragColor), eventuelt gl_FragData dersom vi rendrer til flere targets. Vi kan og velge å få ut dybde via gl_FragDepth
  • Forkaste hele fragmentet, med andre ord ingen utdata
Fragment shader ut-verdier
  • gl_FragColor
  • gl_FragDepth
  • gl_FragData

Merk at fragment shader ikke har tilgang til Framebuffer, og derfor ikke kan brukes til .feks blending.

Inspirasjon

Alle bilder er hentet fra "3Dshaders.com"

{gallery}custom_articles/opengl/glsl prosessor/galleri{/gallery}