Für meine neue Engine programmiere ich als Nebenprojekt gerade einen Pascal Compiler, der Pasal Quelltext zu OpenGL Vertex und Pixel Shadern compiliert. Die Idee ist nicht nur Cg,glslang und HLSL sondern auch Pascal als Shading Language zu haben. Der Compiler ist modular aufgebaut und erzeugt erst einen Zwischencode, der dann auf die jeweilige Extension wie ARB_VERTEX_PROGRAM,ARB_FRAGMENT_PROGRAM,Register Combiner oder ARB_TEXTURE_ENV umgesetzt wird. Momentan bin ich allerdings erst bei ARB_VERTEX_PROGRAM. Der Compiler optimiert, indem fertige Teilausdrücke zusammengefaßt werden, Zuweisungen ersetzt werden und Variablen, deren Wert für den weiteren Programablauf unwichtig ist, wiederverwendet werden. Es gibt als Datentyp single,vector und vector3. Außerdem gib es auch Arrays, aber nur als Konstante. Bis jetzt gibt es die arihtmetischen Operatoren und noch einige zusätzliche definierte Funktionen wie vec_cross,vec_dot,vec_dist., usw.. Es gibt je nach benutzter Extension gibt es globale Variablen. Diese Globalen Variablen entsprechen OpenGL Eigenschaften. state ist z.B. ein Record der den aktuellen OpenGL State enthält. mvp ist dann ein Array von Vectoren, das die Modelview Matrix*Projection Matrix beinhaltet. Result ist der endgültige Vertex, wie er an den Pixel Shader weitergeleitet wird und vertex ist der Vertex der aus dem Vertex Array gelesen oder über die glvertex Befehle erzeugt wird. Diese Konstanten hängen von der Extension ab, die gerade benutzt wird. Die ARB_VERTEX_PROGRAM Extension bietet z.B. die gleichen Konstanten in einem Vertex Program an. Das heißt aber nicht, das hier einfach nur der Name kopiert wird, sondern diese Variablen sind extra definiert.
Der Compiler ist bei weitem noch nicht fertig und daher werden noch viele Funktionen,Operatoren und Anweisungen hinzukommen.
Ein sehr einfaches Programm sieht z.B. so aus: Die letzte Zuweisung kann man sich eigentlich sparen, aber hier soll eben auch die Benutzung von lokalen Variablen dargestellt werden.
Code:
program Test;
uses arb_vertex_program;
const
mvp:array[0..3] of vector=state.matrix.mvp;
var
pos:vector;
begin
pos:=vec_matrixmult(vertex.position,mvp[
0]);
result.position:=pos;
end.
Man kann auch die with Anweisung und den dot Operator benutzen.
Da es vermutlich nicht mehr viele neue Versionen von den ARB_???_PROGRAM Extensions geben wird, wenn OpenGL 2.0 erstmal für alle Grafikkarten verfügbar ist, lohnt es sich nicht langfristig solchen Code zu erzeugen. Stattdessen wird fxPascal ein Konverter von Pascal nach glslang, der in OpenGL eingebauten Shader Sprache. Dabei wird das Program korrekt geparst und analysiert und nicht einfach mit Suchen&Ersetzen gearbeitet, weil man sonst nicht korrekt die Fehler im Pascal Syntax erkennen kann.
Registriert: Sa Mai 04, 2002 19:48 Beiträge: 3827 Wohnort: Tespe (nahe Hamburg)
Beitrag von Lars aus technischen Gründen von mir gepostet:
Der Konverter von fxPascal nach der OpenGL Shading Language ist schon sei längerem fertig, aber es gibt ja noch keine Treiber um das Program ausführlich zu testen.
Die Extensions ARB_vertex_program und ARB_fragment_program sind auch weiterhin nützlich und deshalb habe ich eine zusätzliche Sprache entwickelt, die direkt auf diesem Extensions aufsetzt und an Pascal angelehnt ist. Es gibt die zwei Klassen TFragmentProgram und TVertexProgram, die für die jeweilige Extension übersetzen und auch optimieren. Der Quelltext wird als Stream im Constructor übergeben und bei Fehlern wird eine Exception ausgelöst. Das ARB Program kann man dann aus der Eigentschaft Source auslesen und mit der Funktion GetSymbolOffset kann man die Position einer Variable abfragen.
Alle Programme bestehen aus optionalen Deklarationsblöcken und einem anschließenden Begin End Block. Im var Block werden temporäre Variablen deklariert. Im Param Block kann man die Program Parameter definieren und im Varying Block wird die Schnittstelle zwischen Vertex und Fragment Program festgelegt.
Beispiel:
Code:
var
a,b,c;
param
param1,params[10];
varying
texcoord;
Es gibt keine speziellen Datentypen, weil alles Vektoren sind. Im Param Block kann man aber Arrays definieren, indem man die Anzahl der Elemente in Klammern hinter den Bezeichner schreibt. Der Begin End Block besteht aus einer Reihe von Anweisungen. Es gibt die Zuweisung mit ":=", with, if then else und discard; Discard ist nur in Fragmentprogrammen erlaubt und sorgt dafür, daß dieses Fragment nicht gezeichnet wird. Es können alle Variablen der jeweiligen ARB Erweiterung benutzt werden. Ein ganz einfaches Program wäre z.B.
Es gibt folgende Operatoren:
+,-,*,/,
=,<>,<=,<,>,>=
NOT,AND,OR,XOR
In beiden Program Typen sind folgenden Funktionen erlaubt:
min(x,y)
Minimum von x und y
max(x,y)
Maximum von x und y
abs(x)
Absolutwert
cross(x,y)
Kreuzprodukt
dot(x,y)dot3(x,y)
3 Komponenten Skalarprodukt
dot4(x,y)
4 Komponenten Skalarprodukt
doth(x,y)
Homogeneous Dot Product
floor(x)
größter ganzer Integer, der kleiner als x ist
frac(x)
Gibt den Realteil von x zurück.
exp2(x)
Berechnet 2 hoch x
log2(x)
Berechnet den 2er Logarithmus von x
power(x,y)
=x hoch y
normalize(x)
Normalisiert x
length(x)
Berechnet die Länge von x
dist(x,y)
Berechnet die Entfernung von x und y
sqr(x)
=x*x
sqrt(x)
Gibt die Wurzel der ersten Komponente von x zurück
rsqrt(x)
Berechnet den Kehrwert der Wurzel vor der ersten Komponente von x
matrixmult3(matrix,x)
Multipliziert x mit der 3*3 Matrix
matrixmult4(matrix,x)
Multipliziert x mit der 4*4 Matrix
vector(x,y,z,w)
Gibt den Vektor aus den Parametern zurück
matrix(row1,row2,row3[,row4]);
Gibt eine Matrix aus den Paramtervektoren zurück
clamp(x,min,max)
=max(min,min(x,max))
sat(x)
=clamp(x,0,1), wird in Fragment Programmen speziell optimiert
reflect(x,y)
Berechnet den Refletionsvektor von x an y
sin(x)
Berechnet den Sinus von x
cos(x)
Berechnet den Cosinus von x
pi
=PI
lightatten(vec,size)
Berechnet die Lichthelligkeit einer Lichtquelle der Größe size an dem Punkt vec, der relativ zur Lichtquelle angegeben wird.
Die folgenden Funktionen gelten nur für Fragment Programme
Texture1D(tex,coord[,bias]);
Texture2D(tex,coord[,bias]);
Texture3D(tex,coord[,bias]);
TextureCubeMap(tex,coord[,bias]);
TextureRect(tex,coord[,bias]);
Die Funktionen lesen jeweils an der angegebenen Stelle aus der Texture tex. Tex ist die Nummer der Textureeinheit, aus der man lesen möchte.
Optional kann auch noch ein LOD Bias angegeben werde.
Texture1DProj(tex,coord);
Texture2DProj(tex,coord);
Texture3DProj(tex,coord);
TextureCubeMapProj(tex,coord);
TextureRectProj(tex,coord);
Die Funktionen lesen jeweils an der Stelle coord/coord.w aus der Texture tex.
NormalMap(tex,coord[,bias]);
Mit der Funktion NormalMap kann eine Normalmap gelesen und entpackt werden.
Ich habe jetzt mal eine neue Version an den Beitrag angehängt. Ich habe Fehler beseitigt und den Quelltext aufgeräumt, die Code Optimierung verbessert, benutzerdefinierte Funktionen mit dem function Schlüsselwort hinzugefügt und ein Tutorial mit ca. 30 Seiten geschrieben.
Ich habe die neue Version fertig. Es gibt jetzt die beiden Datentypen vec4 und single, die Code Optimierung wurde verbessert und Fehler wurden beseitigt. Man kann die Constructoren jetzt auch mit einem String als Parameter aufrufen. Es gibt auch Prozeduren und bei den Parametern die entsprechenden Parametertypen wie const,var oder out. Man kann jetzt ebenfalls auch globale Konstanten und konstante Arrays deklarieren. Im Programmierhandbuch werden die neuen Fähigkeiten beschrieben und es ist bei den Beispielen ein Kapitel zu volumetrischem Licht dazugekommen.
Ich habe jetzt mal wieder eine neue Version fertig. Die Änderungen sind:
1.Programme haben Programkopf und in der uses Klausel die benutzten Extensions möglich sind: ARB_vertex_program,ARB_fragment_program,ARB_position_invariant, ATI_draw_buffers
2.Die Funktion CompileProgram wird für die Kompilierung benutzt und wählt automatisch die richtige Klasse aus. Die Klassen muß man selber nicht mehr verwenden. Man kann alle benutzen Parameter in einer Liste erhalten.
3.For Schleifen: to und downto Variante,Start und Ende muß aber konstant sein, es sind nur integer erlaubt
4.Neuer Datentype Integer für For Schleifen
5.Compiler Befehle
{$ifdef}{$else}{$endif}
{$define}{$undefine}
{$optimize} {$regcount}
6.Bessere Optimierung
-Teilausdrücke werden effizienter ersetzt
-Wahlweise Optimierung auf Länge oder Registerbenutzung des Shaders
-Lebendigkeitsanalyse um minimale Anzahl von benötigten Variablen zu finden
7.Compiler Warnungen und Hinweise
8.Neues Symbol program_env[0..31] für Environment Parameter
Außerdem habe ich das PDF aktualisiert, daß die neue Version und auch die Vorgehensweise des Compilers ausführlich beschreibt.
Nach eingier Zeit habe ich nochmal eine neue Version veröffentlicht. Es wurden hauptsächlich Fehler behoben und eine Kommandozeilenversion des Compilers mit Quelltext hinzugefügt.
@Mars: Den Fehler mit dem Parallax Mapping habe ich leider noch nicht gefunden, obwohl ich die beiden Dateien zeilenweise durchgegangen bin.
Mitglieder in diesem Forum: 0 Mitglieder und 62 Gäste
Du darfst keine neuen Themen in diesem Forum erstellen. Du darfst keine Antworten zu Themen in diesem Forum erstellen. Du darfst deine Beiträge in diesem Forum nicht ändern. Du darfst deine Beiträge in diesem Forum nicht löschen. Du darfst keine Dateianhänge in diesem Forum erstellen.