fMultiPass.pas 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. unit fMultiPass;
  2. interface
  3. uses
  4. Winapi.OpenGL,
  5. System.SysUtils,
  6. System.Classes,
  7. Vcl.Graphics,
  8. Vcl.Controls,
  9. Vcl.Forms,
  10. Vcl.Dialogs,
  11. Vcl.StdCtrls,
  12. GLS.Scene,
  13. GLS.Objects,
  14. GLS.SceneViewer,
  15. GLS.Texture,
  16. GLS.Context,
  17. GLS.GeomObjects,
  18. GLS.State,
  19. GLS.Color,
  20. GLS.Material,
  21. GLS.Coordinates,
  22. GLS.RenderContextInfo,
  23. GLS.BaseClasses;
  24. type
  25. TFormMultiPath = class(TForm)
  26. GLScene1: TGLScene;
  27. GLSceneViewer1: TGLSceneViewer;
  28. GLCamera1: TGLCamera;
  29. GLLightSource1: TGLLightSource;
  30. Torus1: TGLTorus;
  31. BUBind: TButton;
  32. Sphere1: TGLSphere;
  33. GLMaterialLibrary1: TGLMaterialLibrary;
  34. GLAnnulus1: TGLAnnulus;
  35. GLAnnulus2: TGLAnnulus;
  36. GLCube1: TGLCube;
  37. GLSphere1: TGLSphere;
  38. procedure BUBindClick(Sender: TObject);
  39. procedure GLSceneViewer1MouseDown(Sender: TObject;
  40. Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  41. procedure GLSceneViewer1MouseMove(Sender: TObject; Shift: TShiftState;
  42. X, Y: Integer);
  43. private
  44. public
  45. mx, my: Integer;
  46. end;
  47. var
  48. FormMultiPath: TFormMultiPath;
  49. implementation
  50. {$R *.dfm}
  51. type
  52. THiddenLineShader = class(TGLShader)
  53. private
  54. BackgroundColor, LineColor: TColorVector;
  55. PassCount: Integer;
  56. public
  57. procedure DoApply(var rci: TGLRenderContextInfo; Sender: TObject); override;
  58. function DoUnApply(var rci: TGLRenderContextInfo): Boolean; override;
  59. end;
  60. TOutLineShader = class(TGLShader)
  61. private
  62. BackgroundColor, LineColor: TColorVector;
  63. OutlineSmooth, Lighting: Boolean;
  64. OutlineWidth, Oldlinewidth: Single;
  65. PassCount: Integer;
  66. public
  67. procedure DoApply(var rci: TGLRenderContextInfo; Sender: TObject); override;
  68. function DoUnApply(var rci: TGLRenderContextInfo): Boolean; override;
  69. end;
  70. procedure THiddenLineShader.DoApply(var rci: TGLRenderContextInfo; Sender:
  71. TObject);
  72. begin
  73. // new object getting rendered, 1st pass
  74. PassCount := 1;
  75. with rci.GLStates do
  76. begin
  77. // disable lighting, this is a solid fill
  78. Disable(stLighting);
  79. PolygonMode := pmFill;
  80. // use background color
  81. gl.Color3fv(@BackgroundColor);
  82. // enable and adjust polygon offset
  83. Enable(stPolygonOffsetFill);
  84. SetPolygonOffset(1, 2);
  85. end;
  86. end;
  87. function THiddenLineShader.DoUnApply(var rci: TGLRenderContextInfo): Boolean;
  88. begin
  89. case PassCount of
  90. 1:
  91. with rci.GLStates do
  92. begin
  93. // 1st pass completed, we setup for the second
  94. PassCount := 2;
  95. // switch to wireframe and its color
  96. PolygonMode := pmLines;
  97. Disable(stPolygonOffsetLine);
  98. Disable(stLineStipple);
  99. Disable(stLineSmooth);
  100. LineWidth := 1;
  101. gl.Color3fv(@LineColor);
  102. Result := True;
  103. end;
  104. 2:
  105. with rci.GLStates do
  106. begin
  107. // restore state
  108. PolygonMode := pmFill;
  109. Disable(stPolygonOffsetFill);
  110. // we're done
  111. Result := False;
  112. end;
  113. else
  114. // doesn't hurt to be cautious
  115. Assert(False);
  116. Result := False;
  117. end;
  118. end;
  119. procedure TOutLineShader.DoApply(var rci: TGLRenderContextInfo; Sender: TObject);
  120. begin
  121. PassCount := 1;
  122. with rci.GLStates do
  123. begin
  124. Disable(stLighting);
  125. if outlineSmooth then
  126. begin
  127. Enable(stBlend);
  128. SetBlendFunc(bfSrcAlpha, bfOneMinusSrcAlpha);
  129. LineSmoothHint := hintNicest;
  130. Enable(stLineSmooth);
  131. end
  132. else
  133. Disable(stLineSmooth);
  134. LineStippleFactor := 1;
  135. LineStipplePattern := $FFFF;
  136. LineWidth := OutLineWidth;
  137. PolygonMode := pmLines;
  138. CullFaceMode := cmFront;
  139. DepthFunc := cfLEqual;
  140. gl.Color3fv(@lineColor);
  141. end;
  142. end;
  143. function TOutLineShader.DoUnApply(var rci: TGLRenderContextInfo): Boolean;
  144. begin
  145. case PassCount of
  146. 1:
  147. with rci.GLStates do
  148. begin
  149. PassCount := 2;
  150. if lighting then
  151. Enable(stLighting)
  152. else
  153. gl.Color3fv(@backGroundColor);
  154. DepthFunc := cfLess;
  155. PolygonMode := pmFill;
  156. CullFaceMode := cmBack;
  157. Result := True;
  158. end;
  159. 2:
  160. begin
  161. Result := False;
  162. end;
  163. else
  164. Assert(False);
  165. Result := False;
  166. end;
  167. end;
  168. procedure TFormMultiPath.BUBindClick(Sender: TObject);
  169. var
  170. shader1: THiddenLineShader;
  171. shader2, shader3: TOutLineShader;
  172. begin
  173. BUBind.Enabled := False;
  174. // instantiate our shaders
  175. shader1 := THiddenLineShader.Create(Self);
  176. shader1.BackgroundColor :=
  177. ConvertWinColor(GLSceneViewer1.Buffer.BackgroundColor);
  178. shader1.LineColor := clrBlue;
  179. shader2 := TOutLineShader.Create(Self);
  180. with shader2 do
  181. begin
  182. BackgroundColor := ConvertWinColor(GLSceneViewer1.Buffer.BackgroundColor);
  183. Outlinesmooth := true;
  184. OutLineWidth := 2;
  185. Lighting := false;
  186. LineColor := clrBlack;
  187. end;
  188. shader3 := TOutLineShader.Create(Self);
  189. with shader3 do
  190. begin
  191. BackgroundColor := ConvertWinColor(GLSceneViewer1.Buffer.BackgroundColor);
  192. Outlinesmooth := false;
  193. OutLineWidth := 4;
  194. Lighting := true;
  195. LineColor := clrRed;
  196. end;
  197. // binds the shaders to the materials
  198. GLMaterialLibrary1.Materials[0].Shader := shader1;
  199. GLMaterialLibrary1.Materials[1].Shader := shader2;
  200. GLMaterialLibrary1.Materials[2].Shader := shader3;
  201. end;
  202. //
  203. // Classic mouse movement bits
  204. //
  205. procedure TFormMultiPath.GLSceneViewer1MouseDown(Sender: TObject;
  206. Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  207. begin
  208. mx := x;
  209. my := y;
  210. end;
  211. procedure TFormMultiPath.GLSceneViewer1MouseMove(Sender: TObject;
  212. Shift: TShiftState; X, Y: Integer);
  213. begin
  214. if Shift = [ssLeft] then
  215. GLCamera1.MoveAroundTarget(my - y, mx - x)
  216. else if Shift = [ssRight] then
  217. GLCamera1.RotateTarget(my - y, mx - x);
  218. mx := x;
  219. my := y;
  220. end;
  221. end.