* some linux fixes
authorBergmann89 <bergmann89@muo-game.de>
Fri, 31 Oct 2014 15:20:27 +0000 (16:20 +0100)
committerBergmann89 <bergmann89@muo-game.de>
Fri, 31 Oct 2014 15:20:27 +0000 (16:20 +0100)
uglcContextGtk2GLX.pas
uglcShader.pas

index bbde99f..b3ddb20 100644 (file)
@@ -60,10 +60,7 @@ type
 \r
 {$region messages -fold}\r
 procedure TRenderControl.WndProc(var Message: TLMessage);\r
-var\r
-  handled: Boolean;\r
 begin\r
-  handled := false;\r
   case Message.msg of\r
     //LM_ACTIVATEITEM,\r
     //LM_CHANGED,\r
@@ -269,10 +266,8 @@ begin
     CN_SYSCHAR,\r
     CN_NOTIFY:\r
     begin\r
-      if Assigned(fTarget) then begin\r
+      if Assigned(fTarget) then\r
         Message.Result := fTarget.Perform(Message.msg, Message.wParam, Message.lParam);\r
-        handled := true;\r
-      end;\r
     end;\r
   end;\r
   inherited WndProc(Message);\r
@@ -422,6 +417,7 @@ procedure TglcContextGtk2GLX.OpenContext;
 var\r
   Attribs: array of GLint;\r
   tmpContext: GLXContext;\r
+  glxID: GLXDrawable;\r
 begin\r
   inherited OpenContext;\r
 \r
@@ -453,7 +449,8 @@ begin
     SetLength(Attribs, 1);\r
     Attribs[High(Attribs)] := 0;\r
 \r
-    glXMakeCurrent(FDisplay, GDK_DRAWABLE_XID(GTK_WIDGET(FWidget)^.window), tmpContext);\r
+    glxID := GDK_DRAWABLE_XID(GTK_WIDGET(FWidget)^.window);\r
+    glXMakeCurrent(FDisplay, glxID, tmpContext);\r
     ReadImplementationProperties;\r
     if not Assigned(glXCreateContextAttribsARB) or not GLX_ARB_create_context then begin\r
       glXDestroyContext(FDisplay, tmpContext);\r
@@ -500,6 +497,8 @@ begin
 end;\r
 \r
 procedure TglcContextGtk2GLX.Activate;\r
+var\r
+   glxID: GLXDrawable;\r
 begin\r
   if not Assigned(FWidget) then exit;\r
   // make sure the widget is realized\r
@@ -507,30 +506,36 @@ begin
   if not GTK_WIDGET_REALIZED(FWidget) then exit;\r
 \r
   // make current\r
-\r
-  glXMakeCurrent(FDisplay, GDK_DRAWABLE_XID(GTK_WIDGET(FWidget)^.window), FContext);\r
+  glxID := GDK_DRAWABLE_XID(GTK_WIDGET(FWidget)^.window);\r
+  glXMakeCurrent(FDisplay, glxID, FContext);\r
 end;\r
 \r
 procedure TglcContextGtk2GLX.Deactivate;\r
+var\r
+   glxID: GLXDrawable;\r
 begin\r
   if not Assigned(FWidget) then exit;\r
-  glXMakeCurrent(FDisplay, GDK_DRAWABLE_XID(GTK_WIDGET(FWidget)^.window), nil);\r
+  glxID := GDK_DRAWABLE_XID(GTK_WIDGET(FWidget)^.window);\r
+  glXMakeCurrent(FDisplay, glxID, nil);\r
 end;\r
 \r
 function TglcContextGtk2GLX.IsActive: boolean;\r
+var\r
+  glxID: GLXDrawable;\r
 begin\r
+  glxID := GDK_DRAWABLE_XID(GTK_WIDGET(FWidget)^.window);\r
   Result:= (FContext = glXGetCurrentContext()) and\r
            Assigned(FWidget) and\r
-           (GDK_DRAWABLE_XID(GTK_WIDGET(FWidget)^.window) = glXGetCurrentDrawable());\r
+           (glxID = glXGetCurrentDrawable());\r
 end;\r
 \r
 procedure TglcContextGtk2GLX.SwapBuffers;\r
 var\r
-  drawable: PGdkDrawable;\r
+  glxID: GLXDrawable;\r
 begin\r
   if not Assigned(FWidget) then exit;\r
-  drawable:= GTK_WIDGET(FWidget)^.window;\r
-  glXSwapBuffers(FDisplay, GDK_DRAWABLE_XID(drawable));\r
+  glxID := GDK_DRAWABLE_XID(GTK_WIDGET(FWidget)^.window);\r
+  glXSwapBuffers(FDisplay, glxID);\r
 end;\r
 \r
 procedure TglcContextGtk2GLX.SetSwapInterval(const aInterval: GLint);\r
@@ -547,7 +552,7 @@ begin
   raise Exception.Create('not yet implemented');\r
 end;\r
 \r
-class function TglcContextGtk2GLX.ChangeDisplaySettings(const aWidth, aHeight,\r
+class function TglcContextGtk2GLX.{%H-}ChangeDisplaySettings(const aWidth, aHeight,\r
   aBitPerPixel, aFreq: Integer; const aFlags: TglcDisplayFlags): Boolean;\r
 begin\r
   raise Exception.Create('not yet implemented');\r
@@ -559,4 +564,4 @@ begin
 end;\r
 \r
 end.\r
-\r
\ No newline at end of file
+\r
index 634d57f..750e8bc 100644 (file)
-unit uglcShader;
-
-{ Package:      OpenGLCore
-  Prefix:       glc - OpenGL Core
-  Beschreibung: diese Unit enthält eine Klassen-Kapselung der OpenGL Shader Objekte
-  Beispiel:
-    var
-      shader: TglcShaderProgram;
-
-    //write log message to console
-    //    @param aSender: object that send the message
-    //    @param aMsg:    message to write to console
-    procedure LogMessage(aSender: TObject; const aMsg: String);
-    begin
-      writeln(Format('[%p]: %s', [aSender, aMsg]);
-    end;
-
-    //load shader object from file and add it to 'shader'
-    //    @param aFilename: name of file to load shader code from
-    //    @param aType:     type of shader object to create
-    procedure LoadShaderObject(const aFilename: String; const aType: TglcShaderType);
-    var
-      sl: TStringList;
-      so: TglcShaderObject;
-    begin
-      sl := TStringList.Create;
-      try
-        sl.LoadFromFile(aFileName);
-        so := TglcShaderObject.Create(aType);
-        shader.add(so);
-      finally
-        FreeAndNil(sl, @LogMessage);
-      end;
-    end;
-
-    shader := TglcShaderProgram.Create(@LogMessage);
-    try
-      // load shader objects
-      LoadShaderObject('./test_shader.vert', TglcShaderType.stVertex);
-      LoadShaderObject('./test_shader.frag', TglcShaderType.stFragment);
-
-      // compile shader
-      shader.Compile;
-
-      // use shader
-      shader.Enable;
-      shader.Uniform1f('uTest', 0.1234);
-      // do normal rendering
-      shader.Disable;
-
-    finally
-      FreeAndNil(shader);
-    end; }
-
-{$mode objfpc}{$H+}
-
-interface
-
-uses
-  Classes, SysUtils, fgl, dglOpenGL, uglcTypes, ugluMatrix;
-
-type
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-  EglcShader = class(Exception);
-  TglcShaderProgram = class;
-  TglcShaderLogEvent = procedure(aSender: TObject; const aMsg: String) of Object;
-  TglcShaderObject = class(TObject)
-  private
-    fAtachedTo: TglcShaderProgram;
-    fShaderObj: GLHandle;
-    fShaderType: TglcShaderType;
-    fCode: String;
-    fOnLog: TglcShaderLogEvent;
-    fAttachedTo: TglcShaderProgram;
-
-    function GetInfoLog(aObj: GLHandle): String;
-    function GetCompiled: Boolean;
-    procedure Log(const aMsg: String);
-    procedure CreateShaderObj;
-    procedure AttachTo(const aProgram: TglcShaderProgram);
-  public
-    property ShaderObj : GLHandle           read fShaderObj;
-    property ShaderType: TglcShaderType     read fShaderType;
-    property Compiled:   Boolean            read GetCompiled;
-    property AtachedTo:  TglcShaderProgram  read fAtachedTo;
-    property Code:       String             read fCode  write fCode;
-    property OnLog:      TglcShaderLogEvent read fOnLog write fOnLog;
-
-    procedure Compile;
-
-    constructor Create(const aShaderType: TglcShaderType; const aLogEvent: TglcShaderLogEvent = nil);
-    destructor Destroy; override;
-  end;
-  TglcShaderObjectList = specialize TFPGObjectList<TglcShaderObject>;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-  TglcShaderProgram = class(TglcShaderObjectList)
-  private
-    fProgramObj: GLHandle;
-    fOnLog: TglcShaderLogEvent;
-    fFilename: String;
-
-    function GetUniformLocation(const aName: String; out aPos: glInt): Boolean;
-    function GetInfoLog(Obj: GLHandle): String;
-    function GetCompiled: Boolean;
-    function GetLinked: Boolean;
-
-    procedure CreateProgramObj;
-    procedure Log(const msg: String);
-    procedure AttachShaderObj(const aShaderObj: TglcShaderObject);
-  public
-    property ProgramObj: glHandle           read fProgramObj;
-    property Filename:   String             read fFilename;
-    property Compiled:   Boolean            read GetCompiled;
-    property Linked:     Boolean            read GetLinked;
-    property OnLog:      TglcShaderLogEvent read fOnLog               write fOnLog;
-
-    procedure Compile;
-    procedure Enable;
-    procedure Disable;
-
-    procedure Add(aShaderObj: TglcShaderObject);
-    procedure Delete(aID: Integer; aFreeOwnedObj: Boolean = True);
-    procedure Clear;
-
-    function Uniform1f(const aName: String; aP1: GLFloat): Boolean;
-    function Uniform2f(const aName: String; aP1, aP2: GLFloat): Boolean;
-    function Uniform3f(const aName: String; aP1, aP2, aP3: GLFloat): Boolean;
-    function Uniform4f(const aName: String; aP1, aP2, aP3, aP4: GLFloat): Boolean;
-    function Uniform1i(const aName: String; aP1: GLint): Boolean;
-    function Uniform2i(const aName: String; aP1, aP2: GLint): Boolean;
-    function Uniform3i(const aName: String; aP1, aP2, aP3: GLint): Boolean;
-    function Uniform4i(const aName: String; aP1, aP2, aP3, aP4: GLint): Boolean;
-    function Uniform1fv(const aName: String; aCount: GLint; aP1: PGLFloat): Boolean;
-    function Uniform2fv(const aName: String; aCount: GLint; aP1: PGLFloat): Boolean;
-    function Uniform3fv(const aName: String; aCount: GLint; aP1: PGLFloat): Boolean;
-    function Uniform4fv(const aName: String; aCount: GLint; aP1: PGLFloat): Boolean;
-    function Uniform1iv(const aName: String; aCount: GLint; aP1: PGLInt): Boolean;
-    function Uniform2iv(const aName: String; aCount: GLint; aP1: PGLInt): Boolean;
-    function Uniform3iv(const aName: String; aCount: GLint; aP1: PGLInt): Boolean;
-    function Uniform4iv(const aName: String; aCount: GLint; aP1: PGLInt): Boolean;
-    function UniformMatrix2fv(const aName: String; aTranspose: Boolean; aCount: GLint; aP1: PgluMatrix2f): Boolean;
-    function UniformMatrix3fv(const aName: String; aTranspose: Boolean; aCount: GLint; aP1: PgluMatrix3f): Boolean;
-    function UniformMatrix4fv(const aName: String; aTranspose: Boolean; aCount: GLint; aP1: PgluMatrix4f): Boolean;
-
-    function GetUniformfv(const aName: String; aP: PGLfloat): Boolean;
-    function GetUniformfi(const aName: String; aP: PGLint): Boolean;
-    function HasUniform(const aName: String): Boolean;
-
-    procedure LoadFromFile(const aFilename: String);
-    procedure LoadFromStream(const aStream: TStream);
-    procedure SaveToFile(const aFilename: String);
-    procedure SaveToStream(const aStream: TStream);
-
-    constructor Create(const aLogEvent: TglcShaderLogEvent = nil);
-    destructor Destroy; override;
-  end;
-
-implementation
-
-uses
-  RegExpr;
-
-const
-  ERROR_STR_VAR_NAME: String = 'can''t find the variable ''%s'' in the program';
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//glShaderObject////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRI//
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//ließt das Log eines OpenGL-Objekts aus
-//@Obj: Handle des Objekts, dessen Log ausgelesen werden soll;
-//@result: Log des Objekts;
-function TglcShaderObject.GetInfoLog(aObj: GLHandle): String;
-var
-  Msg: PChar;
-  bLen: GLint;
-  sLen: GLsizei;
-begin
-  bLen := 0;
-  glGetShaderiv(aObj, GL_INFO_LOG_LENGTH, @bLen);
-  if bLen > 1 then begin
-    GetMem(Msg, bLen * SizeOf(Char));
-    glGetShaderInfoLog(aObj, bLen, @sLen, Msg);
-    result := PChar(Msg);
-    Dispose(Msg);
-  end;
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//ließt aus, ob der Shader ohne Fehler kompiliert wurde
-//@result: TRUE wenn ohne Fehler kompiliert, sonst FALSE;
-function TglcShaderObject.GetCompiled: Boolean;
-var
-  value: glInt;
-begin
-  glGetShaderiv(fShaderObj, GL_COMPILE_STATUS, @value);
-  result := (value = GL_TRUE);
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//ruft das Log-Event auf, wenn es gesetzt ist
-//@msg: Nachricht die geloggt werden soll;
-procedure TglcShaderObject.Log(const aMsg: String);
-begin
-  if Assigned(fOnLog) then begin
-    fOnLog(self, aMsg);
-  end;
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-procedure TglcShaderObject.CreateShaderObj;
-begin
-  if (fShaderObj <> 0) then
-    exit;
-  fShaderObj := glCreateShader(GLenum(fShaderType));
-  if fShaderObj = 0 then
-    raise EglcShader.Create('can''t create ShaderObject');
-  Log('shader object created: #'+IntToHex(fShaderObj, 4));
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-procedure TglcShaderObject.AttachTo(const aProgram: TglcShaderProgram);
-begin
-  if (aProgram <> fAtachedTo) then begin
-    CreateShaderObj;
-    glAttachShader(aProgram.ProgramObj, fShaderObj);
-    fAttachedTo := aProgram;
-  end;
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBL//
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//kompiliert das Shader-Objekt
-procedure TglcShaderObject.Compile;
-var
-  len, i: GLint;
-  List: TStringList;
-  c: PAnsiChar;
-begin
-  CreateShaderObj;
-  len := Length(fCode);
-  if len > 0 then begin
-    c := PAnsiChar(fCode);
-    glShaderSource(fShaderObj, 1, @c, @len);
-    glCompileShader(fShaderObj);
-    List := TStringList.Create;
-    List.Text := GetInfoLog(fShaderObj);
-    for i := 0 to List.Count-1 do
-      Log(List[i]);
-    List.Free;
-  end else Log('error while compiling: no bound shader code');
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//erzeugt das Objekt
-//@ShaderType: Typ des Shader-Objekts;
-//@LogEvent: Event zum loggen von Fehlern und Ereignissen;
-//@raise: EglcShader wenn der Shadertyp unbekannt oder ungültig ist;
-constructor TglcShaderObject.Create(const aShaderType: TglcShaderType; const aLogEvent: TglcShaderLogEvent);
-begin
-  inherited Create;
-  fCode       := '';
-  fOnLog      := aLogEvent;
-  fShaderType := aShaderType;
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//gibt das Objekt frei
-destructor TglcShaderObject.Destroy;
-begin
-  if (fShaderObj <> 0) then
-    glDeleteShader(fShaderObj);
-  inherited Destroy;
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//glShaderProgram///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRI//
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-function TglcShaderProgram.GetUniformLocation(const aName: String; out aPos: glInt): Boolean;
-begin
-  aPos := glGetUniformLocation(fProgramObj, PChar(aName));
-  result := (aPos <> -1);
-  if not result then
-    Log(StringReplace(ERROR_STR_VAR_NAME, '%s', aName, [rfIgnoreCase, rfReplaceAll]));
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//ließt das Log eines OpenGL-Objekts aus
-//@Obj: Handle des Objekts, dessen Log ausgelesen werden soll;
-//@result: Log des Objekts;
-function TglcShaderProgram.GetInfoLog(Obj: GLHandle): String;
-var
-  Msg: PChar;
-  bLen: GLint;
-  sLen: GLsizei;
-begin
-  bLen := 0;
-  glGetProgramiv(Obj, GL_INFO_LOG_LENGTH, @bLen);
-  if bLen > 1 then begin
-    GetMem(Msg, bLen * SizeOf(Char));
-    glGetProgramInfoLog(Obj, bLen, @sLen, Msg);
-    result := PChar(Msg);
-    Dispose(Msg);
-  end;
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//prüft ob alle Shader ohne Fehler compiliert wurden
-//@result: TRUE wenn alle erfolgreich compiliert, sonst FALSE;
-function TglcShaderProgram.GetCompiled: Boolean;
-var
-  i: Integer;
-begin
-  result := (Count > 0);
-  for i := 0 to Count-1 do
-    result := result and Items[i].Compiled;
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//prüft ob das Programm ohne Fehler gelinkt wurde
-//@result: TRUE wenn linken erfolgreich, sonst FASLE;
-function TglcShaderProgram.GetLinked: Boolean;
-var
-  value: glInt;
-begin
-  glGetProgramiv(fProgramObj, GL_LINK_STATUS, @value);
-  result := (value = GL_TRUE);
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-procedure TglcShaderProgram.CreateProgramObj;
-begin
-  if (fProgramObj = 0) then begin
-    if GL_LibHandle = nil then
-      raise EglcShader.Create('TglShaderProgram.Create - OpenGL not initialized');
-
-    if (wglGetCurrentContext() = 0) or (wglGetCurrentDC() = 0) then
-      raise EglcShader.Create('TglShaderProgram.Create - no valid render context');
-
-    fProgramObj := glCreateProgram();
-    Log('shader program created: #'+IntToHex(fProgramObj, 4));
-  end;
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//ruft das Log-Event auf, wenn es gesetzt ist
-//@msg: Nachricht die geloggt werden soll;
-procedure TglcShaderProgram.Log(const msg: String);
-begin
-  if Assigned(fOnLog) then begin
-    fOnLog(self, msg);
-  end;
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-procedure TglcShaderProgram.AttachShaderObj(const aShaderObj: TglcShaderObject);
-begin
-  CreateProgramObj;
-  aShaderObj.AttachTo(self);
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBL//
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//Kompiliert den Shader-Code
-procedure TglcShaderProgram.Compile;
-var
-  i: Integer;
-  l: TStringList;
-begin
-  CreateProgramObj;
-  for i := 0 to Count-1 do begin
-    AttachShaderObj(Items[i]);
-    Items[i].Compile;
-  end;
-  glLinkProgram(fProgramObj);
-  l := TStringList.Create;
-  l.Text := GetInfoLog(fProgramObj);
-  for i := 0 to l.Count-1 do
-    Log(l[i]);
-  l.Free;
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//aktiviert den Shader
-procedure TglcShaderProgram.Enable;
-begin
-  glUseProgram(fProgramObj);
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//deaktiviert den Shader
-procedure TglcShaderProgram.Disable;
-begin
-  glUseProgram(0);
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//fügt der Liste einen Shader hinzu
-//@ShaderObj: Objekt, das hinzugefügt werden soll;
-procedure TglcShaderProgram.Add(aShaderObj: TglcShaderObject);
-begin
-  inherited Add(aShaderObj);
-  if (fProgramObj <> 0) then
-    AttachShaderObj(aShaderObj);
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//löscht ein ShaderObjekt aus der Liste
-//@ID: Index des Objekts, das gelöscht werden soll;
-//@FreeOwnedObj: wenn TRUE wird das gelöschte Objekt freigegeben;
-procedure TglcShaderProgram.Delete(aID: Integer; aFreeOwnedObj: Boolean);
-var
-  b: Boolean;
-begin
-  if (aID >= 0) and (aID < Count) and (fProgramObj <> 0) then begin
-    glDetachShader(fProgramObj, Items[aID].fShaderObj);
-    Items[aID].fAttachedTo := nil;
-  end;
-  b := FreeObjects;
-  FreeObjects := aFreeOwnedObj;
-  inherited Delete(aID);
-  FreeObjects := b;
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-procedure TglcShaderProgram.Clear;
-begin
-  while (Count > 0) do
-    Delete(0);
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//übergibt einen 1-Komponenten Float-Vektoren an den Shader
-//!!!Der Shader muss dazu aktiviert sein!!!
-//@Name: Name der Variablen die gesetzt werden soll;
-//@p1: Wert der Variable, der gesetzt werden soll;
-//@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
-function TglcShaderProgram.Uniform1f(const aName: String; aP1: GLFloat): Boolean;
-var
-  pos: GLint;
-begin
-  result := GetUniformLocation(aName, pos);
-  if result then
-    glUniform1f(pos, aP1);
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//übergibt einen 2-Komponenten Float-Vektoren an den Shader
-//!!!Der Shader muss dazu aktiviert sein!!!
-//@Name: Name der Variablen die gesetzt werden soll;
-//@p1: Wert der Variable, der gesetzt werden soll;
-//@p2: Wert der Variable, der gesetzt werden soll;
-//@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
-function TglcShaderProgram.Uniform2f(const aName: String; aP1, aP2: GLFloat): Boolean;
-var
-  pos: GLint;
-begin
-  result := GetUniformLocation(aName, pos);
-  if result then
-    glUniform2f(pos, aP1, aP2);
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//übergibt einen 3-Komponenten Float-Vektoren an den Shader
-//!!!Der Shader muss dazu aktiviert sein!!!
-//@Name: Name der Variablen die gesetzt werden soll;
-//@p1: Wert der Variable, der gesetzt werden soll;
-//@p2: Wert der Variable, der gesetzt werden soll;
-//@p3: Wert der Variable, der gesetzt werden soll;
-//@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
-function TglcShaderProgram.Uniform3f(const aName: String; aP1, aP2, aP3: GLFloat): Boolean;
-var
-  pos: GLint;
-begin
-  result := GetUniformLocation(aName, pos);
-  if result then
-    glUniform3f(pos, aP1, aP2, aP3);
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//übergibt einen 4-Komponenten Float-Vektoren an den Shader
-//!!!Der Shader muss dazu aktiviert sein!!!
-//@Name: Name der Variablen die gesetzt werden soll;
-//@p1: Wert der Variable, der gesetzt werden soll;
-//@p2: Wert der Variable, der gesetzt werden soll;
-//@p3: Wert der Variable, der gesetzt werden soll;
-//@p4: Wert der Variable, der gesetzt werden soll;
-//@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
-function TglcShaderProgram.Uniform4f(const aName: String; aP1, aP2, aP3, aP4: GLFloat): Boolean;
-var
-  pos: GLint;
-begin
-  result := GetUniformLocation(aName, pos);
-  if result then
-    glUniform4f(pos, aP1, aP2, aP3, aP4);
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//übergibt einen 1-Komponenten Integer-Vektoren an den Shader
-//!!!Der Shader muss dazu aktiviert sein!!!
-//@Name: Name der Variablen die gesetzt werden soll;
-//@p1: Wert der Variable, der gesetzt werden soll;
-//@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
-function TglcShaderProgram.Uniform1i(const aName: String; aP1: GLint): Boolean;
-var
-  pos: GLint;
-begin
-  result := GetUniformLocation(aName, pos);
-  if result then
-    glUniform1i(pos, aP1);
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//übergibt einen 2-Komponenten Integer-Vektoren an den Shader
-//!!!Der Shader muss dazu aktiviert sein!!!
-//@Name: Name der Variablen die gesetzt werden soll;
-//@p1: Wert der Variable, der gesetzt werden soll;
-//@p1: Wert der Variable, der gesetzt werden soll;
-//@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
-function TglcShaderProgram.Uniform2i(const aName: String; aP1, aP2: GLint): Boolean;
-var
-  pos: GLint;
-begin
-  result := GetUniformLocation(aName, pos);
-  if result then
-    glUniform2i(pos, aP1, aP2);
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//übergibt einen 3-Komponenten Integer-Vektoren an den Shader
-//!!!Der Shader muss dazu aktiviert sein!!!
-//@Name: Name der Variablen die gesetzt werden soll;
-//@p1: Wert der Variable, der gesetzt werden soll;
-//@p2: Wert der Variable, der gesetzt werden soll;
-//@p3: Wert der Variable, der gesetzt werden soll;
-//@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
-function TglcShaderProgram.Uniform3i(const aName: String; aP1, aP2, aP3: GLint): Boolean;
-var
-  pos: GLint;
-begin
-  result := GetUniformLocation(aName, pos);
-  if result then
-    glUniform3i(pos, aP1, aP2, aP3);
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//übergibt einen 4-Komponenten Integer-Vektoren an den Shader
-//!!!Der Shader muss dazu aktiviert sein!!!
-//@Name: Name der Variablen die gesetzt werden soll;
-//@p1: Wert der Variable, der gesetzt werden soll;
-//@p2: Wert der Variable, der gesetzt werden soll;
-//@p3: Wert der Variable, der gesetzt werden soll;
-//@p4: Wert der Variable, der gesetzt werden soll;
-//@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
-function TglcShaderProgram.Uniform4i(const aName: String; aP1, aP2, aP3, aP4: GLint): Boolean;
-var
-  pos: GLint;
-begin
-  result := GetUniformLocation(aName, pos);
-  if result then
-    glUniform4i(pos, aP1, aP2, aP3, aP4);
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//übergibt einen oder mehrere 1-Komponenten Float-Vektoren an den Shader
-//!!!Der Shader muss dazu aktiviert sein!!!
-//@Name: Name der Variablen die gesetzt werden soll;
-//@count: Anzahl an Parametern auf die p1 zeigt;
-//@p1: Zeiger auf den ersten Wert der gesetzt werden soll;
-//@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
-function TglcShaderProgram.Uniform1fv(const aName: String; aCount: GLint; aP1: PGLFloat): Boolean;
-var
-  pos: GLint;
-begin
-  result := GetUniformLocation(aName, pos);
-  if result then
-    glUniform1fv(pos, aCount, aP1);
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//übergibt einen oder mehrere 2-Komponenten Float-Vektoren an den Shader
-//!!!Der Shader muss dazu aktiviert sein!!!
-//@Name: Name der Variablen die gesetzt werden soll;
-//@count: Anzahl an Parametern auf die p1 zeigt;
-//@p1: Zeiger auf den ersten Wert der gesetzt werden soll;
-//@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
-function TglcShaderProgram.Uniform2fv(const aName: String; aCount: GLint; aP1: PGLFloat): Boolean;
-var
-  pos: GLint;
-begin
-  result := GetUniformLocation(aName, pos);
-  if result then
-    glUniform2fv(pos, aCount, aP1);
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//übergibt einen oder mehrere 3-Komponenten Float-Vektoren an den Shader
-//!!!Der Shader muss dazu aktiviert sein!!!
-//@Name: Name der Variablen die gesetzt werden soll;
-//@count: Anzahl an Parametern auf die p1 zeigt;
-//@p1: Zeiger auf den ersten Wert der gesetzt werden soll;
-//@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
-function TglcShaderProgram.Uniform3fv(const aName: String; aCount: GLint; aP1: PGLFloat): Boolean;
-var
-  pos: GLint;
-begin
-  result := GetUniformLocation(aName, pos);
-  if result then
-    glUniform3fv(pos, aCount, aP1);
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//übergibt einen oder mehrere 4-Komponenten Float-Vektoren an den Shader
-//!!!Der Shader muss dazu aktiviert sein!!!
-//@Name: Name der Variablen die gesetzt werden soll;
-//@count: Anzahl an Parametern auf die p1 zeigt;
-//@p1: Zeiger auf den ersten Wert der gesetzt werden soll;
-//@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
-function TglcShaderProgram.Uniform4fv(const aName: String; aCount: GLint; aP1: PGLFloat): Boolean;
-var
-  pos: GLint;
-begin
-  result := GetUniformLocation(aName, pos);
-  if result then
-    glUniform4fv(pos, aCount, aP1);
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//übergibt einen oder mehrere 1-Komponenten Integer-Vektoren an den Shader
-//!!!Der Shader muss dazu aktiviert sein!!!
-//@Name: Name der Variablen die gesetzt werden soll;
-//@count: Anzahl an Parametern auf die p1 zeigt;
-//@p1: Zeiger auf den ersten Wert der gesetzt werden soll;
-//@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
-function TglcShaderProgram.Uniform1iv(const aName: String; aCount: GLint; aP1: PGLInt): Boolean;
-var
-  pos: GLint;
-begin
-  result := GetUniformLocation(aName, pos);
-  if result then
-    glUniform1iv(pos, aCount, aP1);
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//übergibt einen oder mehrere 2-Komponenten Integer-Vektoren an den Shader
-//!!!Der Shader muss dazu aktiviert sein!!!
-//@Name: Name der Variablen die gesetzt werden soll;
-//@count: Anzahl an Parametern auf die p1 zeigt;
-//@p1: Zeiger auf den ersten Wert der gesetzt werden soll;
-//@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
-function TglcShaderProgram.Uniform2iv(const aName: String; aCount: GLint; aP1: PGLInt): Boolean;
-var
-  pos: GLint;
-begin
-  result := GetUniformLocation(aName, pos);
-  if result then
-    glUniform2iv(pos, aCount, aP1);
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//übergibt einen oder mehrere 3-Komponenten Integer-Vektoren an den Shader
-//!!!Der Shader muss dazu aktiviert sein!!!
-//@Name: Name der Variablen die gesetzt werden soll;
-//@count: Anzahl an Parametern auf die p1 zeigt;
-//@p1: Zeiger auf den ersten Wert der gesetzt werden soll;
-//@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
-function TglcShaderProgram.Uniform3iv(const aName: String; aCount: GLint; aP1: PGLInt): Boolean;
-var
-  pos: GLint;
-begin
-  result := GetUniformLocation(aName, pos);
-  if result then
-    glUniform3iv(pos, aCount, aP1);
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//übergibt einen oder mehrere 4-Komponenten Integer-Vektoren an den Shader
-//!!!Der Shader muss dazu aktiviert sein!!!
-//@Name: Name der Variablen die gesetzt werden soll;
-//@count: Anzahl an Parametern auf die p1 zeigt;
-//@p1: Zeiger auf den ersten Wert der gesetzt werden soll;
-//@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
-function TglcShaderProgram.Uniform4iv(const aName: String; aCount: GLint; aP1: PGLInt): Boolean;
-var
-  pos: GLint;
-begin
-  result := GetUniformLocation(aName, pos);
-  if result then
-    glUniform4iv(pos, aCount, aP1) ;
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//übergibt eine oder mehrere 2x2-Matrizen an den Shader
-//!!!Der Shader muss dazu aktiviert sein!!!
-//@Name: Name der Variablen die gesetzt werden soll;
-//@Transpose: wenn TRUe wird die matrix vor der Übergabe transponiert;
-//@Count: Anzahl der zu übergebenden Elemente;
-//@p1: Wert der Variable, der gesetzt werden soll;
-//@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
-function TglcShaderProgram.UniformMatrix2fv(const aName: String; aTranspose: Boolean; aCount: GLint; aP1: PgluMatrix2f): Boolean;
-var
-  pos: GLint;
-begin
-  result := GetUniformLocation(aName, pos);
-  if result then
-    glUniformMatrix2fv(pos, aCount, aTranspose, PGLfloat(aP1));
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//übergibt eine oder mehrere 3x3-Matrizen an den Shader
-//!!!Der Shader muss dazu aktiviert sein!!!
-//@Name: Name der Variablen die gesetzt werden soll;
-//@Transpose: wenn TRUe wird die matrix vor der Übergabe transponiert;
-//@Count: Anzahl der zu übergebenden Elemente;
-//@p1: Wert der Variable, der gesetzt werden soll;
-//@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
-function TglcShaderProgram.UniformMatrix3fv(const aName: String; aTranspose: Boolean; aCount: GLint; aP1: PgluMatrix3f): Boolean;
-var
-  pos: GLint;
-begin
-  result := GetUniformLocation(aName, pos);
-  if result then
-    glUniformMatrix3fv(pos, aCount, aTranspose, PGLfloat(aP1));
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//übergibt eine oder mehrere 4x4-Matrizen an den Shader
-//!!!Der Shader muss dazu aktiviert sein!!!
-//@Name: Name der Variablen die gesetzt werden soll;
-//@Transpose: wenn TRUe wird die matrix vor der Übergabe transponiert;
-//@Count: Anzahl der zu übergebenden Elemente;
-//@p1: Wert der Variable, der gesetzt werden soll;
-//@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
-function TglcShaderProgram.UniformMatrix4fv(const aName: String; aTranspose: Boolean; aCount: GLint; aP1: PgluMatrix4f): Boolean;
-var
-  pos: GLint;
-begin
-  result := GetUniformLocation(aName, pos);
-  if result then
-    glUniformMatrix4fv(pos, aCount, aTranspose, PGLfloat(aP1));
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//holt den Wert einer Float-Uniform-Variable aus dem Shader
-//!!!Der Shader muss dazu aktiviert sein!!!
-//@Name: Name der Variablen die gelesen werden soll;
-//@p: Zeiger auf die Variable, in die der gelesene Wert geschrieben werden soll;
-//@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
-function TglcShaderProgram.GetUniformfv(const aName: String; aP: PGLfloat): Boolean;
-var
-  pos: GLint;
-begin
-  result := GetUniformLocation(aName, pos);
-  if result then
-    glGetUniformfv(fProgramObj, pos, aP);
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//holt den Wert einer Integer-Uniform-Variable aus dem Shader
-//!!!Der Shader muss dazu aktiviert sein!!!
-//@Name: Name der Variablen die gelesen werden soll;
-//@p: Zeiger auf die Variable, in die der gelesene Wert geschrieben werden soll;
-//@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
-function TglcShaderProgram.GetUniformfi(const aName: String; aP: PGLint): Boolean;
-var
-  pos: GLint;
-begin
-  result := GetUniformLocation(aName, pos);
-  if result then
-    glGetUniformiv(fProgramObj, pos, aP);
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-function TglcShaderProgram.HasUniform(const aName: String): Boolean;
-var
-  pos: GLint;
-begin
-  result := GetUniformLocation(aName, pos);
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//läd den Shader aus einer Datei
-//@Filename: Datei aus der gelesen werden soll;
-//@raise: EglcShader, wenn Datei nicht vorhanden ist;
-procedure TglcShaderProgram.LoadFromFile(const aFilename: String);
-var
-  Stream: TFileStream;
-begin
-  if FileExists(aFilename) then begin
-    Stream := TFileStream.Create(aFilename, fmOpenRead);
-    try
-      LoadFromStream(Stream);
-      fFilename := aFilename;
-    finally
-      Stream.Free;
-    end;
-  end else raise EglcShader.Create('TglShaderProgram.LoadFromFile - file not found: '+Filename);
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//läd den Shader aus einem Stream
-//@Stream: Stream aus dem gelesen werden soll;
-//@raise: EglcShader wenn kein Stream-Objekt übergeben wurde;
-procedure TglcShaderProgram.LoadFromStream(const aStream: TStream);
-
-  function GetShaderType(const aStr: String): TglcShaderType;
-  begin
-    if (aStr = 'GL_VERTEX_SHADER') then
-      result := TglcShaderType.stVertex
-    else if (aStr = 'GL_FRAGMENT_SHADER') then
-      result := TglcShaderType.stFragment
-    else if (aStr = 'GL_GEOMETRY_SHADER') then
-      result := TglcShaderType.stGeometry
-    else if (aStr = 'GL_TESS_CONTROL_SHADER') then
-      result := TglcShaderType.stTessControl
-    else if (aStr = 'GL_TESS_EVALUATION_SHADER') then
-      result := TglcShaderType.stTessEvaluation
-    else
-      raise Exception.Create('invalid shader type: ' + aStr);
-  end;
-
-var
-  sl: TStringList;
-  s: String;
-  rx: TRegExpr;
-  LastMatchPos: PtrInt;
-  st: TglcShaderType;
-  o: TglcShaderObject;
-
-  procedure AddObj(const aPos: Integer);
-  begin
-    if (LastMatchPos > 0) then begin
-      o := TglcShaderObject.Create(st, fOnLog);
-      o.Code := Trim(Copy(s, LastMatchPos, aPos - LastMatchPos));
-      Add(o);
-    end;
-  end;
-
-begin
-  if not Assigned(aStream) then
-    raise EglcShader.Create('TglShaderProgram.SaveToStream - stream is nil');
-
-  Clear;
-  sl := TStringList.Create;
-  rx := TRegExpr.Create;
-  try
-    sl.LoadFromStream(aStream);
-    s := sl.Text;
-    LastMatchPos := 0;
-    rx.Expression  := '/\*\s*ShaderObject\s*:\s*(GL_[A-Z_]+)\s*\*/\s*$?';
-    rx.InputString := s;
-
-    while rx.Exec(LastMatchPos+1) do begin
-      AddObj(rx.MatchPos[0]);
-      LastMatchPos := rx.MatchPos[0] + rx.MatchLen[0];
-      st := GetShaderType(rx.Match[1]);
-    end;
-    AddObj(Length(s));
-  finally
-    rx.Free;
-    sl.Free;
-  end;
-
-
-  {
-  if Assigned(aStream) then begin
-    Clear;
-    fFilename := '';
-    reader := TutlStreamReader.Create(aStream);
-    try
-      if reader.ReadAnsiString <> GLSL_FILE_HEADER then
-        raise EglcShader.Create('TglShaderProgram.SaveToStream - incompatible file');
-      v := reader.ReadInteger;
-
-      if v >= 100 then begin //version 1.00
-        c := reader.ReadInteger;
-        for i := 0 to c-1 do begin
-          Add(TglcShaderObject.Create(Cardinal(reader.ReadInteger), fOnLog));
-          Last.fCode := reader.ReadAnsiString;
-        end;
-      end;
-    finally
-      reader.Free;
-    end;
-  end else
-  }
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//speichert den Shader in einer Datei
-//@Filename: Datei in die geschrieben werden soll;
-procedure TglcShaderProgram.SaveToFile(const aFilename: String);
-var
-  Stream: TFileStream;
-begin
-  Stream := TFileStream.Create(aFilename, fmCreate);
-  try
-    SaveToStream(Stream);
-    fFilename := aFilename;
-  finally
-    Stream.Free;
-  end;
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//speichert den Shader in einen Stream
-//@Stream: Stream in den geschrieben werden soll;
-//@raise: EglcShader wenn kein Stream-Objekt übergeben wurde;
-//@raise: EglcShader wenn ungültige Datei;
-procedure TglcShaderProgram.SaveToStream(const aStream: TStream);
-var
-  i: Integer;
-  sl: TStringList;
-  sObj: TglcShaderObject;
-
-  function GetShaderTypeStr(const aShaderType: TglcShaderType): String;
-  begin
-    case aShaderType of
-      TglcShaderType.stVertex:          result := 'GL_VERTEX_SHADER';
-      TglcShaderType.stFragment:        result := 'GL_FRAGMENT_SHADER';
-      TglcShaderType.stGeometry:        result := 'GL_GEOMETRY_SHADER';
-      TglcShaderType.stTessControl:     result := 'GL_TESS_CONTROL_SHADER';
-      TglcShaderType.stTessEvaluation:  result := 'GL_TESS_EVALUATION_SHADER';
-    else
-      result := 'UNKNOWN';
-    end;
-  end;
-
-begin
-  if not Assigned(aStream) then
-    raise EglcShader.Create('TglShaderProgram.LoadFromStream - stream is nil');
-  fFilename := '';
-  sl := TStringList.Create;
-  try
-    for i := 0 to Count-1 do begin
-      sObj := Items[i];
-      sl.Add('/* ShaderObject: ' + GetShaderTypeStr(sObj.ShaderType) + ' */');
-      sl.Add(sObj.Code);
-    end;
-    sl.SaveToStream(aStream);
-  finally
-    sl.Free;
-  end;
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//erzeugt das Objekt
-//@LogEvent: Event zum loggen von Fehlern und Ereignissen;
-//@raise: EglcShader wenn OpenGL nicht initialisiert werden konnte;
-//@raise:
-constructor TglcShaderProgram.Create(const aLogEvent: TglcShaderLogEvent);
-begin
-  inherited Create;
-  fOnLog      := aLogEvent;
-  fFilename   := '';
-  fProgramObj := 0;
-end;
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//gibt das Objekt frei
-destructor TglcShaderProgram.Destroy;
-begin
-  if (fProgramObj <> 0) then
-    glDeleteProgram(fProgramObj);
-  inherited Destroy;
-end;
-
-end.
-
+unit uglcShader;\r
+\r
+{ Package:      OpenGLCore\r
+  Prefix:       glc - OpenGL Core\r
+  Beschreibung: diese Unit enthält eine Klassen-Kapselung der OpenGL Shader Objekte\r
+  Beispiel:\r
+    var\r
+      shader: TglcShaderProgram;\r
+\r
+    //write log message to console\r
+    //    @param aSender: object that send the message\r
+    //    @param aMsg:    message to write to console\r
+    procedure LogMessage(aSender: TObject; const aMsg: String);\r
+    begin\r
+      writeln(Format('[%p]: %s', [aSender, aMsg]);\r
+    end;\r
+\r
+    //load shader object from file and add it to 'shader'\r
+    //    @param aFilename: name of file to load shader code from\r
+    //    @param aType:     type of shader object to create\r
+    procedure LoadShaderObject(const aFilename: String; const aType: TglcShaderType);\r
+    var\r
+      sl: TStringList;\r
+      so: TglcShaderObject;\r
+    begin\r
+      sl := TStringList.Create;\r
+      try\r
+        sl.LoadFromFile(aFileName);\r
+        so := TglcShaderObject.Create(aType);\r
+        shader.add(so);\r
+      finally\r
+        FreeAndNil(sl, @LogMessage);\r
+      end;\r
+    end;\r
+\r
+    shader := TglcShaderProgram.Create(@LogMessage);\r
+    try\r
+      // load shader objects\r
+      LoadShaderObject('./test_shader.vert', TglcShaderType.stVertex);\r
+      LoadShaderObject('./test_shader.frag', TglcShaderType.stFragment);\r
+\r
+      // compile shader\r
+      shader.Compile;\r
+\r
+      // use shader\r
+      shader.Enable;\r
+      shader.Uniform1f('uTest', 0.1234);\r
+      // do normal rendering\r
+      shader.Disable;\r
+\r
+    finally\r
+      FreeAndNil(shader);\r
+    end; }\r
+\r
+{$mode objfpc}{$H+}\r
+\r
+interface\r
+\r
+uses\r
+  Classes, SysUtils, fgl, dglOpenGL, uglcTypes, ugluMatrix, uglcContext;\r
+\r
+type\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+  EglcShader = class(Exception);\r
+  TglcShaderProgram = class;\r
+  TglcShaderLogEvent = procedure(aSender: TObject; const aMsg: String) of Object;\r
+  TglcShaderObject = class(TObject)\r
+  private\r
+    fAtachedTo: TglcShaderProgram;\r
+    fShaderObj: GLHandle;\r
+    fShaderType: TglcShaderType;\r
+    fCode: String;\r
+    fOnLog: TglcShaderLogEvent;\r
+    fAttachedTo: TglcShaderProgram;\r
+\r
+    function GetInfoLog(aObj: GLHandle): String;\r
+    function GetCompiled: Boolean;\r
+    procedure Log(const aMsg: String);\r
+    procedure CreateShaderObj;\r
+    procedure AttachTo(const aProgram: TglcShaderProgram);\r
+  public\r
+    property ShaderObj : GLHandle           read fShaderObj;\r
+    property ShaderType: TglcShaderType     read fShaderType;\r
+    property Compiled:   Boolean            read GetCompiled;\r
+    property AtachedTo:  TglcShaderProgram  read fAtachedTo;\r
+    property Code:       String             read fCode  write fCode;\r
+    property OnLog:      TglcShaderLogEvent read fOnLog write fOnLog;\r
+\r
+    procedure Compile;\r
+\r
+    constructor Create(const aShaderType: TglcShaderType; const aLogEvent: TglcShaderLogEvent = nil);\r
+    destructor Destroy; override;\r
+  end;\r
+  TglcShaderObjectList = specialize TFPGObjectList<TglcShaderObject>;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+  TglcShaderProgram = class(TglcShaderObjectList)\r
+  private\r
+    fProgramObj: GLHandle;\r
+    fOnLog: TglcShaderLogEvent;\r
+    fFilename: String;\r
+\r
+    function GetUniformLocation(const aName: String; out aPos: glInt): Boolean;\r
+    function GetInfoLog(Obj: GLHandle): String;\r
+    function GetCompiled: Boolean;\r
+    function GetLinked: Boolean;\r
+\r
+    procedure CreateProgramObj;\r
+    procedure Log(const msg: String);\r
+    procedure AttachShaderObj(const aShaderObj: TglcShaderObject);\r
+  public\r
+    property ProgramObj: glHandle           read fProgramObj;\r
+    property Filename:   String             read fFilename;\r
+    property Compiled:   Boolean            read GetCompiled;\r
+    property Linked:     Boolean            read GetLinked;\r
+    property OnLog:      TglcShaderLogEvent read fOnLog               write fOnLog;\r
+\r
+    procedure Compile;\r
+    procedure Enable;\r
+    procedure Disable;\r
+\r
+    procedure Add(aShaderObj: TglcShaderObject);\r
+    procedure Delete(aID: Integer; aFreeOwnedObj: Boolean = True);\r
+    procedure Clear;\r
+\r
+    function Uniform1f(const aName: String; aP1: GLFloat): Boolean;\r
+    function Uniform2f(const aName: String; aP1, aP2: GLFloat): Boolean;\r
+    function Uniform3f(const aName: String; aP1, aP2, aP3: GLFloat): Boolean;\r
+    function Uniform4f(const aName: String; aP1, aP2, aP3, aP4: GLFloat): Boolean;\r
+    function Uniform1i(const aName: String; aP1: GLint): Boolean;\r
+    function Uniform2i(const aName: String; aP1, aP2: GLint): Boolean;\r
+    function Uniform3i(const aName: String; aP1, aP2, aP3: GLint): Boolean;\r
+    function Uniform4i(const aName: String; aP1, aP2, aP3, aP4: GLint): Boolean;\r
+    function Uniform1fv(const aName: String; aCount: GLint; aP1: PGLFloat): Boolean;\r
+    function Uniform2fv(const aName: String; aCount: GLint; aP1: PGLFloat): Boolean;\r
+    function Uniform3fv(const aName: String; aCount: GLint; aP1: PGLFloat): Boolean;\r
+    function Uniform4fv(const aName: String; aCount: GLint; aP1: PGLFloat): Boolean;\r
+    function Uniform1iv(const aName: String; aCount: GLint; aP1: PGLInt): Boolean;\r
+    function Uniform2iv(const aName: String; aCount: GLint; aP1: PGLInt): Boolean;\r
+    function Uniform3iv(const aName: String; aCount: GLint; aP1: PGLInt): Boolean;\r
+    function Uniform4iv(const aName: String; aCount: GLint; aP1: PGLInt): Boolean;\r
+    function UniformMatrix2fv(const aName: String; aTranspose: Boolean; aCount: GLint; aP1: PgluMatrix2f): Boolean;\r
+    function UniformMatrix3fv(const aName: String; aTranspose: Boolean; aCount: GLint; aP1: PgluMatrix3f): Boolean;\r
+    function UniformMatrix4fv(const aName: String; aTranspose: Boolean; aCount: GLint; aP1: PgluMatrix4f): Boolean;\r
+\r
+    function GetUniformfv(const aName: String; aP: PGLfloat): Boolean;\r
+    function GetUniformfi(const aName: String; aP: PGLint): Boolean;\r
+    function HasUniform(const aName: String): Boolean;\r
+\r
+    procedure LoadFromFile(const aFilename: String);\r
+    procedure LoadFromStream(const aStream: TStream);\r
+    procedure SaveToFile(const aFilename: String);\r
+    procedure SaveToStream(const aStream: TStream);\r
+\r
+    constructor Create(const aLogEvent: TglcShaderLogEvent = nil);\r
+    destructor Destroy; override;\r
+  end;\r
+\r
+implementation\r
+\r
+uses\r
+  RegExpr;\r
+\r
+const\r
+  ERROR_STR_VAR_NAME: String = 'can''t find the variable ''%s'' in the program';\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//glShaderObject////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRI//\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//ließt das Log eines OpenGL-Objekts aus\r
+//@Obj: Handle des Objekts, dessen Log ausgelesen werden soll;\r
+//@result: Log des Objekts;\r
+function TglcShaderObject.GetInfoLog(aObj: GLHandle): String;\r
+var\r
+  Msg: PChar;\r
+  bLen: GLint;\r
+  sLen: GLsizei;\r
+begin\r
+  bLen := 0;\r
+  glGetShaderiv(aObj, GL_INFO_LOG_LENGTH, @bLen);\r
+  if bLen > 1 then begin\r
+    GetMem(Msg, bLen * SizeOf(Char));\r
+    glGetShaderInfoLog(aObj, bLen, @sLen, Msg);\r
+    result := PChar(Msg);\r
+    Dispose(Msg);\r
+  end;\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//ließt aus, ob der Shader ohne Fehler kompiliert wurde\r
+//@result: TRUE wenn ohne Fehler kompiliert, sonst FALSE;\r
+function TglcShaderObject.GetCompiled: Boolean;\r
+var\r
+  value: glInt;\r
+begin\r
+  glGetShaderiv(fShaderObj, GL_COMPILE_STATUS, @value);\r
+  result := (value = GL_TRUE);\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//ruft das Log-Event auf, wenn es gesetzt ist\r
+//@msg: Nachricht die geloggt werden soll;\r
+procedure TglcShaderObject.Log(const aMsg: String);\r
+begin\r
+  if Assigned(fOnLog) then begin\r
+    fOnLog(self, aMsg);\r
+  end;\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+procedure TglcShaderObject.CreateShaderObj;\r
+begin\r
+  if (fShaderObj <> 0) then\r
+    exit;\r
+  fShaderObj := glCreateShader(GLenum(fShaderType));\r
+  if fShaderObj = 0 then\r
+    raise EglcShader.Create('can''t create ShaderObject');\r
+  Log('shader object created: #'+IntToHex(fShaderObj, 4));\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+procedure TglcShaderObject.AttachTo(const aProgram: TglcShaderProgram);\r
+begin\r
+  if (aProgram <> fAtachedTo) then begin\r
+    CreateShaderObj;\r
+    glAttachShader(aProgram.ProgramObj, fShaderObj);\r
+    fAttachedTo := aProgram;\r
+  end;\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBL//\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//kompiliert das Shader-Objekt\r
+procedure TglcShaderObject.Compile;\r
+var\r
+  len, i: GLint;\r
+  List: TStringList;\r
+  c: PAnsiChar;\r
+begin\r
+  CreateShaderObj;\r
+  len := Length(fCode);\r
+  if len > 0 then begin\r
+    c := PAnsiChar(fCode);\r
+    glShaderSource(fShaderObj, 1, @c, @len);\r
+    glCompileShader(fShaderObj);\r
+    List := TStringList.Create;\r
+    List.Text := GetInfoLog(fShaderObj);\r
+    for i := 0 to List.Count-1 do\r
+      Log(List[i]);\r
+    List.Free;\r
+  end else Log('error while compiling: no bound shader code');\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//erzeugt das Objekt\r
+//@ShaderType: Typ des Shader-Objekts;\r
+//@LogEvent: Event zum loggen von Fehlern und Ereignissen;\r
+//@raise: EglcShader wenn der Shadertyp unbekannt oder ungültig ist;\r
+constructor TglcShaderObject.Create(const aShaderType: TglcShaderType; const aLogEvent: TglcShaderLogEvent);\r
+begin\r
+  inherited Create;\r
+  fCode       := '';\r
+  fOnLog      := aLogEvent;\r
+  fShaderType := aShaderType;\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//gibt das Objekt frei\r
+destructor TglcShaderObject.Destroy;\r
+begin\r
+  if (fShaderObj <> 0) then\r
+    glDeleteShader(fShaderObj);\r
+  inherited Destroy;\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//glShaderProgram///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRI//\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+function TglcShaderProgram.GetUniformLocation(const aName: String; out aPos: glInt): Boolean;\r
+begin\r
+  aPos := glGetUniformLocation(fProgramObj, PChar(aName));\r
+  result := (aPos <> -1);\r
+  if not result then\r
+    Log(StringReplace(ERROR_STR_VAR_NAME, '%s', aName, [rfIgnoreCase, rfReplaceAll]));\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//ließt das Log eines OpenGL-Objekts aus\r
+//@Obj: Handle des Objekts, dessen Log ausgelesen werden soll;\r
+//@result: Log des Objekts;\r
+function TglcShaderProgram.GetInfoLog(Obj: GLHandle): String;\r
+var\r
+  Msg: PChar;\r
+  bLen: GLint;\r
+  sLen: GLsizei;\r
+begin\r
+  bLen := 0;\r
+  glGetProgramiv(Obj, GL_INFO_LOG_LENGTH, @bLen);\r
+  if bLen > 1 then begin\r
+    GetMem(Msg, bLen * SizeOf(Char));\r
+    glGetProgramInfoLog(Obj, bLen, @sLen, Msg);\r
+    result := PChar(Msg);\r
+    Dispose(Msg);\r
+  end;\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//prüft ob alle Shader ohne Fehler compiliert wurden\r
+//@result: TRUE wenn alle erfolgreich compiliert, sonst FALSE;\r
+function TglcShaderProgram.GetCompiled: Boolean;\r
+var\r
+  i: Integer;\r
+begin\r
+  result := (Count > 0);\r
+  for i := 0 to Count-1 do\r
+    result := result and Items[i].Compiled;\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//prüft ob das Programm ohne Fehler gelinkt wurde\r
+//@result: TRUE wenn linken erfolgreich, sonst FASLE;\r
+function TglcShaderProgram.GetLinked: Boolean;\r
+var\r
+  value: glInt;\r
+begin\r
+  glGetProgramiv(fProgramObj, GL_LINK_STATUS, @value);\r
+  result := (value = GL_TRUE);\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+procedure TglcShaderProgram.CreateProgramObj;\r
+begin\r
+  if (fProgramObj = 0) then begin\r
+    if GL_LibHandle = nil then\r
+      raise EglcShader.Create('TglShaderProgram.Create - OpenGL not initialized');\r
+\r
+    if not TglcContext.IsAnyContextActive then\r
+      raise EglcShader.Create('TglShaderProgram.Create - no valid render context');\r
+\r
+    fProgramObj := glCreateProgram();\r
+    Log('shader program created: #'+IntToHex(fProgramObj, 4));\r
+  end;\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//ruft das Log-Event auf, wenn es gesetzt ist\r
+//@msg: Nachricht die geloggt werden soll;\r
+procedure TglcShaderProgram.Log(const msg: String);\r
+begin\r
+  if Assigned(fOnLog) then begin\r
+    fOnLog(self, msg);\r
+  end;\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+procedure TglcShaderProgram.AttachShaderObj(const aShaderObj: TglcShaderObject);\r
+begin\r
+  CreateProgramObj;\r
+  aShaderObj.AttachTo(self);\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBL//\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//Kompiliert den Shader-Code\r
+procedure TglcShaderProgram.Compile;\r
+var\r
+  i: Integer;\r
+  l: TStringList;\r
+begin\r
+  CreateProgramObj;\r
+  for i := 0 to Count-1 do begin\r
+    AttachShaderObj(Items[i]);\r
+    Items[i].Compile;\r
+  end;\r
+  glLinkProgram(fProgramObj);\r
+  l := TStringList.Create;\r
+  l.Text := GetInfoLog(fProgramObj);\r
+  for i := 0 to l.Count-1 do\r
+    Log(l[i]);\r
+  l.Free;\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//aktiviert den Shader\r
+procedure TglcShaderProgram.Enable;\r
+begin\r
+  glUseProgram(fProgramObj);\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//deaktiviert den Shader\r
+procedure TglcShaderProgram.Disable;\r
+begin\r
+  glUseProgram(0);\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//fügt der Liste einen Shader hinzu\r
+//@ShaderObj: Objekt, das hinzugefügt werden soll;\r
+procedure TglcShaderProgram.Add(aShaderObj: TglcShaderObject);\r
+begin\r
+  inherited Add(aShaderObj);\r
+  if (fProgramObj <> 0) then\r
+    AttachShaderObj(aShaderObj);\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//löscht ein ShaderObjekt aus der Liste\r
+//@ID: Index des Objekts, das gelöscht werden soll;\r
+//@FreeOwnedObj: wenn TRUE wird das gelöschte Objekt freigegeben;\r
+procedure TglcShaderProgram.Delete(aID: Integer; aFreeOwnedObj: Boolean);\r
+var\r
+  b: Boolean;\r
+begin\r
+  if (aID >= 0) and (aID < Count) and (fProgramObj <> 0) then begin\r
+    glDetachShader(fProgramObj, Items[aID].fShaderObj);\r
+    Items[aID].fAttachedTo := nil;\r
+  end;\r
+  b := FreeObjects;\r
+  FreeObjects := aFreeOwnedObj;\r
+  inherited Delete(aID);\r
+  FreeObjects := b;\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+procedure TglcShaderProgram.Clear;\r
+begin\r
+  while (Count > 0) do\r
+    Delete(0);\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//übergibt einen 1-Komponenten Float-Vektoren an den Shader\r
+//!!!Der Shader muss dazu aktiviert sein!!!\r
+//@Name: Name der Variablen die gesetzt werden soll;\r
+//@p1: Wert der Variable, der gesetzt werden soll;\r
+//@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);\r
+function TglcShaderProgram.Uniform1f(const aName: String; aP1: GLFloat): Boolean;\r
+var\r
+  pos: GLint;\r
+begin\r
+  result := GetUniformLocation(aName, pos);\r
+  if result then\r
+    glUniform1f(pos, aP1);\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//übergibt einen 2-Komponenten Float-Vektoren an den Shader\r
+//!!!Der Shader muss dazu aktiviert sein!!!\r
+//@Name: Name der Variablen die gesetzt werden soll;\r
+//@p1: Wert der Variable, der gesetzt werden soll;\r
+//@p2: Wert der Variable, der gesetzt werden soll;\r
+//@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);\r
+function TglcShaderProgram.Uniform2f(const aName: String; aP1, aP2: GLFloat): Boolean;\r
+var\r
+  pos: GLint;\r
+begin\r
+  result := GetUniformLocation(aName, pos);\r
+  if result then\r
+    glUniform2f(pos, aP1, aP2);\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//übergibt einen 3-Komponenten Float-Vektoren an den Shader\r
+//!!!Der Shader muss dazu aktiviert sein!!!\r
+//@Name: Name der Variablen die gesetzt werden soll;\r
+//@p1: Wert der Variable, der gesetzt werden soll;\r
+//@p2: Wert der Variable, der gesetzt werden soll;\r
+//@p3: Wert der Variable, der gesetzt werden soll;\r
+//@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);\r
+function TglcShaderProgram.Uniform3f(const aName: String; aP1, aP2, aP3: GLFloat): Boolean;\r
+var\r
+  pos: GLint;\r
+begin\r
+  result := GetUniformLocation(aName, pos);\r
+  if result then\r
+    glUniform3f(pos, aP1, aP2, aP3);\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//übergibt einen 4-Komponenten Float-Vektoren an den Shader\r
+//!!!Der Shader muss dazu aktiviert sein!!!\r
+//@Name: Name der Variablen die gesetzt werden soll;\r
+//@p1: Wert der Variable, der gesetzt werden soll;\r
+//@p2: Wert der Variable, der gesetzt werden soll;\r
+//@p3: Wert der Variable, der gesetzt werden soll;\r
+//@p4: Wert der Variable, der gesetzt werden soll;\r
+//@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);\r
+function TglcShaderProgram.Uniform4f(const aName: String; aP1, aP2, aP3, aP4: GLFloat): Boolean;\r
+var\r
+  pos: GLint;\r
+begin\r
+  result := GetUniformLocation(aName, pos);\r
+  if result then\r
+    glUniform4f(pos, aP1, aP2, aP3, aP4);\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//übergibt einen 1-Komponenten Integer-Vektoren an den Shader\r
+//!!!Der Shader muss dazu aktiviert sein!!!\r
+//@Name: Name der Variablen die gesetzt werden soll;\r
+//@p1: Wert der Variable, der gesetzt werden soll;\r
+//@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);\r
+function TglcShaderProgram.Uniform1i(const aName: String; aP1: GLint): Boolean;\r
+var\r
+  pos: GLint;\r
+begin\r
+  result := GetUniformLocation(aName, pos);\r
+  if result then\r
+    glUniform1i(pos, aP1);\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//übergibt einen 2-Komponenten Integer-Vektoren an den Shader\r
+//!!!Der Shader muss dazu aktiviert sein!!!\r
+//@Name: Name der Variablen die gesetzt werden soll;\r
+//@p1: Wert der Variable, der gesetzt werden soll;\r
+//@p1: Wert der Variable, der gesetzt werden soll;\r
+//@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);\r
+function TglcShaderProgram.Uniform2i(const aName: String; aP1, aP2: GLint): Boolean;\r
+var\r
+  pos: GLint;\r
+begin\r
+  result := GetUniformLocation(aName, pos);\r
+  if result then\r
+    glUniform2i(pos, aP1, aP2);\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//übergibt einen 3-Komponenten Integer-Vektoren an den Shader\r
+//!!!Der Shader muss dazu aktiviert sein!!!\r
+//@Name: Name der Variablen die gesetzt werden soll;\r
+//@p1: Wert der Variable, der gesetzt werden soll;\r
+//@p2: Wert der Variable, der gesetzt werden soll;\r
+//@p3: Wert der Variable, der gesetzt werden soll;\r
+//@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);\r
+function TglcShaderProgram.Uniform3i(const aName: String; aP1, aP2, aP3: GLint): Boolean;\r
+var\r
+  pos: GLint;\r
+begin\r
+  result := GetUniformLocation(aName, pos);\r
+  if result then\r
+    glUniform3i(pos, aP1, aP2, aP3);\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//übergibt einen 4-Komponenten Integer-Vektoren an den Shader\r
+//!!!Der Shader muss dazu aktiviert sein!!!\r
+//@Name: Name der Variablen die gesetzt werden soll;\r
+//@p1: Wert der Variable, der gesetzt werden soll;\r
+//@p2: Wert der Variable, der gesetzt werden soll;\r
+//@p3: Wert der Variable, der gesetzt werden soll;\r
+//@p4: Wert der Variable, der gesetzt werden soll;\r
+//@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);\r
+function TglcShaderProgram.Uniform4i(const aName: String; aP1, aP2, aP3, aP4: GLint): Boolean;\r
+var\r
+  pos: GLint;\r
+begin\r
+  result := GetUniformLocation(aName, pos);\r
+  if result then\r
+    glUniform4i(pos, aP1, aP2, aP3, aP4);\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//übergibt einen oder mehrere 1-Komponenten Float-Vektoren an den Shader\r
+//!!!Der Shader muss dazu aktiviert sein!!!\r
+//@Name: Name der Variablen die gesetzt werden soll;\r
+//@count: Anzahl an Parametern auf die p1 zeigt;\r
+//@p1: Zeiger auf den ersten Wert der gesetzt werden soll;\r
+//@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);\r
+function TglcShaderProgram.Uniform1fv(const aName: String; aCount: GLint; aP1: PGLFloat): Boolean;\r
+var\r
+  pos: GLint;\r
+begin\r
+  result := GetUniformLocation(aName, pos);\r
+  if result then\r
+    glUniform1fv(pos, aCount, aP1);\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//übergibt einen oder mehrere 2-Komponenten Float-Vektoren an den Shader\r
+//!!!Der Shader muss dazu aktiviert sein!!!\r
+//@Name: Name der Variablen die gesetzt werden soll;\r
+//@count: Anzahl an Parametern auf die p1 zeigt;\r
+//@p1: Zeiger auf den ersten Wert der gesetzt werden soll;\r
+//@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);\r
+function TglcShaderProgram.Uniform2fv(const aName: String; aCount: GLint; aP1: PGLFloat): Boolean;\r
+var\r
+  pos: GLint;\r
+begin\r
+  result := GetUniformLocation(aName, pos);\r
+  if result then\r
+    glUniform2fv(pos, aCount, aP1);\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//übergibt einen oder mehrere 3-Komponenten Float-Vektoren an den Shader\r
+//!!!Der Shader muss dazu aktiviert sein!!!\r
+//@Name: Name der Variablen die gesetzt werden soll;\r
+//@count: Anzahl an Parametern auf die p1 zeigt;\r
+//@p1: Zeiger auf den ersten Wert der gesetzt werden soll;\r
+//@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);\r
+function TglcShaderProgram.Uniform3fv(const aName: String; aCount: GLint; aP1: PGLFloat): Boolean;\r
+var\r
+  pos: GLint;\r
+begin\r
+  result := GetUniformLocation(aName, pos);\r
+  if result then\r
+    glUniform3fv(pos, aCount, aP1);\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//übergibt einen oder mehrere 4-Komponenten Float-Vektoren an den Shader\r
+//!!!Der Shader muss dazu aktiviert sein!!!\r
+//@Name: Name der Variablen die gesetzt werden soll;\r
+//@count: Anzahl an Parametern auf die p1 zeigt;\r
+//@p1: Zeiger auf den ersten Wert der gesetzt werden soll;\r
+//@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);\r
+function TglcShaderProgram.Uniform4fv(const aName: String; aCount: GLint; aP1: PGLFloat): Boolean;\r
+var\r
+  pos: GLint;\r
+begin\r
+  result := GetUniformLocation(aName, pos);\r
+  if result then\r
+    glUniform4fv(pos, aCount, aP1);\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//übergibt einen oder mehrere 1-Komponenten Integer-Vektoren an den Shader\r
+//!!!Der Shader muss dazu aktiviert sein!!!\r
+//@Name: Name der Variablen die gesetzt werden soll;\r
+//@count: Anzahl an Parametern auf die p1 zeigt;\r
+//@p1: Zeiger auf den ersten Wert der gesetzt werden soll;\r
+//@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);\r
+function TglcShaderProgram.Uniform1iv(const aName: String; aCount: GLint; aP1: PGLInt): Boolean;\r
+var\r
+  pos: GLint;\r
+begin\r
+  result := GetUniformLocation(aName, pos);\r
+  if result then\r
+    glUniform1iv(pos, aCount, aP1);\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//übergibt einen oder mehrere 2-Komponenten Integer-Vektoren an den Shader\r
+//!!!Der Shader muss dazu aktiviert sein!!!\r
+//@Name: Name der Variablen die gesetzt werden soll;\r
+//@count: Anzahl an Parametern auf die p1 zeigt;\r
+//@p1: Zeiger auf den ersten Wert der gesetzt werden soll;\r
+//@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);\r
+function TglcShaderProgram.Uniform2iv(const aName: String; aCount: GLint; aP1: PGLInt): Boolean;\r
+var\r
+  pos: GLint;\r
+begin\r
+  result := GetUniformLocation(aName, pos);\r
+  if result then\r
+    glUniform2iv(pos, aCount, aP1);\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//übergibt einen oder mehrere 3-Komponenten Integer-Vektoren an den Shader\r
+//!!!Der Shader muss dazu aktiviert sein!!!\r
+//@Name: Name der Variablen die gesetzt werden soll;\r
+//@count: Anzahl an Parametern auf die p1 zeigt;\r
+//@p1: Zeiger auf den ersten Wert der gesetzt werden soll;\r
+//@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);\r
+function TglcShaderProgram.Uniform3iv(const aName: String; aCount: GLint; aP1: PGLInt): Boolean;\r
+var\r
+  pos: GLint;\r
+begin\r
+  result := GetUniformLocation(aName, pos);\r
+  if result then\r
+    glUniform3iv(pos, aCount, aP1);\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//übergibt einen oder mehrere 4-Komponenten Integer-Vektoren an den Shader\r
+//!!!Der Shader muss dazu aktiviert sein!!!\r
+//@Name: Name der Variablen die gesetzt werden soll;\r
+//@count: Anzahl an Parametern auf die p1 zeigt;\r
+//@p1: Zeiger auf den ersten Wert der gesetzt werden soll;\r
+//@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);\r
+function TglcShaderProgram.Uniform4iv(const aName: String; aCount: GLint; aP1: PGLInt): Boolean;\r
+var\r
+  pos: GLint;\r
+begin\r
+  result := GetUniformLocation(aName, pos);\r
+  if result then\r
+    glUniform4iv(pos, aCount, aP1) ;\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//übergibt eine oder mehrere 2x2-Matrizen an den Shader\r
+//!!!Der Shader muss dazu aktiviert sein!!!\r
+//@Name: Name der Variablen die gesetzt werden soll;\r
+//@Transpose: wenn TRUe wird die matrix vor der Übergabe transponiert;\r
+//@Count: Anzahl der zu übergebenden Elemente;\r
+//@p1: Wert der Variable, der gesetzt werden soll;\r
+//@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);\r
+function TglcShaderProgram.UniformMatrix2fv(const aName: String; aTranspose: Boolean; aCount: GLint; aP1: PgluMatrix2f): Boolean;\r
+var\r
+  pos: GLint;\r
+begin\r
+  result := GetUniformLocation(aName, pos);\r
+  if result then\r
+    glUniformMatrix2fv(pos, aCount, aTranspose, PGLfloat(aP1));\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//übergibt eine oder mehrere 3x3-Matrizen an den Shader\r
+//!!!Der Shader muss dazu aktiviert sein!!!\r
+//@Name: Name der Variablen die gesetzt werden soll;\r
+//@Transpose: wenn TRUe wird die matrix vor der Übergabe transponiert;\r
+//@Count: Anzahl der zu übergebenden Elemente;\r
+//@p1: Wert der Variable, der gesetzt werden soll;\r
+//@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);\r
+function TglcShaderProgram.UniformMatrix3fv(const aName: String; aTranspose: Boolean; aCount: GLint; aP1: PgluMatrix3f): Boolean;\r
+var\r
+  pos: GLint;\r
+begin\r
+  result := GetUniformLocation(aName, pos);\r
+  if result then\r
+    glUniformMatrix3fv(pos, aCount, aTranspose, PGLfloat(aP1));\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//übergibt eine oder mehrere 4x4-Matrizen an den Shader\r
+//!!!Der Shader muss dazu aktiviert sein!!!\r
+//@Name: Name der Variablen die gesetzt werden soll;\r
+//@Transpose: wenn TRUe wird die matrix vor der Übergabe transponiert;\r
+//@Count: Anzahl der zu übergebenden Elemente;\r
+//@p1: Wert der Variable, der gesetzt werden soll;\r
+//@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);\r
+function TglcShaderProgram.UniformMatrix4fv(const aName: String; aTranspose: Boolean; aCount: GLint; aP1: PgluMatrix4f): Boolean;\r
+var\r
+  pos: GLint;\r
+begin\r
+  result := GetUniformLocation(aName, pos);\r
+  if result then\r
+    glUniformMatrix4fv(pos, aCount, aTranspose, PGLfloat(aP1));\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//holt den Wert einer Float-Uniform-Variable aus dem Shader\r
+//!!!Der Shader muss dazu aktiviert sein!!!\r
+//@Name: Name der Variablen die gelesen werden soll;\r
+//@p: Zeiger auf die Variable, in die der gelesene Wert geschrieben werden soll;\r
+//@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);\r
+function TglcShaderProgram.GetUniformfv(const aName: String; aP: PGLfloat): Boolean;\r
+var\r
+  pos: GLint;\r
+begin\r
+  result := GetUniformLocation(aName, pos);\r
+  if result then\r
+    glGetUniformfv(fProgramObj, pos, aP);\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//holt den Wert einer Integer-Uniform-Variable aus dem Shader\r
+//!!!Der Shader muss dazu aktiviert sein!!!\r
+//@Name: Name der Variablen die gelesen werden soll;\r
+//@p: Zeiger auf die Variable, in die der gelesene Wert geschrieben werden soll;\r
+//@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);\r
+function TglcShaderProgram.GetUniformfi(const aName: String; aP: PGLint): Boolean;\r
+var\r
+  pos: GLint;\r
+begin\r
+  result := GetUniformLocation(aName, pos);\r
+  if result then\r
+    glGetUniformiv(fProgramObj, pos, aP);\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+function TglcShaderProgram.HasUniform(const aName: String): Boolean;\r
+var\r
+  pos: GLint;\r
+begin\r
+  result := GetUniformLocation(aName, pos);\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//läd den Shader aus einer Datei\r
+//@Filename: Datei aus der gelesen werden soll;\r
+//@raise: EglcShader, wenn Datei nicht vorhanden ist;\r
+procedure TglcShaderProgram.LoadFromFile(const aFilename: String);\r
+var\r
+  Stream: TFileStream;\r
+begin\r
+  if FileExists(aFilename) then begin\r
+    Stream := TFileStream.Create(aFilename, fmOpenRead);\r
+    try\r
+      LoadFromStream(Stream);\r
+      fFilename := aFilename;\r
+    finally\r
+      Stream.Free;\r
+    end;\r
+  end else raise EglcShader.Create('TglShaderProgram.LoadFromFile - file not found: '+Filename);\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//läd den Shader aus einem Stream\r
+//@Stream: Stream aus dem gelesen werden soll;\r
+//@raise: EglcShader wenn kein Stream-Objekt übergeben wurde;\r
+procedure TglcShaderProgram.LoadFromStream(const aStream: TStream);\r
+\r
+  function GetShaderType(const aStr: String): TglcShaderType;\r
+  begin\r
+    if (aStr = 'GL_VERTEX_SHADER') then\r
+      result := TglcShaderType.stVertex\r
+    else if (aStr = 'GL_FRAGMENT_SHADER') then\r
+      result := TglcShaderType.stFragment\r
+    else if (aStr = 'GL_GEOMETRY_SHADER') then\r
+      result := TglcShaderType.stGeometry\r
+    else if (aStr = 'GL_TESS_CONTROL_SHADER') then\r
+      result := TglcShaderType.stTessControl\r
+    else if (aStr = 'GL_TESS_EVALUATION_SHADER') then\r
+      result := TglcShaderType.stTessEvaluation\r
+    else\r
+      raise Exception.Create('invalid shader type: ' + aStr);\r
+  end;\r
+\r
+var\r
+  sl: TStringList;\r
+  s: String;\r
+  rx: TRegExpr;\r
+  LastMatchPos: PtrInt;\r
+  st: TglcShaderType;\r
+  o: TglcShaderObject;\r
+\r
+  procedure AddObj(const aPos: Integer);\r
+  begin\r
+    if (LastMatchPos > 0) then begin\r
+      o := TglcShaderObject.Create(st, fOnLog);\r
+      o.Code := Trim(Copy(s, LastMatchPos, aPos - LastMatchPos));\r
+      Add(o);\r
+    end;\r
+  end;\r
+\r
+begin\r
+  if not Assigned(aStream) then\r
+    raise EglcShader.Create('TglShaderProgram.SaveToStream - stream is nil');\r
+\r
+  Clear;\r
+  sl := TStringList.Create;\r
+  rx := TRegExpr.Create;\r
+  try\r
+    sl.LoadFromStream(aStream);\r
+    s := sl.Text;\r
+    LastMatchPos := 0;\r
+    rx.Expression  := '/\*\s*ShaderObject\s*:\s*(GL_[A-Z_]+)\s*\*/\s*$?';\r
+    rx.InputString := s;\r
+\r
+    while rx.Exec(LastMatchPos+1) do begin\r
+      AddObj(rx.MatchPos[0]);\r
+      LastMatchPos := rx.MatchPos[0] + rx.MatchLen[0];\r
+      st := GetShaderType(rx.Match[1]);\r
+    end;\r
+    AddObj(Length(s));\r
+  finally\r
+    rx.Free;\r
+    sl.Free;\r
+  end;\r
+\r
+\r
+  {\r
+  if Assigned(aStream) then begin\r
+    Clear;\r
+    fFilename := '';\r
+    reader := TutlStreamReader.Create(aStream);\r
+    try\r
+      if reader.ReadAnsiString <> GLSL_FILE_HEADER then\r
+        raise EglcShader.Create('TglShaderProgram.SaveToStream - incompatible file');\r
+      v := reader.ReadInteger;\r
+\r
+      if v >= 100 then begin //version 1.00\r
+        c := reader.ReadInteger;\r
+        for i := 0 to c-1 do begin\r
+          Add(TglcShaderObject.Create(Cardinal(reader.ReadInteger), fOnLog));\r
+          Last.fCode := reader.ReadAnsiString;\r
+        end;\r
+      end;\r
+    finally\r
+      reader.Free;\r
+    end;\r
+  end else\r
+  }\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//speichert den Shader in einer Datei\r
+//@Filename: Datei in die geschrieben werden soll;\r
+procedure TglcShaderProgram.SaveToFile(const aFilename: String);\r
+var\r
+  Stream: TFileStream;\r
+begin\r
+  Stream := TFileStream.Create(aFilename, fmCreate);\r
+  try\r
+    SaveToStream(Stream);\r
+    fFilename := aFilename;\r
+  finally\r
+    Stream.Free;\r
+  end;\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//speichert den Shader in einen Stream\r
+//@Stream: Stream in den geschrieben werden soll;\r
+//@raise: EglcShader wenn kein Stream-Objekt übergeben wurde;\r
+//@raise: EglcShader wenn ungültige Datei;\r
+procedure TglcShaderProgram.SaveToStream(const aStream: TStream);\r
+var\r
+  i: Integer;\r
+  sl: TStringList;\r
+  sObj: TglcShaderObject;\r
+\r
+  function GetShaderTypeStr(const aShaderType: TglcShaderType): String;\r
+  begin\r
+    case aShaderType of\r
+      TglcShaderType.stVertex:          result := 'GL_VERTEX_SHADER';\r
+      TglcShaderType.stFragment:        result := 'GL_FRAGMENT_SHADER';\r
+      TglcShaderType.stGeometry:        result := 'GL_GEOMETRY_SHADER';\r
+      TglcShaderType.stTessControl:     result := 'GL_TESS_CONTROL_SHADER';\r
+      TglcShaderType.stTessEvaluation:  result := 'GL_TESS_EVALUATION_SHADER';\r
+    else\r
+      result := 'UNKNOWN';\r
+    end;\r
+  end;\r
+\r
+begin\r
+  if not Assigned(aStream) then\r
+    raise EglcShader.Create('TglShaderProgram.LoadFromStream - stream is nil');\r
+  fFilename := '';\r
+  sl := TStringList.Create;\r
+  try\r
+    for i := 0 to Count-1 do begin\r
+      sObj := Items[i];\r
+      sl.Add('/* ShaderObject: ' + GetShaderTypeStr(sObj.ShaderType) + ' */');\r
+      sl.Add(sObj.Code);\r
+    end;\r
+    sl.SaveToStream(aStream);\r
+  finally\r
+    sl.Free;\r
+  end;\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//erzeugt das Objekt\r
+//@LogEvent: Event zum loggen von Fehlern und Ereignissen;\r
+//@raise: EglcShader wenn OpenGL nicht initialisiert werden konnte;\r
+//@raise:\r
+constructor TglcShaderProgram.Create(const aLogEvent: TglcShaderLogEvent);\r
+begin\r
+  inherited Create;\r
+  fOnLog      := aLogEvent;\r
+  fFilename   := '';\r
+  fProgramObj := 0;\r
+end;\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+//gibt das Objekt frei\r
+destructor TglcShaderProgram.Destroy;\r
+begin\r
+  if (fProgramObj <> 0) then\r
+    glDeleteProgram(fProgramObj);\r
+  inherited Destroy;\r
+end;\r
+\r
+end.\r
+\r
\ No newline at end of file