From 3e58de9f95fccfda8927097886d3607e7291bac9 Mon Sep 17 00:00:00 2001 From: Daniel Evans Date: Tue, 2 Jul 2013 09:58:01 +0100 Subject: [PATCH] Minimal frustum culling implemented --- framework/rwbinarystream.h | 6 ++-- framework2/GTARenderer.cpp | 33 +++++++++++++------ .../include/renderwure/render/GTARenderer.hpp | 4 +++ .../include/renderwure/render/ViewCamera.hpp | 2 -- .../include/renderwure/render/ViewFrustum.hpp | 7 ++-- viewer/main.cpp | 11 ++++++- 6 files changed, 43 insertions(+), 20 deletions(-) diff --git a/framework/rwbinarystream.h b/framework/rwbinarystream.h index b94b324e..86416ca8 100644 --- a/framework/rwbinarystream.h +++ b/framework/rwbinarystream.h @@ -1,6 +1,7 @@ #ifndef _RWBINARYSTREAM_H_ #define _RWBINARYSTREAM_H_ #include "gtfwpre.h" +#include #include #include @@ -41,10 +42,7 @@ namespace RW /** * Vector data */ - struct BSTVector3 - { - float x, y, z; - }; + typedef glm::vec3 BSTVector3; /** * Rotation Matrix diff --git a/framework2/GTARenderer.cpp b/framework2/GTARenderer.cpp index 341ff61c..1eb9bd6d 100644 --- a/framework2/GTARenderer.cpp +++ b/framework2/GTARenderer.cpp @@ -75,34 +75,47 @@ GTARenderer::GTARenderer() void GTARenderer::renderWorld(GTAEngine* engine) { glm::mat4 proj = camera.frustum.projection(); - glm::mat4 view = camera.view; + glm::mat4 view = camera.frustum.view; glUniformMatrix4fv(uniView, 1, GL_FALSE, glm::value_ptr(view)); glUniformMatrix4fv(uniProj, 1, GL_FALSE, glm::value_ptr(proj)); - camera.frustum.update(); + camera.frustum.update(camera.frustum.projection() * view); + + rendered = culled = 0; auto& textureLoader = engine->gameData.textureLoader; for (size_t i = 0; i < engine->instances.size(); ++i) { - auto &obj = engine->instances[i]; + LoaderIPLInstance &obj = engine->instances[i]; std::string modelname = obj.model; if (modelname.substr(0, 3) == "LOD") continue; - auto &model = engine->gameData.models[modelname]; - // std::cout << "Rendering " << modelname << std::endl; + std::unique_ptr &model = engine->gameData.models[modelname]; + + glm::quat rot(-obj.rotW, obj.rotX, obj.rotY, obj.rotZ); + glm::vec3 pos(obj.posX, obj.posY, obj.posZ); + glm::vec3 scale(obj.scaleX, obj.scaleY, obj.scaleZ); if(!model) { std::cout << "model " << modelname << " not there (" << engine->gameData.models.size() << " models loaded)" << std::endl; } - for (size_t g = 0; g < model->geometries.size(); g++) { - + for (size_t g = 0; g < model->geometries.size(); g++) + { + RW::BSGeometryBounds& bounds = model->geometries[g].geometryBounds; + if(! camera.frustum.intersects(bounds.center + pos, bounds.radius)) { + culled++; + continue; + } + else { + rendered++; + } + // This is a hack I have no idea why negating the quaternion fixes the issue but it does. - glm::quat rot(-obj.rotW, obj.rotX, obj.rotY, obj.rotZ); glm::mat4 matrixModel; - matrixModel = glm::translate(matrixModel, glm::vec3(obj.posX, obj.posY, obj.posZ)); - matrixModel = glm::scale(matrixModel, glm::vec3(obj.scaleX, obj.scaleY, obj.scaleZ)); + matrixModel = glm::translate(matrixModel, pos); + matrixModel = glm::scale(matrixModel, scale); matrixModel = matrixModel * glm::mat4_cast(rot); glUniformMatrix4fv(uniModel, 1, GL_FALSE, glm::value_ptr(matrixModel)); diff --git a/framework2/include/renderwure/render/GTARenderer.hpp b/framework2/include/renderwure/render/GTARenderer.hpp index 12195571..7e60d2cc 100644 --- a/framework2/include/renderwure/render/GTARenderer.hpp +++ b/framework2/include/renderwure/render/GTARenderer.hpp @@ -11,6 +11,10 @@ public: ViewCamera camera; + /// The numer of things rendered by the last renderWorld + size_t rendered; + size_t culled; + void renderWorld(GTAEngine* engine); }; diff --git a/framework2/include/renderwure/render/ViewCamera.hpp b/framework2/include/renderwure/render/ViewCamera.hpp index 2c970087..cd409525 100644 --- a/framework2/include/renderwure/render/ViewCamera.hpp +++ b/framework2/include/renderwure/render/ViewCamera.hpp @@ -9,8 +9,6 @@ public: ViewFrustum frustum; - glm::mat4 view; - ViewCamera() : frustum({0.1f, 5000.f, 80.f, 1.f}) { diff --git a/framework2/include/renderwure/render/ViewFrustum.hpp b/framework2/include/renderwure/render/ViewFrustum.hpp index 9e6b2b5f..4b1d8db2 100644 --- a/framework2/include/renderwure/render/ViewFrustum.hpp +++ b/framework2/include/renderwure/render/ViewFrustum.hpp @@ -19,6 +19,8 @@ public: float fov; float aspectRatio; + glm::mat4 view; + ViewPlane planes[6]; ViewFrustum(float near, float far, float fov, float aspect) @@ -32,9 +34,8 @@ public: return glm::perspective(fov, aspectRatio, near, far); } - void update() + void update(const glm::mat4& proj) { - auto proj = projection(); for(size_t i = 0; i < 6; ++i) { float sign = (i%2==0) ? 1.f : -1.f; @@ -56,7 +57,7 @@ public: for(size_t i = 0; i < 6; ++i) { d = glm::dot(planes[i].normal, center) + planes[i].distance; - if( -d < radius ) return false; + if( d < -radius ) return false; } return true; } diff --git a/viewer/main.cpp b/viewer/main.cpp index 717e2cd4..34a2ea8c 100644 --- a/viewer/main.cpp +++ b/viewer/main.cpp @@ -106,7 +106,7 @@ void update() view = glm::translate(view, -plyPos); - gta->renderer.camera.view = view; + gta->renderer.camera.frustum.view = view; i++; } @@ -117,8 +117,17 @@ void render() // Update aspect ratio.. gta->renderer.camera.frustum.aspectRatio = window.getSize().x / (float) window.getSize().y; + + glEnable(GL_CULL_FACE); gta->renderer.renderWorld(gta); + + static size_t fc = 0; + if(fc++ == 60) + { + std::cout << "Rendered: " << gta->renderer.rendered << " / Culled: " << gta->renderer.culled << std::endl; + fc = 0; + } } int main(int argc, char *argv[])