diff --git a/testbed/CMakeLists.txt b/testbed/CMakeLists.txt index 4dc2511b..ff842cff 100644 --- a/testbed/CMakeLists.txt +++ b/testbed/CMakeLists.txt @@ -39,6 +39,8 @@ SET(TESTBED_SOURCES src/Gui.cpp src/Scene.h src/Scene.cpp + src/SceneDemo.h + src/SceneDemo.cpp src/Timer.h src/Timer.cpp ) diff --git a/testbed/common/Box.cpp b/testbed/common/Box.cpp index 3845644a..e3fc397a 100644 --- a/testbed/common/Box.cpp +++ b/testbed/common/Box.cpp @@ -59,7 +59,7 @@ GLuint Box::mCubeIndices[36] = { 0, 1, 2, // Constructor Box::Box(const openglframework::Vector3& size, const openglframework::Vector3 &position, - reactphysics3d::CollisionWorld* world, openglframework::Shader& shader) + reactphysics3d::CollisionWorld* world) : openglframework::Object3D(), mColor(0.01f, 0.62f, 0.39f, 1.0f) { // Initialize the size of the box @@ -98,7 +98,7 @@ Box::Box(const openglframework::Vector3& size, const openglframework::Vector3 &p if (totalNbBoxes == 0) { // Create the Vertex Buffer - createVBOAndVAO(shader); + createVBOAndVAO(); } totalNbBoxes++; @@ -107,8 +107,8 @@ Box::Box(const openglframework::Vector3& size, const openglframework::Vector3 &p } // Constructor -Box::Box(const openglframework::Vector3& size, const openglframework::Vector3 &position, - float mass, reactphysics3d::DynamicsWorld* world, openglframework::Shader& shader) +Box::Box(const openglframework::Vector3& size, const openglframework::Vector3& position, + float mass, reactphysics3d::DynamicsWorld* world) : openglframework::Object3D(), mColor(0.01f, 0.62f, 0.39f, 1.0f) { // Initialize the size of the box @@ -147,7 +147,7 @@ Box::Box(const openglframework::Vector3& size, const openglframework::Vector3 &p if (totalNbBoxes == 0) { // Create the Vertex Buffer - createVBOAndVAO(shader); + createVBOAndVAO(); } totalNbBoxes++; @@ -173,9 +173,14 @@ Box::~Box() { void Box::render(openglframework::Shader& shader, const openglframework::Matrix4& worldToCameraMatrix) { + // Bind the VAO + mVAO.bind(); + // Bind the shader shader.bind(); + mVBOVertices.bind(); + // Set the model to camera matrix const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix * mTransformMatrix; shader.setMatrix4x4Uniform("localToCameraMatrix", localToCameraMatrix); @@ -184,18 +189,30 @@ void Box::render(openglframework::Shader& shader, // model-view matrix) const openglframework::Matrix3 normalMatrix = localToCameraMatrix.getUpperLeft3x3Matrix().getInverse().getTranspose(); - shader.setMatrix3x3Uniform("normalMatrix", normalMatrix); + shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false); // Set the vertex color openglframework::Vector4 color(mColor.r, mColor.g, mColor.b, mColor.a); - shader.setVector4Uniform("vertexColor", color); + shader.setVector4Uniform("vertexColor", color, false); - // Bind the VAO - mVAO.bind(); + // Get the location of shader attribute variables + GLint vertexPositionLoc = shader.getAttribLocation("vertexPosition"); + GLint vertexNormalLoc = shader.getAttribLocation("vertexNormal", false); + + glEnableVertexAttribArray(vertexPositionLoc); + if (vertexNormalLoc != -1) glEnableVertexAttribArray(vertexNormalLoc); + + glVertexAttribPointer(vertexPositionLoc, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), MEMBER_OFFSET(VertexData, position)); + if (vertexNormalLoc != -1) glVertexAttribPointer(vertexNormalLoc, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), MEMBER_OFFSET(VertexData, normal)); // Draw the geometry of the box glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, (char*)NULL); + glDisableVertexAttribArray(vertexPositionLoc); + if (vertexNormalLoc != -1) glDisableVertexAttribArray(vertexNormalLoc); + + mVBOVertices.unbind(); + // Unbind the VAO mVAO.unbind(); @@ -230,14 +247,7 @@ void Box::updateTransform(float interpolationFactor) { // Create the Vertex Buffer Objects used to render to box with OpenGL. /// We create two VBOs (one for vertices and one for indices) to render all the boxes /// in the simulation. -void Box::createVBOAndVAO(openglframework::Shader& shader) { - - // Bind the shader - shader.bind(); - - // Get the location of shader attribute variables - GLint vertexPositionLoc = shader.getAttribLocation("vertexPosition"); - GLint vertexNormalLoc = shader.getAttribLocation("vertexNormal"); +void Box::createVBOAndVAO() { // Create the VBO for the vertices data mVBOVertices.create(); @@ -258,20 +268,11 @@ void Box::createVBOAndVAO(openglframework::Shader& shader) { // Bind the VBO of vertices mVBOVertices.bind(); - glEnableVertexAttribArray(vertexPositionLoc); - glEnableVertexAttribArray(vertexNormalLoc); - - glVertexAttribPointer(vertexPositionLoc, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), MEMBER_OFFSET(VertexData, position)); - glVertexAttribPointer(vertexNormalLoc, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), MEMBER_OFFSET(VertexData, normal)); - // Bind the VBO of indices mVBOIndices.bind(); // Unbind the VAO mVAO.unbind(); - - // Unbind the shader - shader.unbind(); } // Reset the transform diff --git a/testbed/common/Box.h b/testbed/common/Box.h index efacafb4..b322dc8b 100644 --- a/testbed/common/Box.h +++ b/testbed/common/Box.h @@ -86,7 +86,7 @@ class Box : public openglframework::Object3D { // -------------------- Methods -------------------- // /// Create a the VAO and VBOs to render to box with OpenGL - static void createVBOAndVAO(openglframework::Shader &shader); + static void createVBOAndVAO(); public : @@ -94,11 +94,11 @@ class Box : public openglframework::Object3D { /// Constructor Box(const openglframework::Vector3& size, const openglframework::Vector3& position, - reactphysics3d::CollisionWorld* world, openglframework::Shader &shader); + reactphysics3d::CollisionWorld* world); /// Constructor Box(const openglframework::Vector3& size, const openglframework::Vector3& position, - float mass, reactphysics3d::DynamicsWorld *world, openglframework::Shader& shader); + float mass, reactphysics3d::DynamicsWorld *world); /// Destructor ~Box(); diff --git a/testbed/opengl-framework/src/Shader.h b/testbed/opengl-framework/src/Shader.h index 734ee56c..9205fbe0 100644 --- a/testbed/opengl-framework/src/Shader.h +++ b/testbed/opengl-framework/src/Shader.h @@ -34,6 +34,7 @@ #include "maths/Vector4.h" #include #include +#include #include namespace openglframework { @@ -78,57 +79,57 @@ class Shader { void unbind() const; // Return the location of a uniform variable inside a shader program - GLint getUniformLocation(const std::string& variableName) const; + GLint getUniformLocation(const std::string& variableName, bool errorIfMissing = true) const; // Return the location of an attribute variable inside a shader program - GLint getAttribLocation(const std::string& variableName) const; + GLint getAttribLocation(const std::string& variableName, bool errorIfMissing = true) const; // Set a float uniform value to this shader (be careful if the uniform is not // used in the shader, the compiler will remove it, then when you will try // to set it, an assert will occur) - void setFloatUniform(const std::string& variableName, float value) const; + void setFloatUniform(const std::string& variableName, float value, bool errorIfMissing = true) const; // Set an int uniform value to this shader (be careful if the uniform is not // used in the shader, the compiler will remove it, then when you will try // to set it, an assert will occur) - void setIntUniform(const std::string& variableName, int value) const; + void setIntUniform(const std::string& variableName, int value, bool errorIfMissing = true) const; // Set a vector 2 uniform value to this shader (be careful if the uniform is not // used in the shader, the compiler will remove it, then when you will try // to set it, an assert will occur) - void setVector2Uniform(const std::string& variableName, const Vector2& v) const; + void setVector2Uniform(const std::string& variableName, const Vector2& v, bool errorIfMissing = true) const; // Set a vector 3 uniform value to this shader (be careful if the uniform is not // used in the shader, the compiler will remove it, then when you will try // to set it, an assert will occur) - void setVector3Uniform(const std::string& variableName, const Vector3& v) const; + void setVector3Uniform(const std::string& variableName, const Vector3& v, bool errorIfMissing = true) const; // Set a vector 4 uniform value to this shader (be careful if the uniform is not // used in the shader, the compiler will remove it, then when you will try // to set it, an assert will occur) - void setVector4Uniform(const std::string& variableName, const Vector4 &v) const; + void setVector4Uniform(const std::string& variableName, const Vector4 &v, bool errorIfMissing = true) const; // Set a 3x3 matrix uniform value to this shader (be careful if the uniform is not // used in the shader, the compiler will remove it, then when you will try // to set it, an assert will occur) void setMatrix3x3Uniform(const std::string& variableName, const float* matrix, - bool transpose = false) const; + bool transpose = false, bool errorIfMissing = true) const; // Set a 3x3 matrix uniform value to this shader (be careful if the uniform is not // used in the shader, the compiler will remove it, then when you will try // to set it, an assert will occur) - void setMatrix3x3Uniform(const std::string& variableName, const Matrix3& matrix) const; + void setMatrix3x3Uniform(const std::string& variableName, const Matrix3& matrix, bool errorIfMissing = true) const; // Set a 4x4 matrix uniform value to this shader (be careful if the uniform is not // used in the shader, the compiler will remove it, then when you will try // to set it, an assert will occur) void setMatrix4x4Uniform(const std::string& variableName, const float* matrix, - bool transpose = false) const; + bool transpose = false, bool errorIfMissing = true) const; // Set a 4x4 matrix uniform value to this shader (be careful if the uniform is not // used in the shader, the compiler will remove it, then when you will try // to set it, an assert will occur) - void setMatrix4x4Uniform(const std::string& variableName, const Matrix4& matrix) const; + void setMatrix4x4Uniform(const std::string& variableName, const Matrix4& matrix, bool errorIfMissing = true) const; // Return the shader object program ID GLuint getProgramObjectId() const; @@ -150,28 +151,30 @@ inline void Shader::unbind() const { } // Return the location of a uniform variable inside a shader program -inline GLint Shader::getUniformLocation(const std::string& variableName) const { +inline GLint Shader::getUniformLocation(const std::string& variableName, bool errorIfMissing) const { assert(mProgramObjectID != 0); GLint location = glGetUniformLocation(mProgramObjectID, variableName.c_str()); - if (location == -1) { + if (location == -1 && errorIfMissing) { std::cerr << "Error in vertex shader " << mFilenameVertexShader << " or in fragment shader" << mFilenameFragmentShader << " : No Uniform variable : " << variableName << std::endl; + throw std::logic_error("Error in Shader"); } - assert(location != -1); + return location; } // Return the location of an attribute variable inside a shader program -inline GLint Shader::getAttribLocation(const std::string& variableName) const { +inline GLint Shader::getAttribLocation(const std::string& variableName, bool errorIfMissing) const { assert(mProgramObjectID != 0); GLint location = glGetAttribLocation(mProgramObjectID, variableName.c_str()); - if (location == -1) { + if (location == -1 && errorIfMissing) { std::cerr << "Error in vertex shader " << mFilenameVertexShader << " or in fragment shader" << mFilenameFragmentShader << " : No Uniform variable : " << variableName << std::endl; + throw std::logic_error("Error in Shader"); } - assert(location != -1); + return location; } @@ -184,56 +187,74 @@ inline void Shader::destroy() { // Set a float uniform value to this shader (be careful if the uniform is not // used in the shader, the compiler will remove it, then when you will try // to set it, an assert will occur) -inline void Shader::setFloatUniform(const std::string& variableName, float value) const { +inline void Shader::setFloatUniform(const std::string& variableName, float value, bool errorIfMissing) const { assert(mProgramObjectID != 0); - glUniform1f(getUniformLocation(variableName), value); + GLint location = getUniformLocation(variableName, errorIfMissing); + if (location != -1) { + glUniform1f(location, value); + } } // Set an int uniform value to this shader (be careful if the uniform is not // used in the shader, the compiler will remove it, then when you will try // to set it, an assert will occur) -inline void Shader::setIntUniform(const std::string& variableName, int value) const { +inline void Shader::setIntUniform(const std::string& variableName, int value, bool errorIfMissing) const { assert(mProgramObjectID != 0); - glUniform1i(getUniformLocation(variableName), value); + GLint location = getUniformLocation(variableName, errorIfMissing); + if (location != -1) { + glUniform1i(location, value); + } } // Set a vector 2 uniform value to this shader (be careful if the uniform is not // used in the shader, the compiler will remove it, then when you will try // to set it, an assert will occur) -inline void Shader::setVector2Uniform(const std::string& variableName, const Vector2& v) const { +inline void Shader::setVector2Uniform(const std::string& variableName, const Vector2& v, bool errorIfMissing) const { assert(mProgramObjectID != 0); - glUniform2f(getUniformLocation(variableName), v.x, v.y); + GLint location = getUniformLocation(variableName, errorIfMissing); + if (location != -1) { + glUniform2f(location, v.x, v.y); + } } // Set a vector 3 uniform value to this shader (be careful if the uniform is not // used in the shader, the compiler will remove it, then when you will try // to set it, an assert will occur) -inline void Shader::setVector3Uniform(const std::string& variableName, const Vector3 &v) const { +inline void Shader::setVector3Uniform(const std::string& variableName, const Vector3 &v, bool errorIfMissing) const { assert(mProgramObjectID != 0); - glUniform3f(getUniformLocation(variableName), v.x, v.y, v.z); + GLint location = getUniformLocation(variableName, errorIfMissing); + if (location != -1) { + glUniform3f(location, v.x, v.y, v.z); + } } // Set a vector 4 uniform value to this shader (be careful if the uniform is not // used in the shader, the compiler will remove it, then when you will try // to set it, an assert will occur) -inline void Shader::setVector4Uniform(const std::string& variableName, const Vector4& v) const { +inline void Shader::setVector4Uniform(const std::string& variableName, const Vector4& v, bool errorIfMissing) const { assert(mProgramObjectID != 0); - glUniform4f(getUniformLocation(variableName), v.x, v.y, v.z, v.w); + GLint location = getUniformLocation(variableName, errorIfMissing); + if (location != -1) { + glUniform4f(location, v.x, v.y, v.z, v.w); + } } // Set a 4x4 matrix uniform value to this shader (be careful if the uniform is not // used in the shader, the compiler will remove it, then when you will try // to set it, an assert will occur) inline void Shader::setMatrix3x3Uniform(const std::string& variableName, const float* matrix, - bool transpose) const { + bool transpose, bool errorIfMissing) const { assert(mProgramObjectID != 0); - glUniformMatrix3fv(getUniformLocation(variableName), 1, transpose, matrix); + GLint location = getUniformLocation(variableName, errorIfMissing); + if (location != -1) { + glUniformMatrix3fv(location, 1, transpose, matrix); + } } // Set a 3x3 matrix uniform value to this shader (be careful if the uniform is not // used in the shader, the compiler will remove it, then when you will try // to set it, an assert will occur) -inline void Shader::setMatrix3x3Uniform(const std::string& variableName, const Matrix3& matrix) const { +inline void Shader::setMatrix3x3Uniform(const std::string& variableName, const Matrix3& matrix, bool errorIfMissing) const { assert(mProgramObjectID != 0); GLfloat mat[9]; for (int i=0; i<3; i++) { @@ -241,22 +262,28 @@ inline void Shader::setMatrix3x3Uniform(const std::string& variableName, const M mat[i*3 + j] = matrix.getValue(i, j); } } - glUniformMatrix3fv(getUniformLocation(variableName), 1, true, mat); + GLint location = getUniformLocation(variableName, errorIfMissing); + if (location != -1) { + glUniformMatrix3fv(location, 1, true, mat); + } } // Set a 4x4 matrix uniform value to this shader (be careful if the uniform is not // used in the shader, the compiler will remove it, then when you will try // to set it, an assert will occur) inline void Shader::setMatrix4x4Uniform(const std::string& variableName, const float* matrix, - bool transpose) const { + bool transpose, bool errorIfMissing) const { assert(mProgramObjectID != 0); - glUniformMatrix4fv(getUniformLocation(variableName), 1, transpose, matrix); + GLint location = getUniformLocation(variableName, errorIfMissing); + if (location != -1) { + glUniformMatrix4fv(location, 1, transpose, matrix); + } } // Set a 4x4 matrix uniform value to this shader (be careful if the uniform is not // used in the shader, the compiler will remove it, then when you will try // to set it, an assert will occur) -inline void Shader::setMatrix4x4Uniform(const std::string& variableName, const Matrix4& matrix) const { +inline void Shader::setMatrix4x4Uniform(const std::string& variableName, const Matrix4& matrix, bool errorIfMissing) const { assert(mProgramObjectID != 0); GLfloat mat[16]; for (int i=0; i<4; i++) { @@ -264,7 +291,10 @@ inline void Shader::setMatrix4x4Uniform(const std::string& variableName, const M mat[i*4 + j] = matrix.m[i][j]; } } - glUniformMatrix4fv(getUniformLocation(variableName), 1, true, mat); + GLint location = getUniformLocation(variableName, errorIfMissing); + if (location != -1) { + glUniformMatrix4fv(location, 1, true, mat); + } } // Return the shader object program ID diff --git a/testbed/opengl-framework/src/Texture2D.cpp b/testbed/opengl-framework/src/Texture2D.cpp index 1b316b73..6a3f4498 100644 --- a/testbed/opengl-framework/src/Texture2D.cpp +++ b/testbed/opengl-framework/src/Texture2D.cpp @@ -72,6 +72,28 @@ void Texture2D::create(uint width, uint height, uint internalFormat, uint format glBindTexture(GL_TEXTURE_2D, 0); } +// Create the texture +void Texture2D::create(uint width, uint height, uint internalFormat, uint format, uint type, + uint minFilter, uint maxFilter, uint wrapS, uint wrapT, void* data) { + + // Destroy the current texture + destroy(); + + mWidth = width; + mHeight = height; + + // Create the OpenGL texture + glGenTextures(1, &mID); + assert(mID != 0); + glBindTexture(GL_TEXTURE_2D, mID); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapS); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, maxFilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter); + glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, mWidth, mHeight, 0, format, type, data); + glBindTexture(GL_TEXTURE_2D, 0); +} + // Destroy the texture void Texture2D::destroy() { if (mID != 0) { diff --git a/testbed/opengl-framework/src/Texture2D.h b/testbed/opengl-framework/src/Texture2D.h index 9c6fa1c0..08087081 100644 --- a/testbed/opengl-framework/src/Texture2D.h +++ b/testbed/opengl-framework/src/Texture2D.h @@ -71,6 +71,10 @@ class Texture2D { void create(uint width, uint height, uint internalFormat, uint format, uint type, void* data = NULL); + // Create the texture + void create(uint width, uint height, uint internalFormat, uint format, uint type, + uint minFilter, uint maxFilter, uint wrapS, uint wrapT, void* data); + // Destroy the texture void destroy(); diff --git a/testbed/scenes/collisionshapes/CollisionShapesScene.cpp b/testbed/scenes/collisionshapes/CollisionShapesScene.cpp index 040fec2b..758c773b 100644 --- a/testbed/scenes/collisionshapes/CollisionShapesScene.cpp +++ b/testbed/scenes/collisionshapes/CollisionShapesScene.cpp @@ -90,7 +90,7 @@ CollisionShapesScene::CollisionShapesScene(const std::string& name) radius * sin(angle)); // Create a sphere and a corresponding rigid in the dynamics world - Box* box = new Box(BOX_SIZE, position , BOX_MASS, mDynamicsWorld, mPhongShader); + Box* box = new Box(BOX_SIZE, position , BOX_MASS, mDynamicsWorld); // Change the material properties of the rigid body rp3d::Material& material = box->getRigidBody()->getMaterial(); @@ -208,7 +208,7 @@ CollisionShapesScene::CollisionShapesScene(const std::string& name) // Create the floor openglframework::Vector3 floorPosition(0, 0, 0); - mFloor = new Box(FLOOR_SIZE, floorPosition, FLOOR_MASS, mDynamicsWorld, mPhongShader); + mFloor = new Box(FLOOR_SIZE, floorPosition, FLOOR_MASS, mDynamicsWorld); // The floor must be a static rigid body mFloor->getRigidBody()->setType(rp3d::STATIC); diff --git a/testbed/scenes/cubes/CubesScene.cpp b/testbed/scenes/cubes/CubesScene.cpp index 6cb500ea..ce1b5bbf 100644 --- a/testbed/scenes/cubes/CubesScene.cpp +++ b/testbed/scenes/cubes/CubesScene.cpp @@ -32,18 +32,13 @@ using namespace cubesscene; // Constructor CubesScene::CubesScene(const std::string& name) - : Scene(name), mLight0(0), - mPhongShader("shaders/phong.vert", "shaders/phong.frag") { - - // Move the light 0 - mLight0.translateWorld(Vector3(7, 15, 15)); + : SceneDemo(name, SCENE_RADIUS) { // Compute the radius and the center of the scene - float radiusScene = 30.0f; openglframework::Vector3 center(0, 5, 0); // Set the center of the scene - setScenePosition(center, radiusScene); + setScenePosition(center, SCENE_RADIUS); // Gravity vector in the dynamics world rp3d::Vector3 gravity(0, rp3d::decimal(-5.81), 0); @@ -69,7 +64,7 @@ CubesScene::CubesScene(const std::string& name) 0); // Create a cube and a corresponding rigid in the dynamics world - Box* cube = new Box(BOX_SIZE, position , BOX_MASS, mDynamicsWorld, mPhongShader); + Box* cube = new Box(BOX_SIZE, position , BOX_MASS, mDynamicsWorld); // Change the material properties of the rigid body rp3d::Material& material = cube->getRigidBody()->getMaterial(); @@ -81,7 +76,7 @@ CubesScene::CubesScene(const std::string& name) // Create the floor openglframework::Vector3 floorPosition(0, 0, 0); - mFloor = new Box(FLOOR_SIZE, floorPosition, FLOOR_MASS, mDynamicsWorld, mPhongShader); + mFloor = new Box(FLOOR_SIZE, floorPosition, FLOOR_MASS, mDynamicsWorld); // The floor must be a static rigid body mFloor->getRigidBody()->setType(rp3d::STATIC); @@ -171,39 +166,25 @@ void CubesScene::update() { } } -// Render the scene -void CubesScene::render() { - - glEnable(GL_DEPTH_TEST); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glEnable(GL_CULL_FACE); +// Render the scene in a single pass +void CubesScene::renderSinglePass(Shader& shader) { // Get the world-space to camera-space matrix const openglframework::Matrix4 worldToCameraMatrix = mCamera.getTransformMatrix().getInverse(); // Bind the shader - mPhongShader.bind(); - - // Set the variables of the shader - mPhongShader.setMatrix4x4Uniform("projectionMatrix", mCamera.getProjectionMatrix()); - mPhongShader.setVector3Uniform("light0PosCameraSpace",worldToCameraMatrix * mLight0.getOrigin()); - mPhongShader.setVector3Uniform("lightAmbientColor", Vector3(0.3f, 0.3f, 0.3f)); - const Color& diffCol = mLight0.getDiffuseColor(); - const Color& specCol = mLight0.getSpecularColor(); - mPhongShader.setVector3Uniform("light0DiffuseColor", Vector3(diffCol.r, diffCol.g, diffCol.b)); - mPhongShader.setVector3Uniform("light0SpecularColor", Vector3(specCol.r, specCol.g, specCol.b)); - mPhongShader.setFloatUniform("shininess", 60.0f); + shader.bind(); // Render all the cubes of the scene for (std::vector::iterator it = mBoxes.begin(); it != mBoxes.end(); ++it) { - (*it)->render(mPhongShader, worldToCameraMatrix); + (*it)->render(shader, worldToCameraMatrix); } // Render the floor - mFloor->render(mPhongShader, worldToCameraMatrix); + mFloor->render(shader, worldToCameraMatrix); // Unbind the shader - mPhongShader.unbind(); + shader.unbind(); } // Reset the scene diff --git a/testbed/scenes/cubes/CubesScene.h b/testbed/scenes/cubes/CubesScene.h index 4c3df694..695aa89a 100644 --- a/testbed/scenes/cubes/CubesScene.h +++ b/testbed/scenes/cubes/CubesScene.h @@ -30,30 +30,25 @@ #include "openglframework.h" #include "reactphysics3d.h" #include "Box.h" -#include "Scene.h" +#include "SceneDemo.h" namespace cubesscene { // Constants -const int NB_CUBES = 20; // Number of boxes in the scene +const float SCENE_RADIUS = 30.0f; // Radius of the scene in meters +const int NB_CUBES = 20; // Number of boxes in the scene const openglframework::Vector3 BOX_SIZE(2, 2, 2); // Box dimensions in meters const openglframework::Vector3 FLOOR_SIZE(50, 0.5f, 50); // Floor dimensions in meters const float BOX_MASS = 1.0f; // Box mass in kilograms const float FLOOR_MASS = 100.0f; // Floor mass in kilograms // Class CubesScene -class CubesScene : public Scene { +class CubesScene : public SceneDemo { protected : // -------------------- Attributes -------------------- // - /// Light 0 - openglframework::Light mLight0; - - /// Phong shader - openglframework::Shader mPhongShader; - /// All the boxes of the scene std::vector mBoxes; @@ -80,8 +75,8 @@ class CubesScene : public Scene { /// Update the scene (take a simulation step) virtual void update(); - /// Render the scene - virtual void render(); + /// Render the scene in a single pass + virtual void renderSinglePass(openglframework::Shader& shader); /// Reset the scene virtual void reset(); diff --git a/testbed/scenes/joints/JointsScene.cpp b/testbed/scenes/joints/JointsScene.cpp index ea5e413b..655c629e 100644 --- a/testbed/scenes/joints/JointsScene.cpp +++ b/testbed/scenes/joints/JointsScene.cpp @@ -291,7 +291,7 @@ void JointsScene::createBallAndSocketJoints() { // Create a box and a corresponding rigid in the dynamics world mBallAndSocketJointChainBoxes[i] = new Box(boxDimension, positionBox , boxMass, - mDynamicsWorld, mPhongShader); + mDynamicsWorld); // The fist box cannot move (static body) if (i == 0) { @@ -336,7 +336,7 @@ void JointsScene::createSliderJoint() { // Create a box and a corresponding rigid in the dynamics world openglframework::Vector3 box1Dimension(2, 4, 2); - mSliderJointBottomBox = new Box(box1Dimension, positionBox1 , BOX_MASS, mDynamicsWorld, mPhongShader); + mSliderJointBottomBox = new Box(box1Dimension, positionBox1 , BOX_MASS, mDynamicsWorld); // The fist box cannot move mSliderJointBottomBox->getRigidBody()->setType(rp3d::STATIC); @@ -352,7 +352,7 @@ void JointsScene::createSliderJoint() { // Create a box and a corresponding rigid in the dynamics world openglframework::Vector3 box2Dimension(1.5f, 4, 1.5f); - mSliderJointTopBox = new Box(box2Dimension, positionBox2, BOX_MASS, mDynamicsWorld, mPhongShader); + mSliderJointTopBox = new Box(box2Dimension, positionBox2, BOX_MASS, mDynamicsWorld); // Change the material properties of the rigid body rp3d::Material& material2 = mSliderJointTopBox->getRigidBody()->getMaterial(); @@ -388,7 +388,7 @@ void JointsScene::createPropellerHingeJoint() { // Create a box and a corresponding rigid in the dynamics world openglframework::Vector3 boxDimension(10, 1, 1); - mPropellerBox = new Box(boxDimension, positionBox1 , BOX_MASS, mDynamicsWorld, mPhongShader); + mPropellerBox = new Box(boxDimension, positionBox1 , BOX_MASS, mDynamicsWorld); // Change the material properties of the rigid body rp3d::Material& material = mPropellerBox->getRigidBody()->getMaterial(); @@ -423,7 +423,7 @@ void JointsScene::createFixedJoints() { // Create a box and a corresponding rigid in the dynamics world openglframework::Vector3 boxDimension(1.5, 1.5, 1.5); - mFixedJointBox1 = new Box(boxDimension, positionBox1 , BOX_MASS, mDynamicsWorld, mPhongShader); + mFixedJointBox1 = new Box(boxDimension, positionBox1 , BOX_MASS, mDynamicsWorld); // Change the material properties of the rigid body rp3d::Material& material1 = mFixedJointBox1->getRigidBody()->getMaterial(); @@ -435,7 +435,7 @@ void JointsScene::createFixedJoints() { openglframework::Vector3 positionBox2(-5, 7, 0); // Create a box and a corresponding rigid in the dynamics world - mFixedJointBox2 = new Box(boxDimension, positionBox2 , BOX_MASS, mDynamicsWorld, mPhongShader); + mFixedJointBox2 = new Box(boxDimension, positionBox2 , BOX_MASS, mDynamicsWorld); // Change the material properties of the rigid body rp3d::Material& material2 = mFixedJointBox2->getRigidBody()->getMaterial(); @@ -470,7 +470,7 @@ void JointsScene::createFloor() { // Create the floor openglframework::Vector3 floorPosition(0, 0, 0); - mFloor = new Box(FLOOR_SIZE, floorPosition, FLOOR_MASS, mDynamicsWorld, mPhongShader); + mFloor = new Box(FLOOR_SIZE, floorPosition, FLOOR_MASS, mDynamicsWorld); // The floor must be a static rigid body mFloor->getRigidBody()->setType(rp3d::STATIC); diff --git a/testbed/scenes/raycast/RaycastScene.cpp b/testbed/scenes/raycast/RaycastScene.cpp index a7d6bee0..3d74979e 100644 --- a/testbed/scenes/raycast/RaycastScene.cpp +++ b/testbed/scenes/raycast/RaycastScene.cpp @@ -60,7 +60,7 @@ RaycastScene::RaycastScene(const std::string& name) openglframework::Vector3 position2(0, 0, 0); // Create a box and a corresponding collision body in the dynamics world - mBox = new Box(BOX_SIZE, position2, mCollisionWorld, mPhongShader); + mBox = new Box(BOX_SIZE, position2, mCollisionWorld); mBox->getCollisionBody()->setIsActive(false); // ---------- Sphere ---------- // diff --git a/testbed/shaders/depth.frag b/testbed/shaders/depth.frag index 9b32019e..75c12abe 100644 --- a/testbed/shaders/depth.frag +++ b/testbed/shaders/depth.frag @@ -1,3 +1,5 @@ +#version 330 + /******************************************************************************** * OpenGL-Framework * * Copyright (c) 2015 Daniel Chappuis * @@ -6,7 +8,7 @@ * This software is provided 'as-is', without any express or implied warranty. * * In no event will the authors be held liable for any damages arising from the * * use of this software. * -* * +* * * Permission is granted to anyone to use this software for any purpose, * * including commercial applications, and to alter it and redistribute it * * freely, subject to the following restrictions: * @@ -23,10 +25,11 @@ * * ********************************************************************************/ -void main(void) { +// Out variable +out vec4 color; // Output color - // Compute the depth of the pixel - float depth = +void main() { - gl_FragColor = vec4(depth, depth, depth, 1); + // Compute the final color + color = vec4(1, 1, 1, 1); } diff --git a/testbed/shaders/depth.vert b/testbed/shaders/depth.vert index 09b9ff9a..ec0c0705 100644 --- a/testbed/shaders/depth.vert +++ b/testbed/shaders/depth.vert @@ -1,3 +1,5 @@ +#version 330 + /******************************************************************************** * OpenGL-Framework * * Copyright (c) 2015 Daniel Chappuis * @@ -24,13 +26,14 @@ ********************************************************************************/ // Uniform variables -uniform mat4 modelToWorldMatrix; // Model too world coordinates matrix -uniform mat4 worldToCameraMatrix; // World to camera coordinates matrix +uniform mat4 localToCameraMatrix; // Local-space to camera-space matrix uniform mat4 projectionMatrix; // Projection matrix -void main(void) { +// In variables +in vec4 vertexPosition; + +void main() { // Compute the clip-space vertex coordinates - gl_Position = projectionMatrix * worldToCameraMatrix * - modelToWorldMatrix * gl_Vertex; + gl_Position = projectionMatrix * localToCameraMatrix * vertexPosition; } diff --git a/testbed/shaders/gui.frag b/testbed/shaders/gui.frag deleted file mode 100644 index a00d52bb..00000000 --- a/testbed/shaders/gui.frag +++ /dev/null @@ -1,10 +0,0 @@ -#version 330 -uniform sampler2D Texture; -in vec2 Frag_UV; -in vec4 Frag_Color; -out vec4 Out_Color; - -void main() -{ - Out_Color = Frag_Color * texture( Texture, Frag_UV.st); -} diff --git a/testbed/shaders/gui.vert b/testbed/shaders/gui.vert deleted file mode 100644 index 18870a74..00000000 --- a/testbed/shaders/gui.vert +++ /dev/null @@ -1,15 +0,0 @@ -#version 330 - -uniform mat4 ProjMtx; -in vec2 Position; -in vec2 UV; -in vec4 Color; -out vec2 Frag_UV; -out vec4 Frag_Color; - -void main() -{ - Frag_UV = UV; - Frag_Color = Color; - gl_Position = ProjMtx * vec4(Position.xy,0,1); -} diff --git a/testbed/src/SceneDemo.cpp b/testbed/src/SceneDemo.cpp new file mode 100644 index 00000000..0b5fa0ef --- /dev/null +++ b/testbed/src/SceneDemo.cpp @@ -0,0 +1,124 @@ +/******************************************************************************** +* ReactPhysics3D physics library, http://www.reactphysics3d.com * +* Copyright (c) 2010-2015 Daniel Chappuis * +********************************************************************************* +* * +* This software is provided 'as-is', without any express or implied warranty. * +* In no event will the authors be held liable for any damages arising from the * +* use of this software. * +* * +* Permission is granted to anyone to use this software for any purpose, * +* including commercial applications, and to alter it and redistribute it * +* freely, subject to the following restrictions: * +* * +* 1. The origin of this software must not be misrepresented; you must not claim * +* that you wrote the original software. If you use this software in a * +* product, an acknowledgment in the product documentation would be * +* appreciated but is not required. * +* * +* 2. Altered source versions must be plainly marked as such, and must not be * +* misrepresented as being the original software. * +* * +* 3. This notice may not be removed or altered from any source distribution. * +* * +********************************************************************************/ + +// Libraries +#include "SceneDemo.h" +#include + +using namespace openglframework; + +// Constructor +SceneDemo::SceneDemo(const std::string& name, float sceneRadius) : Scene(name), mLight0(0), + mDepthShader("shaders/depth.vert", "shaders/depth.frag"), + mPhongShader("shaders/phong.vert", "shaders/phong.frag") { + + // Move the light0 + mLight0.translateWorld(Vector3(7, 15, 15)); + + // Camera at light0 postion for the shadow map + mShadowMapLightCamera.translateWorld(mLight0.getOrigin()); + mShadowMapLightCamera.setDimensions(SHADOWMAP_WIDTH, SHADOWMAP_HEIGHT); + mShadowMapLightCamera.setFieldOfView(45.0f); + mShadowMapLightCamera.setSceneRadius(sceneRadius); + mShadowMapLightCamera.setZoom(1.0); + + // Bias matrix for the shadow map + mShadowMapBiasMatrix.setAllValues(0.5f, 0.0f, 0.0f, 0.5f, + 0.0f, 0.5f, 0.5f, 0.5f, + 0.0f, 0.0f, 0.0f, 0.5f, + 0.0f, 0.0f, 0.0f, 1.0f); + + // Create the Shadow map FBO and texture + createShadowMapFBOAndTexture(); +} + +// Destructor +SceneDemo::~SceneDemo() { + + mShadowMapTexture.destroy(); + mFBOShadowMap.destroy(); +} + +// Render the scene (in multiple passes for shadow mapping) +void SceneDemo::render() { + + glEnable(GL_DEPTH_TEST); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glEnable(GL_CULL_FACE); + + // Get the world-space to camera-space matrix + const openglframework::Matrix4 worldToCameraMatrix = mCamera.getTransformMatrix().getInverse(); + + // ---------- Render the scene to generate the shadow map (first pass) ----------- // + + // Bind the shader + mDepthShader.bind(); + + // Set the variables of the shader + mDepthShader.setMatrix4x4Uniform("projectionMatrix", mCamera.getProjectionMatrix()); + + // Render the objects of the scene + renderSinglePass(mDepthShader); + + // Unbind the shader + mDepthShader.unbind(); + + // ---------- Render the scene for final rendering (second pass) ----------- // + + mPhongShader.bind(); + + // Set the variables of the shader + mPhongShader.setMatrix4x4Uniform("projectionMatrix", mCamera.getProjectionMatrix()); + mPhongShader.setVector3Uniform("light0PosCameraSpace",worldToCameraMatrix * mLight0.getOrigin()); + mPhongShader.setVector3Uniform("lightAmbientColor", Vector3(0.3f, 0.3f, 0.3f)); + const Color& diffCol = mLight0.getDiffuseColor(); + const Color& specCol = mLight0.getSpecularColor(); + mPhongShader.setVector3Uniform("light0DiffuseColor", Vector3(diffCol.r, diffCol.g, diffCol.b)); + mPhongShader.setVector3Uniform("light0SpecularColor", Vector3(specCol.r, specCol.g, specCol.b)); + mPhongShader.setFloatUniform("shininess", 60.0f); + + // Render the objects of the scene + renderSinglePass(mPhongShader); + + mPhongShader.unbind(); +} + +// Create the Shadow map FBO and texture +void SceneDemo::createShadowMapFBOAndTexture() { + + // Create the texture for the depth values + mShadowMapTexture.create(SHADOWMAP_WIDTH, SHADOWMAP_HEIGHT, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, + GL_UNSIGNED_BYTE, GL_NEAREST, GL_NEAREST, GL_CLAMP, GL_CLAMP, NULL); + + // Create the FBO for the shadow map + mFBOShadowMap.create(0, 0, false); + mFBOShadowMap.bind(GL_NONE); + mFBOShadowMap.attachTexture(GL_DEPTH_ATTACHMENT_EXT, mShadowMapTexture.getID()); +} + +// Render the shadow map +void SceneDemo::renderShadowMap() { + +} diff --git a/testbed/src/SceneDemo.h b/testbed/src/SceneDemo.h new file mode 100644 index 00000000..4bcc8d91 --- /dev/null +++ b/testbed/src/SceneDemo.h @@ -0,0 +1,94 @@ +/******************************************************************************** +* ReactPhysics3D physics library, http://www.reactphysics3d.com * +* Copyright (c) 2010-2015 Daniel Chappuis * +********************************************************************************* +* * +* This software is provided 'as-is', without any express or implied warranty. * +* In no event will the authors be held liable for any damages arising from the * +* use of this software. * +* * +* Permission is granted to anyone to use this software for any purpose, * +* including commercial applications, and to alter it and redistribute it * +* freely, subject to the following restrictions: * +* * +* 1. The origin of this software must not be misrepresented; you must not claim * +* that you wrote the original software. If you use this software in a * +* product, an acknowledgment in the product documentation would be * +* appreciated but is not required. * +* * +* 2. Altered source versions must be plainly marked as such, and must not be * +* misrepresented as being the original software. * +* * +* 3. This notice may not be removed or altered from any source distribution. * +* * +********************************************************************************/ + +#ifndef SCENEDEMO_H +#define SCENEDEMO_H + +// Libraries +#include "Scene.h" + +// Constants +const int SHADOWMAP_WIDTH = 1024; +const int SHADOWMAP_HEIGHT = 1024; + +// Class SceneDemo +// Abstract class that represents a 3D scene for the ReactPhysics3D examples. +// This scene has a single light source with shadow mapping. +class SceneDemo : public Scene { + + protected: + + // -------------------- Attributes -------------------- // + + /// Light 0 + openglframework::Light mLight0; + + /// FBO for the shadow map + openglframework::FrameBufferObject mFBOShadowMap; + + /// Shadow map texture + openglframework::Texture2D mShadowMapTexture; + + /// Camera at light0 position for the shadow map + openglframework::Camera mShadowMapLightCamera; + + /// Bias matrix for the shadow map + openglframework::Matrix4 mShadowMapBiasMatrix; + + /// Depth shader to render the shadow map + openglframework::Shader mDepthShader; + + /// Phong shader + openglframework::Shader mPhongShader; + + + // -------------------- Methods -------------------- // + + // Create the Shadow map FBO and texture + void createShadowMapFBOAndTexture(); + + // Render the shadow map + void renderShadowMap(); + + public: + + // -------------------- Methods -------------------- // + + /// Constructor + SceneDemo(const std::string& name, float sceneRadius); + + /// Destructor + virtual ~SceneDemo(); + + /// Render the scene (possibly in multiple passes for shadow mapping) + virtual void render(); + + /// Render the scene in a single pass + virtual void renderSinglePass(openglframework::Shader& shader)=0; +}; + +#endif + +