fOcclusionQuery.pas 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. unit fOcclusionQuery;
  2. interface
  3. uses
  4. Winapi.OpenGL,
  5. System.SysUtils,
  6. System.Variants,
  7. System.Classes,
  8. System.UITypes,
  9. Vcl.Graphics,
  10. Vcl.Controls,
  11. Vcl.Forms,
  12. Vcl.Dialogs,
  13. Vcl.StdCtrls,
  14. Vcl.ExtCtrls,
  15. GLS.Scene,
  16. GLS.VectorTypes,
  17. GLS.GeomObjects,
  18. GLS.Objects,
  19. GLS.Cadencer,
  20. GLS.SceneViewer,
  21. GLS.Coordinates,
  22. GLS.BaseClasses,
  23. GLS.RenderContextInfo,
  24. GLS.Context;
  25. type
  26. TFormOcclusionQuery = class(TForm)
  27. GLScene1: TGLScene;
  28. GLSceneViewer1: TGLSceneViewer;
  29. GLCadencer1: TGLCadencer;
  30. GLCamera1: TGLCamera;
  31. GLCube1: TGLCube;
  32. GLCylinder1: TGLCylinder;
  33. GLDummyCube1: TGLDummyCube;
  34. OGLBeginQueries: TGLDirectOpenGL;
  35. dcTestObjects: TGLDummyCube;
  36. OGLEndQueries: TGLDirectOpenGL;
  37. GLTorus1: TGLTorus;
  38. GLLightSource1: TGLLightSource;
  39. GLDummyCube2: TGLDummyCube;
  40. GLCube2: TGLCube;
  41. Timer1: TTimer;
  42. Panel1: TPanel;
  43. Label1: TLabel;
  44. Label2: TLabel;
  45. Label3: TLabel;
  46. GLCone1: TGLCone;
  47. CheckBox1: TCheckBox;
  48. LabelFPS: TLabel;
  49. procedure OGLBeginQueriesRender(Sender: TObject;
  50. var rci: TGLRenderContextInfo);
  51. procedure OGLEndQueriesRender(Sender: TObject;
  52. var rci: TGLRenderContextInfo);
  53. procedure FormDestroy(Sender: TObject);
  54. procedure GLCadencer1Progress(Sender: TObject; const deltaTime,
  55. newTime: Double);
  56. procedure Timer1Timer(Sender: TObject);
  57. procedure GLSceneViewer1BeforeRender(Sender: TObject);
  58. private
  59. public
  60. end;
  61. var
  62. FormOcclusionQuery: TFormOcclusionQuery;
  63. TimerQuery: TGLTimerQueryHandle;
  64. OcclusionQuery: TGLOcclusionQueryHandle;
  65. bOcclusionQuery: TGLBooleanOcclusionQueryHandle;
  66. queriesCreated: boolean;
  67. timerQuerySupported: Boolean;
  68. timeTaken: Integer; // in nanoseconds
  69. samplesPassed: Integer;
  70. implementation
  71. {$R *.dfm}
  72. procedure TFormOcclusionQuery.FormDestroy(Sender: TObject);
  73. begin
  74. // Delete the queries
  75. TimerQuery.Free;
  76. OcclusionQuery.Free;
  77. bOcclusionQuery.Free;
  78. end;
  79. procedure TFormOcclusionQuery.GLCadencer1Progress(Sender: TObject; const deltaTime,
  80. newTime: Double);
  81. begin
  82. // Move some of the scene objects around
  83. GLDummyCube1.Position.X := Sin(newTime);
  84. dcTestObjects.Turn(DeltaTime * 50);
  85. dcTestObjects.Position.z := 2 * Sin(newTime);
  86. GLDummyCube2.Position.X := -sin(newTime);
  87. end;
  88. procedure TFormOcclusionQuery.GLSceneViewer1BeforeRender(Sender: TObject);
  89. begin
  90. // Occlusion queries are supported by extensions with lower version of OpenGL.
  91. // To use them, you'd need to check if GL_NV_occlusion_query or GL_ARB_occlusion_query
  92. // extensions are present, and makes the appropriate calls to the functions/procedures
  93. // they provide.
  94. if (not TGLOcclusionQueryHandle.IsSupported) then
  95. begin
  96. Messagedlg('Requires hardware that supports occlusion queries to run',
  97. mtError, [mbOK], 0);
  98. Close;
  99. end;
  100. end;
  101. procedure TFormOcclusionQuery.OGLBeginQueriesRender(Sender: TObject;
  102. var rci: TGLRenderContextInfo);
  103. begin
  104. // Generate the queries, if not already created
  105. if not queriesCreated then
  106. begin
  107. OcclusionQuery := TGLOcclusionQueryHandle.CreateAndAllocate();
  108. CheckBox1.Enabled := TGLBooleanOcclusionQueryHandle.IsSupported;
  109. if CheckBox1.Enabled then
  110. bOcclusionQuery := TGLBooleanOcclusionQueryHandle.CreateAndAllocate();
  111. timerQuerySupported := TGLTimerQueryHandle.IsSupported;
  112. if timerQuerySupported then
  113. TimerQuery := TGLTimerQueryHandle.CreateAndAllocate();
  114. queriesCreated := true;
  115. end;
  116. // Begin the timer + occlusion queries
  117. if timerQuerySupported then
  118. TimerQuery.BeginQuery;
  119. if CheckBox1.Checked then
  120. bOcclusionQuery.BeginQuery
  121. else
  122. OcclusionQuery.BeginQuery;
  123. end;
  124. procedure TFormOcclusionQuery.OGLEndQueriesRender(Sender: TObject;
  125. var rci: TGLRenderContextInfo);
  126. var
  127. lQuery: TGLQueryHandle;
  128. begin
  129. // End the timer + occlusion queries
  130. if CheckBox1.Checked then
  131. lQuery := bOcclusionQuery
  132. else
  133. lQuery := OcclusionQuery;
  134. lQuery.EndQuery;
  135. if timerQuerySupported then
  136. TimerQuery.EndQuery;
  137. // Most of the frame rate is lost waiting for results to become available
  138. // + updating the captions every frame, but as this is a demo, we want to
  139. // see what is going on.
  140. while not lQuery.IsResultAvailable do
  141. { wait }; // would normally do something in this period before checking if
  142. // result is available
  143. samplesPassed := OcclusionQuery.PixelCount;
  144. if timerQuerySupported then
  145. begin
  146. while not TimerQuery.IsResultAvailable do
  147. { wait }; // would normally do something in this period before checking if
  148. // result is available
  149. timeTaken := TimerQuery.Time;
  150. // Use this line instead of the one above to use 64 bit timer, to allow
  151. // recording time periods more than a couple of seconds (requires Delphi 7+)
  152. // timeTaken := TimerQuery.QueryResultUInt64;
  153. end;
  154. case CheckBox1.Checked of
  155. True:
  156. begin
  157. label3.Visible := not lQuery.QueryResultBool;
  158. end;
  159. False:
  160. begin
  161. label3.Visible := (samplesPassed = 0);
  162. label2.caption := 'Number of test pixels visible: ' + IntToStr(samplesPassed);
  163. end;
  164. end;
  165. end;
  166. procedure TFormOcclusionQuery.Timer1Timer(Sender: TObject);
  167. begin
  168. // Convert time taken from ns => ms & display
  169. if timerQuerySupported then
  170. label1.caption := 'Time taken: ' + FloatToSTr(timeTaken / 1000000) + ' ms'
  171. else
  172. label1.Caption := 'Time query unavailable, requires hardware support';
  173. LabelFPS.Caption := GLSceneViewer1.FramesPerSecondText(0);
  174. GLSceneViewer1.ResetPerformanceMonitor;
  175. end;
  176. end.