260 lines
9.6 KiB
C++

#include "Gedeng/DirectionalLight.h"
#include "Gedeng/Input.h"
#include "Gedeng/Logger.h"
#include "Gedeng/ObjMesh.h"
#include "Gedeng/ParticleSystem.h"
#include "Gedeng/QuadMesh.h"
#include "Gedeng/Shader.h"
#include "Gedeng/TextLabel.h"
#include "Gedeng/Vector3.h"
#include <GLFW/glfw3.h>
#define GEDENG_MAIN
#include <Gedeng.h>
class FullDemo : public Gedeng::Application {
public:
FullDemo(unsigned long ms_per_update, unsigned int window_size_x, unsigned int window_size_y,
Gedeng::String window_name)
: Application(ms_per_update, window_size_x, window_size_y, window_name), particle_interval(0.2),
number_of_steps(10.0), number_of_refinement_steps(10.0), bump_depth(0.1), tessellation_factor(16.0),
render_shader(Gedeng::Shader("Shader/bump.vs", "Shader/bump.fs")),
debug_shader(Gedeng::Shader("Shader/depth-debug.vs", "Shader/depth-debug.fs")),
camera(Gedeng::FPSCamera(90, 1920, 1080, 0.1, 1000.0)),
albedo("Resources/Textures/PavingStones/PavingStones070_2K_Color.jpg", Gedeng::Texture::Settings()),
bump("Resources/Textures/PavingStones/PavingStones070_2K_Displacement.jpg", Gedeng::Texture::Settings()),
normal("Resources/Textures/PavingStones/PavingStones070_2K_Normal.jpg", Gedeng::Texture::Settings()),
particle_tex1("Resources/Textures/Particles/circle.png", Gedeng::Texture::Settings()),
particle_tex2("Resources/Textures/Particles/magic.png", Gedeng::Texture::Settings()),
particle_tex3("Resources/Textures/Particles/smoke.png", Gedeng::Texture::Settings()),
heightmap("Resources/Textures/terrain.png", Gedeng::Texture::Settings()), quad_mesh(Gedeng::QuadMesh(10.0)),
light(glm::vec3(0.57735, -0.57735, 0.57735)),
mesh1("Resources/Meshes/Monkey.obj", Gedeng::ObjMesh::Settings()),
mesh2("Resources/Meshes/bench.obj", Gedeng::ObjMesh::Settings()),
mesh3("Resources/Meshes/ring.obj", Gedeng::ObjMesh::Settings()), size_x(128), size_y(128), size_z(128),
mc_render_shader(
Gedeng::Shader("Shader/MarchingCubes/mc.vs", "Shader/MarchingCubes/mc.fs", "Shader/MarchingCubes/mc.gs")),
mc_noise_shader(Gedeng::Shader("Shader/MarchingCubes/noise.vs", "Shader/MarchingCubes/noise.fs")),
noise(Gedeng::Framebuffer3D(size_x, size_y, size_z)) {
particles.set_position(glm::vec3(0.0f, 0.0f, -10.0f));
particles.set_velocity(glm::vec3(-2, 4, -2), glm::vec3(2, 6, 2));
particles.set_gravity(glm::vec3(0, -4, 0));
particles.set_color(glm::vec3(0.0f, 0.5f, 1.0f));
particles.set_lifetime(1.0f, 1.5f);
particles.set_size(0.1);
particles.set_interval(particle_interval);
particles.set_number_of_particles(1);
particles.set_textures(&particle_tex1, &particle_tex2, &particle_tex3);
camera.translate(glm::vec3(0.0, 2.0, 1.0));
// camera.rotate(30, glm::vec3(1.0, 0.0, 0.0));
mesh1.translate(glm::vec3(2.0, 3.0, -2.0));
mesh2.translate(glm::vec3(-3.0, 0.0, -3.0));
mesh3.translate(glm::vec3(5.0, 0.0, 5.0));
mesh3.rotate(45.0, glm::vec3(0.0, 1.0, 0.0));
terrain_mesh.translate(glm::vec3(0.0, 1.0, 0.0));
terrain_shader.add_vertex_shader("Shader/terrain.vs");
terrain_shader.add_fragment_shader("Shader/terrain.fs");
terrain_shader.add_tessellation_control_shader("Shader/terrain.tcs");
terrain_shader.add_tessellation_evaluation_shader("Shader/terrain.tes");
terrain_shader.link();
// Each MC noise layer needs vertices, so we define two triangles which span a rectangle
float data[6][2] = {{-1.0f, -1.0f}, {-1.0, 1.0}, {1.0, -1.0}, {1.0f, 1.0f}, {-1.0, 1.0}, {1.0, -1.0}};
vertex_rectangle.set_data(sizeof(data), 2, data, GL_STATIC_DRAW);
}
~FullDemo() = default;
void fixed_update(double delta) override {
camera.update(delta);
if (Gedeng::Input::is_mouse_down(GLFW_MOUSE_BUTTON_LEFT))
particles.set_position(camera.get_view_ray().get_plane_collision().collision_position);
if (Gedeng::Input::is_key_down(GLFW_KEY_2)) particle_interval = fmax(particle_interval + 0.1 * delta, 0.02);
if (Gedeng::Input::is_key_down(GLFW_KEY_1)) particle_interval = fmax(particle_interval - 0.1 * delta, 0.02);
if (Gedeng::Input::is_key_down(GLFW_KEY_4)) tessellation_factor += delta * 8.0;
if (Gedeng::Input::is_key_down(GLFW_KEY_3)) tessellation_factor -= delta * 8.0;
if (Gedeng::Input::is_key_down(GLFW_KEY_6)) number_of_steps += delta * 5.0;
if (Gedeng::Input::is_key_down(GLFW_KEY_5)) number_of_steps -= delta * 5.0;
if (Gedeng::Input::is_key_down(GLFW_KEY_8)) number_of_refinement_steps += delta * 5.0;
if (Gedeng::Input::is_key_down(GLFW_KEY_7)) number_of_refinement_steps -= delta * 5.0;
if (Gedeng::Input::is_key_down(GLFW_KEY_0)) bump_depth += delta * 0.1;
if (Gedeng::Input::is_key_down(GLFW_KEY_9)) bump_depth -= delta * 0.1;
particles.set_interval(particle_interval);
}
void dynamic_update(double delta) override {
// Marching cubes
// Create the noise
glViewport(0, 0, size_x, size_y);
mc_noise_shader.use();
noise.bind_and_clear();
mc_noise_shader.setFloat("height", camera.get_translation().y / size_z);
for (int i = 0; i < size_z; i++) {
// Create one layer
mc_noise_shader.setFloat("layer", i * (1.0f / (static_cast<float>(size_z - 1))));
noise.bind_layer(i);
// Each layer is made up of a rectangle of vertices
vertex_rectangle.draw();
}
// Shadows
light.clear_shadows();
light.render_shadow(quad_mesh);
light.render_shadow(mesh1);
light.render_shadow(mesh2);
light.render_shadow(mesh3);
// Actual Rendering
glViewport(0, 0, 1920, 1080);
// Marching Cubes
mc_render_shader.use();
// Bind the screen framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClearColor(0.6f, 0.9f, 0.9f, 1.0f);
glClearColor(0.1, 0.1f, 0.1, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Bind the camera to the rendering shader
mc_render_shader.setMat4("proj", camera.get_projection());
mc_render_shader.setMat4("view", camera.get_view());
// Set other variables
mc_render_shader.setFloat("step", 1.0 / static_cast<float>(size_z - 1));
mc_render_shader.setFloat("threshold", 0.4);
mc_render_shader.setInt("size_x", size_x);
mc_render_shader.setInt("size_y", size_y);
mc_render_shader.setInt("size_z", size_z);
// Bind the noise texture to the rendering shader
noise.bind_to(0);
// Draw all layers as polygons
glPolygonMode(GL_FRONT_AND_BACK, Gedeng::Input::is_key_down(GLFW_KEY_X) ? GL_LINE : GL_FILL);
glDrawArrays(GL_POINTS, 0, size_x * size_y * size_z);
// Normal
render_shader.use();
// Camera
render_shader.setMat4("projection", camera.get_projection());
render_shader.setMat4("view", camera.get_view());
render_shader.setVec3("viewPos", camera.get_translation());
// Lighting
light.set_in_shader(render_shader);
render_shader.setFloat("number_of_steps", glm::max(0.0f, number_of_steps));
render_shader.setFloat("number_of_refinement_steps", glm::max(0.0f, number_of_refinement_steps));
render_shader.setFloat("bump_depth", glm::max(0.0f, bump_depth));
// Textures
albedo.bind_to(0);
normal.bind_to(1);
bump.bind_to(2);
light.bind_depth_map_to(3);
// Quad which is rendered onto
quad_mesh.render(render_shader);
// Particles
particles.set_camera(camera);
particles.update(delta);
particles.render();
// Props
render_shader.use();
mesh1.render(render_shader);
mesh2.render(render_shader);
mesh3.render(render_shader);
// Terrain
terrain_shader.use();
heightmap.bind_to(0);
terrain_shader.setMat4("projection", camera.get_projection());
terrain_shader.setMat4("view", camera.get_view());
terrain_shader.setInt("tessellation_factor", static_cast<int>(tessellation_factor));
terrain_mesh.render_patches(terrain_shader);
// Log framerate
GG_CLIENT_INFO(std::string("Framerate: ") + std::to_string(1.0 / delta));
}
private:
float particle_interval;
float number_of_steps;
float number_of_refinement_steps;
float bump_depth;
float tessellation_factor;
Gedeng::Shader render_shader;
Gedeng::Shader debug_shader;
Gedeng::Shader terrain_shader;
Gedeng::VertexBuffer vertex_rectangle;
Gedeng::FPSCamera camera;
Gedeng::Texture albedo;
Gedeng::Texture bump;
Gedeng::Texture normal;
Gedeng::Texture particle_tex1;
Gedeng::Texture particle_tex2;
Gedeng::Texture particle_tex3;
Gedeng::Texture heightmap;
Gedeng::QuadMesh quad_mesh;
Gedeng::QuadMesh terrain_mesh;
Gedeng::ParticleSystem particles;
Gedeng::DirectionalLight light;
Gedeng::ObjMesh mesh1;
Gedeng::ObjMesh mesh2;
Gedeng::ObjMesh mesh3;
// Marching cubes
int size_x;
int size_y;
int size_z;
float height = 0.0;
Gedeng::Shader mc_render_shader;
Gedeng::Shader mc_noise_shader;
Gedeng::Framebuffer3D noise;
Gedeng::VertexBuffer mc_vertex_rectangle;
};
Gedeng::Application *Gedeng::create_application() {
GG_CLIENT_INFO("Creating Application");
return new FullDemo(20, 1920, 1080, String("Parallax Demo"));
}