3 { Package: OpenGLCore
\r
4 Prefix: glc - OpenGL Core
\r
5 Beschreibung: diese Unit enthält eine Klassen-Kapselung der OpenGL Shader Objekte
\r
8 shader: TglcShaderProgram;
\r
10 //write log message to console
\r
11 // @param aSender: object that send the message
\r
12 // @param aMsg: message to write to console
\r
13 procedure LogMessage(aSender: TObject; const aMsg: String);
\r
15 writeln(Format('[%p]: %s', [aSender, aMsg]);
\r
18 //load shader object from file and add it to 'shader'
\r
19 // @param aFilename: name of file to load shader code from
\r
20 // @param aType: type of shader object to create
\r
21 procedure LoadShaderObject(const aFilename: String; const aType: TglcShaderType);
\r
24 so: TglcShaderObject;
\r
26 sl := TStringList.Create;
\r
28 sl.LoadFromFile(aFileName);
\r
29 so := TglcShaderObject.Create(aType);
\r
32 FreeAndNil(sl, @LogMessage);
\r
36 shader := TglcShaderProgram.Create(@LogMessage);
\r
38 // load shader objects
\r
39 LoadShaderObject('./test_shader.vert', TglcShaderType.stVertex);
\r
40 LoadShaderObject('./test_shader.frag', TglcShaderType.stFragment);
\r
47 shader.Uniform1f('uTest', 0.1234);
\r
48 // do normal rendering
\r
60 Classes, SysUtils, fgl, dglOpenGL, uglcTypes, ugluMatrix, uglcContext;
\r
63 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
64 EglcShader = class(Exception);
\r
65 TglcShaderProgram = class;
\r
66 TglcShaderLogEvent = procedure(aSender: TObject; const aMsg: String) of Object;
\r
67 TglcShaderObject = class(TObject)
\r
69 fAtachedTo: TglcShaderProgram;
\r
70 fShaderObj: GLHandle;
\r
71 fShaderType: TglcShaderType;
\r
73 fOnLog: TglcShaderLogEvent;
\r
74 fAttachedTo: TglcShaderProgram;
\r
76 function GetInfoLog(aObj: GLHandle): String;
\r
77 function GetCompiled: Boolean;
\r
78 procedure Log(const aMsg: String);
\r
79 procedure CreateShaderObj;
\r
80 procedure AttachTo(const aProgram: TglcShaderProgram);
\r
82 property ShaderObj : GLHandle read fShaderObj;
\r
83 property ShaderType: TglcShaderType read fShaderType;
\r
84 property Compiled: Boolean read GetCompiled;
\r
85 property AtachedTo: TglcShaderProgram read fAtachedTo;
\r
86 property Code: String read fCode write fCode;
\r
87 property OnLog: TglcShaderLogEvent read fOnLog write fOnLog;
\r
91 constructor Create(const aShaderType: TglcShaderType; const aLogEvent: TglcShaderLogEvent = nil);
\r
92 destructor Destroy; override;
\r
94 TglcShaderObjectList = specialize TFPGObjectList<TglcShaderObject>;
\r
96 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
97 TglcShaderProgram = class(TglcShaderObjectList)
\r
99 fProgramObj: GLHandle;
\r
100 fOnLog: TglcShaderLogEvent;
\r
103 function GetUniformLocation(const aName: String; out aPos: glInt): Boolean;
\r
104 function GetInfoLog(Obj: GLHandle): String;
\r
105 function GetCompiled: Boolean;
\r
106 function GetLinked: Boolean;
\r
108 procedure CreateProgramObj;
\r
109 procedure Log(const msg: String);
\r
110 procedure AttachShaderObj(const aShaderObj: TglcShaderObject);
\r
112 property ProgramObj: glHandle read fProgramObj;
\r
113 property Filename: String read fFilename;
\r
114 property Compiled: Boolean read GetCompiled;
\r
115 property Linked: Boolean read GetLinked;
\r
116 property OnLog: TglcShaderLogEvent read fOnLog write fOnLog;
\r
122 procedure Add(aShaderObj: TglcShaderObject);
\r
123 procedure Delete(aID: Integer; aFreeOwnedObj: Boolean = True);
\r
126 function Uniform1f(const aName: String; aP1: GLFloat): Boolean;
\r
127 function Uniform2f(const aName: String; aP1, aP2: GLFloat): Boolean;
\r
128 function Uniform3f(const aName: String; aP1, aP2, aP3: GLFloat): Boolean;
\r
129 function Uniform4f(const aName: String; aP1, aP2, aP3, aP4: GLFloat): Boolean;
\r
130 function Uniform1i(const aName: String; aP1: GLint): Boolean;
\r
131 function Uniform2i(const aName: String; aP1, aP2: GLint): Boolean;
\r
132 function Uniform3i(const aName: String; aP1, aP2, aP3: GLint): Boolean;
\r
133 function Uniform4i(const aName: String; aP1, aP2, aP3, aP4: GLint): Boolean;
\r
134 function Uniform1fv(const aName: String; aCount: GLint; aP1: PGLFloat): Boolean;
\r
135 function Uniform2fv(const aName: String; aCount: GLint; aP1: PGLFloat): Boolean;
\r
136 function Uniform3fv(const aName: String; aCount: GLint; aP1: PGLFloat): Boolean;
\r
137 function Uniform4fv(const aName: String; aCount: GLint; aP1: PGLFloat): Boolean;
\r
138 function Uniform1iv(const aName: String; aCount: GLint; aP1: PGLInt): Boolean;
\r
139 function Uniform2iv(const aName: String; aCount: GLint; aP1: PGLInt): Boolean;
\r
140 function Uniform3iv(const aName: String; aCount: GLint; aP1: PGLInt): Boolean;
\r
141 function Uniform4iv(const aName: String; aCount: GLint; aP1: PGLInt): Boolean;
\r
142 function UniformMatrix2fv(const aName: String; aTranspose: Boolean; aCount: GLint; aP1: PgluMatrix2f): Boolean;
\r
143 function UniformMatrix3fv(const aName: String; aTranspose: Boolean; aCount: GLint; aP1: PgluMatrix3f): Boolean;
\r
144 function UniformMatrix4fv(const aName: String; aTranspose: Boolean; aCount: GLint; aP1: PgluMatrix4f): Boolean;
\r
146 function GetUniformfv(const aName: String; aP: PGLfloat): Boolean;
\r
147 function GetUniformfi(const aName: String; aP: PGLint): Boolean;
\r
148 function HasUniform(const aName: String): Boolean;
\r
150 procedure LoadFromFile(const aFilename: String);
\r
151 procedure LoadFromStream(const aStream: TStream);
\r
152 procedure SaveToFile(const aFilename: String);
\r
153 procedure SaveToStream(const aStream: TStream);
\r
155 constructor Create(const aLogEvent: TglcShaderLogEvent = nil);
\r
156 destructor Destroy; override;
\r
165 ERROR_STR_VAR_NAME: String = 'can''t find the variable ''%s'' in the program';
\r
167 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
168 //glShaderObject////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
169 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
170 //PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRI//
\r
171 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
172 //ließt das Log eines OpenGL-Objekts aus
\r
173 //@Obj: Handle des Objekts, dessen Log ausgelesen werden soll;
\r
174 //@result: Log des Objekts;
\r
175 function TglcShaderObject.GetInfoLog(aObj: GLHandle): String;
\r
182 glGetShaderiv(aObj, GL_INFO_LOG_LENGTH, @bLen);
\r
183 if bLen > 1 then begin
\r
184 GetMem(Msg, bLen * SizeOf(Char));
\r
185 glGetShaderInfoLog(aObj, bLen, @sLen, Msg);
\r
186 result := PChar(Msg);
\r
191 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
192 //ließt aus, ob der Shader ohne Fehler kompiliert wurde
\r
193 //@result: TRUE wenn ohne Fehler kompiliert, sonst FALSE;
\r
194 function TglcShaderObject.GetCompiled: Boolean;
\r
198 glGetShaderiv(fShaderObj, GL_COMPILE_STATUS, @value);
\r
199 result := (value = GL_TRUE);
\r
202 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
203 //ruft das Log-Event auf, wenn es gesetzt ist
\r
204 //@msg: Nachricht die geloggt werden soll;
\r
205 procedure TglcShaderObject.Log(const aMsg: String);
\r
207 if Assigned(fOnLog) then begin
\r
208 fOnLog(self, aMsg);
\r
212 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
213 procedure TglcShaderObject.CreateShaderObj;
\r
215 if (fShaderObj <> 0) then
\r
217 fShaderObj := glCreateShader(GLenum(fShaderType));
\r
218 if fShaderObj = 0 then
\r
219 raise EglcShader.Create('can''t create ShaderObject');
\r
220 Log('shader object created: #'+IntToHex(fShaderObj, 4));
\r
223 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
224 procedure TglcShaderObject.AttachTo(const aProgram: TglcShaderProgram);
\r
226 if (aProgram <> fAtachedTo) then begin
\r
228 glAttachShader(aProgram.ProgramObj, fShaderObj);
\r
229 fAttachedTo := aProgram;
\r
233 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
234 //PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBL//
\r
235 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
236 //kompiliert das Shader-Objekt
\r
237 procedure TglcShaderObject.Compile;
\r
244 len := Length(fCode);
\r
245 if len > 0 then begin
\r
246 c := PAnsiChar(fCode);
\r
247 glShaderSource(fShaderObj, 1, @c, @len);
\r
248 glCompileShader(fShaderObj);
\r
249 List := TStringList.Create;
\r
250 List.Text := GetInfoLog(fShaderObj);
\r
251 for i := 0 to List.Count-1 do
\r
254 end else Log('error while compiling: no bound shader code');
\r
257 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
258 //erzeugt das Objekt
\r
259 //@ShaderType: Typ des Shader-Objekts;
\r
260 //@LogEvent: Event zum loggen von Fehlern und Ereignissen;
\r
261 //@raise: EglcShader wenn der Shadertyp unbekannt oder ungültig ist;
\r
262 constructor TglcShaderObject.Create(const aShaderType: TglcShaderType; const aLogEvent: TglcShaderLogEvent);
\r
266 fOnLog := aLogEvent;
\r
267 fShaderType := aShaderType;
\r
270 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
271 //gibt das Objekt frei
\r
272 destructor TglcShaderObject.Destroy;
\r
274 if (fShaderObj <> 0) then
\r
275 glDeleteShader(fShaderObj);
\r
279 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
280 //glShaderProgram///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
281 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
282 //PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRIVATE//PRI//
\r
283 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
284 function TglcShaderProgram.GetUniformLocation(const aName: String; out aPos: glInt): Boolean;
\r
286 aPos := glGetUniformLocation(fProgramObj, PChar(aName));
\r
287 result := (aPos <> -1);
\r
289 Log(StringReplace(ERROR_STR_VAR_NAME, '%s', aName, [rfIgnoreCase, rfReplaceAll]));
\r
292 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
293 //ließt das Log eines OpenGL-Objekts aus
\r
294 //@Obj: Handle des Objekts, dessen Log ausgelesen werden soll;
\r
295 //@result: Log des Objekts;
\r
296 function TglcShaderProgram.GetInfoLog(Obj: GLHandle): String;
\r
303 glGetProgramiv(Obj, GL_INFO_LOG_LENGTH, @bLen);
\r
304 if bLen > 1 then begin
\r
305 GetMem(Msg, bLen * SizeOf(Char));
\r
306 glGetProgramInfoLog(Obj, bLen, @sLen, Msg);
\r
307 result := PChar(Msg);
\r
312 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
313 //prüft ob alle Shader ohne Fehler compiliert wurden
\r
314 //@result: TRUE wenn alle erfolgreich compiliert, sonst FALSE;
\r
315 function TglcShaderProgram.GetCompiled: Boolean;
\r
319 result := (Count > 0);
\r
320 for i := 0 to Count-1 do
\r
321 result := result and Items[i].Compiled;
\r
324 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
325 //prüft ob das Programm ohne Fehler gelinkt wurde
\r
326 //@result: TRUE wenn linken erfolgreich, sonst FASLE;
\r
327 function TglcShaderProgram.GetLinked: Boolean;
\r
331 glGetProgramiv(fProgramObj, GL_LINK_STATUS, @value);
\r
332 result := (value = GL_TRUE);
\r
335 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
336 procedure TglcShaderProgram.CreateProgramObj;
\r
338 if (fProgramObj = 0) then begin
\r
339 if GL_LibHandle = nil then
\r
340 raise EglcShader.Create('TglShaderProgram.Create - OpenGL not initialized');
\r
342 if not TglcContext.IsAnyContextActive then
\r
343 raise EglcShader.Create('TglShaderProgram.Create - no valid render context');
\r
345 fProgramObj := glCreateProgram();
\r
346 Log('shader program created: #'+IntToHex(fProgramObj, 4));
\r
350 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
351 //ruft das Log-Event auf, wenn es gesetzt ist
\r
352 //@msg: Nachricht die geloggt werden soll;
\r
353 procedure TglcShaderProgram.Log(const msg: String);
\r
355 if Assigned(fOnLog) then begin
\r
360 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
361 procedure TglcShaderProgram.AttachShaderObj(const aShaderObj: TglcShaderObject);
\r
364 aShaderObj.AttachTo(self);
\r
367 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
368 //PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBLIC//PUBL//
\r
369 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
370 //Kompiliert den Shader-Code
\r
371 procedure TglcShaderProgram.Compile;
\r
377 for i := 0 to Count-1 do begin
\r
378 AttachShaderObj(Items[i]);
\r
381 glLinkProgram(fProgramObj);
\r
382 l := TStringList.Create;
\r
383 l.Text := GetInfoLog(fProgramObj);
\r
384 for i := 0 to l.Count-1 do
\r
389 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
390 //aktiviert den Shader
\r
391 procedure TglcShaderProgram.Enable;
\r
393 glUseProgram(fProgramObj);
\r
396 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
397 //deaktiviert den Shader
\r
398 procedure TglcShaderProgram.Disable;
\r
403 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
404 //fügt der Liste einen Shader hinzu
\r
405 //@ShaderObj: Objekt, das hinzugefügt werden soll;
\r
406 procedure TglcShaderProgram.Add(aShaderObj: TglcShaderObject);
\r
408 inherited Add(aShaderObj);
\r
409 if (fProgramObj <> 0) then
\r
410 AttachShaderObj(aShaderObj);
\r
413 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
414 //löscht ein ShaderObjekt aus der Liste
\r
415 //@ID: Index des Objekts, das gelöscht werden soll;
\r
416 //@FreeOwnedObj: wenn TRUE wird das gelöschte Objekt freigegeben;
\r
417 procedure TglcShaderProgram.Delete(aID: Integer; aFreeOwnedObj: Boolean);
\r
421 if (aID >= 0) and (aID < Count) and (fProgramObj <> 0) then begin
\r
422 glDetachShader(fProgramObj, Items[aID].fShaderObj);
\r
423 Items[aID].fAttachedTo := nil;
\r
426 FreeObjects := aFreeOwnedObj;
\r
427 inherited Delete(aID);
\r
431 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
432 procedure TglcShaderProgram.Clear;
\r
434 while (Count > 0) do
\r
438 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
439 //übergibt einen 1-Komponenten Float-Vektoren an den Shader
\r
440 //!!!Der Shader muss dazu aktiviert sein!!!
\r
441 //@Name: Name der Variablen die gesetzt werden soll;
\r
442 //@p1: Wert der Variable, der gesetzt werden soll;
\r
443 //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
\r
444 function TglcShaderProgram.Uniform1f(const aName: String; aP1: GLFloat): Boolean;
\r
448 result := GetUniformLocation(aName, pos);
\r
450 glUniform1f(pos, aP1);
\r
453 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
454 //übergibt einen 2-Komponenten Float-Vektoren an den Shader
\r
455 //!!!Der Shader muss dazu aktiviert sein!!!
\r
456 //@Name: Name der Variablen die gesetzt werden soll;
\r
457 //@p1: Wert der Variable, der gesetzt werden soll;
\r
458 //@p2: Wert der Variable, der gesetzt werden soll;
\r
459 //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
\r
460 function TglcShaderProgram.Uniform2f(const aName: String; aP1, aP2: GLFloat): Boolean;
\r
464 result := GetUniformLocation(aName, pos);
\r
466 glUniform2f(pos, aP1, aP2);
\r
469 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
470 //übergibt einen 3-Komponenten Float-Vektoren an den Shader
\r
471 //!!!Der Shader muss dazu aktiviert sein!!!
\r
472 //@Name: Name der Variablen die gesetzt werden soll;
\r
473 //@p1: Wert der Variable, der gesetzt werden soll;
\r
474 //@p2: Wert der Variable, der gesetzt werden soll;
\r
475 //@p3: Wert der Variable, der gesetzt werden soll;
\r
476 //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
\r
477 function TglcShaderProgram.Uniform3f(const aName: String; aP1, aP2, aP3: GLFloat): Boolean;
\r
481 result := GetUniformLocation(aName, pos);
\r
483 glUniform3f(pos, aP1, aP2, aP3);
\r
486 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
487 //übergibt einen 4-Komponenten Float-Vektoren an den Shader
\r
488 //!!!Der Shader muss dazu aktiviert sein!!!
\r
489 //@Name: Name der Variablen die gesetzt werden soll;
\r
490 //@p1: Wert der Variable, der gesetzt werden soll;
\r
491 //@p2: Wert der Variable, der gesetzt werden soll;
\r
492 //@p3: Wert der Variable, der gesetzt werden soll;
\r
493 //@p4: Wert der Variable, der gesetzt werden soll;
\r
494 //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
\r
495 function TglcShaderProgram.Uniform4f(const aName: String; aP1, aP2, aP3, aP4: GLFloat): Boolean;
\r
499 result := GetUniformLocation(aName, pos);
\r
501 glUniform4f(pos, aP1, aP2, aP3, aP4);
\r
504 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
505 //übergibt einen 1-Komponenten Integer-Vektoren an den Shader
\r
506 //!!!Der Shader muss dazu aktiviert sein!!!
\r
507 //@Name: Name der Variablen die gesetzt werden soll;
\r
508 //@p1: Wert der Variable, der gesetzt werden soll;
\r
509 //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
\r
510 function TglcShaderProgram.Uniform1i(const aName: String; aP1: GLint): Boolean;
\r
514 result := GetUniformLocation(aName, pos);
\r
516 glUniform1i(pos, aP1);
\r
519 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
520 //übergibt einen 2-Komponenten Integer-Vektoren an den Shader
\r
521 //!!!Der Shader muss dazu aktiviert sein!!!
\r
522 //@Name: Name der Variablen die gesetzt werden soll;
\r
523 //@p1: Wert der Variable, der gesetzt werden soll;
\r
524 //@p1: Wert der Variable, der gesetzt werden soll;
\r
525 //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
\r
526 function TglcShaderProgram.Uniform2i(const aName: String; aP1, aP2: GLint): Boolean;
\r
530 result := GetUniformLocation(aName, pos);
\r
532 glUniform2i(pos, aP1, aP2);
\r
535 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
536 //übergibt einen 3-Komponenten Integer-Vektoren an den Shader
\r
537 //!!!Der Shader muss dazu aktiviert sein!!!
\r
538 //@Name: Name der Variablen die gesetzt werden soll;
\r
539 //@p1: Wert der Variable, der gesetzt werden soll;
\r
540 //@p2: Wert der Variable, der gesetzt werden soll;
\r
541 //@p3: Wert der Variable, der gesetzt werden soll;
\r
542 //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
\r
543 function TglcShaderProgram.Uniform3i(const aName: String; aP1, aP2, aP3: GLint): Boolean;
\r
547 result := GetUniformLocation(aName, pos);
\r
549 glUniform3i(pos, aP1, aP2, aP3);
\r
552 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
553 //übergibt einen 4-Komponenten Integer-Vektoren an den Shader
\r
554 //!!!Der Shader muss dazu aktiviert sein!!!
\r
555 //@Name: Name der Variablen die gesetzt werden soll;
\r
556 //@p1: Wert der Variable, der gesetzt werden soll;
\r
557 //@p2: Wert der Variable, der gesetzt werden soll;
\r
558 //@p3: Wert der Variable, der gesetzt werden soll;
\r
559 //@p4: Wert der Variable, der gesetzt werden soll;
\r
560 //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
\r
561 function TglcShaderProgram.Uniform4i(const aName: String; aP1, aP2, aP3, aP4: GLint): Boolean;
\r
565 result := GetUniformLocation(aName, pos);
\r
567 glUniform4i(pos, aP1, aP2, aP3, aP4);
\r
570 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
571 //übergibt einen oder mehrere 1-Komponenten Float-Vektoren an den Shader
\r
572 //!!!Der Shader muss dazu aktiviert sein!!!
\r
573 //@Name: Name der Variablen die gesetzt werden soll;
\r
574 //@count: Anzahl an Parametern auf die p1 zeigt;
\r
575 //@p1: Zeiger auf den ersten Wert der gesetzt werden soll;
\r
576 //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
\r
577 function TglcShaderProgram.Uniform1fv(const aName: String; aCount: GLint; aP1: PGLFloat): Boolean;
\r
581 result := GetUniformLocation(aName, pos);
\r
583 glUniform1fv(pos, aCount, aP1);
\r
586 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
587 //übergibt einen oder mehrere 2-Komponenten Float-Vektoren an den Shader
\r
588 //!!!Der Shader muss dazu aktiviert sein!!!
\r
589 //@Name: Name der Variablen die gesetzt werden soll;
\r
590 //@count: Anzahl an Parametern auf die p1 zeigt;
\r
591 //@p1: Zeiger auf den ersten Wert der gesetzt werden soll;
\r
592 //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
\r
593 function TglcShaderProgram.Uniform2fv(const aName: String; aCount: GLint; aP1: PGLFloat): Boolean;
\r
597 result := GetUniformLocation(aName, pos);
\r
599 glUniform2fv(pos, aCount, aP1);
\r
602 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
603 //übergibt einen oder mehrere 3-Komponenten Float-Vektoren an den Shader
\r
604 //!!!Der Shader muss dazu aktiviert sein!!!
\r
605 //@Name: Name der Variablen die gesetzt werden soll;
\r
606 //@count: Anzahl an Parametern auf die p1 zeigt;
\r
607 //@p1: Zeiger auf den ersten Wert der gesetzt werden soll;
\r
608 //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
\r
609 function TglcShaderProgram.Uniform3fv(const aName: String; aCount: GLint; aP1: PGLFloat): Boolean;
\r
613 result := GetUniformLocation(aName, pos);
\r
615 glUniform3fv(pos, aCount, aP1);
\r
618 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
619 //übergibt einen oder mehrere 4-Komponenten Float-Vektoren an den Shader
\r
620 //!!!Der Shader muss dazu aktiviert sein!!!
\r
621 //@Name: Name der Variablen die gesetzt werden soll;
\r
622 //@count: Anzahl an Parametern auf die p1 zeigt;
\r
623 //@p1: Zeiger auf den ersten Wert der gesetzt werden soll;
\r
624 //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
\r
625 function TglcShaderProgram.Uniform4fv(const aName: String; aCount: GLint; aP1: PGLFloat): Boolean;
\r
629 result := GetUniformLocation(aName, pos);
\r
631 glUniform4fv(pos, aCount, aP1);
\r
634 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
635 //übergibt einen oder mehrere 1-Komponenten Integer-Vektoren an den Shader
\r
636 //!!!Der Shader muss dazu aktiviert sein!!!
\r
637 //@Name: Name der Variablen die gesetzt werden soll;
\r
638 //@count: Anzahl an Parametern auf die p1 zeigt;
\r
639 //@p1: Zeiger auf den ersten Wert der gesetzt werden soll;
\r
640 //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
\r
641 function TglcShaderProgram.Uniform1iv(const aName: String; aCount: GLint; aP1: PGLInt): Boolean;
\r
645 result := GetUniformLocation(aName, pos);
\r
647 glUniform1iv(pos, aCount, aP1);
\r
650 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
651 //übergibt einen oder mehrere 2-Komponenten Integer-Vektoren an den Shader
\r
652 //!!!Der Shader muss dazu aktiviert sein!!!
\r
653 //@Name: Name der Variablen die gesetzt werden soll;
\r
654 //@count: Anzahl an Parametern auf die p1 zeigt;
\r
655 //@p1: Zeiger auf den ersten Wert der gesetzt werden soll;
\r
656 //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
\r
657 function TglcShaderProgram.Uniform2iv(const aName: String; aCount: GLint; aP1: PGLInt): Boolean;
\r
661 result := GetUniformLocation(aName, pos);
\r
663 glUniform2iv(pos, aCount, aP1);
\r
666 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
667 //übergibt einen oder mehrere 3-Komponenten Integer-Vektoren an den Shader
\r
668 //!!!Der Shader muss dazu aktiviert sein!!!
\r
669 //@Name: Name der Variablen die gesetzt werden soll;
\r
670 //@count: Anzahl an Parametern auf die p1 zeigt;
\r
671 //@p1: Zeiger auf den ersten Wert der gesetzt werden soll;
\r
672 //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
\r
673 function TglcShaderProgram.Uniform3iv(const aName: String; aCount: GLint; aP1: PGLInt): Boolean;
\r
677 result := GetUniformLocation(aName, pos);
\r
679 glUniform3iv(pos, aCount, aP1);
\r
682 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
683 //übergibt einen oder mehrere 4-Komponenten Integer-Vektoren an den Shader
\r
684 //!!!Der Shader muss dazu aktiviert sein!!!
\r
685 //@Name: Name der Variablen die gesetzt werden soll;
\r
686 //@count: Anzahl an Parametern auf die p1 zeigt;
\r
687 //@p1: Zeiger auf den ersten Wert der gesetzt werden soll;
\r
688 //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
\r
689 function TglcShaderProgram.Uniform4iv(const aName: String; aCount: GLint; aP1: PGLInt): Boolean;
\r
693 result := GetUniformLocation(aName, pos);
\r
695 glUniform4iv(pos, aCount, aP1) ;
\r
698 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
699 //übergibt eine oder mehrere 2x2-Matrizen an den Shader
\r
700 //!!!Der Shader muss dazu aktiviert sein!!!
\r
701 //@Name: Name der Variablen die gesetzt werden soll;
\r
702 //@Transpose: wenn TRUe wird die matrix vor der Übergabe transponiert;
\r
703 //@Count: Anzahl der zu übergebenden Elemente;
\r
704 //@p1: Wert der Variable, der gesetzt werden soll;
\r
705 //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
\r
706 function TglcShaderProgram.UniformMatrix2fv(const aName: String; aTranspose: Boolean; aCount: GLint; aP1: PgluMatrix2f): Boolean;
\r
710 result := GetUniformLocation(aName, pos);
\r
712 glUniformMatrix2fv(pos, aCount, aTranspose, PGLfloat(aP1));
\r
715 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
716 //übergibt eine oder mehrere 3x3-Matrizen an den Shader
\r
717 //!!!Der Shader muss dazu aktiviert sein!!!
\r
718 //@Name: Name der Variablen die gesetzt werden soll;
\r
719 //@Transpose: wenn TRUe wird die matrix vor der Übergabe transponiert;
\r
720 //@Count: Anzahl der zu übergebenden Elemente;
\r
721 //@p1: Wert der Variable, der gesetzt werden soll;
\r
722 //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
\r
723 function TglcShaderProgram.UniformMatrix3fv(const aName: String; aTranspose: Boolean; aCount: GLint; aP1: PgluMatrix3f): Boolean;
\r
727 result := GetUniformLocation(aName, pos);
\r
729 glUniformMatrix3fv(pos, aCount, aTranspose, PGLfloat(aP1));
\r
732 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
733 //übergibt eine oder mehrere 4x4-Matrizen an den Shader
\r
734 //!!!Der Shader muss dazu aktiviert sein!!!
\r
735 //@Name: Name der Variablen die gesetzt werden soll;
\r
736 //@Transpose: wenn TRUe wird die matrix vor der Übergabe transponiert;
\r
737 //@Count: Anzahl der zu übergebenden Elemente;
\r
738 //@p1: Wert der Variable, der gesetzt werden soll;
\r
739 //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
\r
740 function TglcShaderProgram.UniformMatrix4fv(const aName: String; aTranspose: Boolean; aCount: GLint; aP1: PgluMatrix4f): Boolean;
\r
744 result := GetUniformLocation(aName, pos);
\r
746 glUniformMatrix4fv(pos, aCount, aTranspose, PGLfloat(aP1));
\r
749 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
750 //holt den Wert einer Float-Uniform-Variable aus dem Shader
\r
751 //!!!Der Shader muss dazu aktiviert sein!!!
\r
752 //@Name: Name der Variablen die gelesen werden soll;
\r
753 //@p: Zeiger auf die Variable, in die der gelesene Wert geschrieben werden soll;
\r
754 //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
\r
755 function TglcShaderProgram.GetUniformfv(const aName: String; aP: PGLfloat): Boolean;
\r
759 result := GetUniformLocation(aName, pos);
\r
761 glGetUniformfv(fProgramObj, pos, aP);
\r
764 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
765 //holt den Wert einer Integer-Uniform-Variable aus dem Shader
\r
766 //!!!Der Shader muss dazu aktiviert sein!!!
\r
767 //@Name: Name der Variablen die gelesen werden soll;
\r
768 //@p: Zeiger auf die Variable, in die der gelesene Wert geschrieben werden soll;
\r
769 //@result: TRUE wenn erfolgreich, sonst FALSE (Variablenname konnte nicht aufgelöst werden);
\r
770 function TglcShaderProgram.GetUniformfi(const aName: String; aP: PGLint): Boolean;
\r
774 result := GetUniformLocation(aName, pos);
\r
776 glGetUniformiv(fProgramObj, pos, aP);
\r
779 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
780 function TglcShaderProgram.HasUniform(const aName: String): Boolean;
\r
784 result := GetUniformLocation(aName, pos);
\r
787 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
788 //läd den Shader aus einer Datei
\r
789 //@Filename: Datei aus der gelesen werden soll;
\r
790 //@raise: EglcShader, wenn Datei nicht vorhanden ist;
\r
791 procedure TglcShaderProgram.LoadFromFile(const aFilename: String);
\r
793 Stream: TFileStream;
\r
795 if FileExists(aFilename) then begin
\r
796 Stream := TFileStream.Create(aFilename, fmOpenRead);
\r
798 LoadFromStream(Stream);
\r
799 fFilename := aFilename;
\r
803 end else raise EglcShader.Create('TglShaderProgram.LoadFromFile - file not found: '+Filename);
\r
806 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
807 //läd den Shader aus einem Stream
\r
808 //@Stream: Stream aus dem gelesen werden soll;
\r
809 //@raise: EglcShader wenn kein Stream-Objekt übergeben wurde;
\r
810 procedure TglcShaderProgram.LoadFromStream(const aStream: TStream);
\r
812 function GetShaderType(const aStr: String): TglcShaderType;
\r
814 if (aStr = 'GL_VERTEX_SHADER') then
\r
815 result := TglcShaderType.stVertex
\r
816 else if (aStr = 'GL_FRAGMENT_SHADER') then
\r
817 result := TglcShaderType.stFragment
\r
818 else if (aStr = 'GL_GEOMETRY_SHADER') then
\r
819 result := TglcShaderType.stGeometry
\r
820 else if (aStr = 'GL_TESS_CONTROL_SHADER') then
\r
821 result := TglcShaderType.stTessControl
\r
822 else if (aStr = 'GL_TESS_EVALUATION_SHADER') then
\r
823 result := TglcShaderType.stTessEvaluation
\r
825 raise Exception.Create('invalid shader type: ' + aStr);
\r
832 LastMatchPos: PtrInt;
\r
833 st: TglcShaderType;
\r
834 o: TglcShaderObject;
\r
836 procedure AddObj(const aPos: Integer);
\r
838 if (LastMatchPos > 0) then begin
\r
839 o := TglcShaderObject.Create(st, fOnLog);
\r
840 o.Code := Trim(Copy(s, LastMatchPos, aPos - LastMatchPos));
\r
846 if not Assigned(aStream) then
\r
847 raise EglcShader.Create('TglShaderProgram.SaveToStream - stream is nil');
\r
850 sl := TStringList.Create;
\r
851 rx := TRegExpr.Create;
\r
853 sl.LoadFromStream(aStream);
\r
856 rx.Expression := '/\*\s*ShaderObject\s*:\s*(GL_[A-Z_]+)\s*\*/\s*$?';
\r
857 rx.InputString := s;
\r
859 while rx.Exec(LastMatchPos+1) do begin
\r
860 AddObj(rx.MatchPos[0]);
\r
861 LastMatchPos := rx.MatchPos[0] + rx.MatchLen[0];
\r
862 st := GetShaderType(rx.Match[1]);
\r
872 if Assigned(aStream) then begin
\r
875 reader := TutlStreamReader.Create(aStream);
\r
877 if reader.ReadAnsiString <> GLSL_FILE_HEADER then
\r
878 raise EglcShader.Create('TglShaderProgram.SaveToStream - incompatible file');
\r
879 v := reader.ReadInteger;
\r
881 if v >= 100 then begin //version 1.00
\r
882 c := reader.ReadInteger;
\r
883 for i := 0 to c-1 do begin
\r
884 Add(TglcShaderObject.Create(Cardinal(reader.ReadInteger), fOnLog));
\r
885 Last.fCode := reader.ReadAnsiString;
\r
895 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
896 //speichert den Shader in einer Datei
\r
897 //@Filename: Datei in die geschrieben werden soll;
\r
898 procedure TglcShaderProgram.SaveToFile(const aFilename: String);
\r
900 Stream: TFileStream;
\r
902 Stream := TFileStream.Create(aFilename, fmCreate);
\r
904 SaveToStream(Stream);
\r
905 fFilename := aFilename;
\r
911 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
912 //speichert den Shader in einen Stream
\r
913 //@Stream: Stream in den geschrieben werden soll;
\r
914 //@raise: EglcShader wenn kein Stream-Objekt übergeben wurde;
\r
915 //@raise: EglcShader wenn ungültige Datei;
\r
916 procedure TglcShaderProgram.SaveToStream(const aStream: TStream);
\r
920 sObj: TglcShaderObject;
\r
922 function GetShaderTypeStr(const aShaderType: TglcShaderType): String;
\r
924 case aShaderType of
\r
925 TglcShaderType.stVertex: result := 'GL_VERTEX_SHADER';
\r
926 TglcShaderType.stFragment: result := 'GL_FRAGMENT_SHADER';
\r
927 TglcShaderType.stGeometry: result := 'GL_GEOMETRY_SHADER';
\r
928 TglcShaderType.stTessControl: result := 'GL_TESS_CONTROL_SHADER';
\r
929 TglcShaderType.stTessEvaluation: result := 'GL_TESS_EVALUATION_SHADER';
\r
931 result := 'UNKNOWN';
\r
936 if not Assigned(aStream) then
\r
937 raise EglcShader.Create('TglShaderProgram.LoadFromStream - stream is nil');
\r
939 sl := TStringList.Create;
\r
941 for i := 0 to Count-1 do begin
\r
943 sl.Add('/* ShaderObject: ' + GetShaderTypeStr(sObj.ShaderType) + ' */');
\r
946 sl.SaveToStream(aStream);
\r
952 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
953 //erzeugt das Objekt
\r
954 //@LogEvent: Event zum loggen von Fehlern und Ereignissen;
\r
955 //@raise: EglcShader wenn OpenGL nicht initialisiert werden konnte;
\r
957 constructor TglcShaderProgram.Create(const aLogEvent: TglcShaderLogEvent);
\r
960 fOnLog := aLogEvent;
\r
965 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\r
966 //gibt das Objekt frei
\r
967 destructor TglcShaderProgram.Destroy;
\r
969 if (fProgramObj <> 0) then
\r
970 glDeleteProgram(fProgramObj);
\r