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.

389 lines
15KB

  1. /*
  2. ==============================================================================
  3. This file was auto-generated!
  4. ==============================================================================
  5. */
  6. #include "../JuceLibraryCode/JuceHeader.h"
  7. #include "Resources/WavefrontObjParser.h"
  8. //==============================================================================
  9. /*
  10. This component lives inside our window, and this is where you should put all
  11. your controls and content.
  12. */
  13. class MainContentComponent : public OpenGLAppComponent
  14. {
  15. public:
  16. //==============================================================================
  17. MainContentComponent()
  18. {
  19. setSize (800, 600);
  20. }
  21. ~MainContentComponent()
  22. {
  23. shutdownOpenGL();
  24. }
  25. void initialise() override
  26. {
  27. createShaders();
  28. }
  29. void shutdown() override
  30. {
  31. shader = nullptr;
  32. shape = nullptr;
  33. attributes = nullptr;
  34. uniforms = nullptr;
  35. }
  36. Matrix3D<float> getProjectionMatrix() const
  37. {
  38. float w = 1.0f / (0.5f + 0.1f);
  39. float h = w * getLocalBounds().toFloat().getAspectRatio (false);
  40. return Matrix3D<float>::fromFrustum (-w, w, -h, h, 4.0f, 30.0f);
  41. }
  42. Matrix3D<float> getViewMatrix() const
  43. {
  44. Matrix3D<float> viewMatrix (Vector3D<float> (0.0f, 0.0f, -10.0f));
  45. Matrix3D<float> rotationMatrix
  46. = viewMatrix.rotated (Vector3D<float> (-0.3f, 5.0f * std::sin (getFrameCounter() * 0.01f), 0.0f));
  47. return rotationMatrix * viewMatrix;
  48. }
  49. void render() override
  50. {
  51. jassert (OpenGLHelpers::isContextActive());
  52. const float desktopScale = (float) openGLContext.getRenderingScale();
  53. OpenGLHelpers::clear (Colour::greyLevel (0.1f));
  54. glEnable (GL_BLEND);
  55. glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  56. glViewport (0, 0, roundToInt (desktopScale * getWidth()), roundToInt (desktopScale * getHeight()));
  57. shader->use();
  58. if (uniforms->projectionMatrix != nullptr)
  59. uniforms->projectionMatrix->setMatrix4 (getProjectionMatrix().mat, 1, false);
  60. if (uniforms->viewMatrix != nullptr)
  61. uniforms->viewMatrix->setMatrix4 (getViewMatrix().mat, 1, false);
  62. shape->draw (openGLContext, *attributes);
  63. // Reset the element buffers so child Components draw correctly
  64. openGLContext.extensions.glBindBuffer (GL_ARRAY_BUFFER, 0);
  65. openGLContext.extensions.glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0);
  66. }
  67. void paint (Graphics& g) override
  68. {
  69. // You can add your component specific drawing code here!
  70. // This will draw over the top of the openGL background.
  71. g.setColour(Colours::white);
  72. g.setFont (20);
  73. g.drawText ("OpenGL Example", 25, 20, 300, 30, Justification::left);
  74. g.drawLine (20, 20, 170, 20);
  75. g.drawLine (20, 50, 170, 50);
  76. }
  77. void resized() override
  78. {
  79. // This is called when the MainContentComponent is resized.
  80. // If you add any child components, this is where you should
  81. // update their positions.
  82. }
  83. void createShaders()
  84. {
  85. vertexShader =
  86. "attribute vec4 position;\n"
  87. "attribute vec4 sourceColour;\n"
  88. "attribute vec2 texureCoordIn;\n"
  89. "\n"
  90. "uniform mat4 projectionMatrix;\n"
  91. "uniform mat4 viewMatrix;\n"
  92. "\n"
  93. "varying vec4 destinationColour;\n"
  94. "varying vec2 textureCoordOut;\n"
  95. "\n"
  96. "void main()\n"
  97. "{\n"
  98. " destinationColour = sourceColour;\n"
  99. " textureCoordOut = texureCoordIn;\n"
  100. " gl_Position = projectionMatrix * viewMatrix * position;\n"
  101. "}\n";
  102. fragmentShader =
  103. #if JUCE_OPENGL_ES
  104. "varying lowp vec4 destinationColour;\n"
  105. "varying lowp vec2 textureCoordOut;\n"
  106. #else
  107. "varying vec4 destinationColour;\n"
  108. "varying vec2 textureCoordOut;\n"
  109. #endif
  110. "\n"
  111. "void main()\n"
  112. "{\n"
  113. #if JUCE_OPENGL_ES
  114. " lowp vec4 colour = vec4(0.95, 0.57, 0.03, 0.7);\n"
  115. #else
  116. " vec4 colour = vec4(0.95, 0.57, 0.03, 0.7);\n"
  117. #endif
  118. " gl_FragColor = colour;\n"
  119. "}\n";
  120. ScopedPointer<OpenGLShaderProgram> newShader (new OpenGLShaderProgram (openGLContext));
  121. String statusText;
  122. if (newShader->addVertexShader (OpenGLHelpers::translateVertexShaderToV3 (vertexShader))
  123. && newShader->addFragmentShader (OpenGLHelpers::translateFragmentShaderToV3 (fragmentShader))
  124. && newShader->link())
  125. {
  126. shape = nullptr;
  127. attributes = nullptr;
  128. uniforms = nullptr;
  129. shader = newShader;
  130. shader->use();
  131. shape = new Shape (openGLContext);
  132. attributes = new Attributes (openGLContext, *shader);
  133. uniforms = new Uniforms (openGLContext, *shader);
  134. statusText = "GLSL: v" + String (OpenGLShaderProgram::getLanguageVersion(), 2);
  135. }
  136. else
  137. {
  138. statusText = newShader->getLastError();
  139. }
  140. }
  141. private:
  142. //==============================================================================
  143. struct Vertex
  144. {
  145. float position[3];
  146. float normal[3];
  147. float colour[4];
  148. float texCoord[2];
  149. };
  150. //==============================================================================
  151. // This class just manages the attributes that the shaders use.
  152. struct Attributes
  153. {
  154. Attributes (OpenGLContext& openGLContext, OpenGLShaderProgram& shaderProgram)
  155. {
  156. position = createAttribute (openGLContext, shaderProgram, "position");
  157. normal = createAttribute (openGLContext, shaderProgram, "normal");
  158. sourceColour = createAttribute (openGLContext, shaderProgram, "sourceColour");
  159. texureCoordIn = createAttribute (openGLContext, shaderProgram, "texureCoordIn");
  160. }
  161. void enable (OpenGLContext& openGLContext)
  162. {
  163. if (position != nullptr)
  164. {
  165. openGLContext.extensions.glVertexAttribPointer (position->attributeID, 3, GL_FLOAT, GL_FALSE, sizeof (Vertex), 0);
  166. openGLContext.extensions.glEnableVertexAttribArray (position->attributeID);
  167. }
  168. if (normal != nullptr)
  169. {
  170. openGLContext.extensions.glVertexAttribPointer (normal->attributeID, 3, GL_FLOAT, GL_FALSE, sizeof (Vertex), (GLvoid*) (sizeof (float) * 3));
  171. openGLContext.extensions.glEnableVertexAttribArray (normal->attributeID);
  172. }
  173. if (sourceColour != nullptr)
  174. {
  175. openGLContext.extensions.glVertexAttribPointer (sourceColour->attributeID, 4, GL_FLOAT, GL_FALSE, sizeof (Vertex), (GLvoid*) (sizeof (float) * 6));
  176. openGLContext.extensions.glEnableVertexAttribArray (sourceColour->attributeID);
  177. }
  178. if (texureCoordIn != nullptr)
  179. {
  180. openGLContext.extensions.glVertexAttribPointer (texureCoordIn->attributeID, 2, GL_FLOAT, GL_FALSE, sizeof (Vertex), (GLvoid*) (sizeof (float) * 10));
  181. openGLContext.extensions.glEnableVertexAttribArray (texureCoordIn->attributeID);
  182. }
  183. }
  184. void disable (OpenGLContext& openGLContext)
  185. {
  186. if (position != nullptr) openGLContext.extensions.glDisableVertexAttribArray (position->attributeID);
  187. if (normal != nullptr) openGLContext.extensions.glDisableVertexAttribArray (normal->attributeID);
  188. if (sourceColour != nullptr) openGLContext.extensions.glDisableVertexAttribArray (sourceColour->attributeID);
  189. if (texureCoordIn != nullptr) openGLContext.extensions.glDisableVertexAttribArray (texureCoordIn->attributeID);
  190. }
  191. ScopedPointer<OpenGLShaderProgram::Attribute> position, normal, sourceColour, texureCoordIn;
  192. private:
  193. static OpenGLShaderProgram::Attribute* createAttribute (OpenGLContext& openGLContext,
  194. OpenGLShaderProgram& shader,
  195. const char* attributeName)
  196. {
  197. if (openGLContext.extensions.glGetAttribLocation (shader.getProgramID(), attributeName) < 0)
  198. return nullptr;
  199. return new OpenGLShaderProgram::Attribute (shader, attributeName);
  200. }
  201. };
  202. //==============================================================================
  203. // This class just manages the uniform values that the demo shaders use.
  204. struct Uniforms
  205. {
  206. Uniforms (OpenGLContext& openGLContext, OpenGLShaderProgram& shaderProgram)
  207. {
  208. projectionMatrix = createUniform (openGLContext, shaderProgram, "projectionMatrix");
  209. viewMatrix = createUniform (openGLContext, shaderProgram, "viewMatrix");
  210. }
  211. ScopedPointer<OpenGLShaderProgram::Uniform> projectionMatrix, viewMatrix;
  212. private:
  213. static OpenGLShaderProgram::Uniform* createUniform (OpenGLContext& openGLContext,
  214. OpenGLShaderProgram& shaderProgram,
  215. const char* uniformName)
  216. {
  217. if (openGLContext.extensions.glGetUniformLocation (shaderProgram.getProgramID(), uniformName) < 0)
  218. return nullptr;
  219. return new OpenGLShaderProgram::Uniform (shaderProgram, uniformName);
  220. }
  221. };
  222. //==============================================================================
  223. /** This loads a 3D model from an OBJ file and converts it into some vertex buffers
  224. that we can draw.
  225. */
  226. struct Shape
  227. {
  228. Shape (OpenGLContext& openGLContext)
  229. {
  230. if (shapeFile.load (BinaryData::teapot_obj).wasOk())
  231. for (int i = 0; i < shapeFile.shapes.size(); ++i)
  232. vertexBuffers.add (new VertexBuffer (openGLContext, *shapeFile.shapes.getUnchecked(i)));
  233. }
  234. void draw (OpenGLContext& openGLContext, Attributes& glAttributes)
  235. {
  236. for (int i = 0; i < vertexBuffers.size(); ++i)
  237. {
  238. VertexBuffer& vertexBuffer = *vertexBuffers.getUnchecked (i);
  239. vertexBuffer.bind();
  240. glAttributes.enable (openGLContext);
  241. glDrawElements (GL_TRIANGLES, vertexBuffer.numIndices, GL_UNSIGNED_INT, 0);
  242. glAttributes.disable (openGLContext);
  243. }
  244. }
  245. private:
  246. struct VertexBuffer
  247. {
  248. VertexBuffer (OpenGLContext& context, WavefrontObjFile::Shape& aShape) : openGLContext (context)
  249. {
  250. numIndices = aShape.mesh.indices.size();
  251. openGLContext.extensions.glGenBuffers (1, &vertexBuffer);
  252. openGLContext.extensions.glBindBuffer (GL_ARRAY_BUFFER, vertexBuffer);
  253. Array<Vertex> vertices;
  254. createVertexListFromMesh (aShape.mesh, vertices, Colours::green);
  255. openGLContext.extensions.glBufferData (GL_ARRAY_BUFFER,
  256. static_cast<GLsizeiptr> (static_cast<size_t> (vertices.size()) * sizeof (Vertex)),
  257. vertices.getRawDataPointer(), GL_STATIC_DRAW);
  258. openGLContext.extensions.glGenBuffers (1, &indexBuffer);
  259. openGLContext.extensions.glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
  260. openGLContext.extensions.glBufferData (GL_ELEMENT_ARRAY_BUFFER,
  261. static_cast<GLsizeiptr> (static_cast<size_t> (numIndices) * sizeof (juce::uint32)),
  262. aShape.mesh.indices.getRawDataPointer(), GL_STATIC_DRAW);
  263. }
  264. ~VertexBuffer()
  265. {
  266. openGLContext.extensions.glDeleteBuffers (1, &vertexBuffer);
  267. openGLContext.extensions.glDeleteBuffers (1, &indexBuffer);
  268. }
  269. void bind()
  270. {
  271. openGLContext.extensions.glBindBuffer (GL_ARRAY_BUFFER, vertexBuffer);
  272. openGLContext.extensions.glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
  273. }
  274. GLuint vertexBuffer, indexBuffer;
  275. int numIndices;
  276. OpenGLContext& openGLContext;
  277. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (VertexBuffer)
  278. };
  279. WavefrontObjFile shapeFile;
  280. OwnedArray<VertexBuffer> vertexBuffers;
  281. static void createVertexListFromMesh (const WavefrontObjFile::Mesh& mesh, Array<Vertex>& list, Colour colour)
  282. {
  283. const float scale = 0.2f;
  284. WavefrontObjFile::TextureCoord defaultTexCoord = { 0.5f, 0.5f };
  285. WavefrontObjFile::Vertex defaultNormal = { 0.5f, 0.5f, 0.5f };
  286. for (int i = 0; i < mesh.vertices.size(); ++i)
  287. {
  288. const WavefrontObjFile::Vertex& v = mesh.vertices.getReference (i);
  289. const WavefrontObjFile::Vertex& n
  290. = i < mesh.normals.size() ? mesh.normals.getReference (i) : defaultNormal;
  291. const WavefrontObjFile::TextureCoord& tc
  292. = i < mesh.textureCoords.size() ? mesh.textureCoords.getReference (i) : defaultTexCoord;
  293. Vertex vert =
  294. {
  295. { scale * v.x, scale * v.y, scale * v.z, },
  296. { scale * n.x, scale * n.y, scale * n.z, },
  297. { colour.getFloatRed(), colour.getFloatGreen(), colour.getFloatBlue(), colour.getFloatAlpha() },
  298. { tc.x, tc.y }
  299. };
  300. list.add (vert);
  301. }
  302. }
  303. };
  304. const char* vertexShader;
  305. const char* fragmentShader;
  306. ScopedPointer<OpenGLShaderProgram> shader;
  307. ScopedPointer<Shape> shape;
  308. ScopedPointer<Attributes> attributes;
  309. ScopedPointer<Uniforms> uniforms;
  310. String newVertexShader, newFragmentShader;
  311. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainContentComponent)
  312. };
  313. // (This function is called by the app startup code to create our main component)
  314. Component* createMainContentComponent() { return new MainContentComponent(); }