fMultipassC.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. //---------------------------------------------------------------------------
  2. /*: Simple TGLShader based multipass demo.
  3. This demo uses a custom TGLShader subclass to implement the classic
  4. multipass hidden lines rendering technique on a torus: first pass renders
  5. model with filled triangles, second pass does the wireframe.
  6. You'll also note the glPolygonOffset call, it displaces fragments depths
  7. value a little "farther away" so that surface fill depth values do not
  8. interact with the rendering of the lines (comment out the call and you'll
  9. see).
  10. The axis and sphere allow you to see the limit of that simple technique:
  11. it actually "paints" between the lines, so you cannot use it to make
  12. transparent wireframed objects with hidden lines - if that thought ever
  13. blossomed in your mind ;)
  14. Additionnal objects around the show a glow/toon edges effect achieved in two
  15. passes too: the 1st pass activate lines and gives them a width, the second
  16. is used to fill the surface (and clear the lines that aren't on edges).
  17. (TOutLineShader thanks to Delauney Jerome, [email protected])
  18. */
  19. #include <vcl.h>
  20. #pragma hdrstop
  21. #include "fMultipassC.h"
  22. #include <assert.h>
  23. //---------------------------------------------------------------------------
  24. #pragma package(smart_init)
  25. #pragma link "GLS.GeomObjects"
  26. #pragma link "GLS.Objects"
  27. #pragma link "GLS.Scene"
  28. #pragma link "GLS.Texture"
  29. #pragma link "GLS.SceneViewer"
  30. #pragma link "GLS.BaseClasses"
  31. #pragma link "GLS.Coordinates"
  32. #pragma link "GLS.Material"
  33. #pragma link "Stage.OpenGLTokens"
  34. #pragma resource "*.dfm"
  35. TForm1* Form1;
  36. //---------------------------------------------------------------------------
  37. __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) {}
  38. //---------------------------------------------------------------------------
  39. __fastcall THiddenLineShader::THiddenLineShader(TComponent* AOwner) :
  40. TGLShader(AOwner)
  41. {
  42. }
  43. //---------------------------------------------------------------------------
  44. __fastcall THiddenLineShader::~THiddenLineShader(void) {}
  45. //---------------------------------------------------------------------------
  46. void __fastcall THiddenLineShader::DoApply(
  47. TGLRenderContextInfo &rci, System::TObject* Sender)
  48. {
  49. // new object getting rendered, 1st pass
  50. PassCount = 1;
  51. // backup state
  52. glPushAttrib(GL_ENABLE_BIT);
  53. // disable lighting, this is a solid fill
  54. glDisable(GL_LIGHTING);
  55. rci.GLStates->PolygonMode = GL_FRONT_AND_BACK, GL_FILL;
  56. // use background color
  57. glColor3fv(&BackgroundColor.X);
  58. // enable and adjust polygon offset
  59. glEnable(GL_POLYGON_OFFSET_FILL);
  60. glPolygonOffset(1, 2);
  61. }
  62. //---------------------------------------------------------------------------
  63. bool __fastcall THiddenLineShader::DoUnApply(TGLRenderContextInfo &rci)
  64. {
  65. bool result;
  66. switch (PassCount) {
  67. case 1: {
  68. // 1st pass completed, we setup for the second
  69. PassCount = 2;
  70. // switch to wireframe and its color
  71. rci.GLStates->PolygonMode = GL_FRONT_AND_BACK, GL_LINE;
  72. glColor3fv(&LineColor.X);
  73. // disable polygon offset
  74. glDisable(GL_POLYGON_OFFSET_LINE);
  75. result = true;
  76. break;
  77. }
  78. case 2: {
  79. // restore state
  80. glPopAttrib();
  81. // we're done
  82. result = false;
  83. break;
  84. }
  85. default: {
  86. // doesn't hurt to be cautious
  87. assert(false);
  88. result = false;
  89. }
  90. }
  91. return result;
  92. }
  93. //---------------------------------------------------------------------------
  94. __fastcall TOutLineShader::TOutLineShader(TComponent* AOwner) :
  95. TGLShader(AOwner)
  96. {
  97. }
  98. //---------------------------------------------------------------------------
  99. __fastcall TOutLineShader::~TOutLineShader(void) {}
  100. //---------------------------------------------------------------------------
  101. void __fastcall TOutLineShader::DoApply(
  102. TGLRenderContextInfo &rci, System::TObject* Sender)
  103. {
  104. PassCount = 1;
  105. glPushAttrib(GL_ENABLE_BIT);
  106. glDisable(GL_LIGHTING);
  107. if (OutlineSmooth) {
  108. glEnable(GL_BLEND);
  109. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  110. glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
  111. glEnable(GL_LINE_SMOOTH);
  112. } else
  113. glDisable(GL_LINE_SMOOTH);
  114. glGetFloatv(GL_LINE_WIDTH, &OldlineWidth);
  115. glLineWidth(OutlineWidth);
  116. glPolygonMode(GL_BACK, GL_LINE);
  117. glCullFace(GL_FRONT);
  118. glDepthFunc(GL_LEQUAL);
  119. glColor3fv(&LineColor.X);
  120. }
  121. //---------------------------------------------------------------------------
  122. bool __fastcall TOutLineShader::DoUnApply(TGLRenderContextInfo &rci)
  123. {
  124. bool result;
  125. switch (PassCount) {
  126. case 1: {
  127. PassCount = 2;
  128. if (Lighting)
  129. glEnable(GL_LIGHTING);
  130. else
  131. glColor3fv(&BackgroundColor.X);
  132. glDepthFunc(GL_LESS);
  133. glCullFace(GL_BACK);
  134. glPolygonMode(GL_BACK, GL_FILL);
  135. result = true;
  136. break;
  137. }
  138. case 2: {
  139. glPopAttrib();
  140. glLineWidth(OldlineWidth);
  141. result = false;
  142. break;
  143. }
  144. default: {
  145. assert(false);
  146. result = false;
  147. }
  148. }
  149. return result;
  150. }
  151. //---------------------------------------------------------------------------
  152. void __fastcall TForm1::BUBindClick(TObject* Sender)
  153. {
  154. THiddenLineShader* shader1;
  155. TOutLineShader *shader2, *shader3;
  156. BUBind->Enabled = False;
  157. // instantiate our shaders
  158. shader1 = new THiddenLineShader(this);
  159. shader1->BackgroundColor =
  160. ConvertWinColor(GLSceneViewer1->Buffer->BackgroundColor, 0);
  161. shader1->LineColor = clrBlue;
  162. shader2 = new TOutLineShader(this);
  163. shader2->BackgroundColor =
  164. ConvertWinColor(GLSceneViewer1->Buffer->BackgroundColor, 0);
  165. shader2->OutlineSmooth = true;
  166. shader2->OutlineWidth = 2;
  167. shader2->Lighting = false;
  168. shader2->LineColor = clrBlack;
  169. shader3 = new TOutLineShader(this);
  170. shader3->BackgroundColor =
  171. ConvertWinColor(GLSceneViewer1->Buffer->BackgroundColor, 0);
  172. shader3->OutlineSmooth = false;
  173. shader3->OutlineWidth = 4;
  174. shader3->Lighting = true;
  175. shader3->LineColor = clrRed;
  176. // binds the shaders to the materials
  177. GLMaterialLibrary1->Materials->Items[0]->Shader = shader1;
  178. GLMaterialLibrary1->Materials->Items[1]->Shader = shader2;
  179. GLMaterialLibrary1->Materials->Items[2]->Shader = shader3;
  180. }
  181. //---------------------------------------------------------------------------
  182. void __fastcall TForm1::GLSceneViewer1MouseDown(
  183. TObject* Sender, TMouseButton Button, TShiftState Shift, int X, int Y)
  184. {
  185. mx = X;
  186. my = Y;
  187. }
  188. //---------------------------------------------------------------------------
  189. void __fastcall TForm1::GLSceneViewer1MouseMove(
  190. TObject* Sender, TShiftState Shift, int X, int Y)
  191. {
  192. if (Shift.Contains(ssLeft))
  193. GLCamera1->MoveAroundTarget(my - Y, mx - X);
  194. else if (Shift.Contains(ssRight))
  195. GLCamera1->RotateTarget(my - Y, mx - X, 0);
  196. mx = X;
  197. my = Y;
  198. }
  199. //---------------------------------------------------------------------------