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.

250 lines
8.4KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-12 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 "../JuceDemoHeader.h"
  19. #if JUCE_OPENGL
  20. //==============================================================================
  21. class OpenGL2DShaderDemo : public Component,
  22. private CodeDocument::Listener,
  23. private ComboBox::Listener,
  24. private Timer
  25. {
  26. public:
  27. OpenGL2DShaderDemo()
  28. : fragmentEditorComp (fragmentDocument, nullptr)
  29. {
  30. setOpaque (true);
  31. MainAppWindow::getMainAppWindow()->setOpenGLRenderingEngine();
  32. addAndMakeVisible (statusLabel);
  33. statusLabel.setJustificationType (Justification::topLeft);
  34. statusLabel.setColour (Label::textColourId, Colours::black);
  35. statusLabel.setFont (Font (14.0f));
  36. Array<ShaderPreset> presets (getPresets());
  37. StringArray presetNames;
  38. for (int i = 0; i < presets.size(); ++i)
  39. presetBox.addItem (presets[i].name, i + 1);
  40. addAndMakeVisible (presetLabel);
  41. presetLabel.setText ("Shader Preset:", dontSendNotification);
  42. presetLabel.attachToComponent (&presetBox, true);
  43. addAndMakeVisible (presetBox);
  44. presetBox.addListener (this);
  45. Colour editorBackground (Colours::white.withAlpha (0.6f));
  46. fragmentEditorComp.setColour (CodeEditorComponent::backgroundColourId, editorBackground);
  47. fragmentEditorComp.setOpaque (false);
  48. fragmentDocument.addListener (this);
  49. addAndMakeVisible (fragmentEditorComp);
  50. presetBox.setSelectedItemIndex (0);
  51. }
  52. ~OpenGL2DShaderDemo()
  53. {
  54. shader = nullptr;
  55. }
  56. void paint (Graphics& g)
  57. {
  58. g.fillCheckerBoard (getLocalBounds(), 48, 48, Colours::lightgrey, Colours::white);
  59. if (shader == nullptr || shader->getFragmentShaderCode() != fragmentCode)
  60. {
  61. shader = nullptr;
  62. if (fragmentCode.isNotEmpty())
  63. {
  64. shader = new OpenGLGraphicsContextCustomShader (fragmentCode);
  65. Result result (shader->checkCompilation (g.getInternalContext()));
  66. if (result.failed())
  67. {
  68. statusLabel.setText (result.getErrorMessage(), dontSendNotification);
  69. shader = nullptr;
  70. }
  71. }
  72. }
  73. if (shader != nullptr)
  74. {
  75. statusLabel.setText (String::empty, dontSendNotification);
  76. shader->fillRect (g.getInternalContext(), getLocalBounds());
  77. }
  78. }
  79. void resized() override
  80. {
  81. Rectangle<int> area (getLocalBounds().reduced (4));
  82. statusLabel.setBounds (area.removeFromTop (75));
  83. area.removeFromTop (area.getHeight() / 2);
  84. Rectangle<int> presets (area.removeFromTop (25));
  85. presets.removeFromLeft (100);
  86. presetBox.setBounds (presets.removeFromLeft (150));
  87. area.removeFromTop (4);
  88. fragmentEditorComp.setBounds (area);
  89. }
  90. void selectPreset (int preset)
  91. {
  92. fragmentDocument.replaceAllContent (getPresets()[preset].fragmentShader);
  93. startTimer (1);
  94. }
  95. ScopedPointer<OpenGLGraphicsContextCustomShader> shader;
  96. Label statusLabel, presetLabel;
  97. ComboBox presetBox;
  98. CodeDocument fragmentDocument;
  99. CodeEditorComponent fragmentEditorComp;
  100. String fragmentCode;
  101. private:
  102. enum { shaderLinkDelay = 500 };
  103. void codeDocumentTextInserted (const String& /*newText*/, int /*insertIndex*/) override
  104. {
  105. startTimer (shaderLinkDelay);
  106. }
  107. void codeDocumentTextDeleted (int /*startIndex*/, int /*endIndex*/) override
  108. {
  109. startTimer (shaderLinkDelay);
  110. }
  111. void timerCallback() override
  112. {
  113. stopTimer();
  114. fragmentCode = fragmentDocument.getAllContent();
  115. repaint();
  116. }
  117. void comboBoxChanged (ComboBox*) override
  118. {
  119. selectPreset (presetBox.getSelectedItemIndex());
  120. }
  121. struct ShaderPreset
  122. {
  123. const char* name;
  124. const char* fragmentShader;
  125. };
  126. static Array<ShaderPreset> getPresets()
  127. {
  128. #define SHADER_DEMO_HEADER \
  129. "/* This demo shows the use of the OpenGLGraphicsContextCustomShader,\n" \
  130. " which allows a 2D area to be filled using a GL shader program.\n" \
  131. "\n" \
  132. " Edit the shader program below and it will be \n" \
  133. " recompiled in real-time!\n" \
  134. "*/\n\n"
  135. ShaderPreset presets[] =
  136. {
  137. {
  138. "Simple Gradient",
  139. SHADER_DEMO_HEADER
  140. "void main()\n"
  141. "{\n"
  142. " " JUCE_MEDIUMP " vec4 colour1 = vec4 (1.0, 0.4, 0.6, 1.0);\n"
  143. " " JUCE_MEDIUMP " vec4 colour2 = vec4 (0.0, 0.8, 0.6, 1.0);\n"
  144. " " JUCE_MEDIUMP " float alpha = pixelPos.x / 1000.0;\n"
  145. " gl_FragColor = pixelAlpha * mix (colour1, colour2, alpha);\n"
  146. "}\n"
  147. },
  148. {
  149. "Circular Gradient",
  150. SHADER_DEMO_HEADER
  151. "void main()\n"
  152. "{\n"
  153. " " JUCE_MEDIUMP " vec4 colour1 = vec4 (1.0, 0.4, 0.6, 1.0);\n"
  154. " " JUCE_MEDIUMP " vec4 colour2 = vec4 (0.3, 0.4, 0.4, 1.0);\n"
  155. " " JUCE_MEDIUMP " float alpha = distance (pixelPos, vec2 (600.0, 500.0)) / 400.0;\n"
  156. " gl_FragColor = pixelAlpha * mix (colour1, colour2, alpha);\n"
  157. "}\n"
  158. },
  159. {
  160. "Cicle",
  161. SHADER_DEMO_HEADER
  162. "void main()\n"
  163. "{\n"
  164. " " JUCE_MEDIUMP " vec4 colour1 = vec4 (0.1, 0.1, 0.9, 1.0);\n"
  165. " " JUCE_MEDIUMP " vec4 colour2 = vec4 (0.0, 0.8, 0.6, 1.0);\n"
  166. " " JUCE_MEDIUMP " float distance = distance (pixelPos, vec2 (600.0, 500.0));\n"
  167. "\n"
  168. " " JUCE_MEDIUMP " float innerRadius = 200.0;\n"
  169. " " JUCE_MEDIUMP " float outerRadius = 210.0;\n"
  170. "\n"
  171. " if (distance < innerRadius)\n"
  172. " gl_FragColor = colour1;\n"
  173. " else if (distance > outerRadius)\n"
  174. " gl_FragColor = colour2;\n"
  175. " else\n"
  176. " gl_FragColor = mix (colour1, colour2, (distance - innerRadius) / (outerRadius - innerRadius));\n"
  177. "\n"
  178. " gl_FragColor *= pixelAlpha;\n"
  179. "}\n"
  180. },
  181. {
  182. "Solid Colour",
  183. SHADER_DEMO_HEADER
  184. "void main()\n"
  185. "{\n"
  186. " gl_FragColor = vec4 (1.0, 0.6, 0.1, pixelAlpha);\n"
  187. "}\n"
  188. }
  189. };
  190. return Array<ShaderPreset> (presets, numElementsInArray (presets));
  191. }
  192. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OpenGL2DShaderDemo)
  193. };
  194. //==============================================================================
  195. // This static object will register this demo type in a global list of demos..
  196. static JuceDemoType<OpenGL2DShaderDemo> demo ("20 Graphics: OpenGL 2D");
  197. #endif