| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613 |
- //
- // This unit is part of the GLScene Engine, http://glscene.org
- //
- unit GLS.ShaderTextureSharing;
- (*
- This shader allows to apply multiple textures, gathering them from existing materials.
- This allows saving resources, since you can reference the textures of any material in
- any materialLibrary.
- Note that actually the component references a Material (not a texture) but
- it uses that material's texture. The referenced material settings will be ignored,
- but the texture's settings (like TextureMode, ImageGamma, ImageBrightness) will be used.
- Instead the local material settings (listed in the collection) will be used.
- *)
- interface
- uses
- System.Classes,
- System.SysUtils,
-
- GLScene,
- GLContext,
- GLTexture,
- GLVectorTypes,
- GLVectorGeometry,
- GlColor,
- GLMaterial,
- GLS.Strings,
- GLVectorFileObjects,
- XOpenGL,
- GLState,
- GLPersistentClasses,
- GLCoordinates,
- GLRenderContextInfo;
- type
- TGLTextureSharingShader = class;
- TGLTextureSharingShaderMaterial = class(TGLInterfacedCollectionItem, IGLMaterialLibrarySupported)
- private
- FTextureMatrix: TMatrix;
- FNeedToUpdateTextureMatrix: Boolean;
- FTextureMatrixIsUnitary: Boolean;
- FLibMaterial: TGLLibMaterial;
- FTexOffset: TGLCoordinates2;
- FTexScale: TGLCoordinates2;
- FBlendingMode: TGLBlendingMode;
- FSpecular: TGLColor;
- FAmbient: TGLColor;
- FDiffuse: TGLColor;
- FEmission: TGLColor;
- FShininess: TGLShininess;
- FMaterialLibrary: TGLMaterialLibrary;
- FLibMaterialName: TGLLibMaterialName;
- procedure SetAmbient(const Value: TGLColor);
- procedure SetDiffuse(const Value: TGLColor);
- procedure SetEmission(const Value: TGLColor);
- procedure SetShininess(const Value: TGLShininess);
- procedure SetSpecular(const Value: TGLColor);
- procedure SetMaterialLibrary(const Value: TGLMaterialLibrary);
- procedure SetLibMaterialName(const Value: TGLLibMaterialName);
- procedure SetBlendingMode(const Value: TGLBlendingMode);
- procedure SetLibMaterial(const Value: TGLLibMaterial);
- procedure SetTexOffset(const Value: TGLCoordinates2);
- procedure SetTexScale(const Value: TGLCoordinates2);
- function GetTextureMatrix: TMatrix;
- function GetTextureMatrixIsUnitary: Boolean;
- protected
- procedure coordNotifychange(Sender: TObject);
- procedure OtherNotifychange(Sender: TObject);
- function GetDisplayName: string; override;
- function GetTextureSharingShader: TGLTextureSharingShader;
- // Implementing IGLMaterialLibrarySupported.
- function GetMaterialLibrary: TGLAbstractMaterialLibrary; virtual;
- public
- procedure Apply(var rci: TGLRenderContextInfo);
- procedure UnApply(var rci: TGLRenderContextInfo);
- constructor Create(Collection: TCollection); override;
- destructor Destroy; override;
- property LibMaterial: TGLLibMaterial read FLibMaterial write SetLibMaterial;
- property TextureMatrix: TMatrix read GetTextureMatrix;
- property TextureMatrixIsUnitary: Boolean read GetTextureMatrixIsUnitary;
- published
- property TexOffset: TGLCoordinates2 read FTexOffset write SetTexOffset;
- property TexScale: TGLCoordinates2 read FTexScale write SetTexScale;
- property BlendingMode: TGLBlendingMode read FBlendingMode write SetBlendingMode;
- property Emission: TGLColor read FEmission write SetEmission;
- property Ambient: TGLColor read FAmbient write SetAmbient;
- property Diffuse: TGLColor read FDiffuse write SetDiffuse;
- property Specular: TGLColor read FSpecular write SetSpecular;
- property Shininess: TGLShininess read FShininess write SetShininess;
- property MaterialLibrary: TGLMaterialLibrary read FMaterialLibrary write SetMaterialLibrary;
- property LibMaterialName: TGLLibMaterialName read FLibMaterialName write SetLibMaterialName;
- end;
- TGLTextureSharingShaderMaterials = class(TOwnedCollection)
- protected
- function GetItems(const AIndex: Integer): TGLTextureSharingShaderMaterial;
- procedure SetItems(const AIndex: Integer; const Value: TGLTextureSharingShaderMaterial);
- function GetParent: TGLTextureSharingShader;
- public
- function Add: TGLTextureSharingShaderMaterial;
- constructor Create(AOwner: TGLTextureSharingShader);
- property Items[const AIndex: Integer]: TGLTextureSharingShaderMaterial read GetItems write SetItems; default;
- end;
- TGLTextureSharingShader = class(TGLShader)
- private
- FMaterials: TGLTextureSharingShaderMaterials;
- FCurrentPass: Integer;
- procedure SetMaterials(const Value: TGLTextureSharingShaderMaterials);
- protected
- procedure DoApply(var rci: TGLRenderContextInfo; Sender: TObject); override;
- function DoUnApply(var rci: TGLRenderContextInfo): Boolean; override;
- procedure Notification(AComponent: TComponent; Operation: TOperation); override;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- function AddLibMaterial(const ALibMaterial: TGLLibMaterial): TGLTextureSharingShaderMaterial;
- function FindLibMaterial(const ALibMaterial: TGLLibMaterial): TGLTextureSharingShaderMaterial;
- published
- property Materials: TGLTextureSharingShaderMaterials read FMaterials write SetMaterials;
- end;
- //================================================
- implementation
- //================================================
- //-----------------------------------
- // TGLTextureSharingShaderMaterial
- //-----------------------------------
- procedure TGLTextureSharingShaderMaterial.Apply(var rci: TGLRenderContextInfo);
- begin
- if not Assigned(FLibMaterial) then
- Exit;
- xgl.BeginUpdate;
- if Assigned(FLibMaterial.Shader) then
- begin
- case FLibMaterial.Shader.ShaderStyle of
- ssHighLevel: FLibMaterial.Shader.Apply(rci, FLibMaterial);
- ssReplace:
- begin
- FLibMaterial.Shader.Apply(rci, FLibMaterial);
- Exit;
- end;
- end;
- end;
- if not FLibMaterial.Material.Texture.Disabled then
- begin
- if not (GetTextureMatrixIsUnitary) then
- begin
- rci.GLStates.SetGLTextureMatrix(TextureMatrix);
- end;
- end;
- if moNoLighting in FLibMaterial.Material.MaterialOptions then
- rci.GLStates.Disable(stLighting);
- if stLighting in rci.GLStates.States then
- begin
- rci.GLStates.SetGLMaterialColors(cmFront,
- Emission.Color, Ambient.Color, Diffuse.Color, Specular.Color, Shininess);
- rci.GLStates.PolygonMode :=FLibMaterial.Material.PolygonMode;
- end
- else
- FLibMaterial.Material.FrontProperties.ApplyNoLighting(rci, cmFront);
- if (stCullFace in rci.GLStates.States) then
- begin
- case FLibMaterial.Material.FaceCulling of
- fcBufferDefault: if not rci.bufferFaceCull then
- begin
- rci.GLStates.Disable(stCullFace);
- FLibMaterial.Material.BackProperties.Apply(rci, cmBack);
- end;
- fcCull: ; // nothing to do
- fcNoCull:
- begin
- rci.GLStates.Disable(stCullFace);
- FLibMaterial.Material.BackProperties.Apply(rci, cmBack);
- end;
- else
- Assert(False);
- end;
- end
- else
- begin
- // currently NOT culling
- case FLibMaterial.Material.FaceCulling of
- fcBufferDefault:
- begin
- if rci.bufferFaceCull then
- rci.GLStates.Enable(stCullFace)
- else
- FLibMaterial.Material.BackProperties.Apply(rci, cmBack);
- end;
- fcCull: rci.GLStates.Enable(stCullFace);
- fcNoCull: FLibMaterial.Material.BackProperties.Apply(rci, cmBack);
- else
- Assert(False);
- end;
- end;
- // Apply Blending mode
- if not rci.ignoreBlendingRequests then
- case BlendingMode of
- bmOpaque:
- begin
- rci.GLStates.Disable(stBlend);
- rci.GLStates.Disable(stAlphaTest);
- end;
- bmTransparency:
- begin
- rci.GLStates.Enable(stBlend);
- rci.GLStates.Enable(stAlphaTest);
- rci.GLStates.SetBlendFunc(bfSrcAlpha, bfOneMinusSrcAlpha);
- end;
- bmAdditive:
- begin
- rci.GLStates.Enable(stBlend);
- rci.GLStates.Enable(stAlphaTest);
- rci.GLStates.SetBlendFunc(bfSrcAlpha, bfOne);
- end;
- bmAlphaTest50:
- begin
- rci.GLStates.Disable(stBlend);
- rci.GLStates.Enable(stAlphaTest);
- rci.GLStates.SetGLAlphaFunction(cfGEqual, 0.5);
- end;
- bmAlphaTest100:
- begin
- rci.GLStates.Disable(stBlend);
- rci.GLStates.Enable(stAlphaTest);
- rci.GLStates.SetGLAlphaFunction(cfGEqual, 1.0);
- end;
- bmModulate:
- begin
- rci.GLStates.Enable(stBlend);
- rci.GLStates.Enable(stAlphaTest);
- rci.GLStates.SetBlendFunc(bfDstColor, bfZero);
- end;
- else
- Assert(False);
- end;
- // Fog switch
- if moIgnoreFog in FLibMaterial.Material.MaterialOptions then
- begin
- if stFog in rci.GLStates.States then
- begin
- rci.GLStates.Disable(stFog);
- Inc(rci.fogDisabledCounter);
- end;
- end;
- if not Assigned(FLibMaterial.Material.TextureEx) then
- begin
- if Assigned(FLibMaterial.Material.Texture) then
- FLibMaterial.Material.Texture.Apply(rci);
- end
- else
- begin
- if Assigned(FLibMaterial.Material.Texture) and not FLibMaterial.Material.TextureEx.IsTextureEnabled(0) then
- FLibMaterial.Material.Texture.Apply(rci)
- else
- if FLibMaterial.Material.TextureEx.Count > 0 then
- FLibMaterial.Material.TextureEx.Apply(rci);
- end;
- if Assigned(FLibMaterial.Shader) then
- begin
- case FLibMaterial.Shader.ShaderStyle of
- ssLowLevel: FLibMaterial.Shader.Apply(rci, FLibMaterial);
- end;
- end;
- xgl.EndUpdate;
- end;
- procedure TGLTextureSharingShaderMaterial.coordNotifychange(Sender: TObject);
- begin
- FNeedToUpdateTextureMatrix := True;
- GetTextureSharingShader.NotifyChange(Self);
- end;
- constructor TGLTextureSharingShaderMaterial.Create(Collection: TCollection);
- begin
- inherited;
- FSpecular := TGLColor.Create(Self);
- FSpecular.OnNotifyChange := OtherNotifychange;
- FAmbient := TGLColor.Create(Self);
- FAmbient.OnNotifyChange := OtherNotifychange;
- FDiffuse := TGLColor.Create(Self);
- FDiffuse.OnNotifyChange := OtherNotifychange;
- FEmission := TGLColor.Create(Self);
- FEmission.OnNotifyChange := OtherNotifychange;
- FTexOffset := TGLCoordinates2.CreateInitialized(Self, NullHmgVector, csPoint2d);
- FTexOffset.OnNotifyChange := coordNotifychange;
- FTexScale := TGLCoordinates2.CreateInitialized(Self, XYZHmgVector, csPoint2d);
- FTexScale.OnNotifyChange := coordNotifychange;
- FNeedToUpdateTextureMatrix := True;
- end;
- destructor TGLTextureSharingShaderMaterial.Destroy;
- begin
- FSpecular.Free;
- FAmbient.Free;
- FDiffuse.Free;
- FEmission.Free;
- FTexOffset.Free;
- FTexScale.Free;
- inherited;
- end;
- function TGLTextureSharingShaderMaterial.GetDisplayName: string;
- var
- st: string;
- begin
- if Assigned(MaterialLibrary) then
- st := MaterialLibrary.Name
- else
- st := '';
- Result := '[' + st + '.' + Self.LibMaterialName + ']';
- end;
- function TGLTextureSharingShaderMaterial.GetMaterialLibrary: TGLAbstractMaterialLibrary;
- begin
- Result := FMaterialLibrary;
- end;
- function TGLTextureSharingShaderMaterial.GetTextureMatrix: TMatrix;
- begin
- if FNeedToUpdateTextureMatrix then
- begin
- if not (TexOffset.Equals(NullHmgVector) and TexScale.Equals(XYZHmgVector)) then
- begin
- FTextureMatrixIsUnitary := False;
- FTextureMatrix := CreateScaleAndTranslationMatrix(TexScale.AsVector, TexOffset.AsVector)
- end
- else
- FTextureMatrixIsUnitary := True;
- FNeedToUpdateTextureMatrix := False;
- end;
- Result := FTextureMatrix;
- end;
- function TGLTextureSharingShaderMaterial.GetTextureMatrixIsUnitary: Boolean;
- begin
- if FNeedToUpdateTextureMatrix then
- GetTextureMatrix;
- Result := FTextureMatrixIsUnitary;
- end;
- function TGLTextureSharingShaderMaterial.GetTextureSharingShader: TGLTextureSharingShader;
- begin
- if Collection is TGLTextureSharingShaderMaterials then
- Result := TGLTextureSharingShaderMaterials(Collection).GetParent
- else
- Result := nil;
- end;
- procedure TGLTextureSharingShaderMaterial.OtherNotifychange(Sender: TObject);
- begin
- GetTextureSharingShader.NotifyChange(Self);
- end;
- procedure TGLTextureSharingShaderMaterial.SetAmbient(const Value: TGLColor);
- begin
- FAmbient.Assign(Value);
- end;
- procedure TGLTextureSharingShaderMaterial.SetBlendingMode(const Value: TGLBlendingMode);
- begin
- FBlendingMode := Value;
- end;
- procedure TGLTextureSharingShaderMaterial.SetDiffuse(const Value: TGLColor);
- begin
- FDiffuse.Assign(Value);
- end;
- procedure TGLTextureSharingShaderMaterial.SetEmission(const Value: TGLColor);
- begin
- FEmission.Assign(Value);
- end;
- procedure TGLTextureSharingShaderMaterial.SetLibMaterialName(const Value: TGLLibMaterialName);
- begin
- FLibMaterialName := Value;
- if (FLibMaterialName = '') or (FMaterialLibrary = nil) then
- FLibMaterial := nil
- else
- SetLibMaterial(FMaterialLibrary.LibMaterialByName(FLibMaterialName));
- end;
- procedure TGLTextureSharingShaderMaterial.SetLibMaterial(const Value: TGLLibMaterial);
- begin
- FLibMaterial := Value;
- if FLibMaterial <> nil then
- begin
- FLibMaterialName := FLibMaterial.DisplayName;
- FMaterialLibrary := TGLMaterialLibrary(TGLLibMaterials(Value.Collection).Owner);
- if not (csloading in GetTextureSharingShader.ComponentState) then
- begin
- FTexOffset.Assign(FLibMaterial.TextureOffset);
- FTexScale.Assign(FLibMaterial.TextureScale);
- FBlendingMode := FLibMaterial.Material.BlendingMode;
- fEmission.Assign(FLibMaterial.Material.FrontProperties.Emission);
- fAmbient.Assign(FLibMaterial.Material.FrontProperties.Ambient);
- fDiffuse.Assign(FLibMaterial.Material.FrontProperties.Diffuse);
- fSpecular.Assign(FLibMaterial.Material.FrontProperties.Specular);
- fShininess := FLibMaterial.Material.FrontProperties.Shininess;
- end;
- end;
- end;
- procedure TGLTextureSharingShaderMaterial.SetMaterialLibrary(const Value: TGLMaterialLibrary);
- begin
- FMaterialLibrary := Value;
- if (FLibMaterialName = '') or (FMaterialLibrary = nil) then
- FLibMaterial := nil
- else
- SetLibMaterial(FMaterialLibrary.LibMaterialByName(FLibMaterialName));
- end;
- procedure TGLTextureSharingShaderMaterial.SetShininess(const Value: TGLShininess);
- begin
- FShininess := Value;
- end;
- procedure TGLTextureSharingShaderMaterial.SetSpecular(const Value: TGLColor);
- begin
- FSpecular.Assign(Value);
- end;
- procedure TGLTextureSharingShaderMaterial.SetTexOffset(const Value: TGLCoordinates2);
- begin
- FTexOffset.Assign(Value);
- FNeedToUpdateTextureMatrix := True;
- end;
- procedure TGLTextureSharingShaderMaterial.SetTexScale(const Value: TGLCoordinates2);
- begin
- FTexScale.Assign(Value);
- FNeedToUpdateTextureMatrix := True;
- end;
- procedure TGLTextureSharingShaderMaterial.UnApply(var rci: TGLRenderContextInfo);
- begin
- if not Assigned(FLibMaterial) then
- Exit;
- if Assigned(FLibMaterial.Shader) then
- begin
- case FLibMaterial.Shader.ShaderStyle of
- ssLowLevel: FLibMaterial.Shader.UnApply(rci);
- ssReplace:
- begin
- FLibMaterial.Shader.UnApply(rci);
- Exit;
- end;
- end;
- end;
- FLibMaterial.Material.UnApply(rci);
- if not FLibMaterial.Material.Texture.Disabled then
- if not (GetTextureMatrixIsUnitary) then
- begin
- rci.GLStates.ResetGLTextureMatrix;
- end;
- if Assigned(FLibMaterial.Shader) then
- begin
- case FLibMaterial.Shader.ShaderStyle of
- ssHighLevel: FLibMaterial.Shader.UnApply(rci);
- end;
- end;
- end;
- //-----------------------------------
- // TGLTextureSharingShader
- //-----------------------------------
- function TGLTextureSharingShader.AddLibMaterial(const ALibMaterial: TGLLibMaterial): TGLTextureSharingShaderMaterial;
- begin
- Result := FMaterials.Add;
- Result.SetLibMaterial(ALibMaterial);
- end;
- constructor TGLTextureSharingShader.Create(AOwner: TComponent);
- begin
- inherited;
- FMaterials := TGLTextureSharingShaderMaterials.Create(Self);
- ShaderStyle := ssReplace;
- end;
- destructor TGLTextureSharingShader.Destroy;
- begin
- FMaterials.Free;
- inherited;
- end;
- procedure TGLTextureSharingShader.DoApply(var rci: TGLRenderContextInfo; Sender: TObject);
- begin
- if Materials.Count > 0 then
- begin
- rci.GLStates.Enable(stDepthTest);
- rci.GLStates.DepthFunc := cfLEqual;
- Materials[0].Apply(rci);
- FCurrentPass := 1;
- end;
- end;
- function TGLTextureSharingShader.DoUnApply(var rci: TGLRenderContextInfo): Boolean;
- begin
- Result := False;
- if Materials.Count > 0 then
- begin
- Materials[FCurrentPass - 1].UnApply(rci);
- if FCurrentPass < Materials.Count then
- begin
- Materials[FCurrentPass].Apply(rci);
- Inc(FCurrentPass);
- Result := True;
- end
- else
- begin
- rci.GLStates.DepthFunc := cfLess;
- rci.GLStates.Disable(stBlend);
- rci.GLStates.Disable(stAlphaTest);
- FCurrentPass := 0;
- end;
- end;
- end;
- function TGLTextureSharingShader.FindLibMaterial(const ALibMaterial: TGLLibMaterial): TGLTextureSharingShaderMaterial;
- var
- I: Integer;
- begin
- Result := nil;
- for I := 0 to FMaterials.Count - 1 do
- if FMaterials[I].FLibMaterial = ALibMaterial then
- begin
- Result := FMaterials[I];
- Break;
- end;
- end;
- procedure TGLTextureSharingShader.Notification(AComponent: TComponent; Operation: TOperation);
- var
- I: Integer;
- begin
- inherited;
- if Operation = opRemove then
- begin
- if AComponent is TGLMaterialLibrary then
- begin
- for I := 0 to Materials.Count - 1 do
- begin
- if Materials.Items[I].MaterialLibrary = AComponent then
- Materials.Items[I].MaterialLibrary := nil;
- end;
- end;
- end;
- end;
- procedure TGLTextureSharingShader.SetMaterials(const Value: TGLTextureSharingShaderMaterials);
- begin
- FMaterials.Assign(Value);
- end;
- //-----------------------------------
- // TGLTextureSharingShaderMaterials
- //-----------------------------------
- function TGLTextureSharingShaderMaterials.Add: TGLTextureSharingShaderMaterial;
- begin
- Result := (inherited Add) as TGLTextureSharingShaderMaterial;
- end;
- constructor TGLTextureSharingShaderMaterials.Create(AOwner: TGLTextureSharingShader);
- begin
- inherited Create(AOwner, TGLTextureSharingShaderMaterial);
- end;
- function TGLTextureSharingShaderMaterials.GetItems(const AIndex: Integer): TGLTextureSharingShaderMaterial;
- begin
- Result := (inherited Items[AIndex]) as TGLTextureSharingShaderMaterial;
- end;
- function TGLTextureSharingShaderMaterials.GetParent: TGLTextureSharingShader;
- begin
- Result := TGLTextureSharingShader(GetOwner);
- end;
- procedure TGLTextureSharingShaderMaterials.SetItems(const AIndex: Integer; const Value: TGLTextureSharingShaderMaterial);
- begin
- inherited Items[AIndex] := Value;
- end;
- //================================================
- initialization
- //================================================
- RegisterClasses([TGLTextureSharingShader, TGLTextureSharingShaderMaterials,
- TGLTextureSharingShaderMaterial]);
- end.
|