Skip to content

Commit

Permalink
Introduce 'terrain' using tessellation shader
Browse files Browse the repository at this point in the history
  • Loading branch information
douze committed Oct 19, 2020
1 parent 3b9a07c commit edb69c2
Show file tree
Hide file tree
Showing 15 changed files with 233 additions and 9 deletions.
17 changes: 15 additions & 2 deletions demo/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,20 @@
#include "renderer.hpp"
#include "scene.hpp"
#include "spdlog/spdlog.h"
#include "terrain.hpp"
#include "terrainmaterial.hpp"
#include "transformation.hpp"
#include "triangle.hpp"
#include "vertexcolormaterial.hpp"

#include <iostream>
#include <string>

using namespace renderer;

int main() {
spdlog::set_level(spdlog::level::debug);

const int width = 1280;
const int height = 800;

Expand All @@ -23,12 +26,22 @@ int main() {
std::shared_ptr<material::VertexColorMaterial> vertexcolormaterial{
std::make_shared<material::VertexColorMaterial>()};

std::shared_ptr<mesh::Terrain> terrain{std::make_shared<mesh::Terrain>()};
std::shared_ptr<material::TerrainMaterial> terrainMaterial{
std::make_shared<material::TerrainMaterial>()};
scene::Node triangleNode{triangle,
mesh::Transformation{glm::vec3{0.0f, 0.0f, -2.0f}},
vertexcolormaterial};
renderer.getScene().getRoot().addChild(triangleNode);

scene::Camera camera{glm::vec3{0.0f, 0.0f, 0.0f}, width, height};
scene::Node terrainNode{terrain,
mesh::Transformation{glm::vec3{0.0f, 0.0f, -4.0f}},
terrainMaterial};
renderer.getScene().getRoot().addChild(terrainNode);

scene::Camera camera{glm::vec3{0.0f, 0.0f, 0.0f},
width / static_cast<float>(height)};

renderer.getScene().setCamera(std::make_shared<scene::Camera>(camera));

return renderer.run();
Expand Down
6 changes: 5 additions & 1 deletion renderer/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,18 @@ target_sources(renderer
"src/mesh.cpp"
"src/transformation.cpp"
"src/camera.cpp"
"src/terrain.cpp"
"src/terrainmaterial.cpp"
"include/renderer.hpp"
"include/triangle.hpp"
"include/material.hpp"
"include/vertexcolormaterial.hpp"
"include/scene.hpp"
"include/mesh.hpp"
"include/transformation.hpp"
"include/camera.hpp")
"include/camera.hpp"
"include/terrain.hpp"
"include/terrainmaterial.hpp")
target_include_directories(renderer
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
target_link_libraries(renderer ${CONAN_LIBS})
Expand Down
3 changes: 1 addition & 2 deletions renderer/include/camera.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ class Camera {
* @brief Create a camera at the desired position.
* @param position of the camera
*/
explicit Camera(const glm::vec3& position, const int width,
const int height) noexcept;
explicit Camera(const glm::vec3& position, float aspect) noexcept;

/**
* @brief Return the view matrix.
Expand Down
7 changes: 7 additions & 0 deletions renderer/include/material.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ class Material {
*/
explicit Material(const std::string& vsPath,
const std::string& fsPath) noexcept;

explicit Material(const std::string& vsPath, const std::string& tcsPath,
const std::string& tesPath,
const std::string& fsPath) noexcept;
/**
* @brief Use this material for the next rendering.
*/
Expand Down Expand Up @@ -66,6 +70,9 @@ class Material {
/** Vertex shader program */
GLuint vs;

GLuint tcs;
GLuint tes;

/** Fragment shader program */
GLuint fs;
};
Expand Down
27 changes: 27 additions & 0 deletions renderer/include/terrain.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#ifndef TERRAIN_H
#define TERRAIN_H

#include "mesh.hpp"
#include <glad/glad.h>

namespace renderer {
namespace mesh {

struct TerrainVertex {
float x, y;
float r, g, b;
};

class Terrain : public Mesh {
public:
explicit Terrain() noexcept;

void render() const;

private:
GLuint vao;
GLuint program;
};
} // namespace mesh
} // namespace renderer
#endif // TERRAIN_H
17 changes: 17 additions & 0 deletions renderer/include/terrainmaterial.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#ifndef TERRAINMATERIAL_H
#define TERRAINMATERIAL_H

#include "material.hpp"

namespace renderer {
namespace material {

class TerrainMaterial : public Material {
public:
explicit TerrainMaterial() noexcept;
};

} // namespace material
} // namespace renderer

#endif // TERRAINMATERIAL_H
5 changes: 2 additions & 3 deletions renderer/src/camera.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@

using namespace renderer::scene;

Camera::Camera(const glm::vec3& position, const int width,
const int height) noexcept
Camera::Camera(const glm::vec3& position, float aspect) noexcept
: position{position}, front{glm::vec3{0.0f, 0.0f, -1.0f}},
up{glm::vec3{0.0f, 1.0f, 0.0f}}, right{glm::vec3{1.0f, 0.0f, 0.0f}},
yaw{0.0f}, pitch{0.0f}, dirty{true},
projectionMatrix{
glm::perspective(45.0f, (float)(width / height), 1.0f, 500.0f)} {}
glm::perspective(45.0f, aspect, 1.0f, 500.0f)} {}

glm::mat4 Camera::getViewMatrix() {
if (dirty) {
Expand Down
37 changes: 36 additions & 1 deletion renderer/src/material.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

using namespace renderer::material;

#include <iostream>

Material::Material(const std::string& vsPath,
const std::string& fsPath) noexcept {
vs = createShaderProgram(GL_VERTEX_SHADER, vsPath);
Expand All @@ -17,6 +19,39 @@ Material::Material(const std::string& vsPath,
glUseProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, fs);
}

void check(GLuint program) {

GLint isLinked = 0;
glGetProgramiv(program, GL_LINK_STATUS, (int*)&isLinked);
if (isLinked == GL_FALSE) {
GLint maxLength = 0;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);
std::vector<GLchar> infoLog(maxLength);
glGetProgramInfoLog(program, maxLength, &maxLength, &infoLog[0]);

for (auto i : infoLog)
std::cout << i;
}
}

Material::Material(const std::string& vsPath, const std::string& tcsPath,
const std::string& tesPath,
const std::string& fsPath) noexcept {
vs = createShaderProgram(GL_VERTEX_SHADER, vsPath);
check(vs);
tcs = createShaderProgram(GL_TESS_CONTROL_SHADER, tcsPath);
check(tcs);
tes = createShaderProgram(GL_TESS_EVALUATION_SHADER, tesPath);
check(tes);
fs = createShaderProgram(GL_FRAGMENT_SHADER, fsPath);

glCreateProgramPipelines(1, &pipeline);
glUseProgramStages(pipeline, GL_VERTEX_SHADER_BIT, vs);
glUseProgramStages(pipeline, GL_TESS_CONTROL_SHADER_BIT, tcs);
glUseProgramStages(pipeline, GL_TESS_EVALUATION_SHADER_BIT, tes);
glUseProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, fs);
}

GLuint Material::createShaderProgram(GLenum type, const std::string& path) {
const std::string source = readShaderFile(path);
const char* csource = source.c_str();
Expand All @@ -41,6 +76,6 @@ void Material::setTransformationMatrix(
void Material::setCameraMatrices(scene::Camera camera) const {
glProgramUniformMatrix4fv(vs, 1, 1, GL_FALSE,
glm::value_ptr(camera.getViewMatrix()));
glProgramUniformMatrix4fv(vs, 2, 1, GL_FALSE,
glProgramUniformMatrix4fv(vs, 2, 1, GL_FALSE,
glm::value_ptr(camera.getProjectionMatrix()));
}
1 change: 1 addition & 0 deletions renderer/src/renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ int Renderer::run() {
updateTimer();
glViewport(0, 0, width, height);
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(0.5, 1.0, 0.5, 1.0);
processKeyboard(timer.delta);
processMouse(timer.delta);
renderNode(scene.getRoot());
Expand Down
33 changes: 33 additions & 0 deletions renderer/src/terrain.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#include "terrain.hpp"

using namespace renderer::mesh;

Terrain::Terrain() noexcept {
const TerrainVertex vertices[4] = {{-1.0f, -1.0f, 1.f, 0.f, 0.f},
{-1.0f, 1.0f, 0.f, 1.f, 0.f},
{1.0f, 1.0f, 0.f, 0.f, 1.f},
{1.0f, -1.0f, 1.f, 1.f, 1.f}};

GLuint vbo;
glCreateBuffers(1, &vbo);
glNamedBufferStorage(vbo, sizeof(vertices), vertices, GL_DYNAMIC_STORAGE_BIT);

glCreateVertexArrays(1, &vao);

glVertexArrayVertexBuffer(vao, 0, vbo, 0, sizeof(TerrainVertex));

glEnableVertexArrayAttrib(vao, 0);
glVertexArrayAttribFormat(vao, 0, 2, GL_FLOAT, GL_FALSE, 0);
glVertexArrayAttribBinding(vao, 0, 0);

glEnableVertexArrayAttrib(vao, 1);
glVertexArrayAttribFormat(vao, 1, 3, GL_FLOAT, GL_FALSE, (sizeof(float) * 2));
glVertexArrayAttribBinding(vao, 1, 0);
}

void Terrain::render() const {
glBindVertexArray(vao);
glPatchParameteri(GL_PATCH_VERTICES, 4);
glDrawArrays(GL_PATCHES, 0, 4);
}

7 changes: 7 additions & 0 deletions renderer/src/terrainmaterial.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#include "terrainmaterial.hpp"

using namespace renderer::material;

TerrainMaterial::TerrainMaterial() noexcept
: Material{"terrain.vs.glsl", "terrain.tcs.glsl", "terrain.tes.glsl",
"terrain.fs.glsl"} {}
11 changes: 11 additions & 0 deletions resources/shaders/terrain.fs.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#version 460

in TE_OUT {
vec3 color;
} fs_in;

out vec4 color;

void main() {
color = vec4(fs_in.color, 1.0);
}
25 changes: 25 additions & 0 deletions resources/shaders/terrain.tcs.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#version 460

layout(vertices = 4) out;

in V_OUT {
vec3 color;
} tcs_in[];

out TC_OUT {
vec3 color;
} tcs_out[];

void main(void) {
gl_TessLevelOuter[0] = 2.0;
gl_TessLevelOuter[1] = 4.0;
gl_TessLevelOuter[2] = 6.0;
gl_TessLevelOuter[3] = 8.0;

gl_TessLevelInner[0] = 8.0;
gl_TessLevelInner[1] = 8.0;

gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;

tcs_out[gl_InvocationID].color = tcs_in[gl_InvocationID].color;
}
29 changes: 29 additions & 0 deletions resources/shaders/terrain.tes.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#version 460

layout(quads, equal_spacing, ccw) in;

in TC_OUT {
vec3 color;
} tes_in[];

out TE_OUT {
vec3 color;
} tes_out;

vec4 interpolate4(in vec4 v0, in vec4 v1, in vec4 v2, in vec4 v3) {
vec4 a = mix(v0, v1, gl_TessCoord.x);
vec4 b = mix(v3, v2, gl_TessCoord.x);
return mix(a, b, gl_TessCoord.y);
}

vec3 interpolate3(in vec3 v0, in vec3 v1, in vec3 v2, in vec3 v3) {
vec3 a = mix(v0, v1, gl_TessCoord.x);
vec3 b = mix(v3, v2, gl_TessCoord.x);
return mix(a, b, gl_TessCoord.y);
}

void main() {
gl_Position = interpolate4(gl_in[0].gl_Position, gl_in[1].gl_Position, gl_in[2].gl_Position, gl_in[3].gl_Position);
tes_out.color = interpolate3(tes_in[0].color, tes_in[1].color,tes_in[2].color, tes_in[3].color).xyz;
}

17 changes: 17 additions & 0 deletions resources/shaders/terrain.vs.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#version 460

layout (location = 0) in vec2 position;
layout (location = 1) in vec3 color;

layout (location = 0) uniform mat4 model;
layout (location = 1) uniform mat4 view;
layout (location = 2) uniform mat4 projection;

out VS_OUT {
vec3 color;
} vs_out;

void main() {
gl_Position = projection * view * model * vec4(position, 0.0, 1.0);
vs_out.color = color;
}

0 comments on commit edb69c2

Please sign in to comment.