Implement frustum culling (WIP)
This commit is contained in:
parent
3051fbd3b9
commit
5691afe59b
@ -198,7 +198,7 @@ int start() {
|
|||||||
glm::mat4 view = kekData.activeCamera->transformationMatrix();
|
glm::mat4 view = kekData.activeCamera->transformationMatrix();
|
||||||
|
|
||||||
glm::mat4 projection;
|
glm::mat4 projection;
|
||||||
projection = glm::perspective(glm::radians(90.0f), kekData.screenWidth / (float) kekData.screenHeight, KEK_CAMERA_NEAR, KEK_CAMERA_FAR);
|
projection = glm::perspective(glm::radians(KEK_CAMERA_FOV), kekData.screenWidth / (float) kekData.screenHeight, KEK_CAMERA_NEAR, KEK_CAMERA_FAR);
|
||||||
|
|
||||||
glm::vec3 position = kekData.activeCamera->getPosition();
|
glm::vec3 position = kekData.activeCamera->getPosition();
|
||||||
|
|
||||||
@ -279,7 +279,10 @@ int start() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Timer drawTimer;
|
Timer drawTimer;
|
||||||
kekData.activeScene->draw(kekData.shader);
|
|
||||||
|
Frustum frustum = getActiveCamera()->getFrustum((float) kekData.screenHeight / kekData.screenWidth);
|
||||||
|
|
||||||
|
kekData.activeScene->draw(kekData.shader, frustum);
|
||||||
timings.renderTime = drawTimer.elapsedSeconds();
|
timings.renderTime = drawTimer.elapsedSeconds();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -292,7 +295,7 @@ int start() {
|
|||||||
int time = (int) (glfwGetTime() * 10);
|
int time = (int) (glfwGetTime() * 10);
|
||||||
if(time != prevTime) {
|
if(time != prevTime) {
|
||||||
int fps = (int) floor(1.0f / kekData.lastTimings.frameTime);
|
int fps = (int) floor(1.0f / kekData.lastTimings.frameTime);
|
||||||
std::string str = "FPS: " + std::to_string(fps) + " (" + formatSeconds(kekData.lastTimings.frameTime) + ")" + " | Physics: " + formatSeconds(kekData.lastTimings.physicsTime) + ", Lighting: " + formatSeconds(kekData.lastTimings.lightingTime) + ", Render: " + formatSeconds(kekData.lastTimings.renderTime) + ", Idle: " + formatSeconds(kekData.lastTimings.idleTime);
|
std::string str = "FPS: " + std::to_string(fps) + " (" + formatSeconds(kekData.lastTimings.frameTime) + ")" + " | Physics: " + formatSeconds(kekData.lastTimings.physicsTime) + ", Lighting: " + formatSeconds(kekData.lastTimings.lightingTime) + ", Render: " + formatSeconds(kekData.lastTimings.renderTime) + ", Swap: " + formatSeconds(kekData.lastTimings.swapTime);
|
||||||
fpsText->setText(str);
|
fpsText->setText(str);
|
||||||
}
|
}
|
||||||
prevTime = time;
|
prevTime = time;
|
||||||
@ -305,11 +308,11 @@ int start() {
|
|||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
Timer idleTimer;
|
Timer swapTimer;
|
||||||
// Swap buffers and poll window events
|
// Swap buffers and poll window events
|
||||||
glfwSwapBuffers(kekData.window);
|
glfwSwapBuffers(kekData.window);
|
||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
timings.idleTime = idleTimer.elapsedSeconds();
|
timings.swapTime = swapTimer.elapsedSeconds();
|
||||||
|
|
||||||
timings.frameTime = frameTimer.elapsedSeconds();
|
timings.frameTime = frameTimer.elapsedSeconds();
|
||||||
kekData.lastTimings = timings;
|
kekData.lastTimings = timings;
|
||||||
|
@ -11,6 +11,7 @@ namespace kek {
|
|||||||
|
|
||||||
GameObject::GameObject() {
|
GameObject::GameObject() {
|
||||||
this->physics = nullptr;
|
this->physics = nullptr;
|
||||||
|
this->boundingVolume = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
GameObject::~GameObject() {
|
GameObject::~GameObject() {
|
||||||
@ -21,9 +22,12 @@ GameObject::~GameObject() {
|
|||||||
|
|
||||||
void GameObject::addMesh(Mesh *mesh) {
|
void GameObject::addMesh(Mesh *mesh) {
|
||||||
meshes.push_back(mesh);
|
meshes.push_back(mesh);
|
||||||
|
boundingVolume = mesh->createBoundingVolume(); // TODO: move somewhere else
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameObject::draw(Shader *shader) {
|
void GameObject::draw(Shader *shader, const Frustum &frustum) {
|
||||||
|
if(boundingVolume && !boundingVolume->isContained(frustum, getPosition(), getRotation())) return;
|
||||||
|
|
||||||
glm::mat4 model = glm::mat4(1.0f);
|
glm::mat4 model = glm::mat4(1.0f);
|
||||||
model = glm::translate(model, getPosition()) * glm::mat4_cast(getRotation());
|
model = glm::translate(model, getPosition()) * glm::mat4_cast(getRotation());
|
||||||
glUniformMatrix4fv(glGetUniformLocation(kekData.shader->id, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
glUniformMatrix4fv(glGetUniformLocation(kekData.shader->id, "model"), 1, GL_FALSE, glm::value_ptr(model));
|
||||||
|
@ -26,9 +26,9 @@ void Scene::removeObject(GameObject *object) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::draw(Shader *shader) {
|
void Scene::draw(Shader *shader, const Frustum &frustum) {
|
||||||
for(GameObject *obj : objects) {
|
for(GameObject *obj : objects) {
|
||||||
obj->draw(shader);
|
obj->draw(shader, frustum);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,11 +8,25 @@
|
|||||||
#include <glm/gtx/matrix_decompose.hpp>
|
#include <glm/gtx/matrix_decompose.hpp>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
#include "constants.h"
|
||||||
#include "object.h"
|
#include "object.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
namespace kek {
|
namespace kek {
|
||||||
|
|
||||||
|
float Plane::getDistance(glm::vec3 point) const {
|
||||||
|
return glm::dot(point, normal) - distance;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Frustum::contains(glm::vec3 point) const {
|
||||||
|
return near.getDistance(point) >= 0 && far.getDistance(point) >= 0 && left.getDistance(point) >= 0 && right.getDistance(point) >= 0 && top.getDistance(point) >= 0 && bottom.getDistance(point) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SphereBoundingVolume::isContained(const Frustum &frustum, glm::vec3 position, glm::quat rotation) {
|
||||||
|
glm::vec3 point = position + offset;
|
||||||
|
return frustum.near.getDistance(point) >= -radius && frustum.far.getDistance(point) >= -radius && frustum.left.getDistance(point) >= -radius && frustum.right.getDistance(point) >= -radius && frustum.top.getDistance(point) >= -radius && frustum.bottom.getDistance(point) >= -radius;
|
||||||
|
}
|
||||||
|
|
||||||
Camera::Camera() {
|
Camera::Camera() {
|
||||||
this->position = glm::vec3(0.0f, 0.0f, 0.0f);
|
this->position = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||||
this->direction = glm::vec3(0.0f, 0.0f, -1.0f);
|
this->direction = glm::vec3(0.0f, 0.0f, -1.0f);
|
||||||
@ -125,4 +139,25 @@ void Camera::applyEuler(glm::vec3 euler) {
|
|||||||
roll = euler.z;
|
roll = euler.z;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
Frustum Camera::getFrustum(float aspect) {
|
||||||
|
float halfW = KEK_CAMERA_FAR * tanf(glm::radians(KEK_CAMERA_FOV * 0.5f));
|
||||||
|
float halfH = halfW * aspect;
|
||||||
|
glm::vec3 farPoint = KEK_CAMERA_FAR * direction;
|
||||||
|
|
||||||
|
float rollRad = glm::radians(roll);
|
||||||
|
float x = sin(rollRad);
|
||||||
|
float y = cos(rollRad);
|
||||||
|
glm::vec3 up = glm::vec3(x, y, 0.0f);
|
||||||
|
glm::vec3 cameraRight = glm::normalize(glm::cross(direction, up));
|
||||||
|
glm::vec3 cameraUp = glm::normalize(glm::cross(cameraRight, direction));
|
||||||
|
|
||||||
|
Plane near = Plane(position + KEK_CAMERA_NEAR * direction, direction);
|
||||||
|
Plane far = Plane(position + farPoint, -direction);
|
||||||
|
Plane left = Plane(position, glm::cross(farPoint + cameraRight * -halfW, cameraUp));
|
||||||
|
Plane right = Plane(position, glm::cross(cameraUp, farPoint + cameraRight * halfW));
|
||||||
|
Plane top = Plane(position, glm::cross(farPoint + cameraUp * halfH, cameraRight));
|
||||||
|
Plane bottom = Plane(position, glm::cross(cameraRight, farPoint + cameraUp * -halfH));
|
||||||
|
return Frustum(near, far, top, bottom, left, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "mesh.h"
|
#include "mesh.h"
|
||||||
|
|
||||||
|
#include "camera.h"
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
|
|
||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
@ -90,4 +91,12 @@ void Mesh::draw(Shader *shader) {
|
|||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BoundingVolume *Mesh::createBoundingVolume() {
|
||||||
|
float maxDist = 0;
|
||||||
|
for(Vertex v : vertices) {
|
||||||
|
maxDist = glm::max(maxDist, glm::length(glm::vec3(v.pos.x, v.pos.y, v.pos.z)));
|
||||||
|
}
|
||||||
|
return new SphereBoundingVolume(glm::vec3(0), maxDist);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,10 +2,64 @@
|
|||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
#include "glm/geometric.hpp"
|
||||||
#include "object.h"
|
#include "object.h"
|
||||||
|
|
||||||
namespace kek {
|
namespace kek {
|
||||||
|
|
||||||
|
class Plane {
|
||||||
|
glm::vec3 normal;
|
||||||
|
float distance;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Plane(glm::vec3 normal, float distance)
|
||||||
|
: normal(glm::normalize(normal)),
|
||||||
|
distance(distance){};
|
||||||
|
|
||||||
|
Plane(glm::vec3 point, glm::vec3 normal)
|
||||||
|
: normal(glm::normalize(normal)),
|
||||||
|
distance(glm::dot(this->normal, point)){};
|
||||||
|
|
||||||
|
float getDistance(glm::vec3 point) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Frustum {
|
||||||
|
const Plane near;
|
||||||
|
const Plane far;
|
||||||
|
const Plane top;
|
||||||
|
const Plane bottom;
|
||||||
|
const Plane left;
|
||||||
|
const Plane right;
|
||||||
|
|
||||||
|
Frustum(Plane near, Plane far, Plane top, Plane bottom, Plane left, Plane right)
|
||||||
|
: near(near),
|
||||||
|
far(far),
|
||||||
|
top(top),
|
||||||
|
bottom(bottom),
|
||||||
|
left(left),
|
||||||
|
right(right){};
|
||||||
|
|
||||||
|
bool contains(glm::vec3 point) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
class BoundingVolume {
|
||||||
|
public:
|
||||||
|
virtual bool isContained(const Frustum &frustum, glm::vec3 position, glm::quat rotation) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SphereBoundingVolume: public BoundingVolume {
|
||||||
|
private:
|
||||||
|
glm::vec3 offset;
|
||||||
|
float radius;
|
||||||
|
|
||||||
|
public:
|
||||||
|
SphereBoundingVolume(glm::vec3 offset, float radius)
|
||||||
|
: offset(offset),
|
||||||
|
radius(radius) {}
|
||||||
|
|
||||||
|
virtual bool isContained(const Frustum &frustum, glm::vec3 position, glm::quat rotation);
|
||||||
|
};
|
||||||
|
|
||||||
class Camera: public DefaultObject {
|
class Camera: public DefaultObject {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -38,6 +92,8 @@ class Camera: public DefaultObject {
|
|||||||
glm::vec3 eulerAngles();
|
glm::vec3 eulerAngles();
|
||||||
|
|
||||||
void applyEuler(glm::vec3 euler);
|
void applyEuler(glm::vec3 euler);
|
||||||
|
|
||||||
|
Frustum getFrustum(float aspect);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#define KEK_NOCLIP_SPEED 10.0f
|
#define KEK_NOCLIP_SPEED 10.0f
|
||||||
|
|
||||||
|
#define KEK_CAMERA_FOV 90.0f
|
||||||
#define KEK_CAMERA_NEAR 0.1f
|
#define KEK_CAMERA_NEAR 0.1f
|
||||||
#define KEK_CAMERA_FAR 100.0f
|
#define KEK_CAMERA_FAR 100.0f
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "camera.h"
|
||||||
#include "mesh.h"
|
#include "mesh.h"
|
||||||
#include "object.h"
|
#include "object.h"
|
||||||
#include "physics.h"
|
#include "physics.h"
|
||||||
@ -12,6 +13,7 @@ class GameObject: public DefaultRotateableObject {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::vector<Mesh *> meshes;
|
std::vector<Mesh *> meshes;
|
||||||
|
BoundingVolume *boundingVolume;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PhysicsObjectData *physics;
|
PhysicsObjectData *physics;
|
||||||
@ -23,7 +25,7 @@ class GameObject: public DefaultRotateableObject {
|
|||||||
// Adds a mesh to the GameObject. The GameObject takes ownership of the Mesh, so don't use Meshes in multiple GameObjects
|
// Adds a mesh to the GameObject. The GameObject takes ownership of the Mesh, so don't use Meshes in multiple GameObjects
|
||||||
void addMesh(Mesh *mesh);
|
void addMesh(Mesh *mesh);
|
||||||
|
|
||||||
void draw(Shader *shader);
|
void draw(Shader *shader, const Frustum &frustum);
|
||||||
|
|
||||||
void addPhysics(btCollisionShape *shape, float mass, int collisionFlags = 0);
|
void addPhysics(btCollisionShape *shape, float mass, int collisionFlags = 0);
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "camera.h"
|
||||||
#include "shader.h"
|
#include "shader.h"
|
||||||
#include "texture.h"
|
#include "texture.h"
|
||||||
|
|
||||||
@ -44,6 +45,8 @@ class Mesh {
|
|||||||
~Mesh();
|
~Mesh();
|
||||||
|
|
||||||
void draw(Shader *shader);
|
void draw(Shader *shader);
|
||||||
|
|
||||||
|
BoundingVolume *createBoundingVolume();
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "camera.h"
|
||||||
#include "gameobject.h"
|
#include "gameobject.h"
|
||||||
#include "light.h"
|
#include "light.h"
|
||||||
|
|
||||||
@ -24,7 +25,7 @@ class Scene {
|
|||||||
void removeObject(GameObject *object);
|
void removeObject(GameObject *object);
|
||||||
|
|
||||||
// Draws the scene
|
// Draws the scene
|
||||||
void draw(Shader *shader);
|
void draw(Shader *shader, const Frustum &frustum);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ struct Timings {
|
|||||||
float physicsTime = 0;
|
float physicsTime = 0;
|
||||||
float lightingTime = 0;
|
float lightingTime = 0;
|
||||||
float renderTime = 0;
|
float renderTime = 0;
|
||||||
float idleTime = 0;
|
float swapTime = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Timer {
|
class Timer {
|
||||||
|
Loading…
Reference in New Issue
Block a user