Может не совсем кореектно работать, поскольку я его немного исправил(в оригинале используются несколько специфических вещей, которые нужны только в моем проекте) и не компилировал. Написанно не оптимально, но работает.
unit Shaders;
interface
uses OpenGL, Classes, SysUtils, Dialogs, OGLExt;
type
TShaderObject = class
public
Constructor Create(VSFileName,FSFileName:string);
Procedure SetShader; virtual;
Procedure ResetShader;
protected
VS, FS, SP: integer;
UseVS, UseFS:boolean;
end;
implementation
function LoadShader(const src: String; const stype: GLenum): GLhandleARB;
var
source: PChar;
compiled, len: Integer;
log: String;
function GetInfoLog(s: GLhandleARB): String;
var
blen, slen: Integer;
infolog: array of Char;
begin
glGetObjectParameterivARB(s, GL_OBJECT_INFO_LOG_LENGTH_ARB, @blen);
if blen > 1 then
begin
SetLength(infolog, blen);
glGetInfoLogARB(s, blen, slen, @infolog[0]);
Result := String(infolog);
Exit;
end;
Result := '';
end;
begin
source := PChar(src);
len := Length(src);
Result := glCreateShaderObjectARB(stype);
glShaderSourceARB(Result, 1, @source, @len);
glCompileShaderARB(Result);
glGetObjectParameterivARB(Result, GL_OBJECT_COMPILE_STATUS_ARB, @compiled);
log := GetInfoLog(Result);
if compiled <> 1 then
begin
raise Exception.Create(log);
end;
end;
function LoadShaderFromFile(const filename: String; const stype: GLenum): GLhandleARB;
var
txt: TStringList;
F:TTextFile;
begin
txt := TStringList.Create;
txt.LoadFromFile(filename);
try
Result := LoadShader(txt.Text, stype);
except on E: Exception do
raise Exception.Create(filename + ' contains errors!' + #10 + e.Message);
end;
txt.Free;
end;
constructor TShaderObject.Create(VSFileName, FSFileName: string);
begin
if CanUseShaders then
begin
if Length(VSFileName)>0 then if FileExists(VSFileName) then UseVS:=True else UseVS:=False;
if Length(FSFileName)>0 then if FileExists(FSFileName) then UseFS:=True else UseFS:=False;
SP:=glCreateProgramObjectARB();
if UseVS then
begin
VS:=LoadShaderFromFile(VSFileName,GL_VERTEX_SHADER_ARB);
glAttachObjectARB(SP,VS);
end;
if UseFS then
begin
FS:=LoadShaderFromFile(FSFileName,GL_FRAGMENT_SHADER_ARB);
glAttachObjectARB(SP,FS);
end;
glLinkProgramARB(SP);
end;
end;
procedure TShaderObject.ResetShader;
begin
if CanUseShaders then
glUseProgramObjectARB(0);
end;
procedure TShaderObject.SetShader;
begin
if CanUseShaders then
glUseProgramObjectARB(SP);
end;
end.
Не вижу смысла писать здесь целый пример. Поскольку все элементарно.
CanUseShaders - глобальная переменная, указывающая, можно ли юзать шейдеры.
У меня она выставляется в true если видуха и драйвера поддерживают шейдеры.
Constructor Create(VSFileName,FSFileName:string);
- загружает из файлов шейдеры. Теоретически можно не указывать
Procedure SetShader;
- делает шейдер активным.
Procedure ResetShader;
- сбасывает шейдеры. Используется стандартная обработка. Для сброса можно вызывать метод любого шейдера.
Понятно что это базоый класс, который можно использовать только для простых шейдеров.
Или для порождения новых, более мощных.
К сожалению сейчас не могу представить рабочий вариант унаследованного шейдера.
Но там все элементарно, просто вводятся дополнительные возможности для передачи значений на конвеер.