From 95f246bbd2cb9e50f00eacbab1b1fd3c54feda62 Mon Sep 17 00:00:00 2001 From: karl Date: Sun, 30 May 2021 19:38:26 +0200 Subject: [PATCH] Preparations for tessellation: new demo + wireframe + new Shader types --- SConstruct | 1 + Shader/bump.fs | 2 +- Shader/terrain.fs | 15 ++++ Shader/terrain.tcs | 23 ++++++ Shader/terrain.tes | 25 ++++++ Shader/terrain.vs | 21 +++++ include/Gedeng/QuadMesh.h | 8 ++ include/Gedeng/Shader.h | 12 +++ test/full-demo/main.cpp | 157 ++++++++++++++++++++++++++++++++++++++ 9 files changed, 263 insertions(+), 1 deletion(-) create mode 100644 Shader/terrain.fs create mode 100644 Shader/terrain.tcs create mode 100644 Shader/terrain.tes create mode 100644 Shader/terrain.vs create mode 100644 test/full-demo/main.cpp diff --git a/SConstruct b/SConstruct index cd63400..c69edc9 100644 --- a/SConstruct +++ b/SConstruct @@ -59,3 +59,4 @@ testEnv.Program('test/bin/test-app.out', Glob('test/test-app/*.cpp')) testEnv.Program('test/bin/parallax-demo.out', Glob('test/parallax-demo/*.cpp')) testEnv.Program('test/bin/particle-demo.out', Glob('test/particle-demo/*.cpp')) testEnv.Program('test/bin/shadow-demo.out', Glob('test/shadow-demo/*.cpp')) +testEnv.Program('test/bin/full-demo.out', Glob('test/full-demo/*.cpp')) diff --git a/Shader/bump.fs b/Shader/bump.fs index 4bc59d5..75f1fe4 100644 --- a/Shader/bump.fs +++ b/Shader/bump.fs @@ -133,6 +133,6 @@ void main() { float shadow = get_shadow(fs_in.FragPosLightSpace, normal); // Apply - FragColor = vec4(ambient + albedo + specular - shadow * 0.25, 1.0); + FragColor = vec4(ambient + albedo + specular - shadow * 0.3, 1.0); } diff --git a/Shader/terrain.fs b/Shader/terrain.fs new file mode 100644 index 0000000..804a588 --- /dev/null +++ b/Shader/terrain.fs @@ -0,0 +1,15 @@ +#version 430 + +in PipelineData { + vec4 position; + vec2 texture_coordinate; +} fs_in; + +uniform sampler2D diffuse_texture; + +out vec4 color; + +void main() { + vec4 diffuse_texel = texture(diffuse_texture, fs_in.texture_coordinate); + color = vec4(1.0); // color = vec4(diffuse_texel); +} \ No newline at end of file diff --git a/Shader/terrain.tcs b/Shader/terrain.tcs new file mode 100644 index 0000000..55adbf2 --- /dev/null +++ b/Shader/terrain.tcs @@ -0,0 +1,23 @@ +#version 430 + +layout(vertices = 3) out; + +in PipelineData { + vec4 position; + vec2 texture_coordinate; +} tc_in[]; + +out PipelineData { + vec4 position; + vec2 texture_coordinate; +} tc_out[]; + +void main() { + tc_out[gl_InvocationID].texture_coordinate = tc_in[gl_InvocationID].texture_coordinate; + tc_out[gl_InvocationID].position = tc_in[gl_InvocationID].position; + + gl_TessLevelInner[0] = 1; + gl_TessLevelOuter[0] = 1; + gl_TessLevelOuter[1] = 1; + gl_TessLevelOuter[2] = 1; +} \ No newline at end of file diff --git a/Shader/terrain.tes b/Shader/terrain.tes new file mode 100644 index 0000000..48509e3 --- /dev/null +++ b/Shader/terrain.tes @@ -0,0 +1,25 @@ +#version 430 + +layout(triangles) in; + +in PipelineData { + vec4 position; + vec2 texture_coordinate; +} te_in[]; + +out PipelineData { + vec4 position; + vec2 texture_coordinate; +} te_out; + +void main() { + te_out.texture_coordinate = gl_TessCoord.x * te_in[0].texture_coordinate; + te_out.texture_coordinate += gl_TessCoord.y * te_in[1].texture_coordinate; + te_out.texture_coordinate += gl_TessCoord.z * te_in[2].texture_coordinate; + + te_out.position = gl_TessCoord.x * te_in[0].position; + te_out.position += gl_TessCoord.y * te_in[1].position; + te_out.position += gl_TessCoord.z * te_in[2].position; + + gl_Position = te_out.position; +} \ No newline at end of file diff --git a/Shader/terrain.vs b/Shader/terrain.vs new file mode 100644 index 0000000..8951e91 --- /dev/null +++ b/Shader/terrain.vs @@ -0,0 +1,21 @@ +#version 430 + +in vec3 position; +in vec2 texture_coordinate; + +uniform mat4 model; +uniform mat4 projection_view; + +out PipelineData { + vec4 position; + vec2 texture_coordinate; +} vs_out; + +void main() { + mat4 pvm = projection_view * model; + vs_out.texture_coordinate = texture_coordinate; + vec4 homogenous_position = vec4(position, 1.0); + vs_out.position = pvm * homogenous_position; + + gl_Position = vs_out.position; +} \ No newline at end of file diff --git a/include/Gedeng/QuadMesh.h b/include/Gedeng/QuadMesh.h index 71cc795..0a6d120 100644 --- a/include/Gedeng/QuadMesh.h +++ b/include/Gedeng/QuadMesh.h @@ -110,6 +110,14 @@ class QuadMesh : public Mesh { glBindVertexArray(0); } + void render_patches(Shader &shader) const { + shader.setMat4("model", get_matrix()); + + glBindVertexArray(quadVAO); + glDrawArrays(GL_PATCHES, 0, 6); + glBindVertexArray(0); + } + private: unsigned int quadVAO = 0; unsigned int quadVBO; diff --git a/include/Gedeng/Shader.h b/include/Gedeng/Shader.h index 6a72dc2..3a4188c 100644 --- a/include/Gedeng/Shader.h +++ b/include/Gedeng/Shader.h @@ -71,6 +71,18 @@ class Shader { glDeleteShader(shader); } + void add_tessellation_control_shader(const char *path) { + unsigned int shader = load_shader(path, GL_TESS_CONTROL_SHADER); + glAttachShader(ID, shader); + glDeleteShader(shader); + } + + void add_tessellation_evaluation_shader(const char *path) { + unsigned int shader = load_shader(path, GL_TESS_EVALUATION_SHADER); + glAttachShader(ID, shader); + glDeleteShader(shader); + } + void add_transform_feedback(const char **varyings, size_t varying_count) { for (size_t i = 0; i < varying_count; i++) { // TODO: Is this loop required? glTransformFeedbackVaryings(ID, varying_count, varyings, GL_INTERLEAVED_ATTRIBS); diff --git a/test/full-demo/main.cpp b/test/full-demo/main.cpp new file mode 100644 index 0000000..5e6fd47 --- /dev/null +++ b/test/full-demo/main.cpp @@ -0,0 +1,157 @@ +#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 +#define GEDENG_MAIN +#include + +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), + 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()), + 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()) { + 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)); + } + + ~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); + + particles.set_interval(particle_interval); + } + + void dynamic_update(double delta) override { + // Wireframe? + if (Gedeng::Input::is_key_down(GLFW_KEY_B)) { + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + } else { + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + } + + // Shadows + light.clear_shadows(); + light.render_shadow(quad_mesh); + light.render_shadow(mesh1); + light.render_shadow(mesh2); + light.render_shadow(mesh3); + + glViewport(0, 0, 1920, 1080); + glClearColor(0.1, 0.1f, 0.1, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + 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); + } + + private: + float particle_interval; + + float number_of_steps; + float number_of_refinement_steps; + float bump_depth; + + Gedeng::Shader render_shader; + Gedeng::Shader debug_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::QuadMesh quad_mesh; + Gedeng::QuadMesh terrain_mesh; + + Gedeng::ParticleSystem particles; + + Gedeng::DirectionalLight light; + + Gedeng::ObjMesh mesh1; + Gedeng::ObjMesh mesh2; + Gedeng::ObjMesh mesh3; +}; + +Gedeng::Application *Gedeng::create_application() { + GG_CLIENT_INFO("Creating Application"); + return new FullDemo(20, 1920, 1080, String("Parallax Demo")); +}