Skip to content

Instantly share code, notes, and snippets.

@matkatmusic matkatmusic/opengl.cpp Secret
Last active Mar 18, 2018

Embed
What would you like to do?
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
You can’t perform that action at this time.