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 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();
|
||||
|
||||
@ -279,7 +279,10 @@ int start() {
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
@ -292,7 +295,7 @@ int start() {
|
||||
int time = (int) (glfwGetTime() * 10);
|
||||
if(time != prevTime) {
|
||||
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);
|
||||
}
|
||||
prevTime = time;
|
||||
@ -305,11 +308,11 @@ int start() {
|
||||
glDisable(GL_BLEND);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
Timer idleTimer;
|
||||
Timer swapTimer;
|
||||
// Swap buffers and poll window events
|
||||
glfwSwapBuffers(kekData.window);
|
||||
glfwPollEvents();
|
||||
timings.idleTime = idleTimer.elapsedSeconds();
|
||||
timings.swapTime = swapTimer.elapsedSeconds();
|
||||
|
||||
timings.frameTime = frameTimer.elapsedSeconds();
|
||||
kekData.lastTimings = timings;
|
||||
|
@ -11,6 +11,7 @@ namespace kek {
|
||||
|
||||
GameObject::GameObject() {
|
||||
this->physics = nullptr;
|
||||
this->boundingVolume = nullptr;
|
||||
}
|
||||
|
||||
GameObject::~GameObject() {
|
||||
@ -21,9 +22,12 @@ GameObject::~GameObject() {
|
||||
|
||||
void GameObject::addMesh(Mesh *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);
|
||||
model = glm::translate(model, getPosition()) * glm::mat4_cast(getRotation());
|
||||
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) {
|
||||
obj->draw(shader);
|
||||
obj->draw(shader, frustum);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,11 +8,25 @@
|
||||
#include <glm/gtx/matrix_decompose.hpp>
|
||||
#include <math.h>
|
||||
|
||||
#include "constants.h"
|
||||
#include "object.h"
|
||||
#include "utils.h"
|
||||
|
||||
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() {
|
||||
this->position = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||
this->direction = glm::vec3(0.0f, 0.0f, -1.0f);
|
||||
@ -125,4 +139,25 @@ void Camera::applyEuler(glm::vec3 euler) {
|
||||
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 "camera.h"
|
||||
#include "constants.h"
|
||||
|
||||
#include <GL/glew.h>
|
||||
@ -90,4 +91,12 @@ void Mesh::draw(Shader *shader) {
|
||||
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/geometric.hpp"
|
||||
#include "object.h"
|
||||
|
||||
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 {
|
||||
|
||||
public:
|
||||
@ -38,6 +92,8 @@ class Camera: public DefaultObject {
|
||||
glm::vec3 eulerAngles();
|
||||
|
||||
void applyEuler(glm::vec3 euler);
|
||||
|
||||
Frustum getFrustum(float aspect);
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
#define KEK_NOCLIP_SPEED 10.0f
|
||||
|
||||
#define KEK_CAMERA_FOV 90.0f
|
||||
#define KEK_CAMERA_NEAR 0.1f
|
||||
#define KEK_CAMERA_FAR 100.0f
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "camera.h"
|
||||
#include "mesh.h"
|
||||
#include "object.h"
|
||||
#include "physics.h"
|
||||
@ -12,6 +13,7 @@ class GameObject: public DefaultRotateableObject {
|
||||
|
||||
protected:
|
||||
std::vector<Mesh *> meshes;
|
||||
BoundingVolume *boundingVolume;
|
||||
|
||||
public:
|
||||
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
|
||||
void addMesh(Mesh *mesh);
|
||||
|
||||
void draw(Shader *shader);
|
||||
void draw(Shader *shader, const Frustum &frustum);
|
||||
|
||||
void addPhysics(btCollisionShape *shape, float mass, int collisionFlags = 0);
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "camera.h"
|
||||
#include "shader.h"
|
||||
#include "texture.h"
|
||||
|
||||
@ -44,6 +45,8 @@ class Mesh {
|
||||
~Mesh();
|
||||
|
||||
void draw(Shader *shader);
|
||||
|
||||
BoundingVolume *createBoundingVolume();
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "camera.h"
|
||||
#include "gameobject.h"
|
||||
#include "light.h"
|
||||
|
||||
@ -24,7 +25,7 @@ class Scene {
|
||||
void removeObject(GameObject *object);
|
||||
|
||||
// Draws the scene
|
||||
void draw(Shader *shader);
|
||||
void draw(Shader *shader, const Frustum &frustum);
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ struct Timings {
|
||||
float physicsTime = 0;
|
||||
float lightingTime = 0;
|
||||
float renderTime = 0;
|
||||
float idleTime = 0;
|
||||
float swapTime = 0;
|
||||
};
|
||||
|
||||
class Timer {
|
||||
|
Loading…
Reference in New Issue
Block a user