mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-21 01:24:21 +00:00
OpenGL Example (unrefined)
This commit is contained in:
parent
41f21aed7e
commit
fb319467bd
47 changed files with 14498 additions and 2053 deletions
403
examples/OpenGLAppExample/Source/MainComponent.cpp
Normal file
403
examples/OpenGLAppExample/Source/MainComponent.cpp
Normal file
|
|
@ -0,0 +1,403 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file was auto-generated!
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef MAINCOMPONENT_H_INCLUDED
|
||||
#define MAINCOMPONENT_H_INCLUDED
|
||||
|
||||
#include "../JuceLibraryCode/JuceHeader.h"
|
||||
#include "WavefrontObjParser.h"
|
||||
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/*
|
||||
This component lives inside our window, and this is where you should put all
|
||||
your controls and content.
|
||||
*/
|
||||
class MainContentComponent : public OpenGLAppComponent
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
MainContentComponent()
|
||||
{
|
||||
setSize (800, 600);
|
||||
}
|
||||
|
||||
~MainContentComponent()
|
||||
{
|
||||
shutdownOpenGL();
|
||||
}
|
||||
|
||||
void initialise() override
|
||||
{
|
||||
setShaders();
|
||||
}
|
||||
|
||||
void shutdown() override
|
||||
{
|
||||
shader = nullptr;
|
||||
shape = nullptr;
|
||||
attributes = nullptr;
|
||||
uniforms = nullptr;
|
||||
}
|
||||
|
||||
|
||||
Matrix3D<float> getProjectionMatrix() const
|
||||
{
|
||||
float w = 1.0f / (0.5 + 0.1f);
|
||||
float h = w * getLocalBounds().toFloat().getAspectRatio (false);
|
||||
return Matrix3D<float>::fromFrustum (-w, w, -h, h, 4.0f, 30.0f);
|
||||
}
|
||||
|
||||
Matrix3D<float> getViewMatrix() const
|
||||
{
|
||||
Matrix3D<float> viewMatrix (Vector3D<float> (0.0f, 0.0f, -10.0f));
|
||||
|
||||
//viewMatrix *= draggableOrientation.getRotationMatrix();
|
||||
|
||||
// Matrix3D<float> rotationMatrix = viewMatrix.rotated (Vector3D<float> (rotation, rotation, -0.3f));
|
||||
Matrix3D<float> rotationMatrix = viewMatrix.rotated (Vector3D<float> (-0.3f, 5.0f*sin(getFrameCounter()*0.01f), 0.0f));
|
||||
|
||||
|
||||
return viewMatrix * rotationMatrix;
|
||||
}
|
||||
|
||||
void render() override
|
||||
{
|
||||
|
||||
jassert (OpenGLHelpers::isContextActive());
|
||||
|
||||
const float desktopScale = (float) openGLContext.getRenderingScale();
|
||||
OpenGLHelpers::clear (Colour::greyLevel(0.1));
|
||||
|
||||
glEnable (GL_DEPTH_TEST);
|
||||
glDepthFunc (GL_LESS);
|
||||
glEnable (GL_BLEND);
|
||||
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
openGLContext.extensions.glActiveTexture (GL_TEXTURE0);
|
||||
glEnable (GL_TEXTURE_2D);
|
||||
|
||||
glViewport (0, 0, roundToInt (desktopScale * getWidth()), roundToInt (desktopScale * getHeight()));
|
||||
|
||||
shader->use();
|
||||
|
||||
if (uniforms->projectionMatrix != nullptr)
|
||||
uniforms->projectionMatrix->setMatrix4 (getProjectionMatrix().mat, 1, false);
|
||||
|
||||
if (uniforms->viewMatrix != nullptr)
|
||||
uniforms->viewMatrix->setMatrix4 (getViewMatrix().mat, 1, false);
|
||||
|
||||
shape->draw (openGLContext, *attributes);
|
||||
|
||||
// Reset the element buffers so child Components draw correctly
|
||||
openGLContext.extensions.glBindBuffer (GL_ARRAY_BUFFER, 0);
|
||||
openGLContext.extensions.glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
|
||||
}
|
||||
|
||||
void paint (Graphics& g) override
|
||||
{
|
||||
// You can add your component specific drawing code here!
|
||||
// This will draw over the top of the openGL background.
|
||||
|
||||
// g.setColour(Colours::white);
|
||||
// g.drawEllipse (100, 100, 50, 50, 2);
|
||||
}
|
||||
|
||||
void resized() override
|
||||
{
|
||||
// This is called when the MainContentComponent is resized.
|
||||
// If you add any child components, this is where you should
|
||||
// update their positions.
|
||||
|
||||
}
|
||||
|
||||
void setShaders()
|
||||
{
|
||||
vertexShader = {
|
||||
"attribute vec4 position;\n"
|
||||
"attribute vec4 sourceColour;\n"
|
||||
"attribute vec2 texureCoordIn;\n"
|
||||
"\n"
|
||||
"uniform mat4 projectionMatrix;\n"
|
||||
"uniform mat4 viewMatrix;\n"
|
||||
"\n"
|
||||
"varying vec4 destinationColour;\n"
|
||||
"varying vec2 textureCoordOut;\n"
|
||||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" destinationColour = sourceColour;\n"
|
||||
" textureCoordOut = texureCoordIn;\n"
|
||||
" gl_Position = projectionMatrix * viewMatrix * position;\n"
|
||||
"}\n"};
|
||||
|
||||
fragmentShader = {
|
||||
#if JUCE_OPENGL_ES
|
||||
"varying lowp vec4 destinationColour;\n"
|
||||
"varying lowp vec2 textureCoordOut;\n"
|
||||
#else
|
||||
"varying vec4 destinationColour;\n"
|
||||
"varying vec2 textureCoordOut;\n"
|
||||
#endif
|
||||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" vec4 colour = vec4(0.95, 0.57, 0.03, 0.8);\n"
|
||||
" gl_FragColor = colour;\n"
|
||||
"}\n" };
|
||||
|
||||
|
||||
|
||||
ScopedPointer<OpenGLShaderProgram> newShader (new OpenGLShaderProgram (openGLContext));
|
||||
String statusText;
|
||||
|
||||
if (newShader->addVertexShader (OpenGLHelpers::translateVertexShaderToV3 (vertexShader))
|
||||
&& newShader->addFragmentShader (OpenGLHelpers::translateFragmentShaderToV3 (fragmentShader))
|
||||
&& newShader->link())
|
||||
{
|
||||
shape = nullptr;
|
||||
attributes = nullptr;
|
||||
uniforms = nullptr;
|
||||
|
||||
shader = newShader;
|
||||
shader->use();
|
||||
|
||||
shape = new Shape (openGLContext);
|
||||
attributes = new Attributes (openGLContext, *shader);
|
||||
uniforms = new Uniforms (openGLContext, *shader);
|
||||
|
||||
statusText = "GLSL: v" + String (OpenGLShaderProgram::getLanguageVersion(), 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
statusText = newShader->getLastError();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
|
||||
// private member variables
|
||||
|
||||
struct Vertex
|
||||
{
|
||||
float position[3];
|
||||
float normal[3];
|
||||
float colour[4];
|
||||
float texCoord[2];
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
// This class just manages the attributes that the demo shaders use.
|
||||
struct Attributes
|
||||
{
|
||||
Attributes (OpenGLContext& openGLContext, OpenGLShaderProgram& shader)
|
||||
{
|
||||
position = createAttribute (openGLContext, shader, "position");
|
||||
normal = createAttribute (openGLContext, shader, "normal");
|
||||
sourceColour = createAttribute (openGLContext, shader, "sourceColour");
|
||||
texureCoordIn = createAttribute (openGLContext, shader, "texureCoordIn");
|
||||
}
|
||||
|
||||
void enable (OpenGLContext& openGLContext)
|
||||
{
|
||||
if (position != nullptr)
|
||||
{
|
||||
openGLContext.extensions.glVertexAttribPointer (position->attributeID, 3, GL_FLOAT, GL_FALSE, sizeof (Vertex), 0);
|
||||
openGLContext.extensions.glEnableVertexAttribArray (position->attributeID);
|
||||
}
|
||||
|
||||
if (normal != nullptr)
|
||||
{
|
||||
openGLContext.extensions.glVertexAttribPointer (normal->attributeID, 3, GL_FLOAT, GL_FALSE, sizeof (Vertex), (GLvoid*) (sizeof (float) * 3));
|
||||
openGLContext.extensions.glEnableVertexAttribArray (normal->attributeID);
|
||||
}
|
||||
|
||||
if (sourceColour != nullptr)
|
||||
{
|
||||
openGLContext.extensions.glVertexAttribPointer (sourceColour->attributeID, 4, GL_FLOAT, GL_FALSE, sizeof (Vertex), (GLvoid*) (sizeof (float) * 6));
|
||||
openGLContext.extensions.glEnableVertexAttribArray (sourceColour->attributeID);
|
||||
}
|
||||
|
||||
if (texureCoordIn != nullptr)
|
||||
{
|
||||
openGLContext.extensions.glVertexAttribPointer (texureCoordIn->attributeID, 2, GL_FLOAT, GL_FALSE, sizeof (Vertex), (GLvoid*) (sizeof (float) * 10));
|
||||
openGLContext.extensions.glEnableVertexAttribArray (texureCoordIn->attributeID);
|
||||
}
|
||||
}
|
||||
|
||||
void disable (OpenGLContext& openGLContext)
|
||||
{
|
||||
if (position != nullptr) openGLContext.extensions.glDisableVertexAttribArray (position->attributeID);
|
||||
if (normal != nullptr) openGLContext.extensions.glDisableVertexAttribArray (normal->attributeID);
|
||||
if (sourceColour != nullptr) openGLContext.extensions.glDisableVertexAttribArray (sourceColour->attributeID);
|
||||
if (texureCoordIn != nullptr) openGLContext.extensions.glDisableVertexAttribArray (texureCoordIn->attributeID);
|
||||
}
|
||||
|
||||
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)
|
||||
return nullptr;
|
||||
|
||||
return new OpenGLShaderProgram::Attribute (shader, attributeName);
|
||||
}
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
// This class just manages the uniform values that the demo shaders use.
|
||||
struct Uniforms
|
||||
{
|
||||
Uniforms (OpenGLContext& openGLContext, OpenGLShaderProgram& shader)
|
||||
{
|
||||
projectionMatrix = createUniform (openGLContext, shader, "projectionMatrix");
|
||||
viewMatrix = createUniform (openGLContext, shader, "viewMatrix");
|
||||
texture = createUniform (openGLContext, shader, "demoTexture");
|
||||
lightPosition = createUniform (openGLContext, shader, "lightPosition");
|
||||
bouncingNumber = createUniform (openGLContext, shader, "bouncingNumber");
|
||||
}
|
||||
|
||||
ScopedPointer<OpenGLShaderProgram::Uniform> projectionMatrix, viewMatrix, texture, lightPosition, bouncingNumber;
|
||||
|
||||
private:
|
||||
static OpenGLShaderProgram::Uniform* createUniform (OpenGLContext& openGLContext,
|
||||
OpenGLShaderProgram& shader,
|
||||
const char* uniformName)
|
||||
{
|
||||
if (openGLContext.extensions.glGetUniformLocation (shader.getProgramID(), uniformName) < 0)
|
||||
return nullptr;
|
||||
|
||||
return new OpenGLShaderProgram::Uniform (shader, uniformName);
|
||||
}
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** This loads a 3D model from an OBJ file and converts it into some vertex buffers
|
||||
that we can draw.
|
||||
*/
|
||||
struct Shape
|
||||
{
|
||||
Shape (OpenGLContext& openGLContext)
|
||||
{
|
||||
if (shapeFile.load (BinaryData::teapot_obj).wasOk())
|
||||
for (int i = 0; i < shapeFile.shapes.size(); ++i)
|
||||
vertexBuffers.add (new VertexBuffer (openGLContext, *shapeFile.shapes.getUnchecked(i)));
|
||||
|
||||
}
|
||||
|
||||
void draw (OpenGLContext& openGLContext, Attributes& attributes)
|
||||
{
|
||||
for (int i = 0; i < vertexBuffers.size(); ++i)
|
||||
{
|
||||
VertexBuffer& vertexBuffer = *vertexBuffers.getUnchecked (i);
|
||||
vertexBuffer.bind();
|
||||
|
||||
attributes.enable (openGLContext);
|
||||
glDrawElements (GL_TRIANGLES, vertexBuffer.numIndices, GL_UNSIGNED_INT, 0);
|
||||
attributes.disable (openGLContext);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
struct VertexBuffer
|
||||
{
|
||||
VertexBuffer (OpenGLContext& context, WavefrontObjFile::Shape& shape) : openGLContext (context)
|
||||
{
|
||||
numIndices = shape.mesh.indices.size();
|
||||
|
||||
openGLContext.extensions.glGenBuffers (1, &vertexBuffer);
|
||||
openGLContext.extensions.glBindBuffer (GL_ARRAY_BUFFER, vertexBuffer);
|
||||
|
||||
Array<Vertex> vertices;
|
||||
createVertexListFromMesh (shape.mesh, vertices, Colours::green);
|
||||
|
||||
openGLContext.extensions.glBufferData (GL_ARRAY_BUFFER, vertices.size() * sizeof (Vertex),
|
||||
vertices.getRawDataPointer(), GL_STATIC_DRAW);
|
||||
|
||||
openGLContext.extensions.glGenBuffers (1, &indexBuffer);
|
||||
openGLContext.extensions.glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
|
||||
openGLContext.extensions.glBufferData (GL_ELEMENT_ARRAY_BUFFER, numIndices * sizeof (juce::uint32),
|
||||
shape.mesh.indices.getRawDataPointer(), GL_STATIC_DRAW);
|
||||
}
|
||||
|
||||
~VertexBuffer()
|
||||
{
|
||||
openGLContext.extensions.glDeleteBuffers (1, &vertexBuffer);
|
||||
openGLContext.extensions.glDeleteBuffers (1, &indexBuffer);
|
||||
}
|
||||
|
||||
void bind()
|
||||
{
|
||||
openGLContext.extensions.glBindBuffer (GL_ARRAY_BUFFER, vertexBuffer);
|
||||
openGLContext.extensions.glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
|
||||
}
|
||||
|
||||
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;
|
||||
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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const char* vertexShader;
|
||||
const char* fragmentShader;
|
||||
|
||||
ScopedPointer<OpenGLShaderProgram> shader;
|
||||
ScopedPointer<Shape> shape;
|
||||
ScopedPointer<Attributes> attributes;
|
||||
ScopedPointer<Uniforms> uniforms;
|
||||
|
||||
String newVertexShader, newFragmentShader;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainContentComponent)
|
||||
};
|
||||
|
||||
|
||||
// (This function is called by the app startup code to create our main component)
|
||||
Component* createMainContentComponent() { return new MainContentComponent(); }
|
||||
|
||||
|
||||
#endif // MAINCOMPONENT_H_INCLUDED
|
||||
Loading…
Add table
Add a link
Reference in a new issue