GXS.OutlineShader.pas 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. //
  2. // The graphics engine GLXEngine. The unit of GXScene for Delphi
  3. //
  4. unit GXS.OutlineShader;
  5. (*
  6. A simple shader that adds an outline to an object.
  7. Limitations:
  8. 1. Object can be transparent (color alpha < 1) if it doesn't
  9. overlap itself. Texture transparency doesn't work.
  10. 2. Doesn't work with objects (e.g. TgxFreeForm) having it's own
  11. color array.
  12. 3. Doesn't Works with visible backfaces.
  13. *)
  14. interface
  15. {$I Stage.Defines.inc}
  16. uses
  17. Winapi.OpenGL,
  18. Winapi.OpenGLext,
  19. System.Classes,
  20. GXS.Material,
  21. GXS.Color,
  22. GXS.RenderContextInfo,
  23. GXS.Context,
  24. GXS.State,
  25. Stage.TextureFormat;
  26. type
  27. TgxOutlineShader = class(TgxShader)
  28. private
  29. FPassCount: integer;
  30. FLineColor: TgxColor;
  31. FOutlineSmooth: Boolean;
  32. FOutlineWidth: Single;
  33. procedure SetOutlineWidth(v: single);
  34. procedure SetOutlineSmooth(v: boolean);
  35. protected
  36. procedure DoApply(var rci: TgxRenderContextInfo; Sender: TObject); override;
  37. function DoUnApply(var rci: TgxRenderContextInfo): Boolean; override;
  38. public
  39. constructor Create(AOwner: TComponent); override;
  40. destructor Destroy; override;
  41. published
  42. property LineColor: TgxColor read FLineColor write FLineColor;
  43. // Line smoothing control
  44. property LineSmooth: Boolean read FOutlineSmooth write SetOutlineSmooth
  45. default false;
  46. property LineWidth: Single read FOutlineWidth write SetOutlineWidth;
  47. end;
  48. // ------------------------------------------------------------------
  49. implementation
  50. // ------------------------------------------------------------------
  51. // ------------------
  52. // ------------------ TgxOutlineShader ------------------
  53. // ------------------
  54. constructor TgxOutlineShader.Create(AOwner: TComponent);
  55. begin
  56. inherited;
  57. FOutlineSmooth := False;
  58. FOutLineWidth := 2;
  59. FLineColor := TgxColor.CreateInitialized(Self, clrBlack);
  60. ShaderStyle := ssLowLevel;
  61. end;
  62. destructor TgxOutlineShader.Destroy;
  63. begin
  64. FLineColor.Free;
  65. inherited;
  66. end;
  67. procedure TgxOutlineShader.DoApply(var rci: TgxRenderContextInfo; Sender:
  68. TObject);
  69. begin
  70. // We first draw the object as usual in the first pass. This allows objects
  71. // with color alpha < 1 to be rendered correctly with outline.
  72. FPassCount := 1;
  73. end;
  74. function TgxOutlineShader.DoUnApply(var rci: TgxRenderContextInfo): Boolean;
  75. begin
  76. if rci.ignoreMaterials or (stStencilTest in rci.gxStates.States) then
  77. begin
  78. Result := False;
  79. Exit;
  80. end;
  81. case FPassCount of
  82. 1:
  83. with rci.gxStates do
  84. begin
  85. // Now set up to draw the outline in the second pass
  86. Disable(stLighting);
  87. if FOutlineSmooth then
  88. begin
  89. LineSmoothHint := hintNicest;
  90. Enable(stLineSmooth);
  91. end
  92. else
  93. Disable(stLineSmooth);
  94. if FOutlineSmooth or (FlineColor.Alpha < 1) then
  95. begin
  96. Enable(stBlend);
  97. SetBlendFunc(bfSrcAlpha, bfOneMinusSrcAlpha);
  98. end
  99. else
  100. Disable(stBlend);
  101. glColor4fv(@FlineColor.AsAddress^);
  102. LineWidth := FOutlineWidth;
  103. Disable(stLineStipple);
  104. PolygonMode := pmLines;
  105. CullFaceMode := cmFront;
  106. DepthFunc := cfLEqual;
  107. ActiveTextureEnabled[ttTexture2D] := False;
  108. FPassCount := 2;
  109. Result := True; // go for next pass
  110. end;
  111. 2:
  112. with rci.gxStates do
  113. begin
  114. // Restore settings
  115. PolygonMode := pmFill;
  116. CullFaceMode := cmBack;
  117. DepthFunc := cfLequal;
  118. Result := False; // we're done
  119. end;
  120. else
  121. Assert(False);
  122. Result := False;
  123. end;
  124. end;
  125. procedure TgxOutlineShader.SetOutlineWidth(v: single);
  126. begin
  127. if FOutlineWidth <> v then
  128. begin
  129. FOutlineWidth := v;
  130. NotifyChange(self);
  131. end;
  132. end;
  133. procedure TgxOutlineShader.SetOutlineSmooth(v: boolean);
  134. begin
  135. if FOutlineSmooth <> v then
  136. begin
  137. FOutlineSmooth := v;
  138. NotifyChange(self);
  139. end;
  140. end;
  141. end.