how the juce opengl demo loads/renders data.
| struct Vertex | |
| { | |
| float position[3]; | |
| float normal[3]; | |
| float colour[4]; | |
| float texCoord[2]; | |
| }; | |
| struct Shape | |
| { | |
| Shape (OpenGLContext& openGLContext) | |
| { | |
| if (shapeFile.load (BinaryData::teapot_obj).wasOk()) //12. read the binary .obj file into our WavefrontObjFile object | |
| for (int i = 0; i < shapeFile.shapes.size(); ++i) //13. for each shape in the WavefrontObjFile object | |
| vertexBuffers.add (new VertexBuffer (openGLContext, *shapeFile.shapes.getUnchecked(i))); //14. create a new VertexBuffer storing the vertices for it | |
| } | |
| //called during render callback | |
| void draw (OpenGLContext& openGLContext, Attributes& glAttributes) | |
| { | |
| for (int i = 0; i < vertexBuffers.size(); ++i) | |
| { | |
| VertexBuffer& vertexBuffer = *vertexBuffers.getUnchecked (i); //46. get a reference to one of the vertexBuffers on our shape | |
| vertexBuffer.bind(); //47. bind it to the appropriate location. http://docs.gl/gl4/glBindBuffer | |
| glAttributes.enable (openGLContext); //50. enable the attributes for the shape, basically tell the context how to interpret the data | |
| glDrawElements ( //59. now that we know how to interpret the data coming in from the attributes, render primitives from array data | |
| GL_TRIANGLES, // treat the set of vertices in a Vertex object as a complete triangle. triangles do not share vertices. | |
| vertexBuffer.numIndices, // count http://docs.gl/gl4/glDrawElements | |
| GL_UNSIGNED_INT, // how to read them | |
| 0); // first index to read from in the loaded vertexBuffer | |
| glAttributes.disable (openGLContext); //60. disable the attributes for the shape. | |
| } | |
| } | |
| private: | |
| struct VertexBuffer | |
| { | |
| VertexBuffer (OpenGLContext& context, WavefrontObjFile::Shape& aShape) : openGLContext (context) | |
| { | |
| numIndices = aShape.mesh.indices.size(); //15. cache the number of indices in this shape | |
| openGLContext.extensions.glGenBuffers (1, &vertexBuffer); //16. generate a single buffer, store the index in vertexBuffer | |
| openGLContext.extensions.glBindBuffer (GL_ARRAY_BUFFER, vertexBuffer); //17. bind the vertexBuffer object as a GL_ARRAY_BUFFER type | |
| Array<Vertex> vertices; | |
| createVertexListFromMesh (aShape.mesh, vertices, Colours::green); //18. create vertex list from mesh, store in vertices | |
| openGLContext.extensions.glBufferData (GL_ARRAY_BUFFER, //21. fill the vertexBuffer with the vertex data | |
| static_cast<GLsizeiptr> (static_cast<size_t> (vertices.size()) * sizeof (Vertex)), // size of data being loaded into buffer | |
| vertices.getRawDataPointer(), GL_STATIC_DRAW); // pointer to raw vertices | |
| openGLContext.extensions.glGenBuffers (1, &indexBuffer); //22. generate a single buffer, store the index in indexBuffer | |
| openGLContext.extensions.glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, indexBuffer); //23. bind the indexBuffer object as a GL_ELEMENT_ARRAY_BUFFER type | |
| openGLContext.extensions.glBufferData (GL_ELEMENT_ARRAY_BUFFER, //24. fill the indexBuffer with the list of indices in the vertexBuffer | |
| static_cast<GLsizeiptr> (static_cast<size_t> (numIndices) * sizeof (juce::uint32)), //size of data being loaded into buffer | |
| aShape.mesh.indices.getRawDataPointer(), GL_STATIC_DRAW); // pointer to raw indexes | |
| } | |
| ~VertexBuffer() | |
| { | |
| openGLContext.extensions.glDeleteBuffers (1, &vertexBuffer); | |
| openGLContext.extensions.glDeleteBuffers (1, &indexBuffer); | |
| } | |
| void bind() | |
| { | |
| openGLContext.extensions.glBindBuffer (GL_ARRAY_BUFFER, vertexBuffer); //48. bind the vertexBuffer to the GL_ARRAY_BUFFER | |
| openGLContext.extensions.glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, indexBuffer); //49. bind the indexBuffer to the GL_ELEMENT_ARRAY_BUFFER | |
| } | |
| GLuint vertexBuffer, indexBuffer; | |
| int numIndices; | |
| OpenGLContext& openGLContext; | |
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (VertexBuffer) | |
| }; | |
| WavefrontObjFile shapeFile; | |
| OwnedArray<VertexBuffer> vertexBuffers; | |
| static void createVertexListFromMesh (const WavefrontObjFile::Mesh& mesh, Array<Vertex>& list, Colour colour) | |
| { | |
| const float scale = 0.2f; //19. populate the data required for a single vertex object | |
| WavefrontObjFile::TextureCoord defaultTexCoord = { 0.5f, 0.5f }; | |
| WavefrontObjFile::Vertex defaultNormal = { 0.5f, 0.5f, 0.5f }; | |
| for (int i = 0; i < mesh.vertices.size(); ++i) | |
| { | |
| const WavefrontObjFile::Vertex& v = mesh.vertices.getReference (i); | |
| const WavefrontObjFile::Vertex& n | |
| = i < mesh.normals.size() ? mesh.normals.getReference (i) : defaultNormal; | |
| const WavefrontObjFile::TextureCoord& tc | |
| = i < mesh.textureCoords.size() ? mesh.textureCoords.getReference (i) : defaultTexCoord; | |
| Vertex vert = | |
| { | |
| { scale * v.x, scale * v.y, scale * v.z, }, | |
| { scale * n.x, scale * n.y, scale * n.z, }, | |
| { colour.getFloatRed(), colour.getFloatGreen(), colour.getFloatBlue(), colour.getFloatAlpha() }, | |
| { tc.x, tc.y } | |
| }; | |
| list.add (vert); //20. add the populated vertex object to our list of vertices | |
| } | |
| } | |
| struct Attributes | |
| { | |
| Attributes (OpenGLContext& openGLContext, OpenGLShaderProgram& shaderProgram) | |
| { | |
| position = createAttribute (openGLContext, shaderProgram, "position"); //25. create the attribute for shaderParm 'position' | |
| normal = createAttribute (openGLContext, shaderProgram, "normal"); //28. create the attribute for shaderParm "normal" | |
| sourceColour = createAttribute (openGLContext, shaderProgram, "sourceColour"); //29. create the attribute for shaderParm "sourceColour" | |
| texureCoordIn = createAttribute (openGLContext, shaderProgram, "texureCoordIn"); //30. create the attribute for shaderParm "textureCoordIn | |
| } | |
| void enable (OpenGLContext& openGLContext) | |
| { | |
| if (position != nullptr) | |
| { | |
| openGLContext.extensions.glVertexAttribPointer (position->attributeID, 3, GL_FLOAT, GL_FALSE, sizeof (Vertex), 0); //51. tell the context about our position properties | |
| openGLContext.extensions.glEnableVertexAttribArray (position->attributeID); //52. enable reading from the attribute | |
| } | |
| if (normal != nullptr) | |
| { | |
| openGLContext.extensions.glVertexAttribPointer (normal->attributeID, 3, GL_FLOAT, GL_FALSE, sizeof (Vertex), (GLvoid*) (sizeof (float) * 3)); //53. tell the context about our normal properties | |
| openGLContext.extensions.glEnableVertexAttribArray (normal->attributeID); //54. enable reading from the attribute | |
| } | |
| if (sourceColour != nullptr) | |
| { | |
| openGLContext.extensions.glVertexAttribPointer (sourceColour->attributeID, 4, GL_FLOAT, GL_FALSE, sizeof (Vertex), (GLvoid*) (sizeof (float) * 6)); //55. tell the context about our sourceColor property | |
| openGLContext.extensions.glEnableVertexAttribArray (sourceColour->attributeID); //56. enable reading from the attribute | |
| } | |
| if (texureCoordIn != nullptr) | |
| { | |
| openGLContext.extensions.glVertexAttribPointer (texureCoordIn->attributeID, 2, GL_FLOAT, GL_FALSE, sizeof (Vertex), (GLvoid*) (sizeof (float) * 10)); //57. tell the context about our textureCoordIn property | |
| openGLContext.extensions.glEnableVertexAttribArray (texureCoordIn->attributeID); //58. enable reading from the attribute | |
| } | |
| } | |
| void disable (OpenGLContext& openGLContext) | |
| { | |
| if (position != nullptr) openGLContext.extensions.glDisableVertexAttribArray (position->attributeID); //61. disable context's knowledge of how to read 'position' from vertexBuffer into the vertexShader | |
| if (normal != nullptr) openGLContext.extensions.glDisableVertexAttribArray (normal->attributeID); //62. disable context's knowledge of how to read 'normal' from the vertexBuffer into the vertexShader | |
| if (sourceColour != nullptr) openGLContext.extensions.glDisableVertexAttribArray (sourceColour->attributeID); //63. disable contexts knowledge of how to read 'sourceColor' from the vertexBuffer into the vertexShader | |
| if (texureCoordIn != nullptr) openGLContext.extensions.glDisableVertexAttribArray (texureCoordIn->attributeID); //64. disable contexts knowledge of how to read 'textureCoordIn' from the vertexBuffer into the vertexShader | |
| } | |
| ScopedPointer<OpenGLShaderProgram::Attribute> position, normal, sourceColour, texureCoordIn; | |
| private: | |
| static OpenGLShaderProgram::Attribute* createAttribute (OpenGLContext& openGLContext, | |
| OpenGLShaderProgram& shader, | |
| const char* attributeName) | |
| { | |
| if (openGLContext.extensions.glGetAttribLocation (shader.getProgramID(), attributeName) < 0) //26 check if 'attributeName' exists on our program | |
| return nullptr; | |
| return new OpenGLShaderProgram::Attribute (shader, attributeName); //27. create a new attribute if it does | |
| } | |
| }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment