Refactor handling of textures and shaders

This commit is contained in:
Shaun Reed 2022-11-24 15:30:12 -05:00
parent 08620e33a9
commit 42970781db
9 changed files with 245 additions and 357 deletions

View File

@ -56,7 +56,7 @@ cmake -DASSIMP_NEW_INTERFACE=ON -DQTK_UPDATE_SUBMODULES=OFF -DCMAKE_PREFIX_PATH=
#### Development #### Development
This project uses version `15.0.5` of `clang-format` and `clang-tidy`. This project uses version `15.0.5` of `clang-format`.
Before merging any branch we should run `clang-tidy` followed by `clang-format`. Before merging any branch we should run `clang-tidy` followed by `clang-format`.
```bash ```bash
@ -67,7 +67,6 @@ cmake --build build -j $(nproc --ignore=2)
sudo cmake --build build -j $(nproc --ignore=2) --target install sudo cmake --build build -j $(nproc --ignore=2) --target install
``` ```
After this is done, we can check that for the correct version of `15.0.5`.
If this version is any earlier than `15.0.0`, running `clang-format` will fail because this project uses configuration options made available since `15.0.0`. If this version is any earlier than `15.0.0`, running `clang-format` will fail because this project uses configuration options made available since `15.0.0`.
```bash ```bash
@ -75,7 +74,8 @@ clang-format --version
clang-format version 15.0.5 (git@github.com:llvm/llvm-project.git 154e88af7ec97d9b9f389e55d45bf07108a9a097) clang-format version 15.0.5 (git@github.com:llvm/llvm-project.git 154e88af7ec97d9b9f389e55d45bf07108a9a097)
``` ```
CLion has integration for IDE code reformatting actions with `clang-format`. If you're using CLion, the `.clang-format` configuration will be picked up by CLion automatically. CLion has integration for IDE code reformatting actions with `clang-format`.
If you're using CLion, the `.clang-format` configuration will be picked up by CLion automatically.
`clang-tidy` can be run with the following commands. `clang-tidy` can be run with the following commands.
@ -86,7 +86,7 @@ cd qtk
cmake -B build && cmake --build build cmake -B build && cmake --build build
cd build cd build
# Run clang-tidy from within build directory # Run clang-tidy from within build directory
clang-tidy --fix --config-file=../.clang-tidy ../src/*.cpp ../src/*.h ../app/*.cpp ../app/*.h clang-tidy --fix --fix-errors --config-file=../.clang-tidy ../src/*.cpp ../src/*.h ../app/*.cpp ../app/*.h
``` ```
Last we need to run `clang-format`, this can be done with the command directly. Last we need to run `clang-format`, this can be done with the command directly.

View File

@ -51,103 +51,50 @@ void ExampleScene::init() {
mTestPhong = new Qtk::MeshRenderer("phong", Qtk::Cube()); mTestPhong = new Qtk::MeshRenderer("phong", Qtk::Cube());
mTestPhong->mTransform.setTranslation(3.0f, 0.0f, -2.0f); mTestPhong->mTransform.setTranslation(3.0f, 0.0f, -2.0f);
mTestPhong->setShaders(":/solid-phong.vert", ":/solid-phong.frag"); mTestPhong->setShaders(":/solid-phong.vert", ":/solid-phong.frag");
mTestPhong->init();
mTestPhong->mProgram.bind(); // You no longer need to manually bind shader program.
// + But, you can still bind it if you want to.
// mTestPhong->bindShaders();
mTestPhong->setUniform("uColor", QVector3D(0.0f, 0.25f, 0.0f)); mTestPhong->setUniform("uColor", QVector3D(0.0f, 0.25f, 0.0f));
mTestPhong->setUniform("uLightColor", QVector3D(1.0f, 1.0f, 1.0f)); mTestPhong->setUniform("uLightColor", QVector3D(1.0f, 1.0f, 1.0f));
mTestPhong->setUniform("uAmbientStrength", 0.2f); mTestPhong->setUniform("uAmbientStrength", 0.2f);
mTestPhong->setUniform("uSpecularStrength", 0.50f); mTestPhong->setUniform("uSpecularStrength", 0.50f);
mTestPhong->setUniform("uSpecularShine", 256); mTestPhong->setUniform("uSpecularShine", 256);
mTestPhong->reallocateNormals(mTestPhong->getNormals());
mTestPhong->mVAO.bind(); // mTestPhong->releaseShaders();
mTestPhong->mNBO.create();
mTestPhong->mNBO.setUsagePattern(QOpenGLBuffer::StaticDraw);
mTestPhong->mNBO.bind();
mTestPhong->mNBO.allocate(
mTestPhong->getNormals().data(),
mTestPhong->getNormals().size() * sizeof(mTestPhong->getNormals()[0]));
mTestPhong->mProgram.enableAttributeArray(1);
mTestPhong->mProgram.setAttributeBuffer(1, GL_FLOAT, 0, 3, sizeof(QVector3D));
mTestPhong->mNBO.release();
mTestPhong->mVAO.release();
mTestPhong->mProgram.release();
// Initialize Ambient example cube // Initialize Ambient example cube
mTestAmbient = new Qtk::MeshRenderer("ambient", Cube()); mTestAmbient = new Qtk::MeshRenderer("ambient", Cube());
mTestAmbient->mTransform.setTranslation(7.0f, 0.0f, -2.0f); mTestAmbient->mTransform.setTranslation(7.0f, 0.0f, -2.0f);
mTestAmbient->setShaders(":/solid-ambient.vert", ":/solid-ambient.frag"); mTestAmbient->setShaders(":/solid-ambient.vert", ":/solid-ambient.frag");
mTestAmbient->init(); mTestAmbient->init();
mTestAmbient->mProgram.bind();
mTestAmbient->setUniform("uColor", QVector3D(0.0f, 0.25f, 0.0f)); mTestAmbient->setUniform("uColor", QVector3D(0.0f, 0.25f, 0.0f));
mTestAmbient->setUniform("uLightColor", QVector3D(1.0f, 1.0f, 1.0f)); mTestAmbient->setUniform("uLightColor", QVector3D(1.0f, 1.0f, 1.0f));
mTestAmbient->setUniform("uAmbientStrength", 0.2f); mTestAmbient->setUniform("uAmbientStrength", 0.2f);
mTestAmbient->reallocateNormals(mTestAmbient->getNormals());
mTestAmbient->mVAO.bind();
mTestAmbient->mNBO.create();
mTestAmbient->mNBO.setUsagePattern(QOpenGLBuffer::StaticDraw);
mTestAmbient->mNBO.bind();
mTestAmbient->mNBO.allocate(
mTestAmbient->getNormals().data(),
mTestAmbient->getNormals().size()
* sizeof(mTestAmbient->getNormals()[0]));
mTestAmbient->mProgram.enableAttributeArray(1);
mTestAmbient->mProgram.setAttributeBuffer(
1, GL_FLOAT, 0, 3, sizeof(QVector3D));
mTestAmbient->mNBO.release();
mTestAmbient->mVAO.release();
mTestAmbient->mProgram.release();
// Initialize Diffuse example cube // Initialize Diffuse example cube
mTestDiffuse = new Qtk::MeshRenderer("diffuse", Cube()); mTestDiffuse = new Qtk::MeshRenderer("diffuse", Cube());
mTestDiffuse->mTransform.setTranslation(9.0f, 0.0f, -2.0f); mTestDiffuse->mTransform.setTranslation(9.0f, 0.0f, -2.0f);
mTestDiffuse->setShaders(":/solid-diffuse.vert", ":/solid-diffuse.frag"); mTestDiffuse->setShaders(":/solid-diffuse.vert", ":/solid-diffuse.frag");
mTestDiffuse->init(); mTestDiffuse->init();
mTestDiffuse->mProgram.bind();
mTestDiffuse->setUniform("uColor", QVector3D(0.0f, 0.25f, 0.0f)); mTestDiffuse->setUniform("uColor", QVector3D(0.0f, 0.25f, 0.0f));
mTestDiffuse->setUniform("uLightColor", QVector3D(1.0f, 1.0f, 1.0f)); mTestDiffuse->setUniform("uLightColor", QVector3D(1.0f, 1.0f, 1.0f));
mTestDiffuse->setUniform("uAmbientStrength", 0.2f); mTestDiffuse->setUniform("uAmbientStrength", 0.2f);
mTestDiffuse->reallocateNormals(mTestDiffuse->getNormals());
mTestDiffuse->mVAO.bind();
mTestDiffuse->mNBO.create();
mTestDiffuse->mNBO.setUsagePattern(QOpenGLBuffer::StaticDraw);
mTestDiffuse->mNBO.bind();
mTestDiffuse->mNBO.allocate(
mTestDiffuse->getNormals().data(),
mTestDiffuse->getNormals().size()
* sizeof(mTestDiffuse->getNormals()[0]));
mTestDiffuse->mProgram.enableAttributeArray(1);
mTestDiffuse->mProgram.setAttributeBuffer(
1, GL_FLOAT, 0, 3, sizeof(QVector3D));
mTestDiffuse->mNBO.release();
mTestDiffuse->mVAO.release();
mTestDiffuse->mProgram.release();
// Initialize Specular example cube // Initialize Specular example cube
mTestSpecular = new Qtk::MeshRenderer("specular", Cube()); mTestSpecular = new Qtk::MeshRenderer("specular", Cube());
mTestSpecular->mTransform.setTranslation(11.0f, 0.0f, -2.0f); mTestSpecular->mTransform.setTranslation(11.0f, 0.0f, -2.0f);
mTestSpecular->setShaders(":/solid-specular.vert", ":/solid-specular.frag"); mTestSpecular->setShaders(":/solid-specular.vert", ":/solid-specular.frag");
mTestSpecular->init(); mTestSpecular->init();
mTestSpecular->mProgram.bind();
mTestSpecular->setUniform("uColor", QVector3D(0.0f, 0.25f, 0.0f)); mTestSpecular->setUniform("uColor", QVector3D(0.0f, 0.25f, 0.0f));
mTestSpecular->setUniform("uLightColor", QVector3D(1.0f, 1.0f, 1.0f)); mTestSpecular->setUniform("uLightColor", QVector3D(1.0f, 1.0f, 1.0f));
mTestSpecular->setUniform("uAmbientStrength", 0.2f); mTestSpecular->setUniform("uAmbientStrength", 0.2f);
mTestSpecular->setUniform("uSpecularStrength", 0.50f); mTestSpecular->setUniform("uSpecularStrength", 0.50f);
mTestSpecular->setUniform("uSpecularShine", 256); mTestSpecular->setUniform("uSpecularShine", 256);
mTestSpecular->reallocateNormals(mTestSpecular->getNormals());
mTestSpecular->mVAO.bind();
mTestSpecular->mNBO.create();
mTestSpecular->mNBO.setUsagePattern(QOpenGLBuffer::StaticDraw);
mTestSpecular->mNBO.bind();
mTestSpecular->mNBO.allocate(
mTestSpecular->getNormals().data(),
mTestSpecular->getNormals().size()
* sizeof(mTestSpecular->getNormals()[0]));
mTestSpecular->mProgram.enableAttributeArray(1);
mTestSpecular->mProgram.setAttributeBuffer(
1, GL_FLOAT, 0, 3, sizeof(QVector3D));
mTestSpecular->mNBO.release();
mTestSpecular->mVAO.release();
mTestSpecular->mProgram.release();
// //
// Model loading // Model loading
@ -193,7 +140,6 @@ void ExampleScene::init() {
mMeshes.back()->mTransform.scale(0.25f); mMeshes.back()->mTransform.scale(0.25f);
// This function changes values we have allocated in a buffer, so init() after // This function changes values we have allocated in a buffer, so init() after
mMeshes.back()->setColor(GREEN); mMeshes.back()->setColor(GREEN);
mMeshes.back()->init();
mModels.push_back(new Qtk::Model( mModels.push_back(new Qtk::Model(
"alienTest", ":/models/alien-hominid/alien.obj", ":/model-specular.vert", "alienTest", ":/models/alien-hominid/alien.obj", ":/model-specular.vert",
@ -219,7 +165,6 @@ void ExampleScene::init() {
mMeshes.back()->mTransform.scale(0.25f); mMeshes.back()->mTransform.scale(0.25f);
// This function changes values we have allocated in a buffer, so init() after // This function changes values we have allocated in a buffer, so init() after
mMeshes.back()->setColor(GREEN); mMeshes.back()->setColor(GREEN);
mMeshes.back()->init();
mModels.push_back(new Qtk::Model( mModels.push_back(new Qtk::Model(
"spartanTest", ":/models/spartan/spartan.obj", ":/model-normals.vert", "spartanTest", ":/models/spartan/spartan.obj", ":/model-normals.vert",
@ -245,33 +190,15 @@ void ExampleScene::init() {
mMeshes.back()->setDrawType(GL_LINE_LOOP); mMeshes.back()->setDrawType(GL_LINE_LOOP);
// This function changes values we have allocated in a buffer, so init() after // This function changes values we have allocated in a buffer, so init() after
mMeshes.back()->setColor(GREEN); mMeshes.back()->setColor(GREEN);
mMeshes.back()->init();
mMeshes.push_back(new Qtk::MeshRenderer("testPhong", Cube(QTK_DRAW_ARRAYS))); mMeshes.push_back(new Qtk::MeshRenderer("testPhong", Cube(QTK_DRAW_ARRAYS)));
mMeshes.back()->mTransform.setTranslation(5.0f, 0.0f, 10.0f); mMeshes.back()->mTransform.setTranslation(5.0f, 0.0f, 10.0f);
mMeshes.back()->setShaders(":/phong.vert", ":/phong.frag"); mMeshes.back()->setShaders(":/phong.vert", ":/phong.frag");
mMeshes.back()->setColor(QVector3D(0.0f, 0.25f, 0.0f)); mMeshes.back()->setColor(QVector3D(0.0f, 0.25f, 0.0f));
mMeshes.back()->init(); mMeshes.back()->reallocateNormals(mMeshes.back()->getNormals());
mMeshes.back()->mProgram.bind();
mMeshes.back()->mVAO.bind();
mMeshes.back()->mNBO.create();
mMeshes.back()->mNBO.bind();
mMeshes.back()->mNBO.allocate(
mMeshes.back()->getNormals().data(),
mMeshes.back()->getNormals().size()
* sizeof(mMeshes.back()->getNormals()[0]));
mMeshes.back()->mProgram.enableAttributeArray(1);
mMeshes.back()->mProgram.setAttributeBuffer(
1, GL_FLOAT, 0, 3, sizeof(QVector3D));
mMeshes.back()->mNBO.release();
mMeshes.back()->mVAO.release();
mMeshes.back()->setUniform("uMaterial.ambient", QVector3D(0.0f, 0.3f, 0.0f)); mMeshes.back()->setUniform("uMaterial.ambient", QVector3D(0.0f, 0.3f, 0.0f));
mMeshes.back()->setUniform("uMaterial.diffuse", QVector3D(0.0f, 0.2f, 0.0f)); mMeshes.back()->setUniform("uMaterial.diffuse", QVector3D(0.0f, 0.2f, 0.0f));
mMeshes.back()->setUniform("uMaterial.specular", QVector3D(1.0f, 1.0f, 1.0f)); mMeshes.back()->setUniform("uMaterial.specular", QVector3D(1.0f, 1.0f, 1.0f));
mMeshes.back()->setUniform("uMaterial.ambientStrength", 1.0f); mMeshes.back()->setUniform("uMaterial.ambientStrength", 1.0f);
mMeshes.back()->setUniform("uMaterial.diffuseStrength", 1.0f); mMeshes.back()->setUniform("uMaterial.diffuseStrength", 1.0f);
@ -282,7 +209,6 @@ void ExampleScene::init() {
mMeshes.back()->setUniform("uLight.specular", QVector3D(0.62f, 0.55f, 0.37f)); mMeshes.back()->setUniform("uLight.specular", QVector3D(0.62f, 0.55f, 0.37f));
mMeshes.back()->setUniform("uColor", QVector3D(0.0f, 0.25f, 0.0f)); mMeshes.back()->setUniform("uColor", QVector3D(0.0f, 0.25f, 0.0f));
mMeshes.back()->mProgram.release();
// //
// Create simple shapes using MeshRenderer class and data in mesh.h // Create simple shapes using MeshRenderer class and data in mesh.h
@ -312,7 +238,6 @@ void ExampleScene::init() {
mMeshes.back()->setDrawType(GL_LINE_LOOP); mMeshes.back()->setDrawType(GL_LINE_LOOP);
// This function changes values we have allocated in a buffer, so init() after // This function changes values we have allocated in a buffer, so init() after
mMeshes.back()->setColor(GREEN); mMeshes.back()->setColor(GREEN);
mMeshes.back()->init();
// //
// Testing for normals, texture coordinates // Testing for normals, texture coordinates
@ -322,46 +247,25 @@ void ExampleScene::init() {
new Qtk::MeshRenderer("rgbNormalsCubeArraysTest", Cube(QTK_DRAW_ARRAYS))); new Qtk::MeshRenderer("rgbNormalsCubeArraysTest", Cube(QTK_DRAW_ARRAYS)));
mMeshes.back()->mTransform.setTranslation(5.0f, 0.0f, 4.0f); mMeshes.back()->mTransform.setTranslation(5.0f, 0.0f, 4.0f);
mMeshes.back()->setShaders(":/rgb-normals.vert", ":/rgb-normals.frag"); mMeshes.back()->setShaders(":/rgb-normals.vert", ":/rgb-normals.frag");
mMeshes.back()->init(); mMeshes.back()->reallocateNormals(mMeshes.back()->getNormals());
mMeshes.back()->mVAO.bind();
mMeshes.back()->mNBO.create();
mMeshes.back()->mNBO.bind();
mMeshes.back()->mProgram.bind();
mMeshes.back()->mNBO.allocate(
mMeshes.back()->getNormals().data(),
mMeshes.back()->getNormals().size()
* sizeof(mMeshes.back()->getNormals()[0]));
mMeshes.back()->mProgram.enableAttributeArray(1);
mMeshes.back()->mProgram.setAttributeBuffer(
1, GL_FLOAT, 0, 3, sizeof(QVector3D));
mMeshes.back()->mProgram.release();
mMeshes.back()->mNBO.release();
mMeshes.back()->mVAO.release();
// RGB Normals cube to show normals are correct with QTK_DRAW_ELEMENTS_NORMALS // RGB Normals cube to show normals are correct with QTK_DRAW_ELEMENTS_NORMALS
mMeshes.push_back(new Qtk::MeshRenderer( mMeshes.push_back(new Qtk::MeshRenderer(
"rgbNormalsCubeElementsTest", Cube(QTK_DRAW_ELEMENTS_NORMALS))); "rgbNormalsCubeElementsTest", Cube(QTK_DRAW_ELEMENTS_NORMALS)));
mMeshes.back()->mTransform.setTranslation(5.0f, 0.0f, 2.0f); mMeshes.back()->mTransform.setTranslation(5.0f, 0.0f, 2.0f);
mMeshes.back()->setShaders(":/rgb-normals.vert", ":/rgb-normals.frag"); mMeshes.back()->setShaders(":/rgb-normals.vert", ":/rgb-normals.frag");
mMeshes.back()->init(); mMeshes.back()->reallocateNormals(mMeshes.back()->getNormals());
mMeshes.back()->mVAO.bind();
mMeshes.back()->mNBO.create();
mMeshes.back()->mNBO.bind();
mMeshes.back()->mProgram.bind();
mMeshes.back()->mNBO.allocate( Texture crateTexture;
mMeshes.back()->getNormals().data(), crateTexture.setTexture(":/crate.png");
mMeshes.back()->getNormals().size() Cube cube;
* sizeof(mMeshes.back()->getNormals()[0])); auto * m = new MeshRenderer("Test Crate", Cube(QTK_DRAW_ARRAYS));
mMeshes.back()->mProgram.enableAttributeArray(1); m->mTransform.setTranslation(0, 0, 13);
mMeshes.back()->mProgram.setAttributeBuffer( m->setShaders(":/texture2d.vert", ":/texture2d.frag");
1, GL_FLOAT, 0, 3, sizeof(QVector3D)); m->setTexture(crateTexture);
m->setUniform("uTexture", 0);
mMeshes.back()->mProgram.release(); m->reallocateTexCoords(cube.getTexCoords());
mMeshes.back()->mNBO.release(); mMeshes.push_back(m);
mMeshes.back()->mVAO.release();
// Texturing a cube using texture coordinates and glDrawArrays // Texturing a cube using texture coordinates and glDrawArrays
// + Texturing with UVs using glDrawElements requires // + Texturing with UVs using glDrawElements requires
@ -372,53 +276,21 @@ void ExampleScene::init() {
new Qtk::MeshRenderer("uvCubeArraysTest", Cube(QTK_DRAW_ARRAYS))); new Qtk::MeshRenderer("uvCubeArraysTest", Cube(QTK_DRAW_ARRAYS)));
mMeshes.back()->mTransform.setTranslation(-3.0f, 0.0f, -2.0f); mMeshes.back()->mTransform.setTranslation(-3.0f, 0.0f, -2.0f);
mMeshes.back()->setShaders(":/texture2d.vert", ":/texture2d.frag"); mMeshes.back()->setShaders(":/texture2d.vert", ":/texture2d.frag");
mMeshes.back()->init(); mMeshes.back()->setTexture(crateTexture);
mMeshes.back()->mProgram.bind();
mMeshes.back()->setTexture(
OpenGLTextureFactory::initTexture2D(":/crate.png"));
mMeshes.back()->setUniform("uTexture", 0); mMeshes.back()->setUniform("uTexture", 0);
mMeshes.back()->reallocateTexCoords(mMeshes.back()->getTexCoords());
mMeshes.back()->mVAO.bind();
mMeshes.back()->mNBO.destroy();
mMeshes.back()->mNBO.create();
mMeshes.back()->mNBO.bind();
mMeshes.back()->mNBO.allocate(
mMeshes.back()->mShape.getTexCoords().data(),
mMeshes.back()->mShape.getTexCoords().size()
* sizeof(mMeshes.back()->mShape.getTexCoords()[0]));
mMeshes.back()->mProgram.enableAttributeArray(1);
mMeshes.back()->mProgram.setAttributeBuffer(
1, GL_FLOAT, 0, 2, sizeof(QVector2D));
mMeshes.back()->mNBO.release();
mMeshes.back()->mVAO.release();
mMeshes.back()->mProgram.release();
// Test drawing a cube with texture coordinates using glDrawElements // Test drawing a cube with texture coordinates using glDrawElements
mMeshes.push_back(new Qtk::MeshRenderer( mMeshes.push_back(new Qtk::MeshRenderer(
"uvCubeElementsTest", Cube(QTK_DRAW_ELEMENTS_NORMALS))); "uvCubeElementsTest", Cube(QTK_DRAW_ELEMENTS_NORMALS)));
mMeshes.back()->mTransform.setTranslation(-1.7f, 0.0f, -2.0f); mMeshes.back()->mTransform.setTranslation(-1.7f, 0.0f, -2.0f);
mMeshes.back()->setTexture(":/crate.png");
mMeshes.back()->setShaders(":/texture2d.vert", ":/texture2d.frag"); mMeshes.back()->setShaders(":/texture2d.vert", ":/texture2d.frag");
mMeshes.back()->init(); mMeshes.back()->bindShaders();
mMeshes.back()->mVAO.bind(); mMeshes.back()->setUniform("uTexture", 0);
mMeshes.back()->mNBO.create(); mMeshes.back()->reallocateNormals(mMeshes.back()->getNormals());
mMeshes.back()->mNBO.bind(); mMeshes.back()->reallocateTexCoords(mMeshes.back()->getTexCoords(), 3);
mMeshes.back()->mProgram.bind(); mMeshes.back()->releaseShaders();
mMeshes.back()->mNBO.allocate(
mMeshes.back()->getTexCoords().data(),
mMeshes.back()->getTexCoords().size()
* sizeof(mMeshes.back()->getTexCoords()[0]));
mMeshes.back()->mProgram.enableAttributeArray(1);
mMeshes.back()->mProgram.setAttributeBuffer(
1, GL_FLOAT, 0, 3, sizeof(QVector3D));
mMeshes.back()->setTexture(
OpenGLTextureFactory::initTexture2D(":/crate.png"));
mMeshes.back()->mProgram.setUniformValue("uTexture", 0);
mMeshes.back()->mProgram.release();
mMeshes.back()->mNBO.release();
mMeshes.back()->mVAO.release();
mMeshes.back()->mTransform.rotate(45.0f, 0.0f, 1.0f, 0.0f); mMeshes.back()->mTransform.rotate(45.0f, 0.0f, 1.0f, 0.0f);
// Texturing a cube using a cube map // Texturing a cube using a cube map
@ -429,26 +301,9 @@ void ExampleScene::init() {
mMeshes.back()->mTransform.setRotation(45.0f, 0.0f, 1.0f, 0.0f); mMeshes.back()->mTransform.setRotation(45.0f, 0.0f, 1.0f, 0.0f);
mMeshes.back()->setShaders( mMeshes.back()->setShaders(
":/texture-cubemap.vert", ":/texture-cubemap.frag"); ":/texture-cubemap.vert", ":/texture-cubemap.frag");
mMeshes.back()->init(); mMeshes.back()->setCubeMap(":/crate.png");
mMeshes.back()->mProgram.bind();
mMeshes.back()->setTexture(OpenGLTextureFactory::initCubeMap(":/crate.png"));
mMeshes.back()->setUniform("uTexture", 0); mMeshes.back()->setUniform("uTexture", 0);
mMeshes.back()->reallocateTexCoords(mMeshes.back()->getTexCoords());
mMeshes.back()->mVAO.bind();
mMeshes.back()->mNBO.destroy();
mMeshes.back()->mNBO.create();
mMeshes.back()->mNBO.bind();
mMeshes.back()->mNBO.allocate(
mMeshes.back()->mShape.getTexCoords().data(),
mMeshes.back()->mShape.getTexCoords().size()
* sizeof(mMeshes.back()->mShape.getTexCoords()[0]));
mMeshes.back()->mProgram.enableAttributeArray(1);
mMeshes.back()->mProgram.setAttributeBuffer(
1, GL_FLOAT, 0, 2, sizeof(QVector2D));
mMeshes.back()->mNBO.release();
mMeshes.back()->mVAO.release();
mMeshes.back()->mProgram.release();
// Create a cube with custom shaders // Create a cube with custom shaders
// + Apply RGB normals shader and spin the cube for a neat effect // + Apply RGB normals shader and spin the cube for a neat effect
@ -456,120 +311,40 @@ void ExampleScene::init() {
new Qtk::MeshRenderer("rgbNormalsCube", Cube(QTK_DRAW_ARRAYS))); new Qtk::MeshRenderer("rgbNormalsCube", Cube(QTK_DRAW_ARRAYS)));
mMeshes.back()->mTransform.setTranslation(5.0f, 2.0f, -2.0f); mMeshes.back()->mTransform.setTranslation(5.0f, 2.0f, -2.0f);
mMeshes.back()->setShaders(":/rgb-normals.vert", ":/rgb-normals.frag"); mMeshes.back()->setShaders(":/rgb-normals.vert", ":/rgb-normals.frag");
mMeshes.back()->init(); mMeshes.back()->reallocateNormals(mMeshes.back()->getNormals());
mMeshes.back()->mVAO.bind();
mMeshes.back()->mNBO.create();
mMeshes.back()->mNBO.bind();
mMeshes.back()->mProgram.bind();
mMeshes.back()->mNBO.allocate(
mMeshes.back()->getNormals().data(),
mMeshes.back()->getNormals().size()
* sizeof(mMeshes.back()->getNormals()[0]));
mMeshes.back()->mProgram.enableAttributeArray(1);
mMeshes.back()->mProgram.setAttributeBuffer(
1, GL_FLOAT, 0, 3, sizeof(QVector3D));
mMeshes.back()->mProgram.release();
mMeshes.back()->mNBO.release();
mMeshes.back()->mVAO.release();
// RGB Normals triangle to show normals are correct with QTK_DRAW_ARRAYS // RGB Normals triangle to show normals are correct with QTK_DRAW_ARRAYS
mMeshes.push_back(new Qtk::MeshRenderer( mMeshes.push_back(new Qtk::MeshRenderer(
"rgbTriangleArraysTest", Triangle(QTK_DRAW_ARRAYS))); "rgbTriangleArraysTest", Triangle(QTK_DRAW_ARRAYS)));
mMeshes.back()->mTransform.setTranslation(7.0f, 0.0f, 2.0f); mMeshes.back()->mTransform.setTranslation(7.0f, 0.0f, 2.0f);
mMeshes.back()->setShaders(":/rgb-normals.vert", ":/rgb-normals.frag"); mMeshes.back()->setShaders(":/rgb-normals.vert", ":/rgb-normals.frag");
mMeshes.back()->init(); mMeshes.back()->reallocateNormals(mMeshes.back()->getNormals());
mMeshes.back()->mProgram.bind();
mMeshes.back()->mVAO.bind();
mMeshes.back()->mNBO.create();
mMeshes.back()->mNBO.bind();
mMeshes.back()->mNBO.allocate(
mMeshes.back()->getNormals().data(),
mMeshes.back()->getNormals().size()
* sizeof(mMeshes.back()->getNormals()[0]));
mMeshes.back()->mProgram.enableAttributeArray(1);
mMeshes.back()->mProgram.setAttributeBuffer(
1, GL_FLOAT, 0, 3, sizeof(QVector3D));
mMeshes.back()->mNBO.release();
mMeshes.back()->mVAO.release();
mMeshes.back()->mProgram.release();
// RGB Normals triangle to show normals are correct with QTK_DRAW_ELEMENTS // RGB Normals triangle to show normals are correct with QTK_DRAW_ELEMENTS
mMeshes.push_back(new Qtk::MeshRenderer( mMeshes.push_back(new Qtk::MeshRenderer(
"rgbTriangleElementsTest", Triangle(QTK_DRAW_ELEMENTS_NORMALS))); "rgbTriangleElementsTest", Triangle(QTK_DRAW_ELEMENTS_NORMALS)));
mMeshes.back()->mTransform.setTranslation(7.0f, 0.0f, 4.0f); mMeshes.back()->mTransform.setTranslation(7.0f, 0.0f, 4.0f);
mMeshes.back()->setShaders(":/rgb-normals.vert", ":/rgb-normals.frag"); mMeshes.back()->setShaders(":/rgb-normals.vert", ":/rgb-normals.frag");
mMeshes.back()->init(); mMeshes.back()->reallocateNormals(mMeshes.back()->getNormals());
mMeshes.back()->mProgram.bind();
mMeshes.back()->mVAO.bind();
mMeshes.back()->mNBO.create();
mMeshes.back()->mNBO.bind();
mMeshes.back()->mNBO.allocate(
mMeshes.back()->getNormals().data(),
mMeshes.back()->getNormals().size()
* sizeof(mMeshes.back()->getNormals()[0]));
mMeshes.back()->mProgram.enableAttributeArray(1);
mMeshes.back()->mProgram.setAttributeBuffer(
1, GL_FLOAT, 0, 3, sizeof(QVector3D));
mMeshes.back()->mNBO.release();
mMeshes.back()->mVAO.release();
mMeshes.back()->mProgram.release();
// Test drawing triangle with glDrawArrays with texture coordinates // Test drawing triangle with glDrawArrays with texture coordinates
mMeshes.push_back( mMeshes.push_back(
new Qtk::MeshRenderer("testTriangleArraysUV", Triangle(QTK_DRAW_ARRAYS))); new Qtk::MeshRenderer("testTriangleArraysUV", Triangle(QTK_DRAW_ARRAYS)));
mMeshes.back()->mTransform.setTranslation(-3.0f, 2.0f, -2.0f); mMeshes.back()->mTransform.setTranslation(-3.0f, 2.0f, -2.0f);
mMeshes.back()->setShaders(":/texture2d.vert", ":/texture2d.frag"); mMeshes.back()->setShaders(":/texture2d.vert", ":/texture2d.frag");
mMeshes.back()->init();
mMeshes.back()->mProgram.bind();
mMeshes.back()->setTexture(":/crate.png"); mMeshes.back()->setTexture(":/crate.png");
mMeshes.back()->setUniform("uTexture", 0); mMeshes.back()->setUniform("uTexture", 0);
mMeshes.back()->reallocateTexCoords(mMeshes.back()->getTexCoords());
mMeshes.back()->mVAO.bind();
mMeshes.back()->mNBO.destroy();
mMeshes.back()->mNBO.create();
mMeshes.back()->mNBO.bind();
mMeshes.back()->mNBO.allocate(
mMeshes.back()->mShape.getTexCoords().data(),
mMeshes.back()->mShape.getTexCoords().size()
* sizeof(mMeshes.back()->mShape.getTexCoords()[0]));
mMeshes.back()->mProgram.enableAttributeArray(1);
mMeshes.back()->mProgram.setAttributeBuffer(
1, GL_FLOAT, 0, 2, sizeof(QVector2D));
mMeshes.back()->mNBO.release();
mMeshes.back()->mVAO.release();
mMeshes.back()->mProgram.release();
// Test drawing triangle with glDrawElements with texture coordinates // Test drawing triangle with glDrawElements with texture coordinates
mMeshes.push_back(new Qtk::MeshRenderer( mMeshes.push_back(new Qtk::MeshRenderer(
"testTriangleElementsUV", Triangle(QTK_DRAW_ELEMENTS_NORMALS))); "testTriangleElementsUV", Triangle(QTK_DRAW_ELEMENTS_NORMALS)));
mMeshes.back()->mTransform.setTranslation(-2.5f, 0.0f, -1.0f); mMeshes.back()->mTransform.setTranslation(-2.5f, 0.0f, -1.0f);
mMeshes.back()->setShaders(":/texture2d.vert", ":/texture2d.frag"); mMeshes.back()->setShaders(":/texture2d.vert", ":/texture2d.frag");
mMeshes.back()->init(); mMeshes.back()->setTexture(":/crate.png");
mMeshes.back()->mProgram.bind();
// mMeshes.back()->setTexture(OpenGLTextureFactory::initTexture2D(":/crate.png"));
mMeshes.back()->mTexture.setTexture(":/crate.png");
mMeshes.back()->setUniform("uTexture", 0); mMeshes.back()->setUniform("uTexture", 0);
mMeshes.back()->reallocateTexCoords(mMeshes.back()->getTexCoords());
mMeshes.back()->mVAO.bind();
mMeshes.back()->mNBO.destroy();
mMeshes.back()->mNBO.create();
mMeshes.back()->mNBO.bind();
mMeshes.back()->mNBO.allocate(
mMeshes.back()->mShape.getTexCoords().data(),
mMeshes.back()->mShape.getTexCoords().size()
* sizeof(mMeshes.back()->mShape.getTexCoords()[0]));
mMeshes.back()->mProgram.enableAttributeArray(1);
mMeshes.back()->mProgram.setAttributeBuffer(
1, GL_FLOAT, 0, 2, sizeof(QVector2D));
mMeshes.back()->mNBO.release();
mMeshes.back()->mVAO.release();
mMeshes.back()->mProgram.release();
// //
// Lighting cube examples // Lighting cube examples
@ -579,10 +354,7 @@ void ExampleScene::init() {
mMeshes.back()->mTransform.setTranslation(5.0f, 0.0f, -2.0f); mMeshes.back()->mTransform.setTranslation(5.0f, 0.0f, -2.0f);
mMeshes.back()->setShaders( mMeshes.back()->setShaders(
":/solid-perspective.vert", ":/solid-perspective.frag"); ":/solid-perspective.vert", ":/solid-perspective.frag");
mMeshes.back()->init();
mMeshes.back()->mProgram.bind();
mMeshes.back()->setUniform("uColor", QVector3D(0.0f, 0.25f, 0.0f)); mMeshes.back()->setUniform("uColor", QVector3D(0.0f, 0.25f, 0.0f));
mMeshes.back()->mProgram.release();
// Create objects that represent light sources for lighting examples // Create objects that represent light sources for lighting examples
mMeshes.push_back( mMeshes.push_back(
@ -612,7 +384,7 @@ void ExampleScene::draw() {
mesh->draw(); mesh->draw();
} }
mTestPhong->mProgram.bind(); mTestPhong->bindShaders();
mTestPhong->setUniform( mTestPhong->setUniform(
"uModelInverseTransposed", "uModelInverseTransposed",
mTestPhong->mTransform.toMatrix().normalMatrix()); mTestPhong->mTransform.toMatrix().normalMatrix());
@ -621,16 +393,16 @@ void ExampleScene::draw() {
MeshRenderer::getInstance("phongLight")->mTransform.getTranslation()); MeshRenderer::getInstance("phongLight")->mTransform.getTranslation());
mTestPhong->setUniform( mTestPhong->setUniform(
"uCameraPosition", ExampleScene::Camera().transform().getTranslation()); "uCameraPosition", ExampleScene::Camera().transform().getTranslation());
mTestPhong->mProgram.release(); mTestPhong->releaseShaders();
mTestPhong->draw(); mTestPhong->draw();
mTestAmbient->mProgram.bind(); mTestAmbient->bindShaders();
mTestAmbient->setUniform( mTestAmbient->setUniform(
"uCameraPosition", ExampleScene::Camera().transform().getTranslation()); "uCameraPosition", ExampleScene::Camera().transform().getTranslation());
mTestAmbient->mProgram.release(); mTestAmbient->releaseShaders();
mTestAmbient->draw(); mTestAmbient->draw();
mTestDiffuse->mProgram.bind(); mTestDiffuse->bindShaders();
mTestDiffuse->setUniform( mTestDiffuse->setUniform(
"uModelInverseTransposed", "uModelInverseTransposed",
mTestDiffuse->mTransform.toMatrix().normalMatrix()); mTestDiffuse->mTransform.toMatrix().normalMatrix());
@ -639,10 +411,10 @@ void ExampleScene::draw() {
MeshRenderer::getInstance("diffuseLight")->mTransform.getTranslation()); MeshRenderer::getInstance("diffuseLight")->mTransform.getTranslation());
mTestDiffuse->setUniform( mTestDiffuse->setUniform(
"uCameraPosition", ExampleScene::Camera().transform().getTranslation()); "uCameraPosition", ExampleScene::Camera().transform().getTranslation());
mTestDiffuse->mProgram.release(); mTestDiffuse->releaseShaders();
mTestDiffuse->draw(); mTestDiffuse->draw();
mTestSpecular->mProgram.bind(); mTestSpecular->bindShaders();
mTestSpecular->setUniform( mTestSpecular->setUniform(
"uModelInverseTransposed", "uModelInverseTransposed",
mTestSpecular->mTransform.toMatrix().normalMatrix()); mTestSpecular->mTransform.toMatrix().normalMatrix());
@ -651,65 +423,51 @@ void ExampleScene::draw() {
MeshRenderer::getInstance("specularLight")->mTransform.getTranslation()); MeshRenderer::getInstance("specularLight")->mTransform.getTranslation());
mTestSpecular->setUniform( mTestSpecular->setUniform(
"uCameraPosition", ExampleScene::Camera().transform().getTranslation()); "uCameraPosition", ExampleScene::Camera().transform().getTranslation());
mTestSpecular->mProgram.release(); mTestSpecular->releaseShaders();
mTestSpecular->draw(); mTestSpecular->draw();
} }
void ExampleScene::update() { void ExampleScene::update() {
auto position = auto position =
MeshRenderer::getInstance("alienTestLight")->mTransform.getTranslation(); MeshRenderer::getInstance("alienTestLight")->mTransform.getTranslation();
Model::getInstance("alienTest")->setUniform("uLight.position", position); auto alien = Model::getInstance("alienTest");
Model::getInstance("alienTest") alien->setUniform("uLight.position", position);
->setUniform( alien->setUniform(
"uCameraPosition", "uCameraPosition", ExampleScene::Camera().transform().getTranslation());
ExampleScene::Camera().transform().getTranslation()); auto posMatrix = alien->mTransform.toMatrix();
auto posMatrix = Model::getInstance("alienTest")->mTransform.toMatrix(); alien->setUniform("uMVP.normalMatrix", posMatrix.normalMatrix());
Model::getInstance("alienTest") alien->setUniform("uMVP.model", posMatrix);
->setUniform("uMVP.normalMatrix", posMatrix.normalMatrix()); alien->setUniform("uMVP.view", ExampleScene::Camera().toMatrix());
Model::getInstance("alienTest")->setUniform("uMVP.model", posMatrix); alien->setUniform("uMVP.projection", ExampleScene::Projection());
Model::getInstance("alienTest") alien->mTransform.rotate(0.75f, 0.0f, 1.0f, 0.0f);
->setUniform("uMVP.view", ExampleScene::Camera().toMatrix());
Model::getInstance("alienTest")
->setUniform("uMVP.projection", ExampleScene::Projection());
Model::getInstance("alienTest")->mTransform.rotate(0.75f, 0.0f, 1.0f, 0.0f);
position = MeshRenderer::getInstance("spartanTestLight") position = MeshRenderer::getInstance("spartanTestLight")
->mTransform.getTranslation(); ->mTransform.getTranslation();
Model::getInstance("spartanTest")->setUniform("uLight.position", position); auto spartan = Model::getInstance("spartanTest");
Model::getInstance("spartanTest") spartan->setUniform("uLight.position", position);
->setUniform( spartan->setUniform(
"uCameraPosition", "uCameraPosition", ExampleScene::Camera().transform().getTranslation());
ExampleScene::Camera().transform().getTranslation()); posMatrix = spartan->mTransform.toMatrix();
posMatrix = Model::getInstance("spartanTest")->mTransform.toMatrix(); spartan->setUniform("uMVP.normalMatrix", posMatrix.normalMatrix());
Model::getInstance("spartanTest") spartan->setUniform("uMVP.model", posMatrix);
->setUniform("uMVP.normalMatrix", posMatrix.normalMatrix()); spartan->setUniform("uMVP.view", ExampleScene::Camera().toMatrix());
Model::getInstance("spartanTest")->setUniform("uMVP.model", posMatrix); spartan->setUniform("uMVP.projection", ExampleScene::Projection());
Model::getInstance("spartanTest") spartan->mTransform.rotate(0.75f, 0.0f, 1.0f, 0.0f);
->setUniform("uMVP.view", ExampleScene::Camera().toMatrix());
Model::getInstance("spartanTest")
->setUniform("uMVP.projection", ExampleScene::Projection());
Model::getInstance("spartanTest")->mTransform.rotate(0.75f, 0.0f, 1.0f, 0.0f);
MeshRenderer::getInstance("testPhong") auto phong = MeshRenderer::getInstance("testPhong");
->mTransform.rotate(0.75f, 1.0f, 0.5f, 0.0f); phong->mTransform.rotate(0.75f, 1.0f, 0.5f, 0.0f);
MeshRenderer::getInstance("testPhong")->mProgram.bind(); phong->bindShaders();
position = position =
MeshRenderer::getInstance("testLight")->mTransform.getTranslation(); MeshRenderer::getInstance("testLight")->mTransform.getTranslation();
MeshRenderer::getInstance("testPhong") phong->setUniform("uLight.position", position);
->setUniform("uLight.position", position); phong->setUniform(
MeshRenderer::getInstance("testPhong") "uCameraPosition", ExampleScene::Camera().transform().getTranslation());
->setUniform( posMatrix = phong->mTransform.toMatrix();
"uCameraPosition", phong->setUniform("uMVP.normalMatrix", posMatrix.normalMatrix());
ExampleScene::Camera().transform().getTranslation()); phong->setUniform("uMVP.model", posMatrix);
posMatrix = MeshRenderer::getInstance("testPhong")->mTransform.toMatrix(); phong->setUniform("uMVP.view", ExampleScene::Camera().toMatrix());
MeshRenderer::getInstance("testPhong") phong->setUniform("uMVP.projection", ExampleScene::Projection());
->setUniform("uMVP.normalMatrix", posMatrix.normalMatrix()); phong->releaseShaders();
MeshRenderer::getInstance("testPhong")->setUniform("uMVP.model", posMatrix);
MeshRenderer::getInstance("testPhong")
->setUniform("uMVP.view", ExampleScene::Camera().toMatrix());
MeshRenderer::getInstance("testPhong")
->setUniform("uMVP.projection", ExampleScene::Projection());
MeshRenderer::getInstance("testPhong")->mProgram.release();
// Rotate lighting example cubes // Rotate lighting example cubes
mTestPhong->mTransform.rotate(0.75f, 0.5f, 0.3f, 0.2f); mTestPhong->mTransform.rotate(0.75f, 0.5f, 0.3f, 0.2f);

View File

@ -77,6 +77,7 @@ namespace Qtk {
#define UV_RIGHT QVector2D(0.0f, 1.0f) #define UV_RIGHT QVector2D(0.0f, 1.0f)
#define UV_CORNER QVector2D(1.0f, 1.0f) #define UV_CORNER QVector2D(1.0f, 1.0f)
// TODO: Vertices.getData(); Vertices.getStride();
typedef std::vector<QVector3D> Vertices; typedef std::vector<QVector3D> Vertices;
typedef std::vector<QVector3D> Colors; typedef std::vector<QVector3D> Colors;
typedef std::vector<GLuint> Indices; typedef std::vector<GLuint> Indices;
@ -93,10 +94,10 @@ namespace Qtk {
explicit ShapeBase( explicit ShapeBase(
DrawMode mode = QTK_DRAW_ARRAYS, Vertices v = {}, Indices i = {}, DrawMode mode = QTK_DRAW_ARRAYS, Vertices v = {}, Indices i = {},
Colors c = {}, TexCoords t = {}, Normals n = {}) : Colors c = {}, TexCoords t = {}, Normals n = {}) :
mVertices(std::move(std::move(v))), mDrawMode(mode),
mColors(std::move(std::move(c))), mIndices(std::move(std::move(i))), mVertices(std::move(v)), mColors(std::move(c)),
mTexCoords(std::move(std::move(t))), mIndices(std::move(i)), mTexCoords(std::move(t)),
mNormals(std::move(std::move(n))) {} mNormals(std::move(n)) {}
[[nodiscard]] inline const Vertices & getVertices() const { [[nodiscard]] inline const Vertices & getVertices() const {
return mVertices; return mVertices;
@ -116,6 +117,10 @@ namespace Qtk {
return mNormals; return mNormals;
} }
[[nodiscard]] inline size_t getTexCoordsStride() const {
return mTexCoords.size() * sizeof(mTexCoords[0]);
}
protected: protected:
DrawMode mDrawMode; DrawMode mDrawMode;

View File

@ -19,8 +19,7 @@ Qtk::MeshRenderer::MeshManager Qtk::MeshRenderer::sInstances;
MeshRenderer::MeshRenderer(const char * name, const ShapeBase & shape) : MeshRenderer::MeshRenderer(const char * name, const ShapeBase & shape) :
Object(name, shape), mVertexShader(":/multi-color.vert"), Object(name, shape), mVertexShader(":/multi-color.vert"),
mFragmentShader(":/multi-color.frag"), mDrawType(GL_TRIANGLES), mFragmentShader(":/multi-color.frag"), mDrawType(GL_TRIANGLES) {
mHasTexture(false) {
mShape = Shape(shape); mShape = Shape(shape);
init(); init();
sInstances.insert(name, this); sInstances.insert(name, this);
@ -89,7 +88,7 @@ void MeshRenderer::init() {
} }
void MeshRenderer::draw() { void MeshRenderer::draw() {
mProgram.bind(); bindShaders();
mVAO.bind(); mVAO.bind();
if(mTexture.hasTexture()) { if(mTexture.hasTexture()) {
@ -114,17 +113,19 @@ void MeshRenderer::draw() {
} }
mVAO.release(); mVAO.release();
mProgram.release(); releaseShaders();
} }
void MeshRenderer::setShaders( void MeshRenderer::setShaders(
const std::string & vert, const std::string & frag) { const std::string & vert, const std::string & frag) {
mVertexShader = vert; mVertexShader = vert;
mFragmentShader = frag; mFragmentShader = frag;
init();
} }
void MeshRenderer::setUniformMVP( void MeshRenderer::setUniformMVP(
const char * model, const char * view, const char * projection) { const char * model, const char * view, const char * projection) {
ShaderBindScope lock(&mProgram, mBound);
mProgram.setUniformValue(projection, Scene::Projection()); mProgram.setUniformValue(projection, Scene::Projection());
mProgram.setUniformValue(view, Scene::View()); mProgram.setUniformValue(view, Scene::View());
mProgram.setUniformValue(model, mTransform.toMatrix()); mProgram.setUniformValue(model, mTransform.toMatrix());
@ -142,6 +143,39 @@ void MeshRenderer::setColor(const QVector3D & color) {
} }
} }
void MeshRenderer::reallocateTexCoords(const TexCoords & t, unsigned dims) {
mVAO.bind();
mNBO.destroy();
mNBO.create();
mNBO.bind();
mNBO.allocate(t.data(), t.size() * sizeof(t[0]));
enableAttributeArray(1);
if(dims == 2) {
setAttributeBuffer(1, GL_FLOAT, 0, 2, sizeof(QVector2D));
} else if(dims == 3) {
setAttributeBuffer(1, GL_FLOAT, 0, 3, sizeof(QVector3D));
}
mNBO.release();
mVAO.release();
}
void MeshRenderer::reallocateNormals(const Normals & n, unsigned dims) {
// TODO: Store state to track if buffer objects are bound
mVAO.bind();
mNBO.destroy();
mNBO.create();
mNBO.bind();
mNBO.allocate(n.data(), n.size() * sizeof(n[0]));
enableAttributeArray(1);
if(dims == 2) {
setAttributeBuffer(1, GL_FLOAT, 0, 2, sizeof(QVector2D));
} else if(dims == 3) {
setAttributeBuffer(1, GL_FLOAT, 0, 3, sizeof(QVector3D));
}
mNBO.release();
mVAO.release();
}
/******************************************************************************* /*******************************************************************************
* Inherited Virtual Member Functions * Inherited Virtual Member Functions
******************************************************************************/ ******************************************************************************/

View File

@ -15,6 +15,29 @@
#include <utility> #include <utility>
namespace Qtk { namespace Qtk {
class QTKAPI ShaderBindScope {
public:
explicit ShaderBindScope(
QOpenGLShaderProgram * program, bool was_locked) :
mWasBound(was_locked) {
mProgram = program;
if(!mWasBound) {
mProgram->bind();
}
}
~ShaderBindScope() {
if(!mWasBound) {
mProgram->release();
}
}
private:
QOpenGLShaderProgram * mProgram;
bool mWasBound;
};
class QTKAPI MeshRenderer : public Object { class QTKAPI MeshRenderer : public Object {
public: public:
// Delegate constructors // Delegate constructors
@ -52,11 +75,13 @@ namespace Qtk {
void setShaders(const std::string & vert, const std::string & frag); void setShaders(const std::string & vert, const std::string & frag);
template <typename T> inline void setUniform(int location, T value) { template <typename T> inline void setUniform(int location, T value) {
ShaderBindScope lock(&mProgram, mBound);
mProgram.setUniformValue(location, value); mProgram.setUniformValue(location, value);
} }
template <typename T> template <typename T>
inline void setUniform(const char * location, T value) { inline void setUniform(const char * location, T value) {
ShaderBindScope lock(&mProgram, mBound);
mProgram.setUniformValue(location, value); mProgram.setUniformValue(location, value);
} }
@ -71,6 +96,26 @@ namespace Qtk {
void setShape(const Shape & value) override; void setShape(const Shape & value) override;
void setColor(const QVector3D & color); void setColor(const QVector3D & color);
void setAttributeBuffer(
int location, GLenum type, int offset, int tupleSize,
int stride = 0) {
ShaderBindScope lock(&mProgram, mBound);
mVAO.bind();
mProgram.setAttributeBuffer(location, type, offset, tupleSize, stride);
mVAO.release();
}
inline void enableAttributeArray(int location) {
ShaderBindScope lock(&mProgram, mBound);
mVAO.bind();
mProgram.enableAttributeArray(location);
mVAO.release();
}
void reallocateTexCoords(const TexCoords & t, unsigned dims = 2);
void reallocateNormals(const Normals & n, unsigned dims = 3);
// Static QHash of all mesh objects within the scene // Static QHash of all mesh objects within the scene
typedef QHash<QString, MeshRenderer *> MeshManager; typedef QHash<QString, MeshRenderer *> MeshManager;
@ -78,7 +123,6 @@ namespace Qtk {
static MeshManager sInstances; static MeshManager sInstances;
int mDrawType; int mDrawType;
bool mHasTexture;
std::string mVertexShader, mFragmentShader; std::string mVertexShader, mFragmentShader;
}; };
} // namespace Qtk } // namespace Qtk

View File

@ -26,11 +26,12 @@ namespace Qtk {
// Initialize an object with no shape data assigned // Initialize an object with no shape data assigned
explicit Object(const char * name) : explicit Object(const char * name) :
mName(name), mVBO(QOpenGLBuffer::VertexBuffer) {} mName(name), mVBO(QOpenGLBuffer::VertexBuffer), mBound(false) {}
// Initialize an object with shape data assigned // Initialize an object with shape data assigned
Object(const char * name, const ShapeBase & shape) : Object(const char * name, const ShapeBase & shape) :
mName(name), mVBO(QOpenGLBuffer::VertexBuffer), mShape(shape) {} mName(name), mVBO(QOpenGLBuffer::VertexBuffer), mShape(shape),
mBound(false) {}
~Object() override = default; ~Object() override = default;
@ -68,27 +69,46 @@ namespace Qtk {
virtual inline void setTexture( virtual inline void setTexture(
const char * path, bool flipX = false, bool flipY = false) { const char * path, bool flipX = false, bool flipY = false) {
mTexture.setTexture( mTexture.setTexture(path, flipX, flipY);
OpenGLTextureFactory::initTexture2D(path, flipX, flipY));
} }
virtual inline void setTexture(QOpenGLTexture * value) { virtual inline void setCubeMap(const char * path) {
mTexture.setTexture(value); mTexture.setCubeMap(path);
}
virtual inline void setTexture(const Texture & t) {
mTexture.setTexture(t.getPath());
} }
virtual inline void setVertices(const Vertices & value) { virtual inline void setVertices(const Vertices & value) {
mShape.mVertices = value; mShape.mVertices = value;
} }
virtual inline void bindShaders() {
mBound = true;
mProgram.bind();
}
virtual inline void releaseShaders() {
mBound = false;
mProgram.release();
}
QOpenGLBuffer mVBO, mNBO; QOpenGLBuffer mVBO, mNBO;
QOpenGLVertexArrayObject mVAO; QOpenGLVertexArrayObject mVAO;
QOpenGLShaderProgram mProgram;
Transform3D mTransform; Transform3D mTransform;
Shape mShape; Shape mShape;
Texture mTexture; Texture mTexture;
const char * mName; const char * mName;
bool mBound;
private:
virtual inline void setTexture(QOpenGLTexture * value) {
mTexture.setTexture(value);
}
QOpenGLShaderProgram mProgram;
}; };
} // namespace Qtk } // namespace Qtk

View File

@ -21,7 +21,7 @@ Skybox::Skybox(
mVertices(Cube(QTK_DRAW_ELEMENTS).getVertices()), mVertices(Cube(QTK_DRAW_ELEMENTS).getVertices()),
mIndices(Cube(QTK_DRAW_ELEMENTS).getIndexData()) { mIndices(Cube(QTK_DRAW_ELEMENTS).getIndexData()) {
init(); init();
mCubeMap = OpenGLTextureFactory::initCubeMap( mTexture.setCubeMap(
QImage(right.c_str()).mirrored(), QImage(top.c_str()), QImage(right.c_str()).mirrored(), QImage(top.c_str()),
QImage(front.c_str()), QImage(left.c_str()), QImage(bottom.c_str()), QImage(front.c_str()), QImage(left.c_str()), QImage(bottom.c_str()),
QImage(back.c_str())); QImage(back.c_str()));
@ -33,7 +33,7 @@ Skybox::Skybox(const std::string & name) :
":/back.png", name) {} ":/back.png", name) {}
Skybox::Skybox(QOpenGLTexture * cubeMap, const std::string & name) : Skybox::Skybox(QOpenGLTexture * cubeMap, const std::string & name) :
mCubeMap(cubeMap) { mTexture(cubeMap) {
init(); init();
} }
@ -47,7 +47,7 @@ void Skybox::draw() {
mVAO.bind(); mVAO.bind();
mProgram.bind(); mProgram.bind();
mCubeMap->bind(); mTexture.getOpenGLTexture().bind();
mProgram.setUniformValue("uProjectionMatrix", Scene::Projection()); mProgram.setUniformValue("uProjectionMatrix", Scene::Projection());
mProgram.setUniformValue("uViewMatrix", Scene::Camera().toMatrix()); mProgram.setUniformValue("uViewMatrix", Scene::Camera().toMatrix());
@ -55,7 +55,7 @@ void Skybox::draw() {
glDrawElements( glDrawElements(
GL_TRIANGLES, mIndices.size(), GL_UNSIGNED_INT, mIndices.data()); GL_TRIANGLES, mIndices.size(), GL_UNSIGNED_INT, mIndices.data());
mCubeMap->release(); mTexture.getOpenGLTexture().bind();
mProgram.release(); mProgram.release();
mVAO.release(); mVAO.release();

View File

@ -23,9 +23,6 @@ namespace Qtk {
class QTKAPI Skybox : protected QOpenGLFunctions { class QTKAPI Skybox : protected QOpenGLFunctions {
public: public:
// Delegate this constructor to use default skybox images // Delegate this constructor to use default skybox images
// + This allows creating a skybox with no arguments ( auto s = new
// Skybox;
// )
explicit Skybox(const std::string & name = "Skybox"); explicit Skybox(const std::string & name = "Skybox");
explicit Skybox( explicit Skybox(
QOpenGLTexture * cubeMap, const std::string & name = "Skybox"); QOpenGLTexture * cubeMap, const std::string & name = "Skybox");
@ -49,7 +46,7 @@ namespace Qtk {
QOpenGLShaderProgram mProgram; QOpenGLShaderProgram mProgram;
QOpenGLVertexArrayObject mVAO; QOpenGLVertexArrayObject mVAO;
QOpenGLBuffer mVBO; QOpenGLBuffer mVBO;
QOpenGLTexture * mCubeMap; Texture mTexture;
}; };
} // namespace Qtk } // namespace Qtk

View File

@ -10,6 +10,7 @@
#define QTOPENGL_TEXTURE_H #define QTOPENGL_TEXTURE_H
#include <QOpenGLTexture> #include <QOpenGLTexture>
#include <utility>
#include <qtkapi.h> #include <qtkapi.h>
@ -41,43 +42,72 @@ namespace Qtk {
OpenGLTextureFactory() = default; OpenGLTextureFactory() = default;
}; };
// TODO: Struct for (re)storing texture state
class Texture { class Texture {
public: public:
Texture() = default; Texture() = default;
Texture(const Texture & value) = delete; Texture(const Texture & value) {
mOpenGLTexture = OpenGLTextureFactory::initTexture2D(value.mPath);
// Texture(const Texture & value) { mPath = value.mPath;
// mOpenGLTexture = OpenGLTextureFactory::initTexture2D(value.mPath); }
// mPath = value.mPath;
// }
explicit Texture( explicit Texture(
const char * path, bool flipX = false, bool flipY = false) : const char * path, bool flipX = false, bool flipY = false) :
mOpenGLTexture( mOpenGLTexture(
OpenGLTextureFactory::initTexture2D(path, flipX, flipY)), OpenGLTextureFactory::initTexture2D(path, flipX, flipY)),
mPath(path) {} mPath(path) {}
explicit Texture(QOpenGLTexture * texture) : mOpenGLTexture(texture) {}
// explicit Texture(QOpenGLTexture * texture) : mOpenGLTexture(texture) {
// }
~Texture() { mOpenGLTexture->destroy(); } ~Texture() { mOpenGLTexture->destroy(); }
[[nodiscard]] inline QOpenGLTexture & getOpenGLTexture() const { [[nodiscard]] inline QOpenGLTexture & getOpenGLTexture() const {
return *mOpenGLTexture; return *mOpenGLTexture;
} }
[[nodiscard]] inline std::string getPath() const { return mPath; }
void setTexture(
const std::string & path, bool flipX = false, bool flipY = false) {
mOpenGLTexture =
OpenGLTextureFactory::initTexture2D(path.data(), flipX, flipY);
mPath = path.data();
}
void setTexture( void setTexture(
const char * path, bool flipX = false, bool flipY = false) { const char * path, bool flipX = false, bool flipY = false) {
mOpenGLTexture = mOpenGLTexture =
OpenGLTextureFactory::initTexture2D(path, flipX, flipY); OpenGLTextureFactory::initTexture2D(path, flipX, flipY);
mPath = path;
} }
// TODO: This is unsafe because we don't have a path. Encapsulate it.
inline void setTexture(QOpenGLTexture * texture) { inline void setTexture(QOpenGLTexture * texture) {
mOpenGLTexture = texture; mOpenGLTexture = texture;
} }
virtual inline void setCubeMap(const char * path) {
mOpenGLTexture = OpenGLTextureFactory::initCubeMap(path);
mPath = path;
}
virtual inline void setCubeMap(
const char * right, const char * top, const char * front,
const char * left, const char * bottom, const char * back) {
mOpenGLTexture = OpenGLTextureFactory::initCubeMap(
right, top, front, left, bottom, back);
}
virtual inline void setCubeMap(
const QImage & right, const QImage & top, const QImage & front,
const QImage & left, const QImage & bottom, const QImage & back) {
mOpenGLTexture = OpenGLTextureFactory::initCubeMap(
right, top, front, left, bottom, back);
}
[[nodiscard]] inline bool hasTexture() const { [[nodiscard]] inline bool hasTexture() const {
return mOpenGLTexture != Q_NULLPTR; return mOpenGLTexture != Q_NULLPTR;
} }
private:
QOpenGLTexture * mOpenGLTexture = Q_NULLPTR; QOpenGLTexture * mOpenGLTexture = Q_NULLPTR;
const char * mPath {}; const char * mPath {};
}; };