4 Prefix: glc - OpenGL Core
5 Beschreibung: diese Unit enthält eine Klassen-Kapselung der OpenGL Shader Objekte
8 shader: TglcShaderProgram;
10 //write log message to console
11 // @param aSender: object that send the message
12 // @param aMsg: message to write to console
13 procedure LogMessage(aSender: TObject; const aMsg: String);
15 writeln(Format('[%p]: %s', [aSender, aMsg]);
18 //load shader object from file and add it to 'shader'
19 // @param aFilename: name of file to load shader code from
20 // @param aType: type of shader object to create
21 procedure LoadShaderObject(const aFilename: String; const aType: TglcShaderType);
26 sl := TStringList.Create;
28 sl.LoadFromFile(aFileName);
29 so := TglcShaderObject.Create(aType);
32 FreeAndNil(sl, @LogMessage);
36 shader := TglcShaderProgram.Create(@LogMessage);
38 // load shader objects
39 LoadShaderObject('./test_shader.vert', TglcShaderType.stVertex);
40 LoadShaderObject('./test_shader.frag', TglcShaderType.stFragment);
47 shader.Uniform1f('uTest', 0.1234);
48 // do normal rendering
60 Classes, SysUtils, fgl, dglOpenGL, uglcTypes, ugluMatrix;
63 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
64 EglcShader = class(Exception);
65 TglcShaderProgram = class;
66 TglcShaderLogEvent = procedure(aSender: TObject; const aMsg: String) of Object;
67 TglcShaderObject = class(TObject)
69 fAtachedTo: TglcShaderProgram;
71 fShaderType: TglcShaderType;
73 fOnLog: TglcShaderLogEvent;
74 fAttachedTo: TglcShaderProgram;
76 function GetInfoLog(aObj: GLHandle): String;
77 function GetCompiled: Boolean;
78 procedure Log(const aMsg: String);
79 procedure CreateShaderObj;
80 procedure AttachTo(const aProgram: TglcShaderProgram);
82 property ShaderObj : GLHandle read fShaderObj;
83 property ShaderType: TglcShaderType read fShaderType;
84 property Compiled: Boolean read GetCompiled;
85 property AtachedTo: TglcShaderProgram read fAtachedTo;
86 property Code: String read fCode write fCode;
87 property OnLog: TglcShaderLogEvent read fOnLog write fOnLog;
91 constructor Create(const aShaderType: TglcShaderType; const aLogEvent: TglcShaderLogEvent = nil);
92 destructor Destroy; override;
94 TglcShaderObjectList = specialize TFPGObjectList<TglcShaderObject>;
96 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
97 TglcShaderProgram = class(TglcShaderObjectList)
99 fProgramObj: GLHandle;
100 fOnLog: TglcShaderLogEvent;
102 fGeometryInputType: GLint;
103 fGeometryOutputType: GLint;
104 fGeometryVerticesOut: GLint;
106 function GetUniformLocation(const aName: String; out aPos: glInt): Boolean;
107 function GetInfoLog(Obj: GLHandle): String;
108 function GetCompiled: Boolean;
109 function GetLinked: Boolean;
111 procedure CreateProgramObj;
112 procedure Log(const msg: String);
113 procedure AttachShaderObj(const aShaderObj: TglcShaderObject);
115 property ProgramObj: glHandle read fProgramObj;
116 property Filename: String read fFilename;
117 property Compiled: Boolean read GetCompiled;
118 property Linked: Boolean read GetLinked;
119 property OnLog: TglcShaderLogEvent read fOnLog write fOnLog;
120 property GeometryInputType: GLint read fGeometryInputType write fGeometryInputType;
121 property GeometryOutputType: GLint read fGeometryOutputType write fGeometryOutputType;
122 property GeometryVerticesOut: GLint read fGeometryVerticesOut write fGeometryVerticesOut;
128 procedure Add(aShaderObj: TglcShaderObject);
129 procedure Delete(aID: Integer; aFreeOwnedObj: Boolean = True);
132 function Uniform1f(const aName: String; aP1: GLFloat): Boolean;
133 function Uniform2f(const aName: String; aP1, aP2: GLFloat): Boolean;
134 function Uniform3f(const aName: String; aP1, aP2, aP3: GLFloat): Boolean;
135 function Uniform4f(const aName: String; aP1, aP2, aP3, aP4: GLFloat): Boolean;
136 function Uniform1i(const aName: String; aP1: GLint): Boolean;
137 function Uniform2i(const aName: String; aP1, aP2: GLint): Boolean;
138 function Uniform3i(const aName: String; aP1, aP2, aP3: GLint): Boolean;
139 function Uniform4i(const aName: String; aP1, aP2, aP3, aP4: GLint): Boolean;
140 function Uniform1fv(const aName: String; aCount: GLint; aP1: PGLFloat): Boolean;
141 function Uniform2fv(const aName: String; aCount: GLint; aP1: PGLFloat): Boolean;
142 function Uniform3fv(const aName: String; aCount: GLint; aP1: PGLFloat): Boolean;
143 function Uniform4fv(const aName: String; aCount: GLint; aP1: PGLFloat): Boolean;
144 function Uniform1iv(const aName: String; aCount: GLint; aP1: PGLInt): Boolean;
145 function Uniform2iv(const aName: String; aCount: GLint; aP1: PGLInt): Boolean;
146 function Uniform3iv(const aName: String; aCount: GLint; aP1: PGLInt): Boolean;
147 function Uniform4iv(const aName: String; aCount: GLint; aP1: PGLInt): Boolean;
148 function UniformMatrix2fv(const aName: String; aTranspose: Boolean; aCount: GLint; aP1: PgluMatrix2f): Boolean;
149 function UniformMatrix3fv(const aName: String; aTranspose: Boolean; aCount: GLint; aP1: PgluMatrix3f): Boolean;
150 function UniformMatrix4fv(const aName: String; aTranspose: Boolean; aCount: GLint; aP1: PgluMatrix4f): Boolean;
152 function GetUniformfv(const aName: String; aP: PGLfloat): Boolean;
153 function GetUniformfi(const aName: String; aP: PGLint): Boolean;
154 function HasUniform(const aName: String): Boolean;
156 procedure LoadFromFile(const aFilename: String);
157 procedure LoadFromStream(const aStream: TStream);
158 procedure SaveToFile(const aFilename: String);
159 procedure SaveToStream(const aStream: TStream);
161 constructor Create(aLogEvent: TglcShaderLogEvent = nil);
162 destructor Destroy; override;
171 ERROR_STR_VAR_NAME: String = 'can''t find the variable ''%s'' in the program';
173 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
174 //glShaderObject////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
175 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
176 //PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRI//
177 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
178 //ließt das Log eines OpenGL-Objekts aus
179 //@Obj: Handle des Objekts, dessen Log ausgelesen werden soll;
180 //@result: Log des Objekts;
181 function TglcShaderObject.GetInfoLog(aObj: GLHandle): String;
188 glGetShaderiv(aObj, GL_INFO_LOG_LENGTH, @bLen);
189 if bLen > 1 then begin
190 GetMem(Msg, bLen * SizeOf(Char));
191 glGetShaderInfoLog(aObj, bLen, @sLen, Msg);
192 result := PChar(Msg);
197 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
198 //ließt aus, ob der Shader ohne Fehler kompiliert wurde
199 //@result: TRUE wenn ohne Fehler kompiliert, sonst FALSE;
200 function TglcShaderObject.GetCompiled: Boolean;
204 glGetShaderiv(fShaderObj, GL_COMPILE_STATUS, @value);
205 result := (value = GL_TRUE);
208 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
209 //ruft das Log-Event auf, wenn es gesetzt ist
210 //@msg: Nachricht die geloggt werden soll;
211 procedure TglcShaderObject.Log(const aMsg: String);
213 if Assigned(fOnLog) then begin
218 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
219 procedure TglcShaderObject.CreateShaderObj;
221 if (fShaderObj <> 0) then
223 fShaderObj := glCreateShader(GLenum(fShaderType));
224 if fShaderObj = 0 then
225 raise EglcShader.Create('can''t create ShaderObject');
226 Log('shader object created: #'+IntToHex(fShaderObj, 4));
229 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
230 procedure TglcShaderObject.AttachTo(const aProgram: TglcShaderProgram);
232 if (aProgram <> fAtachedTo) then begin
234 glAttachShader(aProgram.ProgramObj, fShaderObj);
235 fAttachedTo := aProgram;
239 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
240 //PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBL//
241 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
242 //kompiliert das Shader-Objekt
243 procedure TglcShaderObject.Compile;
250 len := Length(fCode);
251 if len > 0 then begin
252 c := PAnsiChar(fCode);
253 glShaderSource(fShaderObj, 1, @c, @len);
254 glCompileShader(fShaderObj);
255 List := TStringList.Create;
256 List.Text := GetInfoLog(fShaderObj);
257 for i := 0 to List.Count-1 do
260 end else Log('error while compiling: no bound shader code');
263 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
265 //@ShaderType: Typ des Shader-Objekts;
266 //@LogEvent: Event zum loggen von Fehlern und Ereignissen;
267 //@raise: EglcShader wenn der Shadertyp unbekannt oder ungültig ist;
268 constructor TglcShaderObject.Create(const aShaderType: TglcShaderType; const aLogEvent: TglcShaderLogEvent);
273 fShaderType := aShaderType;
276 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
277 //gibt das Objekt frei
278 destructor TglcShaderObject.Destroy;
280 if (fShaderObj <> 0) then
281 glDeleteShader(fShaderObj);
285 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
286 //glShaderProgram///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
287 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
288 //PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRI//
289 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
290 function TglcShaderProgram.GetUniformLocation(const aName: String; out aPos: glInt): Boolean;
292 aPos := glGetUniformLocation(fProgramObj, PChar(aName));
293 result := (aPos <> -1);
295 Log(StringReplace(ERROR_STR_VAR_NAME, '%s', aName, [rfIgnoreCase, rfReplaceAll]));
298 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
299 //ließt das Log eines OpenGL-Objekts aus
300 //@Obj: Handle des Objekts, dessen Log ausgelesen werden soll;
301 //@result: Log des Objekts;
302 function TglcShaderProgram.GetInfoLog(Obj: GLHandle): String;
309 glGetProgramiv(Obj, GL_INFO_LOG_LENGTH, @bLen);
310 if bLen > 1 then begin
311 GetMem(Msg, bLen * SizeOf(Char));
312 glGetProgramInfoLog(Obj, bLen, @sLen, Msg);
313 result := PChar(Msg);
318 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
319 //prüft ob alle Shader ohne Fehler compiliert wurden
320 //@result: TRUE wenn alle erfolgreich compiliert, sonst FALSE;
321 function TglcShaderProgram.GetCompiled: Boolean;
325 result := (Count > 0);
326 for i := 0 to Count-1 do
327 result := result and Items[i].Compiled;
330 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
331 //prüft ob das Programm ohne Fehler gelinkt wurde
332 //@result: TRUE wenn linken erfolgreich, sonst FASLE;
333 function TglcShaderProgram.GetLinked: Boolean;
337 glGetProgramiv(fProgramObj, GL_LINK_STATUS, @value);
338 result := (value = GL_TRUE);
341 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
342 procedure TglcShaderProgram.CreateProgramObj;
344 if (fProgramObj = 0) then begin
345 if GL_LibHandle = nil then
346 raise EglcShader.Create('TglShaderProgram.Create - OpenGL not initialized');
348 if (wglGetCurrentContext() = 0) or (wglGetCurrentDC() = 0) then
349 raise EglcShader.Create('TglShaderProgram.Create - no valid render context');
351 fProgramObj := glCreateProgram();
352 Log('shader program created: #'+IntToHex(fProgramObj, 4));
356 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
357 //ruft das Log-Event auf, wenn es gesetzt ist
358 //@msg: Nachricht die geloggt werden soll;
359 procedure TglcShaderProgram.Log(const msg: String);
361 if Assigned(fOnLog) then begin
366 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
367 procedure TglcShaderProgram.AttachShaderObj(const aShaderObj: TglcShaderObject);
370 aShaderObj.AttachTo(self);
373 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
374 //PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBL//
375 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
376 //Kompiliert den Shader-Code
377 procedure TglcShaderProgram.Compile;
383 for i := 0 to Count-1 do begin
384 AttachShaderObj(Items[i]);
387 glLinkProgram(fProgramObj);
388 l := TStringList.Create;
389 l.Text := GetInfoLog(fProgramObj);
390 for i := 0 to l.Count-1 do
395 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
396 //aktiviert den Shader
397 procedure TglcShaderProgram.Enable;
399 glUseProgram(fProgramObj);
402 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
403 //deaktiviert den Shader
404 procedure TglcShaderProgram.Disable;
409 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
410 //fügt der Liste einen Shader hinzu
411 //@ShaderObj: Objekt, das hinzugefügt werden soll;
412 procedure TglcShaderProgram.Add(aShaderObj: TglcShaderObject);
414 inherited Add(aShaderObj);
415 if (fProgramObj <> 0) then
416 AttachShaderObj(aShaderObj);
419 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
420 //löscht ein ShaderObjekt aus der Liste
421 //@ID: Index des Objekts, das gelöscht werden soll;
422 //@FreeOwnedObj: wenn TRUE wird das gelöschte Objekt freigegeben;
423 procedure TglcShaderProgram.Delete(aID: Integer; aFreeOwnedObj: Boolean);
427 if (aID >= 0) and (aID < Count) and (fProgramObj <> 0) then begin
428 glDetachShader(fProgramObj, Items[aID].fShaderObj);
429 Items[aID].fAttachedTo := nil;
432 FreeObjects := aFreeOwnedObj;
433 inherited Delete(aID);
437 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
438 procedure TglcShaderProgram.Clear;
444 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
445 //übergibt einen 1-Komponenten Float-Vektoren an den Shader
446 //!!!Der Shader muss dazu aktiviert sein!!!
447 //@Name: Name der Variablen die gesetzt werden soll;
448 //@p1: Wert der Variable, der gesetzt werden soll;
449 //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
450 function TglcShaderProgram.Uniform1f(const aName: String; aP1: GLFloat): Boolean;
454 result := GetUniformLocation(aName, pos);
456 glUniform1f(pos, aP1);
459 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
460 //übergibt einen 2-Komponenten Float-Vektoren an den Shader
461 //!!!Der Shader muss dazu aktiviert sein!!!
462 //@Name: Name der Variablen die gesetzt werden soll;
463 //@p1: Wert der Variable, der gesetzt werden soll;
464 //@p2: Wert der Variable, der gesetzt werden soll;
465 //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
466 function TglcShaderProgram.Uniform2f(const aName: String; aP1, aP2: GLFloat): Boolean;
470 result := GetUniformLocation(aName, pos);
472 glUniform2f(pos, aP1, aP2);
475 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
476 //übergibt einen 3-Komponenten Float-Vektoren an den Shader
477 //!!!Der Shader muss dazu aktiviert sein!!!
478 //@Name: Name der Variablen die gesetzt werden soll;
479 //@p1: Wert der Variable, der gesetzt werden soll;
480 //@p2: Wert der Variable, der gesetzt werden soll;
481 //@p3: Wert der Variable, der gesetzt werden soll;
482 //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
483 function TglcShaderProgram.Uniform3f(const aName: String; aP1, aP2, aP3: GLFloat): Boolean;
487 result := GetUniformLocation(aName, pos);
489 glUniform3f(pos, aP1, aP2, aP3);
492 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
493 //übergibt einen 4-Komponenten Float-Vektoren an den Shader
494 //!!!Der Shader muss dazu aktiviert sein!!!
495 //@Name: Name der Variablen die gesetzt werden soll;
496 //@p1: Wert der Variable, der gesetzt werden soll;
497 //@p2: Wert der Variable, der gesetzt werden soll;
498 //@p3: Wert der Variable, der gesetzt werden soll;
499 //@p4: Wert der Variable, der gesetzt werden soll;
500 //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
501 function TglcShaderProgram.Uniform4f(const aName: String; aP1, aP2, aP3, aP4: GLFloat): Boolean;
505 result := GetUniformLocation(aName, pos);
507 glUniform4f(pos, aP1, aP2, aP3, aP4);
510 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
511 //übergibt einen 1-Komponenten Integer-Vektoren an den Shader
512 //!!!Der Shader muss dazu aktiviert sein!!!
513 //@Name: Name der Variablen die gesetzt werden soll;
514 //@p1: Wert der Variable, der gesetzt werden soll;
515 //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
516 function TglcShaderProgram.Uniform1i(const aName: String; aP1: GLint): Boolean;
520 result := GetUniformLocation(aName, pos);
522 glUniform1i(pos, aP1);
525 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
526 //übergibt einen 2-Komponenten Integer-Vektoren an den Shader
527 //!!!Der Shader muss dazu aktiviert sein!!!
528 //@Name: Name der Variablen die gesetzt werden soll;
529 //@p1: Wert der Variable, der gesetzt werden soll;
530 //@p1: Wert der Variable, der gesetzt werden soll;
531 //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
532 function TglcShaderProgram.Uniform2i(const aName: String; aP1, aP2: GLint): Boolean;
536 result := GetUniformLocation(aName, pos);
538 glUniform2i(pos, aP1, aP2);
541 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
542 //übergibt einen 3-Komponenten Integer-Vektoren an den Shader
543 //!!!Der Shader muss dazu aktiviert sein!!!
544 //@Name: Name der Variablen die gesetzt werden soll;
545 //@p1: Wert der Variable, der gesetzt werden soll;
546 //@p2: Wert der Variable, der gesetzt werden soll;
547 //@p3: Wert der Variable, der gesetzt werden soll;
548 //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
549 function TglcShaderProgram.Uniform3i(const aName: String; aP1, aP2, aP3: GLint): Boolean;
553 result := GetUniformLocation(aName, pos);
555 glUniform3i(pos, aP1, aP2, aP3);
558 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
559 //übergibt einen 4-Komponenten Integer-Vektoren an den Shader
560 //!!!Der Shader muss dazu aktiviert sein!!!
561 //@Name: Name der Variablen die gesetzt werden soll;
562 //@p1: Wert der Variable, der gesetzt werden soll;
563 //@p2: Wert der Variable, der gesetzt werden soll;
564 //@p3: Wert der Variable, der gesetzt werden soll;
565 //@p4: Wert der Variable, der gesetzt werden soll;
566 //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
567 function TglcShaderProgram.Uniform4i(const aName: String; aP1, aP2, aP3, aP4: GLint): Boolean;
571 result := GetUniformLocation(aName, pos);
573 glUniform4i(pos, aP1, aP2, aP3, aP4);
576 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
577 //übergibt einen oder mehrere 1-Komponenten Float-Vektoren an den Shader
578 //!!!Der Shader muss dazu aktiviert sein!!!
579 //@Name: Name der Variablen die gesetzt werden soll;
580 //@count: Anzahl an Parametern auf die p1 zeigt;
581 //@p1: Zeiger auf den ersten Wert der gesetzt werden soll;
582 //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
583 function TglcShaderProgram.Uniform1fv(const aName: String; aCount: GLint; aP1: PGLFloat): Boolean;
587 result := GetUniformLocation(aName, pos);
589 glUniform1fv(pos, aCount, aP1);
592 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
593 //übergibt einen oder mehrere 2-Komponenten Float-Vektoren an den Shader
594 //!!!Der Shader muss dazu aktiviert sein!!!
595 //@Name: Name der Variablen die gesetzt werden soll;
596 //@count: Anzahl an Parametern auf die p1 zeigt;
597 //@p1: Zeiger auf den ersten Wert der gesetzt werden soll;
598 //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
599 function TglcShaderProgram.Uniform2fv(const aName: String; aCount: GLint; aP1: PGLFloat): Boolean;
603 result := GetUniformLocation(aName, pos);
605 glUniform2fv(pos, aCount, aP1);
608 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
609 //übergibt einen oder mehrere 3-Komponenten Float-Vektoren an den Shader
610 //!!!Der Shader muss dazu aktiviert sein!!!
611 //@Name: Name der Variablen die gesetzt werden soll;
612 //@count: Anzahl an Parametern auf die p1 zeigt;
613 //@p1: Zeiger auf den ersten Wert der gesetzt werden soll;
614 //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
615 function TglcShaderProgram.Uniform3fv(const aName: String; aCount: GLint; aP1: PGLFloat): Boolean;
619 result := GetUniformLocation(aName, pos);
621 glUniform3fv(pos, aCount, aP1);
624 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
625 //übergibt einen oder mehrere 4-Komponenten Float-Vektoren an den Shader
626 //!!!Der Shader muss dazu aktiviert sein!!!
627 //@Name: Name der Variablen die gesetzt werden soll;
628 //@count: Anzahl an Parametern auf die p1 zeigt;
629 //@p1: Zeiger auf den ersten Wert der gesetzt werden soll;
630 //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
631 function TglcShaderProgram.Uniform4fv(const aName: String; aCount: GLint; aP1: PGLFloat): Boolean;
635 result := GetUniformLocation(aName, pos);
637 glUniform4fv(pos, aCount, aP1);
640 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
641 //übergibt einen oder mehrere 1-Komponenten Integer-Vektoren an den Shader
642 //!!!Der Shader muss dazu aktiviert sein!!!
643 //@Name: Name der Variablen die gesetzt werden soll;
644 //@count: Anzahl an Parametern auf die p1 zeigt;
645 //@p1: Zeiger auf den ersten Wert der gesetzt werden soll;
646 //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
647 function TglcShaderProgram.Uniform1iv(const aName: String; aCount: GLint; aP1: PGLInt): Boolean;
651 result := GetUniformLocation(aName, pos);
653 glUniform1iv(pos, aCount, aP1);
656 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
657 //übergibt einen oder mehrere 2-Komponenten Integer-Vektoren an den Shader
658 //!!!Der Shader muss dazu aktiviert sein!!!
659 //@Name: Name der Variablen die gesetzt werden soll;
660 //@count: Anzahl an Parametern auf die p1 zeigt;
661 //@p1: Zeiger auf den ersten Wert der gesetzt werden soll;
662 //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
663 function TglcShaderProgram.Uniform2iv(const aName: String; aCount: GLint; aP1: PGLInt): Boolean;
667 result := GetUniformLocation(aName, pos);
669 glUniform2iv(pos, aCount, aP1);
672 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
673 //übergibt einen oder mehrere 3-Komponenten Integer-Vektoren an den Shader
674 //!!!Der Shader muss dazu aktiviert sein!!!
675 //@Name: Name der Variablen die gesetzt werden soll;
676 //@count: Anzahl an Parametern auf die p1 zeigt;
677 //@p1: Zeiger auf den ersten Wert der gesetzt werden soll;
678 //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
679 function TglcShaderProgram.Uniform3iv(const aName: String; aCount: GLint; aP1: PGLInt): Boolean;
683 result := GetUniformLocation(aName, pos);
685 glUniform3iv(pos, aCount, aP1);
688 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
689 //übergibt einen oder mehrere 4-Komponenten Integer-Vektoren an den Shader
690 //!!!Der Shader muss dazu aktiviert sein!!!
691 //@Name: Name der Variablen die gesetzt werden soll;
692 //@count: Anzahl an Parametern auf die p1 zeigt;
693 //@p1: Zeiger auf den ersten Wert der gesetzt werden soll;
694 //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
695 function TglcShaderProgram.Uniform4iv(const aName: String; aCount: GLint; aP1: PGLInt): Boolean;
699 result := GetUniformLocation(aName, pos);
701 glUniform4iv(pos, aCount, aP1) ;
704 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
705 //übergibt eine oder mehrere 2x2-Matrizen an den Shader
706 //!!!Der Shader muss dazu aktiviert sein!!!
707 //@Name: Name der Variablen die gesetzt werden soll;
708 //@Transpose: wenn TRUe wird die matrix vor der Übergabe transponiert;
709 //@Count: Anzahl der zu übergebenden Elemente;
710 //@p1: Wert der Variable, der gesetzt werden soll;
711 //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
712 function TglcShaderProgram.UniformMatrix2fv(const aName: String; aTranspose: Boolean; aCount: GLint; aP1: PgluMatrix2f): Boolean;
716 result := GetUniformLocation(aName, pos);
718 glUniformMatrix2fv(pos, aCount, aTranspose, PGLfloat(aP1));
721 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
722 //übergibt eine oder mehrere 3x3-Matrizen an den Shader
723 //!!!Der Shader muss dazu aktiviert sein!!!
724 //@Name: Name der Variablen die gesetzt werden soll;
725 //@Transpose: wenn TRUe wird die matrix vor der Übergabe transponiert;
726 //@Count: Anzahl der zu übergebenden Elemente;
727 //@p1: Wert der Variable, der gesetzt werden soll;
728 //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
729 function TglcShaderProgram.UniformMatrix3fv(const aName: String; aTranspose: Boolean; aCount: GLint; aP1: PgluMatrix3f): Boolean;
733 result := GetUniformLocation(aName, pos);
735 glUniformMatrix3fv(pos, aCount, aTranspose, PGLfloat(aP1));
738 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
739 //übergibt eine oder mehrere 4x4-Matrizen an den Shader
740 //!!!Der Shader muss dazu aktiviert sein!!!
741 //@Name: Name der Variablen die gesetzt werden soll;
742 //@Transpose: wenn TRUe wird die matrix vor der Übergabe transponiert;
743 //@Count: Anzahl der zu übergebenden Elemente;
744 //@p1: Wert der Variable, der gesetzt werden soll;
745 //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
746 function TglcShaderProgram.UniformMatrix4fv(const aName: String; aTranspose: Boolean; aCount: GLint; aP1: PgluMatrix4f): Boolean;
750 result := GetUniformLocation(aName, pos);
752 glUniformMatrix4fv(pos, aCount, aTranspose, PGLfloat(aP1));
755 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
756 //holt den Wert einer Float-Uniform-Variable aus dem Shader
757 //!!!Der Shader muss dazu aktiviert sein!!!
758 //@Name: Name der Variablen die gelesen werden soll;
759 //@p: Zeiger auf die Variable, in die der gelesene Wert geschrieben werden soll;
760 //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
761 function TglcShaderProgram.GetUniformfv(const aName: String; aP: PGLfloat): Boolean;
765 result := GetUniformLocation(aName, pos);
767 glGetUniformfv(fProgramObj, pos, aP);
770 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
771 //holt den Wert einer Integer-Uniform-Variable aus dem Shader
772 //!!!Der Shader muss dazu aktiviert sein!!!
773 //@Name: Name der Variablen die gelesen werden soll;
774 //@p: Zeiger auf die Variable, in die der gelesene Wert geschrieben werden soll;
775 //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
776 function TglcShaderProgram.GetUniformfi(const aName: String; aP: PGLint): Boolean;
780 result := GetUniformLocation(aName, pos);
782 glGetUniformiv(fProgramObj, pos, aP);
785 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
786 function TglcShaderProgram.HasUniform(const aName: String): Boolean;
790 result := GetUniformLocation(aName, pos);
793 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
794 //läd den Shader aus einer Datei
795 //@Filename: Datei aus der gelesen werden soll;
796 //@raise: EglcShader, wenn Datei nicht vorhanden ist;
797 procedure TglcShaderProgram.LoadFromFile(const aFilename: String);
801 if FileExists(aFilename) then begin
802 Stream := TFileStream.Create(aFilename, fmOpenRead);
804 LoadFromStream(Stream);
805 fFilename := aFilename;
809 end else raise EglcShader.Create('TglShaderProgram.LoadFromFile - file not found: '+Filename);
812 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
813 //läd den Shader aus einem Stream
814 //@Stream: Stream aus dem gelesen werden soll;
815 //@raise: EglcShader wenn kein Stream-Objekt übergeben wurde;
816 procedure TglcShaderProgram.LoadFromStream(const aStream: TStream);
818 function GetShaderType(const aStr: String): TglcShaderType;
820 if (aStr = 'GL_VERTEX_SHADER') then
821 result := TglcShaderType.stVertex
822 else if (aStr = 'GL_FRAGMENT_SHADER') then
823 result := TglcShaderType.stFragment
824 else if (aStr = 'GL_GEOMETRY_SHADER') then
825 result := TglcShaderType.stGeometry
826 else if (aStr = 'GL_TESS_CONTROL_SHADER') then
827 result := TglcShaderType.stTessControl
828 else if (aStr = 'GL_TESS_EVALUATION_SHADER') then
829 result := TglcShaderType.stTessEvaluation
831 raise Exception.Create('invalid shader type: ' + aStr);
838 LastMatchPos: PtrInt;
842 procedure AddObj(const aPos: Integer);
844 if (LastMatchPos > 0) then begin
845 o := TglcShaderObject.Create(st, fOnLog);
846 o.Code := Trim(Copy(s, LastMatchPos, aPos - LastMatchPos));
852 if not Assigned(aStream) then
853 raise EglcShader.Create('TglShaderProgram.SaveToStream - stream is nil');
856 sl := TStringList.Create;
857 rx := TRegExpr.Create;
859 sl.LoadFromStream(aStream);
862 rx.Expression := '/\*\s*ShaderObject\s*:\s*(GL_[A-Z_]+)\s*\*/\s*$?';
865 while rx.Exec(LastMatchPos+1) do begin
866 AddObj(rx.MatchPos[0]);
867 LastMatchPos := rx.MatchPos[0] + rx.MatchLen[0];
868 st := GetShaderType(rx.Match[1]);
878 if Assigned(aStream) then begin
881 reader := TutlStreamReader.Create(aStream);
883 if reader.ReadAnsiString <> GLSL_FILE_HEADER then
884 raise EglcShader.Create('TglShaderProgram.SaveToStream - incompatible file');
885 v := reader.ReadInteger;
887 if v >= 100 then begin //version 1.00
888 c := reader.ReadInteger;
889 for i := 0 to c-1 do begin
890 Add(TglcShaderObject.Create(Cardinal(reader.ReadInteger), fOnLog));
891 Last.fCode := reader.ReadAnsiString;
901 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
902 //speichert den Shader in einer Datei
903 //@Filename: Datei in die geschrieben werden soll;
904 procedure TglcShaderProgram.SaveToFile(const aFilename: String);
908 Stream := TFileStream.Create(aFilename, fmCreate);
910 SaveToStream(Stream);
911 fFilename := aFilename;
917 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
918 //speichert den Shader in einen Stream
919 //@Stream: Stream in den geschrieben werden soll;
920 //@raise: EglcShader wenn kein Stream-Objekt übergeben wurde;
921 //@raise: EglcShader wenn ungültige Datei;
922 procedure TglcShaderProgram.SaveToStream(const aStream: TStream);
926 sObj: TglcShaderObject;
928 function GetShaderTypeStr(const aShaderType: TglcShaderType): String;
931 TglcShaderType.stVertex: result := 'GL_VERTEX_SHADER';
932 TglcShaderType.stFragment: result := 'GL_FRAGMENT_SHADER';
933 TglcShaderType.stGeometry: result := 'GL_GEOMETRY_SHADER';
934 TglcShaderType.stTessControl: result := 'GL_TESS_CONTROL_SHADER';
935 TglcShaderType.stTessEvaluation: result := 'GL_TESS_EVALUATION_SHADER';
942 if not Assigned(aStream) then
943 raise EglcShader.Create('TglShaderProgram.LoadFromStream - stream is nil');
945 sl := TStringList.Create;
947 for i := 0 to Count-1 do begin
949 sl.Add('/* ShaderObject: ' + GetShaderTypeStr(sObj.ShaderType) + ' */');
952 sl.SaveToStream(aStream);
958 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
960 //@LogEvent: Event zum loggen von Fehlern und Ereignissen;
961 //@raise: EglcShader wenn OpenGL nicht initialisiert werden konnte;
963 constructor TglcShaderProgram.Create(aLogEvent: TglcShaderLogEvent);
971 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
972 //gibt das Objekt frei
973 destructor TglcShaderProgram.Destroy;
975 if (fProgramObj <> 0) then
976 glDeleteProgram(fProgramObj);