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

2D图形编程

开发平台:

Delphi

  1. unit GameInstancing;
  2. //---------------------------------------------------------------------------
  3. interface
  4. //---------------------------------------------------------------------------
  5. uses
  6.  d3dx9, Matrices4, AsphyreUtils, InstanceMeshes, AsphyreScene;
  7. //---------------------------------------------------------------------------
  8. type
  9.  PMeshInstance = ^TMeshInstance;
  10.  TMeshInstance = record
  11.   // Original instance data
  12.   Mesh    : TInstanceMesh;
  13.   Color   : Cardinal;
  14.   WorldMtx: TMatrix4;
  15.   // Calculated instance data
  16.   WorldViewMtx: TMatrix4;
  17.   InvWorldTMtx: TMatrix4;
  18.  end;
  19. //---------------------------------------------------------------------------
  20.  TMeshInstances = class
  21.  private
  22.   Instances: array of TMeshInstance;
  23.   DrawOrder: array of PMeshInstance;
  24.   DataCount: Integer;
  25.   Capacity : Integer;
  26.   procedure Grow();
  27.   procedure InitDrawOrder();
  28.   function CompareDrawOrder(Left, Right: PMeshInstance): Integer;
  29.   procedure SortDrawOrder(Left, Right: Integer);
  30.  public
  31.   function Draw(Mesh: TInstanceMesh; Color: Cardinal;
  32.    const WorldMtx: TMatrix4): Integer;
  33.   procedure Render();
  34.   constructor Create();
  35.   destructor Destroy(); override;
  36.  end;
  37. //---------------------------------------------------------------------------
  38. var
  39.  Instances: TMeshInstances = nil;
  40. //---------------------------------------------------------------------------
  41. implementation
  42. //---------------------------------------------------------------------------
  43. uses
  44.  GameTypes, InstanceShaders, GameMeshes;
  45. //---------------------------------------------------------------------------
  46. const
  47.  MinGrow  = 4;
  48.  GrowUnit = 8;
  49. //---------------------------------------------------------------------------
  50. constructor TMeshInstances.Create();
  51. begin
  52.  inherited;
  53.  Capacity := 0;
  54.  DataCount:= 0;
  55. end;
  56. //---------------------------------------------------------------------------
  57. destructor TMeshInstances.Destroy();
  58. begin
  59.  inherited;
  60. end;
  61. //---------------------------------------------------------------------------
  62. procedure TMeshInstances.Grow();
  63. var
  64.  Delta: Integer;
  65. begin
  66.  Delta:= MinGrow + (Capacity div GrowUnit);
  67.  Inc(Capacity, Delta);
  68.  SetLength(Instances, Capacity);
  69.  SetLength(DrawOrder, Capacity);
  70. end;
  71. //---------------------------------------------------------------------------
  72. function TMeshInstances.Draw(Mesh: TInstanceMesh; Color: Cardinal;
  73.  const WorldMtx: TMatrix4): Integer;
  74. begin
  75.  if (DataCount >= Capacity) then Grow();
  76.  Result:= DataCount;
  77.  Inc(DataCount);
  78.  // Insert instance data
  79.  Instances[Result].Mesh    := Mesh;
  80.  Instances[Result].Color   := Color;
  81.  Instances[Result].WorldMtx:= WorldMtx;
  82.  // Precalculate additional instance parameters
  83.  with Instances[Result] do
  84.   begin
  85.    // -> World-View matrix
  86.    D3DXMatrixMultiply(TD3DXMatrix(WorldViewMtx), TD3DXMatrix(WorldMtx),
  87.     PD3DXMatrix(ViewMtx.RawMtx)^);
  88.    // -> Inverse-World transpose matrix
  89.    D3DXMatrixInverse(TD3DXMatrix(InvWorldTMtx), nil, TD3DXMatrix(WorldMtx));
  90.    D3DXMatrixTranspose(TD3DXMatrix(InvWorldTMtx), TD3DXMatrix(InvWorldTMtx));
  91.   end;
  92. end;
  93. //---------------------------------------------------------------------------
  94. procedure TMeshInstances.InitDrawOrder();
  95. var
  96.  i: Integer;
  97. begin
  98.  for i:= 0 to DataCount - 1 do
  99.   DrawOrder[i]:= @Instances[i];
  100. end;
  101. //---------------------------------------------------------------------------
  102. function TMeshInstances.CompareDrawOrder(Left, Right: PMeshInstance): Integer;
  103. begin
  104.  if (Left.Mesh = Right.Mesh) then
  105.   begin // Sort by depth
  106.    Result:= 0;
  107.    if (Left.WorldViewMtx.Data[3, 2] < Right.WorldViewMtx.Data[3, 2]) then
  108.     Result:= -1 else
  109.    if (Left.WorldViewMtx.Data[3, 2] > Right.WorldViewMtx.Data[3, 2]) then
  110.     Result:= 1;
  111.   end else
  112.   begin // Sort by type
  113.    Result:= -1;
  114.    if (Integer(@Left.Mesh) > Integer(@Right.Mesh)) then Result:= 1;
  115.   end;
  116. end;
  117. //---------------------------------------------------------------------------
  118. procedure TMeshInstances.SortDrawOrder(Left, Right: Integer);
  119. var
  120.  Lo, Hi  : Integer;
  121.  TempElem: PMeshInstance;
  122.  MidValue: PMeshInstance;
  123. begin
  124.  Lo:= Left;
  125.  Hi:= Right;
  126.  MidValue:= DrawOrder[(Left + Right) div 2];
  127.  repeat
  128.   while (CompareDrawOrder(DrawOrder[Lo], MidValue) < 0) do Inc(Lo);
  129.   while (CompareDrawOrder(DrawOrder[Hi], MidValue) > 0) do Dec(Hi);
  130.   if (Lo <= Hi) then
  131.    begin
  132.     TempElem:= DrawOrder[Lo];
  133.     DrawOrder[Lo]:= DrawOrder[Hi];
  134.     DrawOrder[Hi]:= TempElem;
  135.     Inc(Lo);
  136.     Dec(Hi);
  137.    end;
  138.  until (Lo > Hi);
  139.  if (Left < Hi) then SortDrawOrder(Left, Hi);
  140.  if (Lo < Right) then SortDrawOrder(Lo, Right);
  141. end;
  142. //---------------------------------------------------------------------------
  143. procedure TMeshInstances.Render();
  144. var
  145.  i: Integer;
  146.  Mesh: TInstanceMesh;
  147.  Count: Integer;
  148. begin
  149.  if (DataCount < 1) then Exit;
  150.  InitDrawOrder();
  151.  SortDrawOrder(0, DataCount - 1);
  152.  Mesh := nil;
  153.  Count:= 0;
  154.  for i:= 0 to DataCount - 1 do
  155. // for i:= DataCount - 1 downto 0 do
  156.   begin
  157.    if ((Mesh <> DrawOrder[i].Mesh)or(Count >= NumShdrInstances))and
  158.     (Mesh <> nil) then
  159.     begin
  160.      InstanceShader.Update();
  161.      Mesh.Draw2(InstanceShader, Count);
  162.      Count:= 0;
  163.     end;
  164.    Mesh:= DrawOrder[i].Mesh;
  165.    InstanceShader.WorldMtx[Count]:= DrawOrder[i].WorldMtx;
  166.    InstanceShader.Color[Count]   := DrawOrder[i].Color;
  167.    Inc(Count);
  168. //   MeshCube.Draw(Shader, DrawOrder[i].WorldMtx, DrawOrder[i].Color);
  169.   end;
  170.  if (Count > 0) then
  171.   begin
  172.    InstanceShader.Update();
  173.    Mesh.Draw2(InstanceShader, Count);
  174.   end;
  175.  DataCount:= 0; 
  176. end;
  177. //---------------------------------------------------------------------------
  178. initialization
  179.  Instances:= TMeshInstances.Create();
  180. //---------------------------------------------------------------------------
  181. finalization
  182.  Instances.Free();
  183.  Instances:= nil;
  184. //---------------------------------------------------------------------------
  185. end.