- C for graphics
-
C for Graphics (Abkürzung: Cg) ist eine von NVIDIA begründete Shader-Hochsprache zum Schreiben von Vertex-Shader- und Pixel-Shader-Programmen. Die Sprache ist weitestgehend unabhängig von der zugrunde liegenden Grafik-API- (OpenGL und DirectX) und dem Grafikkartenhersteller (NVIDIA und ATI).
Inhaltsverzeichnis
Hochsprache
Die Entwicklung einer Shader-Hochsprache wurde dadurch motiviert, dass das Programmieren von Vertex- und Pixel-Shadern in Maschinensprache recht kompliziert und schnell unübersichtlich ist. Weitere Shader-Hochsprachen sind GLSL, HLSL und RenderMan. Einen anderen Ansatz verfolgt Sh als Metasprache.
Syntax
Cg ähnelt von der Syntax her der Programmiersprache C. Bestandteile sind u.a. einfache Datentypen, Arrays, Bedingungen und Schleifen.
Datentypen
- int (32bit integer)
- float (32bit floating point)
- half (16bit floating point)
- fixed (12bit fixed point, 1-1-10)
- double
- bool
- sampler (für Texturobjekte)
Es sei darauf hingewiesen, dass auf manchen Grafikkarten alles auf float gerechnet wird.
Hinzu kommen die entsprechenden Vektoren und Matrizen: float2, float3, float4, float4x4.
Parameter
Ausgabe-Parameter werden mit out gekennzeichnet:
out float4 pos : POSITION; // Eckpunkt, der vom Vertex-Programm weitergegeben wird out float4 color : COLOR; // Farbe, die vom Vertex-Programm weitergegeben wird
Uniform-Parameter werden außerhalb vom Vertex-Programm gesetzt und ändern sich nicht pro Eckpunkt:
z.B. in einem OpenGL-Programm:
CGparameter timeParam = cgGetNamedParameter(vertexProgram, „time"); CGparameter modelviewParam = cgGetNamedParameter(vertexProgram, "modelview"); cgGLSetParameter1f(timeParam, 100); cgGLSetStateMatrixParameter(modelviewParam, CG_GL_MODELVIEW_MATRIX, CG_GL_MATRIX_IDENTITY);
Verwendung dann im Vertex-Programm:
uniform float time; uniform float4x4 modelview;
Zugriff auf OpenGL State
Normalerweise erfolgt der Zugriff über Uniform-Parameter. Diese Parameter müssen im OpenGL-Programm immer neu gesetzt werden. Im Falle eines ARB-Profils ist der Zugriff auf einen OpenGL State möglich, z.B.
glstate.matrix.mvp // Projection * Modelview
Profile
Ein weiterer Aspekt ist die Möglichkeit zum Kompilieren für verschiedene Profile. Das sind verschiedene Versionen von Vertex- bzw. Fragment-Programmen, von denen automatisch das bestmögliche für die vorhandene Hardware aktiviert wird:
CGprofile vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX); cgGLSetOptimalOptions(vertexProfile); CGprofile fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT); cgGLSetOptimalOptions(fragmentProfile);
Profil ausgeben lassen:
cgGetProfileString(fragmentProfile)
Einbindung und Programmierung
Die erstellten Programm-Codes können separat kompiliert und als externe Quelle in ein lauffähiges Hochsprachen-Programm (z.B. C++) eingebunden oder alternativ erst zur Laufzeit übersetzt werden.
Es muss zunächst ein Kontext (Speicher für Programme) erzeugt und dann das Programm kompiliert werden:
CGcontext context = cgCreateContext(); CGprogram program = cgCreateProgramFromFile(context, CG_SOURCE, filename, profile, "main", NULL); cgGLLoadProgram(program); // Programm laden
Anschließend erfolgen Aktivierung und Auswahl des Programms:
// Profil aktivieren (und Programm aktivieren) cgGLEnableProfile(CGProfile profile); … // Ab hier läuft jeder glVertex() durchs eigene Vertex Program … // Profil (und Programm deaktivieren) cgGLDisableProfile(CGProfile profile) … // Ab jetzt läuft wieder jeder glVertex() durch die Standard OpenGL // Pipeline … // Aktuelles Vertex/Fragment Program festlegen cgGLBindProgram(myVertexProgram);
Weblinks
Wikimedia Foundation.