Shader-ek, transzformációk

0. Folytatjuk az előző gyakorlaton elkezdett programot!

main.cpp

Az előző órai beállításokkal a program hiba nélkül fordul.

Ha mégsem:

i Ha fordító nem talál file-okat, pl.:

fatal error C1083: Cannot open include file: 'GL/glut.h': No such file or directory

Be kell állítani a Cg Toolkit és GLEW könyvtárakat a fordítónak:

  1. Tools/Options...
  2. Projects and Solutions/VC++ Directories
  3. Show directories for: Include files - Cg Toolkit és GLEW include könyvár hozzáadása
  4. Show directories for: Library files - Cg Toolkit és GLEW lib könyvár hozzáadása

i Ha linker panaszkodik:

error LNK2001: unresolved external symbol...

A glew32s.lib -et meg kell adni a linkernek a projekt beállításokban.

  1. Project/Properties
  2. Configuration Properties/Linker/Input
  3. Additional dependencies-ben adjuk meg a glew32s.lib -et
  4. C/C++/Preprocessor
  5. Preprocessor Definitions-höz adjuk hozzá ;-vel a GLEW_STATIC értéket

1. Első shader-programunk!

A megjelenítéshez shader-programot fogunk használni. Ezt Cg nyelven készítjünk el, egy effekt file-ban:

simplest.fx, ezt adjuk is hozzá a projekthez!

A rajzolás során először minden a csúcspontra lefut a vertex shader (01-04. sor). Ennek bemenete és kimenete (ebben a programban) csak a pozíció adat. Ezt jelzi a POSITION szemantika.

A csúcspontokat a glDrawArrays függvényben megadott típus alapján a videókártya primitívekbe rendezi. (Tipikusan hárömszögekbe)

Ezeket a raszterizálás bontja fel pixel méretű, de 3D-s elemekre - fragmensekre. Minden egyes fragmensre lefut a fragment shader (másnéven pixel shader)(06-09. sor). Ez - minden esetben - egyetlen szin értékkel tér vissza, ezt adja meg a COLOR0 szemantika.

A rajzoláshoz az effekt file egy technique-jét használjuk (egy effekt több technique-et is tartalmazhat). Egy technique legalább egy pass-t tartalmaz, és minden pass megadja, hogy a használata milyen shader programokat és állapotbeállításokat jelent.

A vertex és fragmens programok neve tetszőleges lehet, a pass VertexProgram és FragmentProgram sorában határozzuk meg őket. A compile kulcsszó jelentése, hogy a shader-eket fordítani kell, illetve az arbvp1 és arbfp1 adja meg a használni kívánt profile-t. A profile határozza meg, hogy az effektünk milyen szintű szolgáltatásokat vár el a hardware-től, és ennek megfelelően, miket tehetünk meg a shader programunkban.

Az arbvp1 és arbfp1 a lehető legkisebb hardware igényű OpenGL profilok.

A Cg által támogatott összes profile listája megtalálható itt.

2. A Cg inicializálása

Az elkészült effekt file-t a Cg segítségével töltjük be, fordítjuk és használjuk az OpenGL mellett.

Ehhez szükségünk lesz a következő (globális) változókra:

Majd írjuk meg a következő függvényt:

A cgCreateContext függvény egy Cg környezet hoz létre, ami majd a Cg programjainkat tárolja.

A cgGLRegisterStates függvény az OpenGL állapotait tesz elérhető az effektünk számára.

A cgCreateEffectFromFile tölti be az effekt file-t és hozza létre belőle a CGeffect -et.

A függvényünk további része (12. sortól) lekérdezi az effekt első technique-jét, és ellenőrzi, hogy használható-e az aktuális hardware-en. Ha nem, egyesével tovább halad a további technique-eken.

Ha sikerült használható technique-et találni, az a myCgTechnique változóba kerül, ha nem sikerült, a programunk hibaüzenettel leáll.

A függvényt a main-ben meg kell hívni, még a glutMainLoop() előtt!

Az initCg függvény hivatkozik egy checkForCgError függvényre. Ez a hibakezelést egyszerűsíti le számunkra. Ennek kódja:

Programunk így már betölti és lefordítja a Cg effektünket, de maga a program még nem fordul! A linker hibát fog jelezni, ugyanis a cg.lib és cgGL.lib file-okat hozzá kell adni a projekthez a glew32s.lib-hez hasonló módon.

A program hibátlan fordítás és helyes futás esetén kék alapon egy fehér nyolcszöget rajzol ki, a konzol ablakba pedig a "Use technique MyTechnique" szöveget írja ki.

3. Rajzolás shader-ekkel

A shader programjaink használatához végig kell iterálni a kiválasztott technique pass-ein, és minden glDrawArrays hívás előtt az aktuális pass beállításait át kell adni az OpenGL-nek.

Ehhez írjuk át a display függvényünket a következőre:

A programunk ezek után fordítható és futtatható!

A nyolcszög a fragment shader-ben megadott színnel fog megjelenni. Próbáljuk ki, hogy más értéket adunk meg színnek a simplest.fx 8. sorában!

4. Shader paraméterek és elérésük

Bővítsük a programunkat, hogy meg lehessen adni a kirajzolt modell színét!

Ehhez adjunk meg egy új változót az effekt file-unk legelején, és módosítsuk a fragmens programot!

Az effekt paraméter eléréséhez létre kell hoznunk egy új (globláis) változót a C++ programunkban, és ezt le kell kérnünk a Cg-től. Végül ezen keresztül módosíthatjuk a myColor shader paramétert.

A globális változónk:

A initCg() végére írjuk hozzá:

5. Transzformációs mátrixok

A modell forgatásához, mozgatásához, stb. transzformációs mátrixokra lesz szükségünk.

Ehhez a OpenGL Mathematics könyvtárat fogjuk használni. (Letölthető innen.)


Ajánlott irodalom