The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

256 lines
10KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-9 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. #include "../jucedemo_headers.h"
  19. #if JUCE_OPENGL
  20. //==============================================================================
  21. class DemoOpenGLCanvas : public OpenGLComponent,
  22. public Timer
  23. {
  24. public:
  25. DemoOpenGLCanvas()
  26. : OpenGLComponent (openGLDefault), rotation (0.0f),
  27. textScrollPos (200)
  28. {
  29. infoLabel.setText ("These sliders demonstrate how components can be added as children "
  30. "of an OpenGLComponent, in which case, their content will be rendered into "
  31. "an OpenGL framebuffer and efficiently overlaid onto your GL content.", false);
  32. infoLabel.setInterceptsMouseClicks (false, false);
  33. addAndMakeVisible (&infoLabel);
  34. infoLabel.setBounds ("parent.width * 0.05, bottom - 150, parent.width * 0.4, parent.height - 60");
  35. speedSlider.setRange (-10.0, 10.0, 0.1);
  36. speedSlider.setPopupMenuEnabled (true);
  37. speedSlider.setValue (Random::getSystemRandom().nextDouble() * 3.0, false, false);
  38. speedSlider.setSliderStyle (Slider::LinearHorizontal);
  39. speedSlider.setTextBoxStyle (Slider::TextBoxLeft, false, 80, 20);
  40. addAndMakeVisible (&speedSlider);
  41. speedSlider.setBounds ("parent.width * 0.05, parent.height - 65, parent.width * 0.6, top + 24");
  42. sizeSlider.setRange (0.2, 2.0, 0.01);
  43. sizeSlider.setPopupMenuEnabled (true);
  44. sizeSlider.setValue (Random::getSystemRandom().nextDouble() + 0.5, false, false);
  45. sizeSlider.setSliderStyle (Slider::LinearHorizontal);
  46. sizeSlider.setTextBoxStyle (Slider::TextBoxLeft, false, 80, 20);
  47. addAndMakeVisible (&sizeSlider);
  48. sizeSlider.setBounds ("parent.width * 0.05, parent.height - 35, parent.width * 0.6, top + 24");
  49. startTimer (1000 / 30);
  50. }
  51. ~DemoOpenGLCanvas()
  52. {
  53. stopRenderThread();
  54. }
  55. // when the component creates a new internal context, this is called, and
  56. // we'll use the opportunity to create some images to use as textures.
  57. void newOpenGLContextCreated()
  58. {
  59. logoImage = createLogoImage();
  60. dynamicTextureImage = Image (Image::ARGB, 128, 128, true, OpenGLImageType());
  61. }
  62. void releaseOpenGLContext()
  63. {
  64. // We have to make sure we release any openGL images before the
  65. // GL context gets closed..
  66. logoImage = Image::null;
  67. dynamicTextureImage = Image::null;
  68. }
  69. void mouseDown (const MouseEvent& e)
  70. {
  71. draggableOrientation.mouseDown (e.getPosition());
  72. }
  73. void mouseDrag (const MouseEvent& e)
  74. {
  75. draggableOrientation.mouseDrag (e.getPosition());
  76. triggerRepaint();
  77. }
  78. void resized()
  79. {
  80. draggableOrientation.setViewport (getLocalBounds());
  81. }
  82. void renderOpenGL()
  83. {
  84. OpenGLHelpers::clear (Colours::darkgrey.withAlpha (1.0f));
  85. updateTextureImage(); // this will update our dynamically-changing texture image.
  86. drawBackground2DStuff(); // draws some 2D content to demonstrate the OpenGLGraphicsContext class
  87. // Having used the juce 2D renderer, it will have messed-up a whole load of GL state, so
  88. // we'll put back any important settings before doing our normal GL 3D drawing..
  89. glEnable (GL_DEPTH_TEST);
  90. glDepthFunc (GL_LESS);
  91. glEnable (GL_BLEND);
  92. glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  93. glEnable (GL_TEXTURE_2D);
  94. #if JUCE_USE_OPENGL_FIXED_FUNCTION
  95. OpenGLHelpers::prepareFor2D (getWidth(), getHeight());
  96. OpenGLHelpers::setPerspective (45.0, getWidth() / (double) getHeight(), 0.1, 100.0);
  97. glTranslatef (0.0f, 0.0f, -5.0f);
  98. draggableOrientation.applyToOpenGLMatrix();
  99. // logoImage and dynamicTextureImage are actually OpenGL images, so we can use this utility function to
  100. // extract the frame buffer which is their backing store, and use it directly.
  101. OpenGLFrameBuffer* tex1 = OpenGLImageType::getFrameBufferFrom (logoImage);
  102. OpenGLFrameBuffer* tex2 = OpenGLImageType::getFrameBufferFrom (dynamicTextureImage);
  103. jassert (tex1 != nullptr && tex2 != nullptr); // (this would mean that our images weren't created correctly)
  104. // This draws the sides of our spinning cube.
  105. // I've used some of the juce helper functions, but you can also just use normal GL calls here too.
  106. tex1->draw3D (-1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, Colours::white);
  107. tex1->draw3D (-1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, Colours::white);
  108. tex1->draw3D (-1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, Colours::white);
  109. tex2->draw3D (-1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, Colours::white);
  110. tex2->draw3D ( 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, Colours::white);
  111. tex2->draw3D (-1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, Colours::white);
  112. #endif
  113. }
  114. void updateTextureImage()
  115. {
  116. // This image is a special framebuffer-backed image, so when we draw to it, the context
  117. // will render directly into its framebuffer
  118. dynamicTextureImage.clear (dynamicTextureImage.getBounds(),
  119. Colours::red.withRotatedHue (fabsf (::sinf (rotation / 300.0f))).withAlpha (0.7f));
  120. Graphics g (dynamicTextureImage);
  121. g.setFont (dynamicTextureImage.getHeight() / 3.0f);
  122. g.setColour (Colours::black);
  123. drawScrollingMessage (g, dynamicTextureImage.getHeight() / 2);
  124. }
  125. void drawBackground2DStuff()
  126. {
  127. OpenGLGraphicsContext glRenderer (*this); // Create an OpenGLGraphicsContext that will draw into this GL window..
  128. Graphics g (&glRenderer); // ..and then wrap it in a normal Graphics object so we can draw with it.
  129. // This stuff just creates a spinning star shape and fills it..
  130. Path p;
  131. const float scale = getHeight() * 0.4f;
  132. p.addStar (Point<float> (getWidth() * 0.7f, getHeight() * 0.4f), 7,
  133. scale * (float) sizeSlider.getValue(), scale,
  134. rotation / 50.0f);
  135. g.setGradientFill (ColourGradient (Colours::green.withRotatedHue (fabsf (::sinf (rotation / 300.0f))),
  136. 0, 0,
  137. Colours::green.withRotatedHue (fabsf (::cosf (rotation / -431.0f))),
  138. 0, (float) getHeight(), false));
  139. g.fillPath (p);
  140. }
  141. void timerCallback()
  142. {
  143. rotation += (float) speedSlider.getValue();
  144. textScrollPos += 1.4f;
  145. triggerRepaint();
  146. }
  147. private:
  148. Image logoImage, dynamicTextureImage;
  149. float rotation, textScrollPos;
  150. Draggable3DOrientation draggableOrientation;
  151. Slider speedSlider, sizeSlider;
  152. Label infoLabel;
  153. // Functions to create a couple of images to use as textures..
  154. static Image createLogoImage()
  155. {
  156. Image image (Image::ARGB, 256, 256, true, OpenGLImageType());
  157. Graphics g (image);
  158. g.fillAll (Colours::lightgrey.withAlpha (0.8f));
  159. g.drawImageWithin (ImageFileFormat::loadFrom (BinaryData::juce_png, BinaryData::juce_pngSize),
  160. 0, 0, image.getWidth(), image.getHeight(), RectanglePlacement::stretchToFit);
  161. drawRandomStars (g, image.getWidth(), image.getHeight());
  162. return image;
  163. }
  164. static void drawRandomStars (Graphics& g, int w, int h)
  165. {
  166. Random r;
  167. for (int i = 10; --i >= 0;)
  168. {
  169. Path pp;
  170. pp.addStar (Point<float> (r.nextFloat() * w, r.nextFloat() * h), r.nextInt (8) + 3, 10.0f, 20.0f, 0.0f);
  171. g.setColour (Colours::pink.withAlpha (0.4f));
  172. g.fillPath (pp);
  173. }
  174. }
  175. void drawScrollingMessage (Graphics& g, int y) const
  176. {
  177. g.drawSingleLineText ("The background, foreground and texture are all being drawn using the OpenGLGraphicsContext class, which "
  178. "lets you use a standard JUCE 2D graphics context to render directly onto an OpenGL window or framebuffer... ",
  179. (int) -std::fmod (textScrollPos, 2500.0f), y);
  180. }
  181. };
  182. //==============================================================================
  183. class OpenGLDemo : public Component
  184. {
  185. public:
  186. OpenGLDemo()
  187. : Component ("OpenGL")
  188. {
  189. addAndMakeVisible (&canvas);
  190. }
  191. void resized()
  192. {
  193. canvas.setBounds (10, 10, getWidth() - 20, getHeight() - 50);
  194. }
  195. private:
  196. DemoOpenGLCanvas canvas;
  197. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OpenGLDemo);
  198. };
  199. //==============================================================================
  200. Component* createOpenGLDemo()
  201. {
  202. return new OpenGLDemo();
  203. }
  204. #endif