AsphyreShaderFX.pas
上传用户:ctlcnc
上传日期:2021-12-10
资源大小:4933k
文件大小:13k
源码类别:

2D图形编程

开发平台:

Delphi

  1. unit AsphyreShaderFX;
  2. //---------------------------------------------------------------------------
  3. // AsphyreShaderFX.pas                                  Modified: 02-Apr-2007
  4. // A wrapper for HLSL shaders and effect framework                Version 1.0
  5. //---------------------------------------------------------------------------
  6. // Important Notice:
  7. //
  8. // If you modify/use this code or one of its parts either in original or
  9. // modified form, you must comply with Mozilla Public License v1.1,
  10. // specifically section 3, "Distribution Obligations". Failure to do so will
  11. // result in the license breach, which will be resolved in the court.
  12. // Remember that violating author's rights is considered a serious crime in
  13. // many countries. Thank you!
  14. //
  15. // !! Please *read* Mozilla Public License 1.1 document located at:
  16. //  http://www.mozilla.org/MPL/
  17. //
  18. // If you require any clarifications about the license, feel free to contact
  19. // us or post your question on our forums at: http://www.afterwarp.net
  20. //---------------------------------------------------------------------------
  21. // The contents of this file are subject to the Mozilla Public License
  22. // Version 1.1 (the "License"); you may not use this file except in
  23. // compliance with the License. You may obtain a copy of the License at
  24. // http://www.mozilla.org/MPL/
  25. //
  26. // Software distributed under the License is distributed on an "AS IS"
  27. // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
  28. // License for the specific language governing rights and limitations
  29. // under the License.
  30. //
  31. // The Original Code is AsphyreShaderFX.pas.
  32. //
  33. // The Initial Developer of the Original Code is M. Sc. Yuriy Kotsarenko.
  34. // Portions created by M. Sc. Yuriy Kotsarenko are Copyright (C) 2007,
  35. // M. Sc. Yuriy Kotsarenko. All Rights Reserved.
  36. //---------------------------------------------------------------------------
  37. interface
  38. //---------------------------------------------------------------------------
  39. uses
  40.  Windows, Direct3D9, d3dx9, Vectors3, AsphyreDevices, AsphyreScene,
  41.  AsphyreEvents;
  42. //---------------------------------------------------------------------------
  43. {$define DebugMode}
  44. //---------------------------------------------------------------------------
  45. type
  46.  TShaderEffectMode = (semCompatibility, semPerformance, semQuality);
  47. //---------------------------------------------------------------------------
  48.  TShaderParameterType = (sptCustom, sptTexture, sptWorldViewProjection,
  49.   sptViewProjection, sptWorldInverseTranspose, sptCameraPosition, sptWorld,
  50.   sptWorldInverse, sptWorldView, sptProjection);
  51. //---------------------------------------------------------------------------
  52.  TShaderParameter = record
  53.   Name  : string;
  54.   Code  : Integer;
  55.   PType : TShaderParameterType;
  56.   Handle: TD3DXHandle;
  57.  end;
  58. //---------------------------------------------------------------------------
  59.  TShaderTechnique = record
  60.   Name  : string;
  61.   Code  : Integer;
  62.   Handle: TD3DXHandle;
  63.  end;
  64. //---------------------------------------------------------------------------
  65.  TAsphyreShaderEffect = class
  66.  private
  67.   Parameters: array of TShaderParameter;
  68.   Techniques: array of TShaderTechnique;
  69.   FEffect: ID3DXEffect;
  70.   FDevice: TAsphyreDevice;
  71.   FNumPasses: Integer;
  72.   function LoadHandles(): Boolean;
  73.   function IndexOfParameter(Code: Integer): Integer;
  74.   function IndexOfTechnique(Code: Integer): Integer;
  75.   procedure ReleaseHandles();
  76.   procedure RequestUpdateParam(Index: Integer);
  77.   procedure OnDeviceReset(Sender: TObject; EventParam: Pointer;
  78.    var Success: Boolean);
  79.   procedure OnDeviceLost(Sender: TObject; EventParam: Pointer;
  80.    var Success: Boolean);
  81.  protected
  82.   procedure DescParam(Param: TShaderParameterType; const Name: string;
  83.    Code: Integer = -1);
  84.   procedure DescTechnique(const Name: string; Code: Integer);
  85.   procedure Describe(); virtual;
  86.   procedure UpdateParam(Code: Integer; out DataPtr: Pointer;
  87.    out DataSize: Integer); virtual;
  88.   function UseTechnique(Code: Integer): Boolean;
  89.   procedure UpdateTexture(Code: Integer;
  90.    out ParamTex: IDirect3DTexture9); virtual;
  91.   procedure UpdateAll();
  92.   procedure BeginUpdate();
  93.   procedure UpdateByCode(Code: Integer);
  94.   procedure EndUpdate();
  95.  public
  96.   property Device: TAsphyreDevice read FDevice;
  97.   property Effect: ID3DXEffect read FEffect;
  98.   property NumPasses: Integer read FNumPasses;
  99.   function LoadFromFile(const FileName: string): Boolean;
  100.   procedure BeginAll();
  101.   procedure EndAll();
  102.   function BeginPass(PassNo: Integer): Boolean;
  103.   procedure EndPass();
  104.   procedure Update(); virtual;
  105.   constructor Create(ADevice: TAsphyreDevice);
  106.   destructor Destroy(); override;
  107.  end;
  108. //---------------------------------------------------------------------------
  109. implementation
  110. //---------------------------------------------------------------------------
  111. constructor TAsphyreShaderEffect.Create(ADevice: TAsphyreDevice);
  112. begin
  113.  inherited Create();
  114.  FDevice:= ADevice;
  115.  Describe();
  116.  EventDeviceLost.Subscribe(OnDeviceLost, FDevice);
  117.  EventDeviceReset.Subscribe(OnDeviceReset, FDevice);
  118. end;
  119. //---------------------------------------------------------------------------
  120. destructor TAsphyreShaderEffect.Destroy();
  121. begin
  122.  EventDeviceReset.Unsubscribe(OnDeviceReset);
  123.  EventDeviceLost.Unsubscribe(OnDeviceLost);
  124.  ReleaseHandles();
  125.  if (FEffect <> nil) then FEffect:= nil;
  126.  inherited;
  127. end;
  128. //---------------------------------------------------------------------------
  129. procedure TAsphyreShaderEffect.ReleaseHandles();
  130. var
  131.  i: Integer;
  132. begin
  133.  for i:= 0 to Length(Parameters) - 1 do
  134.   if (Parameters[i].Handle <> nil) then Parameters[i].Handle:= nil;
  135.  for i:= 0 to Length(Techniques) - 1 do
  136.   if (Techniques[i].Handle <> nil) then Techniques[i].Handle:= nil;
  137. end;
  138. //---------------------------------------------------------------------------
  139. procedure TAsphyreShaderEffect.Describe();
  140. begin
  141.  // no code
  142. end;
  143. //---------------------------------------------------------------------------
  144. procedure TAsphyreShaderEffect.DescParam(Param: TShaderParameterType;
  145.  const Name: string; Code: Integer = -1);
  146. var
  147.  Index: Integer;
  148. begin
  149.  Index:= Length(Parameters);
  150.  SetLength(Parameters, Index + 1);
  151.  Parameters[Index].Name  := Name;
  152.  Parameters[Index].Code  := Code;
  153.  Parameters[Index].PType := Param;
  154.  Parameters[Index].Handle:= nil;
  155. end;
  156. //---------------------------------------------------------------------------
  157. procedure TAsphyreShaderEffect.DescTechnique(const Name: string; Code: Integer);
  158. var
  159.  Index: Integer;
  160. begin
  161.  Index:= Length(Techniques);
  162.  SetLength(Techniques, Index + 1);
  163.  Techniques[Index].Name  := Name;
  164.  Techniques[Index].Code  := Code;
  165. end;
  166. //---------------------------------------------------------------------------
  167. function TAsphyreShaderEffect.LoadHandles(): Boolean;
  168. var
  169.  i: Integer;
  170. begin
  171.  Result:= True;
  172.  for i:= 0 to Length(Parameters) - 1 do
  173.   begin
  174.    Parameters[i].Handle:= FEffect.GetParameterByName(nil,
  175.     PAnsiChar(Parameters[i].Name));
  176.    if (Parameters[i].Handle = nil) then
  177.     begin
  178.      Result:= False;
  179.      Exit;
  180.     end;
  181.   end;
  182.  for i:= 0 to Length(Techniques) - 1 do
  183.   begin
  184.    Techniques[i].Handle:= FEffect.GetTechniqueByName(PAnsiChar(Techniques[i].Name));
  185.    if (Techniques[i].Handle = nil) then
  186.     begin
  187.      Result:= False;
  188.      Exit;
  189.     end;
  190.   end;
  191. end;
  192. //---------------------------------------------------------------------------
  193. procedure TAsphyreShaderEffect.OnDeviceLost(Sender: TObject;
  194.  EventParam: Pointer; var Success: Boolean);
  195. begin
  196.  if (FEffect <> nil) then FEffect.OnLostDevice();
  197. end;
  198. //---------------------------------------------------------------------------
  199. procedure TAsphyreShaderEffect.OnDeviceReset(Sender: TObject;
  200.  EventParam: Pointer; var Success: Boolean);
  201. begin
  202.  if (FEffect <> nil) then FEffect.OnResetDevice();
  203. end;
  204. //---------------------------------------------------------------------------
  205. function TAsphyreShaderEffect.LoadFromFile(const FileName: string): Boolean;
  206. {$ifdef DebugMode}
  207. var
  208.  Errors: ID3DXBuffer;
  209. {$endif}
  210. begin
  211.  if (FEffect <> nil) then FEffect:= nil;
  212.  {$ifdef DebugMode}
  213.  Result:= Succeeded(D3DXCreateEffectFromFile(FDevice.Dev9, PAnsiChar(FileName),
  214.   nil, nil, D3DXSHADER_DEBUG, nil, FEffect, @Errors));
  215.  if (Errors <> nil) then
  216.   OutputDebugString(Errors.GetBufferPointer());
  217.  {$else}
  218.  Result:= Succeeded(D3DXCreateEffectFromFile(FDevice.Dev9, PAnsiChar(FileName),
  219.   nil, nil, 0, nil, FEffect, nil));
  220.  {$endif}
  221.  if (Result) then Result:= LoadHandles();
  222. end;
  223. //---------------------------------------------------------------------------
  224. procedure TAsphyreShaderEffect.UpdateParam(Code: Integer; out DataPtr: Pointer;
  225.  out DataSize: Integer);
  226. begin
  227.  DataPtr := nil;
  228.  DataSize:= 0;
  229. end;
  230. //---------------------------------------------------------------------------
  231. procedure TAsphyreShaderEffect.UpdateTexture(Code: Integer;
  232.  out ParamTex: IDirect3DTexture9);
  233. begin
  234.  ParamTex:= nil;
  235. end;
  236. //---------------------------------------------------------------------------
  237. function TAsphyreShaderEffect.IndexOfParameter(Code: Integer): Integer;
  238. var
  239.  i: Integer;
  240. begin
  241.  Result:= -1;
  242.  for i:= 0 to Length(Parameters) - 1 do
  243.   if (Parameters[i].Code = Code) then
  244.    begin
  245.     Result:= i;
  246.     Break;
  247.    end;
  248. end;
  249. //---------------------------------------------------------------------------
  250. function TAsphyreShaderEffect.IndexOfTechnique(Code: Integer): Integer;
  251. var
  252.  i: Integer;
  253. begin
  254.  Result:= -1;
  255.  for i:= 0 to Length(Techniques) - 1 do
  256.   if (Techniques[i].Code = Code) then
  257.    begin
  258.     Result:= i;
  259.     Break;
  260.    end;
  261. end;
  262. //---------------------------------------------------------------------------
  263. function TAsphyreShaderEffect.UseTechnique(Code: Integer): Boolean;
  264. var
  265.  Index: Integer;
  266. begin
  267.  Index:= IndexOfTechnique(Code);
  268.  if (Index = -1)or(FEffect = nil) then
  269.   begin
  270.    Result:= False;
  271.    Exit;
  272.   end;
  273.  Result:= Succeeded(FEffect.SetTechnique(Techniques[Index].Handle));
  274. end;
  275. //---------------------------------------------------------------------------
  276. procedure TAsphyreShaderEffect.RequestUpdateParam(Index: Integer);
  277. var
  278.  DataPtr : Pointer;
  279.  DataSize: Integer;
  280.  TempTex : IDirect3DTexture9;
  281. begin
  282.  with Parameters[Index] do
  283.   case PType of
  284.    sptWorldViewProjection:
  285.     FEffect.SetMatrix(Handle, TD3DXMatrix(ShdrWorldViewProjection));
  286.    sptViewProjection:
  287.     FEffect.SetMatrix(Handle, TD3DXMatrix(ShdrViewProjection));
  288.    sptWorldInverseTranspose:
  289.     FEffect.SetMatrix(Handle, TD3DXMatrix(ShdrWorldInverseTranspose));
  290.    sptWorldView:
  291.     FEffect.SetMatrix(Handle, TD3DXMatrix(ShdrWorldView));
  292.    sptWorldInverse:
  293.     FEffect.SetMatrix(Handle, TD3DXMatrix(ShdrWorldInverse));
  294.    sptWorld:
  295.     FEffect.SetMatrix(Handle, PD3DXMatrix(WorldMtx.RawMtx)^);
  296.    sptProjection:
  297.     FEffect.SetMatrix(Handle, PD3DXMatrix(ProjMtx.RawMtx)^);
  298.    sptCameraPosition:
  299.     FEffect.SetValue(Handle, @ShdrCameraPosition, SizeOf(TVector3));
  300.    sptTexture:
  301.     begin
  302.      UpdateTexture(Code, TempTex);
  303.      FEffect.SetTexture(Handle, TempTex);
  304.      TempTex:= nil;
  305.     end;
  306.    sptCustom:
  307.     begin
  308.      UpdateParam(Code, DataPtr, DataSize);
  309.      if (DataPtr <> nil)and(DataSize > 0) then
  310.       FEffect.SetValue(Handle, DataPtr, DataSize);
  311.     end;
  312.   end;
  313. end;
  314. //---------------------------------------------------------------------------
  315. procedure TAsphyreShaderEffect.UpdateAll();
  316. var
  317.  i: Integer;
  318. begin
  319.  BeginUpdate();
  320.  for i:= 0 to Length(Parameters) - 1 do
  321.   RequestUpdateParam(i);
  322.  EndUpdate();
  323. end;
  324. //---------------------------------------------------------------------------
  325. procedure TAsphyreShaderEffect.BeginAll();
  326. begin
  327.  if (FEffect <> nil) then FEffect._Begin(@FNumPasses, 0);
  328. end;
  329. //---------------------------------------------------------------------------
  330. procedure TAsphyreShaderEffect.EndAll();
  331. begin
  332.  if (FEffect <> nil) then FEffect._End();
  333. end;
  334. //---------------------------------------------------------------------------
  335. function TAsphyreShaderEffect.BeginPass(PassNo: Integer): Boolean;
  336. begin
  337.  if (FEffect = nil) then
  338.   begin
  339.    Result:= False;
  340.    Exit;
  341.   end;
  342.  Result:= Succeeded(FEffect.BeginPass(PassNo));
  343. end;
  344. //---------------------------------------------------------------------------
  345. procedure TAsphyreShaderEffect.EndPass();
  346. begin
  347.  if (FEffect <> nil) then FEffect.EndPass();
  348. end;
  349. //---------------------------------------------------------------------------
  350. procedure TAsphyreShaderEffect.Update();
  351. begin
  352.  UpdateAll();
  353. end;
  354. //---------------------------------------------------------------------------
  355. procedure TAsphyreShaderEffect.BeginUpdate();
  356. begin
  357.  UpdateShdrCombined();
  358. end;
  359. //---------------------------------------------------------------------------
  360. procedure TAsphyreShaderEffect.EndUpdate();
  361. begin
  362.  FEffect.CommitChanges();
  363. end;
  364. //---------------------------------------------------------------------------
  365. procedure TAsphyreShaderEffect.UpdateByCode(Code: Integer);
  366. var
  367.  Index: Integer;
  368. begin
  369.  Index:= IndexOfParameter(Code);
  370.  if (Index = -1) then Exit;
  371.  RequestUpdateParam(Index);
  372. end;
  373. //---------------------------------------------------------------------------
  374. end.