| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301 |
- //
- // This unit is part of the GLScene Engine, http://glscene.org
- //
- unit GLS.ShaderTexCombine;
- (* A shader that allows texture combiner setup. *)
- interface
- {$I GLScene.inc}
- uses
- Winapi.OpenGL,
- Winapi.OpenGLext,
- System.Classes,
- System.SysUtils,
- GLTexture,
- GLMaterial,
- GLRenderContextInfo,
- GLTextureCombiners,
- OpenGLTokens,
- GLState,
- XOpenGL,
- GLContext,
- GLS.Utils;
- type
- // A shader that can setup the texture combiner.
- TGLTexCombineShader = class(TGLShader)
- private
- FCombiners: TStringList;
- FCommandCache: TCombinerCache;
- FCombinerIsValid: Boolean; // to avoid reparsing invalid stuff
- FDesignTimeEnabled: Boolean;
- FMaterialLibrary: TGLMaterialLibrary;
- FLibMaterial3Name: TGLLibMaterialName;
- currentLibMaterial3: TGLLibMaterial;
- FLibMaterial4Name: TGLLibMaterialName;
- currentLibMaterial4: TGLLibMaterial;
- FApplied3, FApplied4: Boolean;
- protected
- procedure SetCombiners(const val: TStringList);
- procedure SetDesignTimeEnabled(const val: Boolean);
- procedure SetMaterialLibrary(const val: TGLMaterialLibrary);
- procedure SetLibMaterial3Name(const val: TGLLibMaterialName);
- procedure SetLibMaterial4Name(const val: TGLLibMaterialName);
- procedure NotifyLibMaterial3Destruction;
- procedure NotifyLibMaterial4Destruction;
- procedure DoInitialize(var rci: TGLRenderContextInfo; Sender: TObject); override;
- procedure DoApply(var rci: TGLRenderContextInfo; Sender: TObject); override;
- function DoUnApply(var rci: TGLRenderContextInfo): Boolean; override;
- procedure DoFinalize; override;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- procedure Notification(AComponent: TComponent; Operation: TOperation); override;
- procedure NotifyChange(Sender: TObject); override;
- published
- property Combiners: TStringList read FCombiners write SetCombiners;
- property DesignTimeEnabled: Boolean read FDesignTimeEnabled write SetDesignTimeEnabled;
- property MaterialLibrary: TGLMaterialLibrary read FMaterialLibrary write SetMaterialLibrary;
- property LibMaterial3Name: TGLLibMaterialName read FLibMaterial3Name write SetLibMaterial3Name;
- property LibMaterial4Name: TGLLibMaterialName read FLibMaterial4Name write SetLibMaterial4Name;
- end;
- // ------------------------------------------------------------------
- implementation
- // ------------------------------------------------------------------
- // ------------------
- // ------------------ TGLTexCombineShader ------------------
- // ------------------
- constructor TGLTexCombineShader.Create(AOwner: TComponent);
- begin
- inherited;
- ShaderStyle := ssLowLevel;
- FCombiners := TStringList.Create;
- TStringList(FCombiners).OnChange := NotifyChange;
- FCombinerIsValid := True;
- FCommandCache := nil;
- end;
- destructor TGLTexCombineShader.Destroy;
- begin
- if Assigned(currentLibMaterial3) then
- currentLibMaterial3.UnregisterUser(Self);
- if Assigned(currentLibMaterial4) then
- currentLibMaterial4.UnregisterUser(Self);
- inherited;
- FCombiners.Free;
- end;
- procedure TGLTexCombineShader.Notification(AComponent: TComponent; Operation: TOperation);
- begin
- if (FMaterialLibrary = AComponent) and (Operation = opRemove) then
- begin
- NotifyLibMaterial3Destruction;
- NotifyLibMaterial4Destruction;
- FMaterialLibrary := nil;
- end;
- inherited;
- end;
- procedure TGLTexCombineShader.NotifyChange(Sender: TObject);
- begin
- FCombinerIsValid := True;
- FCommandCache := nil;
- inherited NotifyChange(Sender);
- end;
- procedure TGLTexCombineShader.NotifyLibMaterial3Destruction;
- begin
- FLibMaterial3Name := '';
- currentLibMaterial3 := nil;
- end;
- procedure TGLTexCombineShader.NotifyLibMaterial4Destruction;
- begin
- FLibMaterial4Name := '';
- currentLibMaterial4 := nil;
- end;
- procedure TGLTexCombineShader.SetMaterialLibrary(const val: TGLMaterialLibrary);
- begin
- FMaterialLibrary := val;
- SetLibMaterial3Name(LibMaterial3Name);
- SetLibMaterial4Name(LibMaterial4Name);
- end;
- procedure TGLTexCombineShader.SetLibMaterial3Name(const val: TGLLibMaterialName);
- var
- newLibMaterial: TGLLibMaterial;
- begin
- // locate new libmaterial
- if Assigned(FMaterialLibrary) then
- newLibMaterial := MaterialLibrary.Materials.GetLibMaterialByName(val)
- else
- newLibMaterial := nil;
- FLibMaterial3Name := val;
- // unregister if required
- if newLibMaterial <> currentLibMaterial3 then
- begin
- // unregister from old
- if Assigned(currentLibMaterial3) then
- currentLibMaterial3.UnregisterUser(Self);
- currentLibMaterial3 := newLibMaterial;
- // register with new
- if Assigned(currentLibMaterial3) then
- currentLibMaterial3.RegisterUser(Self);
- NotifyChange(Self);
- end;
- end;
- procedure TGLTexCombineShader.SetLibMaterial4Name(const val: TGLLibMaterialName);
- var
- newLibMaterial: TGLLibMaterial;
- begin
- // locate new libmaterial
- if Assigned(FMaterialLibrary) then
- newLibMaterial := MaterialLibrary.Materials.GetLibMaterialByName(val)
- else
- newLibMaterial := nil;
- FLibMaterial4Name := val;
- // unregister if required
- if newLibMaterial <> currentLibMaterial4 then
- begin
- // unregister from old
- if Assigned(currentLibMaterial4) then
- currentLibMaterial4.UnregisterUser(Self);
- currentLibMaterial4 := newLibMaterial;
- // register with new
- if Assigned(currentLibMaterial4) then
- currentLibMaterial4.RegisterUser(Self);
- NotifyChange(Self);
- end;
- end;
- procedure TGLTexCombineShader.DoInitialize(var rci: TGLRenderContextInfo; Sender: TObject);
- begin
- end;
- procedure TGLTexCombineShader.DoApply(var rci: TGLRenderContextInfo; Sender: TObject);
- var
- n, units: Integer;
- begin
- if not GL.ARB_multitexture then
- Exit;
- FApplied3 := False;
- FApplied4 := False;
- if FCombinerIsValid and (FDesignTimeEnabled or (not (csDesigning in ComponentState))) then
- begin
- try
- if Assigned(currentLibMaterial3) or Assigned(currentLibMaterial4) then
- begin
- gl.GetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, @n);
- units := 0;
- if Assigned(currentLibMaterial3) and (n >= 3) then
- begin
- with currentLibMaterial3.Material.Texture do
- begin
- if Enabled then
- begin
- if currentLibMaterial3.TextureMatrixIsIdentity then
- ApplyAsTextureN(3, rci)
- else
- ApplyAsTextureN(3, rci, @currentLibMaterial3.TextureMatrix.V[0].X);
- // ApplyAsTextureN(3, rci, currentLibMaterial3);
- Inc(units, 4);
- FApplied3 := True;
- end;
- end;
- end;
- if Assigned(currentLibMaterial4) and (n >= 4) then
- begin
- with currentLibMaterial4.Material.Texture do
- begin
- if Enabled then
- begin
- if currentLibMaterial4.TextureMatrixIsIdentity then
- ApplyAsTextureN(4, rci)
- else
- ApplyAsTextureN(4, rci, @currentLibMaterial4.TextureMatrix.V[0].X);
- // ApplyAsTextureN(4, rci, currentLibMaterial4);
- Inc(units, 8);
- FApplied4 := True;
- end;
- end;
- end;
- if units > 0 then
- xgl.MapTexCoordToArbitraryAdd(units);
- end;
- if Length(FCommandCache) = 0 then
- FCommandCache := GetTextureCombiners(FCombiners);
- for n := 0 to High(FCommandCache) do
- begin
- rci.GLStates.ActiveTexture := FCommandCache[n].ActiveUnit;
- gl.TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
- gl.TexEnvi(GL_TEXTURE_ENV, FCommandCache[n].Arg1, FCommandCache[n].Arg2);
- end;
- rci.GLStates.ActiveTexture := 0;
- except
- on E: Exception do
- begin
- FCombinerIsValid := False;
- InformationDlg(E.ClassName + ': ' + E.Message);
- end;
- end;
- end;
- end;
- function TGLTexCombineShader.DoUnApply(var rci: TGLRenderContextInfo): Boolean;
- begin
- if FApplied3 then
- with currentLibMaterial3.Material.Texture do
- UnApplyAsTextureN(3, rci, (not currentLibMaterial3.TextureMatrixIsIdentity));
- if FApplied4 then
- with currentLibMaterial4.Material.Texture do
- UnApplyAsTextureN(4, rci, (not currentLibMaterial4.TextureMatrixIsIdentity));
- Result := False;
- end;
- procedure TGLTexCombineShader.DoFinalize;
- begin
- end;
- procedure TGLTexCombineShader.SetCombiners(const val: TStringList);
- begin
- if val <> FCombiners then
- begin
- FCombiners.Assign(val);
- NotifyChange(Self);
- end;
- end;
- procedure TGLTexCombineShader.SetDesignTimeEnabled(const val: Boolean);
- begin
- if val <> FDesignTimeEnabled then
- begin
- FDesignTimeEnabled := val;
- NotifyChange(Self);
- end;
- end;
- end.
|