123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 |
- //
- // The graphics engine GLXEngine. The unit of GXScene for Delphi
- //
- unit GXSL.ShaderCombiner;
- (*
- Allows to combine shaders in different sequences.
- Note, that can't just take 2 random shaders and combine them, because
- shaders often override the objects material and vertex data with a total
- disregard to what existed before it. But in some cases, especially with
- multipass shaders, this unit does magic and allows to reuse and upgrade
- previously written shaders.
- *)
- interface
- {$I Stage.Defines.inc}
- uses
- System.Classes,
- GXS.Material,
- GXS.Scene,
- Stage.VectorGeometry,
- Stage.Strings,
- GXS.RenderContextInfo;
- type
- (* MP - multipass, SP-singlepass, AP - anypass (single or multi)
- One-Two or Two-One determines the order of how the shaders should be applied
- For example, sctTwoMPOneSP means that first one will be applied Shader Two,
- which can be a multipass shader, then Shader One is applied, which should be
- a singlepass shader.
- sctOneMPTwoSP and sctTwoMPOneSP modes are actualy quite Str@nge,
- because... well look at the code yourself
- TODO: Add more modes here, including sctOneAPTwoAP, which should be the
- default one.
- By the way, I admit - the names do look stupid, and if someone gives them
- proper names, I will be only glad. *)
- TgxShaderCombinerType = (sctOneSPTwoAP, sctTwoSPOneAP,
- sctOneMPTwoSP, sctTwoMPOneSP
- );
- TgxCustomShaderCombiner = class(TgxShader)
- private
- FCurrentPass: Integer;
- FCombinerType: TgxShaderCombinerType;
- FShaderOne: TgxShader;
- FShaderTwo: TgxShader;
- procedure SetShaderOne(const Value: TgxShader);
- procedure SetShaderTwo(const Value: TgxShader);
- protected
- procedure DoApply(var rci : TgxRenderContextInfo; Sender : TObject); override;
- function DoUnApply(var rci: TgxRenderContextInfo): Boolean; override;
- procedure Notification(AComponent: TComponent; Operation: TOperation); override;
- property CombinerType: TgxShaderCombinerType read FCombinerType write FCombinerType default sctOneSPTwoAP;
- property ShaderOne: TgxShader read FShaderOne write SetShaderOne;
- property ShaderTwo: TgxShader read FShaderTwo write SetShaderTwo;
- property CurrentPass : Integer read FCurrentPass stored False;
- public
- constructor Create(AOwner: TComponent); override;
- function ShaderSupported: Boolean; override;
- procedure Assign(Source: TPersistent); override;
- end;
- TgxShaderCombiner = class(TgxCustomShaderCombiner)
- published
- property CombinerType;
- property ShaderOne;
- property ShaderTwo;
- property ShaderStyle;
- end;
- //-------------------------------------------------
- implementation
- //-------------------------------------------------
- //-------------------------------------------------
- // TgxCustomShaderCombiner
- //-------------------------------------------------
- procedure TgxCustomShaderCombiner.Assign(Source: TPersistent);
- begin
- inherited;
- if Source is TgxCustomShaderCombiner then
- begin
- SetShaderOne(TgxCustomShaderCombiner(Source).FShaderOne);
- SetShaderTwo(TgxCustomShaderCombiner(Source).FShaderTwo);
- end;
- end;
- constructor TgxCustomShaderCombiner.Create(AOwner: TComponent);
- begin
- inherited;
- FCombinerType := sctOneSPTwoAP;
- end;
- procedure TgxCustomShaderCombiner.DoApply(var rci: TgxRenderContextInfo;
- Sender: TObject);
- begin
- if (csDesigning in ComponentState) then Exit;
- Assert((FShaderOne <> nil) and (FShaderTwo <> nil));
- FCurrentPass:=1;
- case FCombinerType of
- sctOneMPTwoSP:
- begin
- FShaderOne.Apply(rci, Self);
- FShaderTwo.Apply(rci, Self);
- end;
- sctTwoMPOneSP:
- begin
- FShaderTwo.Apply(rci, Self);
- FShaderOne.Apply(rci, Self);
- end;
- sctOneSPTwoAP:
- begin
- FShaderOne.Apply(rci, Self);
- end;
- sctTwoSPOneAP:
- begin
- FShaderTwo.Apply(rci, Self);
- end;
- else
- Assert(False, strErrorEx + strUnknownType);
- end;
- end;
- function TgxCustomShaderCombiner.DoUnApply(var rci: TgxRenderContextInfo): Boolean;
- begin
- case FCombinerType of
- sctOneMPTwoSP:
- begin
- if FShaderOne.UnApply(rci) then
- Result := True
- else
- Result := FShaderTwo.UnApply(rci);
- end;
- sctTwoMPOneSP:
- begin
- if FShaderTwo.UnApply(rci) then
- Result := True
- else
- Result := FShaderOne.UnApply(rci);
- end;
- sctOneSPTwoAP:
- begin
- if FCurrentPass = 1 then
- begin
- FShaderOne.UnApply(rci);
- FShaderTwo.Apply(rci, Self);
- Result := True;
- end
- else
- Result := FShaderTwo.UnApply(rci);
- end;
- sctTwoSPOneAP:
- begin
- if FCurrentPass = 1 then
- begin
- FShaderTwo.UnApply(rci);
- FShaderOne.Apply(rci, Self);
- Result := True;
- end
- else
- Result := FShaderOne.UnApply(rci);
- end;
- else
- begin
- Result := False;
- Assert(False, strErrorEx + strUnknownType);
- end;
- end;
- Inc(FCurrentPass);
- end;
- procedure TgxCustomShaderCombiner.Notification(AComponent: TComponent;
- Operation: TOperation);
- begin
- inherited;
- if Operation = opRemove then
- begin
- if AComponent = FShaderOne then
- FShaderOne := nil
- else if AComponent = FShaderTwo then
- FShaderTwo := nil;
- end;
- end;
- procedure TgxCustomShaderCombiner.SetShaderOne(const Value: TgxShader);
- begin
- if FShaderOne <> nil then
- FShaderOne.RemoveFreeNotification(Self);
- FShaderOne := Value;
- if FShaderOne <> nil then
- FShaderOne.FreeNotification(Self);
- end;
- procedure TgxCustomShaderCombiner.SetShaderTwo(const Value: TgxShader);
- begin
- if FShaderTwo <> nil then
- FShaderTwo.RemoveFreeNotification(Self);
- FShaderTwo := Value;
- if FShaderTwo <> nil then
- FShaderTwo.FreeNotification(Self);
- end;
- function TgxCustomShaderCombiner.ShaderSupported: Boolean;
- begin
- Result := (FShaderOne <> nil) and (FShaderTwo <> nil) and
- FShaderOne.ShaderSupported and FShaderTwo.ShaderSupported;
- end;
- initialization
- RegisterClasses([TgxCustomShaderCombiner, TgxShaderCombiner]);
- end.
|