marching-cubes-opengl/MCRenderer.cpp

88 lines
2.9 KiB
C++

#include "MCRenderer.h"
#include "Framebuffer3D.h"
#include "Input.h"
#include "VertexBuffer.h"
#include <glm/ext/matrix_transform.hpp>
MCRenderer::MCRenderer(int size_x, int size_y, int size_z)
: size_x(size_x), size_y(size_y), size_z(size_z),
render_shader(Shader("Shader/mc.vs", "Shader/mc.fs", "Shader/mc.gs")),
noise_shader(Shader("Shader/noise.vs", "Shader/noise.fs")),
noise(Framebuffer3D(size_x, size_y, size_z)), camera(Camera(90, 1920, 1080, 0.1, 1000.0)) {
// Each 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);
// Move the camera to the center
camera.translate(glm::vec3(size_x / 2.0, size_z / 2.0, size_y / 2.0));
}
void MCRenderer::render(float delta) {
// Create the noise
glViewport(0, 0, size_x, size_y);
noise_shader.use();
noise.bind_and_clear();
if (Input::is_key_down(GLFW_KEY_E)) {
height += delta;
}
if (Input::is_key_down(GLFW_KEY_Q)) {
height -= delta;
}
if (Input::is_key_down(GLFW_KEY_W)) {
camera.translate(glm::vec3(0.0, 0.0, -delta * 20.0));
}
if (Input::is_key_down(GLFW_KEY_S)) {
camera.translate(glm::vec3(0.0, 0.0, delta * 20.0));
}
if (Input::is_key_down(GLFW_KEY_D)) {
camera.rotate(-delta * 90.0, glm::vec3(0.0, 1.0, 0.0));
}
if (Input::is_key_down(GLFW_KEY_A)) {
camera.rotate(delta * 90.0, glm::vec3(0.0, 1.0, 0.0));
}
noise_shader.setFloat("height", height);
for (int i = 0; i < size_z; i++) {
// Create one layer
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();
}
// Actual rendering
glViewport(0, 0, 1920, 1080);
render_shader.use();
// Bind the screen framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// glDrawBuffer(GL_BACK);
glClearColor(0.6f, 0.9f, 0.9f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Bind the camera to the rendering shader
render_shader.setMat4("proj", camera.get_projection());
render_shader.setMat4("view", camera.get_view());
// Set other variables
render_shader.setFloat("step", 1.0 / static_cast<float>(size_z - 1));
render_shader.setFloat("threshold", 0.4);
render_shader.setInt("size_x", size_x);
render_shader.setInt("size_y", size_y);
render_shader.setInt("size_z", size_z);
// Bind the noise texture to the rendering shader
noise.bind_to(0);
// Draw all layers as polygons
glDrawArrays(GL_POINTS, 0, size_x * size_y * size_z);
glPolygonMode(GL_FRONT_AND_BACK, Input::is_key_down(GLFW_KEY_X) ? GL_LINE : GL_FILL);
}