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:
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:
- Tools/Options...
- Projects and Solutions/VC++ Directories
- Show directories for: Include files - Cg Toolkit és GLEW include könyvár hozzáadása
- Show directories for: Library files - Cg Toolkit és GLEW lib könyvár hozzáadása
Ha linker panaszkodik:
error LNK2001: unresolved external symbol...
A glew32s.lib -et meg kell adni a linkernek a projekt beállításokban.
- Project/Properties
- Configuration Properties/Linker/Input
- Additional dependencies-ben adjuk meg a glew32s.lib -et
- C/C++/Preprocessor
- 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
- The Cg Tutorial
- CgReferenceManual.chm ill. CgReferenceManual.pdf a Cg Toolkit könyvtárából
- CgUsersManual.pdf ugyanonnan