依星源码资源网,依星资源网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

【好消息,好消息,好消息】VIP会员可以发表文章赚积分啦 !
查看: 4|回复: 0

[游戏架设教程] [传奇技术]【HGE】绘图底层

[复制链接] 主动推送

1万

主题

1万

帖子

1万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
12523
发表于 6 小时前 | 显示全部楼层 |阅读模式
[传奇技术]【HGE】绘图底层
HGE是基于DX8.0的二维游戏引擎,多年没有更新了。
而我们知道Dx8.0跟DX9.0C是不同层次的。其实基本绘图逻辑差别不是太大,只是性能方面肯定不在一个水平上面。
让我感觉很大困惑的是,HGE的绘图结构效率到底适不适合即时大型网络游戏渲染?因为它的绘图逻辑是基于以前的DX7.0的绘图思想。
先分析它的架构:
  1. 1 (*
  2. 2 ** HGE Primitive type constants
  3. 3 *)
  4. 4 const
  5. 5   HGEPRIM_LINES    = 2;
  6. 6   HGEPRIM_TRIPLES  = 3;
  7. 7   HGEPRIM_QUADS    = 4;
  8. 8
  9. 9 (*
  10. 10 ** HGE Vertex structure
  11. 11 *)
  12. 12 type
  13. 13   THGEVertex = record
  14. 14     X, Y: Single;   // screen position
  15. 15     Z: Single;      // Z-buffer depth 0..1
  16. 16     Col: Longword;  // color
  17. 17     TX, TY: Single; // texture coordinates
  18. 18   end;
  19. 19   PHGEVertex = ^THGEVertex;
  20. 20   THGEVertexArray = array [0..MaxInt div 32 - 1] of THGEVertex;
  21. 21   PHGEVertexArray = ^THGEVertexArray;
  22. 22   TCustomVertex = packed record
  23. 23     x, y, z: single; // Position
  24. 24     rhw: single; // Reciprocal of homogeneous w
  25. 25     Col:  Longword; // Vertex Color
  26. 26     tu, tv: single; // Texture coordinates
  27. 27   end;
  28. 28   PCustomVertex = ^TCustomVertex;
  29. 29
  30. 30 (*
  31. 31 ** HGE Triple structure三角形结构
  32. 32 *)
  33. 33 type
  34. 34   THGETriple = record
  35. 35     V: array [0..2] of THGEVertex;
  36. 36     Tex: ITexture;
  37. 37     Blend: Integer;
  38. 38   end;
  39. 39   PHGETriple = ^THGETriple;
  40. 40
  41. 41 (*
  42. 42 ** HGE Quad structure四边形结构
  43. 43 *)
  44. 44 type
  45. 45   THGEQuad = record
  46. 46     V: array [0..3] of THGEVertex;
  47. 47     Tex: ITexture;
  48. 48     Blend: Integer;
  49. 49   end;
  50. 50   PHGEQuad = ^THGEQuad;
复制代码
FVF常量定义:
1 const2   D3DFVF_HGEVERTEX   = D3DFVF_XYZ or D3DFVF_DIFFUSE or D3DFVF_TEX1;3   VertexDef = D3DFVF_XYZRHW or D3DFVF_DIFFUSE or D3DFVF_TEX1;4   VERTEX_BUFFER_SIZE = 4000; //静态缓冲区的大小基本参数

上面这个过程在D3D编程里面,大家应该很熟悉了,定义顶点结构、定义FVF常量结构。
接着应该是创建顶点缓冲和索引缓冲,HGE定义的是静态缓冲,也就是说缓冲区是在显示卡内存里面的。
继续看它创建缓冲区的代码:
其实这部分是非常关键和重要的,直接影响到引擎的性能。
  1.   1 function THGEImpl.InitLost: Boolean;  //接口的子类实现部分
  2.   2 var
  3.   3   Target: IInternalTarget;
  4.   4   PIndices: PWord;
  5.   5   N: Word;
  6.   6   I: Integer;
  7.   7 begin
  8.   8   Result := False;
  9.   9
  10. 10 // Store render target
  11. 11
  12. 12   FScreenSurf := nil;
  13. 13   FScreenDepth := nil;
  14. 14
  15. 15   {$IFDEF HGE_DX8}
  16. 16   FD3DDevice.GetRenderTarget(FScreenSurf);
  17. 17   {$ELSE}
  18. 18   FD3DDevice.GetRenderTarget(0,FScreenSurf);
  19. 19   {$ENDIF}
  20. 20   FD3DDevice.GetDepthStencilSurface(FScreenDepth);
  21. 21
  22. 22   for I := 0 to FTargets.Count - 1 do begin
  23. 23     Target := IInternalTarget(FTargets[I]);
  24. 24     Target.Lost;
  25. 25   end;
  26. 26
  27. 27 // Create Vertex buffer     
  28. 28   {$IFDEF HGE_DX8}
  29. 29   if (Failed(FD3DDevice.CreateVertexBuffer(VERTEX_BUFFER_SIZE * SizeOf(THGEVertex),
  30. 30     D3DUSAGE_WRITEONLY,D3DFVF_HGEVERTEX,D3DPOOL_DEFAULT,FVB)))
  31. 31   {$ELSE}//这些是DX9部分
  32. 32   if (Failed(FD3DDevice.CreateVertexBuffer(VERTEX_BUFFER_SIZE * SizeOf(THGEVertex),
  33. 33     D3DUSAGE_WRITEONLY,D3DFVF_HGEVERTEX,D3DPOOL_DEFAULT,FVB,nil)))
  34. 34
  35. 35 //D3DUSAGE_WRITEONLY指定应用程序只能写缓存。它允许驱动程序分配最适合的内存地址作为写缓存。注意如果从创建好的这种缓存中读数据,将会返回错误信息。
  36. 36
  37. 37
  38. 38   {$ENDIF}
  39. 39   then begin
  40. 40     PostError('Can''t create D3D vertex buffer');
  41. 41     Exit;
  42. 42   end;
  43. 43
  44. 44   {$IFDEF HGE_DX8}
  45. 45   FD3DDevice.SetVertexShader(D3DFVF_HGEVERTEX);
  46. 46   FD3DDevice.SetStreamSource(0,FVB,SizeOf(THGEVertex));
  47. 47   {$ELSE}//这些是DX9部分
  48. 48   FD3DDevice.SetVertexShader(nil);
  49. 49   FD3DDevice.SetFVF(D3DFVF_HGEVERTEX);
  50. 50   FD3DDevice.SetStreamSource(0,FVB,0,SizeOf(THGEVertex));
  51. 51   {$ENDIF}
  52. 52
  53. 53 // Create and setup Index buffer
  54. 54
  55. 55   {$IFDEF HGE_DX8}
  56. 56   if (Failed(FD3DDevice.CreateIndexBuffer(VERTEX_BUFFER_SIZE * 6 div 4 * SizeOf(Word),
  57. 57     D3DUSAGE_WRITEONLY,D3DFMT_INDEX16,D3DPOOL_DEFAULT,FIB)))
  58. 58   {$ELSE}//这些是DX9部分
  59. 59   if (Failed(FD3DDevice.CreateIndexBuffer(VERTEX_BUFFER_SIZE * 6 div 4 * SizeOf(Word),
  60. 60     D3DUSAGE_WRITEONLY,D3DFMT_INDEX16,D3DPOOL_DEFAULT,FIB,nil)))
  61. 61   {$ENDIF}
  62. 62   then begin
  63. 63     PostError('Can''t create D3D index buffer');
  64. 64     Exit;
  65. 65   end;
  66. 66
  67. 67   N := 0;
  68. 68   {$IFDEF HGE_DX8}
  69. 69   if (Failed(FIB.Lock(0,0,PByte(PIndices),0))) then
  70. 70   {$ELSE}//这些是DX9部分
  71. 71   if (Failed(FIB.Lock(0,0,Pointer(PIndices),0))) then
  72. 72   {$ENDIF}
  73. 73   begin
  74. 74     PostError('Can''t lock D3D index buffer');
  75. 75     Exit;
  76. 76   end;
  77. 77
  78. 78   for I := 0 to (VERTEX_BUFFER_SIZE div 4) - 1 do begin
  79. 79     PIndices^ := N  ; Inc(PIndices);
  80. 80     PIndices^ := N+1; Inc(PIndices);
  81. 81     PIndices^ := N+2; Inc(PIndices);
  82. 82     PIndices^ := N+2; Inc(PIndices);
  83. 83     PIndices^ := N+3; Inc(PIndices);
  84. 84     PIndices^ := N;   Inc(PIndices);
  85. 85     Inc(N,4);
  86. 86   end;
  87. 87
  88. 88   FIB.Unlock;
  89. 89   {$IFDEF HGE_DX8}
  90. 90   FD3DDevice.SetIndices(FIB,0);
  91. 91   {$ELSE}//这些是DX9部分
  92. 92   FD3DDevice.SetIndices(FIB);
  93. 93   {$ENDIF}
  94. 94
  95. 95 // Set common render states
  96. 96
  97. 97   //pD3DDevice->SetRenderState( D3DRS_LASTPIXEL, FALSE );  ignore this
  98. 98   FD3DDevice.SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE);
  99. 99   FD3DDevice.SetRenderState(D3DRS_LIGHTING,0);
  100. 100
  101. 101   FD3DDevice.SetRenderState(D3DRS_ALPHABLENDENABLE,1);
  102. 102   FD3DDevice.SetRenderState(D3DRS_SRCBLEND,D3DBLEND_SRCALPHA);
  103. 103   FD3DDevice.SetRenderState(D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA);
  104. 104
  105. 105   FD3DDevice.SetRenderState(D3DRS_ALPHATESTENABLE,1);
  106. 106   FD3DDevice.SetRenderState(D3DRS_ALPHAREF,1);
  107. 107   FD3DDevice.SetRenderState(D3DRS_ALPHAFUNC,D3DCMP_GREATEREQUAL);
  108. 108
  109. 109   FD3DDevice.SetTextureStageState(0,D3DTSS_COLOROP,  D3DTOP_MODULATE);
  110. 110   FD3DDevice.SetTextureStageState(0,D3DTSS_COLORARG1,D3DTA_TEXTURE);
  111. 111   FD3DDevice.SetTextureStageState(0,D3DTSS_COLORARG2,D3DTA_DIFFUSE);
  112. 112
  113. 113   FD3DDevice.SetTextureStageState(0,D3DTSS_ALPHAOP,  D3DTOP_MODULATE);
  114. 114   FD3DDevice.SetTextureStageState(0,D3DTSS_ALPHAARG1,D3DTA_TEXTURE);
  115. 115   FD3DDevice.SetTextureStageState(0,D3DTSS_ALPHAARG2,D3DTA_DIFFUSE);
  116. 116
  117. 117   {$IFDEF HGE_DX8}
  118. 118   FD3DDevice.SetTextureStageState(0,D3DTSS_MIPFILTER, D3DTEXF_POINT);
  119. 119   {$ELSE}//这些是DX9部分
  120. 120   FD3DDevice.SetSamplerState(0,D3DSAMP_MIPFILTER, D3DTEXF_POINT);
  121. 121   {$ENDIF}
  122. 122
  123. 123   if (FTextureFilter) then begin
  124. 124     {$IFDEF HGE_DX8}
  125. 125     FD3DDevice.SetTextureStageState(0,D3DTSS_MAGFILTER,D3DTEXF_LINEAR);
  126. 126     FD3DDevice.SetTextureStageState(0,D3DTSS_MINFILTER,D3DTEXF_LINEAR);
  127. 127     {$ELSE}//这些是DX9部分
  128. 128     FD3DDevice.SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_LINEAR);
  129. 129     FD3DDevice.SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_LINEAR);
  130. 130     {$ENDIF}
  131. 131   end else begin
  132. 132     {$IFDEF HGE_DX8}
  133. 133     FD3DDevice.SetTextureStageState(0,D3DTSS_MAGFILTER,D3DTEXF_POINT);
  134. 134     FD3DDevice.SetTextureStageState(0,D3DTSS_MINFILTER,D3DTEXF_POINT);
  135. 135     {$ELSE}//这些是DX9部分
  136. 136     FD3DDevice.SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_POINT);
  137. 137     FD3DDevice.SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_POINT);
  138. 138     {$ENDIF}
  139. 139   end;
  140. 140
  141. 141   FPrim := 0;
  142. 142   FCurPrimType := HGEPRIM_QUADS;
  143. 143   FCurBlendMode := BLEND_DEFAULT;
  144. 144   FCurTexture := nil;
  145. 145
  146. 146   FD3DDevice.SetTransform(D3DTS_VIEW,FMatView);
  147. 147   FD3DDevice.SetTransform(D3DTS_PROJECTION,FMatProj);
  148. 148
  149. 149   Result := True;
  150. 150 end;
复制代码
这份代码是HGE包含DX9的,其实很不好,DX9跟DX8在一些方面是不兼容。
显然顶点缓冲区是只写属性,因为最后是从索引缓冲里面读取数据。
这个顶点缓冲的大小是固定的,很难说够不够用。如果不够用怎么办?还没有看到这部分的代码在那里。
或者说,根本没有完全使用完整个顶点缓冲区的容量。
下面再看看他的代码:
  1. 1 function THGEImpl.Gfx_BeginScene(const Target: ITarget): Boolean;
  2. 2 var
  3. 3   {$IFDEF HGE_DX8}
  4. 4   Surf, Depth: IDirect3DSurface8;
  5. 5   {$ELSE}
  6. 6   Surf, Depth: IDirect3DSurface9;
  7. 7   {$ENDIF}
  8. 8   HR: HResult;
  9. 9 begin
  10. 10   Result := False;
  11. 11
  12. 12   HR := FD3DDevice.TestCooperativeLevel;
  13. 13   if (HR = D3DERR_DEVICELOST) then
  14. 14     Exit;
  15. 15   if (HR = D3DERR_DEVICENOTRESET) then
  16. 16     if (not GfxRestore) then
  17. 17       Exit;
  18. 18
  19. 19   if Assigned(FVertArray) then begin
  20. 20     PostError('Gfx_BeginScene: Scene is already being rendered');
  21. 21     Exit;
  22. 22   end;
  23. 23
  24. 24   if (Target <> FCurTarget) then begin
  25. 25     if Assigned(Target) then begin
  26. 26       Target.Tex.Handle.GetSurfaceLevel(0,Surf);
  27. 27       Depth := (Target as IInternalTarget).Depth;
  28. 28     end else begin
  29. 29       Surf := FScreenSurf;
  30. 30       Depth := FScreenDepth;
  31. 31     end;
  32. 32
  33. 33     {$IFDEF HGE_DX8}
  34. 34     if (Failed(FD3DDevice.SetRenderTarget(Surf,Depth)))
  35. 35     {$ELSE}
  36. 36     if (Failed(FD3DDevice.SetRenderTarget(0,Surf)))
  37. 37     {$ENDIF}
  38. 38     then begin
  39. 39       PostError('Gfx_BeginScene: Can''t set render target');
  40. 40       Exit;
  41. 41     end;
  42. 42     if Assigned(Target) then begin
  43. 43       Surf := nil;
  44. 44       if Assigned((Target as IInternalTarget).Depth) then
  45. 45         FD3DDevice.SetRenderState(D3DRS_ZENABLE,D3DZB_TRUE)
  46. 46       else
  47. 47         FD3DDevice.SetRenderState(D3DRS_ZENABLE,D3DZB_FALSE);
  48. 48       SetProjectionMatrix(Target.Width,Target.Height);
  49. 49     end else begin
  50. 50       if (FZBuffer) then
  51. 51         FD3DDevice.SetRenderState(D3DRS_ZENABLE,D3DZB_TRUE)
  52. 52       else
  53. 53         FD3DDevice.SetRenderState(D3DRS_ZENABLE,D3DZB_FALSE);
  54. 54       SetProjectionMatrix(FScreenWidth,FScreenHeight);
  55. 55     end;
  56. 56
  57. 57     FD3DDevice.SetTransform(D3DTS_PROJECTION,FMatProj);
  58. 58     D3DXMatrixIdentity(FMatView);
  59. 59     FD3DDevice.SetTransform(D3DTS_VIEW,FMatView);
  60. 60
  61. 61     FCurTarget := Target;
  62. 62   end;
  63. 63   FD3DDevice.BeginScene;
  64. 64   {$IFDEF HGE_DX8}
  65. 65   FVB.Lock(0,0,PByte(FVertArray),0);
  66. 66   {$ELSE}
  67. 67   FVB.Lock(0,0,Pointer(FVertArray),0);
  68. 68   {$ENDIF}
  69. 69   Result := True;
  70. 70 end;
复制代码

应该看到了,这个是HGE每一帧里面需要调用的开始渲染函数。
在每一帧开始的时候就锁定顶点缓冲,然后把数据拷贝进缓冲区里面。
那么我们了解到的情况是:经常对静态缓冲加解锁是不明智的,因为只有等驱动完成了所有挂起的命令之后才能返回该缓冲的指针。如果经常这样做,这会导致CPU和GPU很多不必要的同步,这样性能将会变得很差。
何况是每一帧开始之后才填充数据,这种方式跟以前的DDRAW7的绘图模式完全是一样的。
  1. procedure THGEImpl.Gfx_EndScene;
  2. begin
  3.   RenderBatch(True);
  4.   FD3DDevice.EndScene;
  5.   if (FCurTarget = nil) then
  6.     FD3DDevice.Present(nil,nil,0,nil);
  7. end;
复制代码
结束渲染之前调用了一次RenderBatch函数,并且传入参数为True。
看看这个函数的功能:
  1. procedure THGEImpl.RenderBatch(const EndScene: Boolean);
  2. begin
  3.   if Assigned(FVertArray) then begin
  4.     FVB.Unlock;
  5.     if (FPrim <> 0) then begin
  6.       case FCurPrimType of
  7.         HGEPRIM_QUADS:
  8.           {$IFDEF HGE_DX8}                     
  9.           FD3DDevice.DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,FPrim shl 2,0,FPrim shl 1);
  10.           {$ELSE}
  11.           FD3DDevice.DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,FPrim shl 2,0,FPrim shl 1);
  12.           {$ENDIF}
  13.         HGEPRIM_TRIPLES:
  14.           FD3DDevice.DrawPrimitive(D3DPT_TRIANGLELIST,0,FPrim);
  15.         HGEPRIM_LINES:
  16.           FD3DDevice.DrawPrimitive(D3DPT_LINELIST,0,FPrim);
  17.       end;

  18.       FPrim := 0;       //绘制完毕,清零了,好像不用累计
  19.     end;

  20.     if (EndScene) then        //结束渲染之前执行
  21.       FVertArray := nil      
  22.     else
  23.       {$IFDEF HGE_DX8}
  24.       FVB.Lock(0,0,PByte(FVertArray),0);
  25.       {$ELSE}
  26.       FVB.Lock(0,0,Pointer(FVertArray),0);  //常规的做法,我们是使用一个无类型指针,这里他使用的是FVertArray这样的指针
  27.       {$ENDIF}
  28.   end;
  29. end;
复制代码
1 FVertArray: PHGEVertexArray;
这个函数是创建精灵的时候,需要调用的函数,也是其它单元经常调用的。
  1. 1 procedure THGEImpl.Gfx_RenderQuad(const Quad: THGEQuad);
  2. 2 begin
  3. 3   if Assigned(FVertArray) then begin
  4. 4     if (FCurPrimType <> HGEPRIM_QUADS)
  5. 5       or (FPrim >= VERTEX_BUFFER_SIZE div HGEPRIM_QUADS)
  6. 6       or (FCurTexture <> Quad.Tex)
  7. 7       or (FCurBlendMode <> Quad.Blend)
  8. 8     then begin
  9. 9       RenderBatch;
  10. 10       FCurPrimType := HGEPRIM_QUADS;
  11. 11       if (FCurBlendMode <> Quad.Blend) then
  12. 12         SetBlendMode(Quad.Blend);
  13. 13       if (Quad.Tex <> FCurTexture) then begin
  14. 14         if Assigned(Quad.Tex) then
  15. 15           FD3DDevice.SetTexture(0,Quad.Tex.Handle)
  16. 16         else
  17. 17           FD3DDevice.SetTexture(0,nil);
  18. 18         FCurTexture := Quad.Tex;
  19. 19       end;
  20. 20     end;
  21. 21
  22. 22     Move(Quad.V,FVertArray[FPrim * HGEPRIM_QUADS],
  23. 23       SizeOf(THGEVertex) * HGEPRIM_QUADS);
  24. 24     Inc(FPrim);
  25. 25   end;
  26. 26 end;
复制代码
这个函数的调用刚好处于开始渲染和结束渲染之间。Move把Quad的数据复制到顶点缓冲里面。要知道Quad结构的数据在被调用之前就已经填充好了。然后再复制入缓冲区里面。
就是说,从渲染开始到渲染结束,都是处于Lock锁定的状态下。所以很难看出HGE的绘图高效在那里。显然这样的渲染方式不适合大量绘制图元,更不用说应用于大型或者超大型网络游戏里面了。
因为锁定状态是按照默认锁定的,就是在GPU绘图这段时间里面,CPU就一直在等待之中,而且系统就处于挂起状态,如果是绘制大量图元呢,结果是可想而知的。
按照我们常规的逻辑,当引擎渲染开始之后,最理想的状态是,这个时候不必再去计算和处理各种数据或者是再锁定缓冲区去修改里面的数据,而是按照渲染序列,一次性批量地进行渲染。
说真的,我看了很久,看不出HGE能够胜任大型网络游戏的优点在那里。怎么看,都好像适合以前那些小型游戏开发。
网上的资料都是研究怎么去学习,还没有看到有人去研究它的实现代码结构方面。希望了解这个引擎的人说下。

好像也不对,看一段代码:
  1. 1 hge->Gfx_BeginScene();     //开始渲染,LOCK锁定缓冲区
  2. 2     bgspr->Render(0,0);    //第一次调用 FHGE.Gfx_RenderQuad(FQuad);
  3. 3     
  4. 4     for(i=0;i<nObjects;i++)
  5. 5     {
  6. 6         pObjects[i].x+=pObjects[i].dx*dt;
  7. 7         if(pObjects[i].x>SCREEN_WIDTH || pObjects[i].x<0) pObjects[i].dx=-pObjects[i].dx;
  8. 8         pObjects[i].y+=pObjects[i].dy*dt;
  9. 9         if(pObjects[i].y>SCREEN_HEIGHT || pObjects[i].y<0) pObjects[i].dy=-pObjects[i].dy;
  10. 10         pObjects[i].scale+=pObjects[i].dscale*dt;
  11. 11         if(pObjects[i].scale>2 || pObjects[i].scale<0.5) pObjects[i].dscale=-pObjects[i].dscale;
  12. 12         pObjects[i].rot+=pObjects[i].drot*dt;
  13. 13         
  14. 14         spr->SetColor(pObjects[i].color);
  15.            //循环调用 FHGE.Gfx_RenderQuad(FQuad);
  16. 15         spr->RenderEx(pObjects[i].x, pObjects[i].y, pObjects[i].rot, pObjects[i].scale);
  17. 16     }
  18. 17
  19. 18     fnt->printf(7,7,"UP and DOWN to adjust number of hares: %d\nSPACE to change blending mode: %d\nFPS: %d", nObjects, nBlend, hge->Timer_GetFPS());
  20. 19     hge->Gfx_EndScene();   //解锁缓冲区,结束渲染
复制代码
  1. int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)  //程序入口

  2. ``````````````
  3.         fnt=new hgeFont("font2.fnt");
  4.         spr=new hgeSprite(tex,0,0,64,64);
  5.         spr->SetHotSpot(32,32);              //在这里生成一个矩形





  6. ------------------------------------------

  7. procedure THGESprite.Render(const X, Y: Single);
  8. var
  9.   TempX1, TempY1, TempX2, TempY2: Single;
  10. begin
  11.   TempX1 := X - FHotX;
  12.   TempY1 := Y - FHotY;
  13.   TempX2 := X + FWidth - FHotX;
  14.   TempY2 := Y + FHeight - FHotY;

  15.   FQuad.V[0].X := TempX1; FQuad.V[0].Y := TempY1;
  16.   FQuad.V[1].X := TempX2; FQuad.V[1].Y := TempY1;
  17.   FQuad.V[2].X := TempX2; FQuad.V[2].Y := TempY2;
  18.   FQuad.V[3].X := TempX1; FQuad.V[3].Y := TempY2;

  19.   FHGE.Gfx_RenderQuad(FQuad);
  20. end;


  21. procedure THGESprite.SetHotSpot(const X, Y: Single);
  22. begin
  23.   FHotX := X;
  24.   FHotY := Y;
  25. end;
复制代码
显然在锁定缓冲区的同时,进行各种运算生成数据,然后批量地进行绘制图元。从流程可以看出来,第一次生成——就是说初次复制到缓冲区的数据是不被立即渲染,而是在第二次生成数据并且调用Gfx_RenderQuad这个函数的时候,才被渲染。也就是上一次的数据放到下一次进行渲染,这样形成了一个延迟渲染的流程。显然这些针对的是批量渲染算法。

显然它只需要锁定一次缓冲区,就可以批量地绘制大量的图元,同时它不需要等到把所有的数据填充入缓冲区之后,再批量地绘制。好像比较适合数据量大的情况,当然这些对于绘制二维图元来说,应该说是足够了。
解决方案在另一个帖子里面。

相关帖子

扫码关注微信公众号,及时获取最新资源信息!下载附件优惠VIP会员6折;永久VIP4折
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

免责声明:
1、本站提供的所有资源仅供参考学习使用,版权归原著所有,禁止下载本站资源参与商业和非法行为,请在24小时之内自行删除!
2、本站所有内容均由互联网收集整理、网友上传,并且以计算机技术研究交流为目的,仅供大家参考、学习,请勿任何商业目的与商业用途。
3、若您需要商业运营或用于其他商业活动,请您购买正版授权并合法使用。
4、论坛的所有内容都不保证其准确性,完整性,有效性,由于源码具有复制性,一经售出,概不退换。阅读本站内容因误导等因素而造成的损失本站不承担连带责任。
5、用户使用本网站必须遵守适用的法律法规,对于用户违法使用本站非法运营而引起的一切责任,由用户自行承担
6、本站所有资源来自互联网转载,版权归原著所有,用户访问和使用本站的条件是必须接受本站“免责声明”,如果不遵守,请勿访问或使用本网站
7、本站使用者因为违反本声明的规定而触犯中华人民共和国法律的,一切后果自己负责,本站不承担任何责任。
8、凡以任何方式登陆本网站或直接、间接使用本网站资料者,视为自愿接受本网站声明的约束。
9、本站以《2013 中华人民共和国计算机软件保护条例》第二章 “软件著作权” 第十七条为原则:为了学习和研究软件内含的设计思想和原理,通过安装、显示、传输或者存储软件等方式使用软件的,可以不经软件著作权人许可,不向其支付报酬。若有学员需要商用本站资源,请务必联系版权方购买正版授权!
10、本网站如无意中侵犯了某个企业或个人的知识产权,请来信【站长信箱312337667@qq.com】告之,本站将立即删除。
郑重声明:
本站所有资源仅供用户本地电脑学习源代码的内含设计思想和原理,禁止任何其他用途!
本站所有资源、教程来自互联网转载,仅供学习交流,不得商业运营资源,不确保资源完整性,图片和资源仅供参考,不提供任何技术服务。
本站资源仅供本地编辑研究学习参考,禁止未经资源商正版授权参与任何商业行为,违法行为!如需商业请购买各资源商正版授权
本站仅收集资源,提供用户自学研究使用,本站不存在私自接受协助用户架设游戏或资源,非法运营资源行为。
 
在线客服
点击这里给我发消息 点击这里给我发消息 点击这里给我发消息
售前咨询热线
312337667

微信扫一扫,私享最新原创实用干货

QQ|免责声明|小黑屋|依星资源网 ( 鲁ICP备2021043233号-3 )|网站地图

GMT+8, 2025-1-24 19:33

Powered by Net188.com X3.4

邮箱:312337667@qq.com 客服QQ:312337667(工作时间:9:00~21:00)

快速回复 返回顶部 返回列表