190 lines
6.0 KiB
C++
190 lines
6.0 KiB
C++
#include "Renderer.hpp"
|
|
|
|
#include "UI.hpp"
|
|
#include "../../../core/world/materials.hpp"
|
|
#include "../../control/Camera.hpp"
|
|
#include "../../Window.hpp"
|
|
#include "../../../core/utils/logger.hpp"
|
|
#include <GL/gl3w.h>
|
|
|
|
#include <TracyOpenGL.hpp>
|
|
|
|
using namespace render::gl;
|
|
|
|
constexpr auto GL_MAJOR = 4;
|
|
constexpr auto GL_MINOR = 6;
|
|
|
|
Renderer::Renderer(const renderOptions& options):
|
|
IndicatorCubeBuffer(GL_LINES, 24, {
|
|
glm::vec3(0, 0, 0), glm::vec3(0, 0, 1),
|
|
glm::vec3(0, 0, 1), glm::vec3(0, 1, 1),
|
|
glm::vec3(0, 1, 1), glm::vec3(0, 1, 0),
|
|
glm::vec3(0, 1, 0), glm::vec3(0, 0, 0),
|
|
glm::vec3(1, 0, 0), glm::vec3(1, 0, 1),
|
|
glm::vec3(1, 0, 1), glm::vec3(1, 1, 1),
|
|
glm::vec3(1, 1, 1), glm::vec3(1, 1, 0),
|
|
glm::vec3(1, 1, 0), glm::vec3(1, 0, 0),
|
|
glm::vec3(0, 0, 0), glm::vec3(1, 0, 0),
|
|
glm::vec3(0, 0, 1), glm::vec3(1, 0, 1),
|
|
glm::vec3(0, 1, 1), glm::vec3(1, 1, 1),
|
|
glm::vec3(0, 1, 0), glm::vec3(1, 1, 0),
|
|
}, {
|
|
glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1),
|
|
glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1),
|
|
glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1),
|
|
glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1),
|
|
glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1),
|
|
glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1),
|
|
glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1),
|
|
glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1),
|
|
glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1),
|
|
glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1),
|
|
glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1),
|
|
glm::vec4(1, 1, 1, 1), glm::vec4(1, 1, 1, 1),
|
|
}) {
|
|
glGenVertexArrays(1, &VertexArrayID);
|
|
glBindVertexArray(VertexArrayID);
|
|
|
|
reloadShaders(options.voxel);
|
|
SkyPass = std::make_unique<pass::SkyProgram>();
|
|
SkyEnable = options.skybox;
|
|
IndicatorPass = std::make_unique<pass::ColorProgram>();
|
|
|
|
FogColor = glm::vec3(options.clear_color.x, options.clear_color.y, options.clear_color.z);
|
|
loadTextures(options.textures, options.mipMapLOD, options.anisotropy);
|
|
}
|
|
|
|
Renderer::~Renderer() {
|
|
unloadTextures();
|
|
glDeleteVertexArrays(1, &VertexArrayID);
|
|
}
|
|
|
|
void framebuffer_size_callback(GLFWwindow *, int width, int height) {
|
|
glViewport(0, 0, width, height);
|
|
}
|
|
|
|
bool Renderer::Load(Window& window, const renderOptions& opt) {
|
|
Window::CreateInfo windowInfo;
|
|
windowInfo.pfnResize = framebuffer_size_callback;
|
|
windowInfo.client = {Window::CreateInfo::Client::Type::GL, GL_MAJOR, GL_MINOR};
|
|
windowInfo.samples = 1;
|
|
if (!window.create(windowInfo))
|
|
return false;
|
|
|
|
if (gl3wInit() != GL3W_OK) {
|
|
LOG_E("Failed to initialize OpenGL");
|
|
return false;
|
|
}
|
|
if (!gl3wIsSupported(GL_MAJOR, GL_MINOR)) {
|
|
LOG_E("OpenGL " << GL_MAJOR << "." << GL_MINOR << " not supported");
|
|
return false;
|
|
}
|
|
LOG_D("OpenGL " << glGetString(GL_VERSION) << ", GLSL " << glGetString(GL_SHADING_LANGUAGE_VERSION));
|
|
|
|
// Enable depth test
|
|
glEnable(GL_DEPTH_TEST);
|
|
// Accept fragment if it closer to the camera than the former one
|
|
glDepthFunc(GL_LEQUAL);
|
|
|
|
// Cull triangles which normal is not towards the camera
|
|
glEnable(GL_CULL_FACE);
|
|
glCullFace(GL_BACK);
|
|
|
|
GLint smp;
|
|
glGetIntegerv(GL_SAMPLES, &smp);
|
|
if (smp > 0) {
|
|
glEnable(GL_MULTISAMPLE);
|
|
}
|
|
|
|
glClearColor(opt.clear_color.x, opt.clear_color.y, opt.clear_color.z, opt.clear_color.w);
|
|
|
|
TracyGpuContext;
|
|
|
|
sInstance = new Renderer(opt);
|
|
return true;
|
|
}
|
|
|
|
void Renderer::loadUI(Window& w) {
|
|
UI::Load(w);
|
|
}
|
|
|
|
|
|
void Renderer::beginFrame() {
|
|
TracyGpuZone("Render");
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
}
|
|
|
|
std::function<buffer::params(glm::mat4)> Renderer::beginWorldPass() {
|
|
WorldPass->useIt();
|
|
WorldPass->start(this);
|
|
return [&](glm::mat4 model) {
|
|
return WorldPass->setup(this, model);
|
|
};
|
|
}
|
|
|
|
std::function<buffer::params(const std::vector<glm::mat4> &)> Renderer::beginEntityPass() {
|
|
EntityPass->useIt();
|
|
EntityPass->start(this);
|
|
return [&](const std::vector<glm::mat4>& models) {
|
|
return EntityPass->setup(this, models);
|
|
};
|
|
}
|
|
|
|
size_t Renderer::drawIndicatorCube(glm::mat4 model) {
|
|
IndicatorPass->useIt();
|
|
return IndicatorCubeBuffer.draw(IndicatorPass->setup(this, model));
|
|
}
|
|
|
|
void Renderer::endPass() {
|
|
if(SkyEnable) {
|
|
SkyPass->draw(this);
|
|
}
|
|
}
|
|
|
|
void Renderer::swapBuffer(Window& w) {
|
|
TracyGpuZone("Swap");
|
|
glfwSwapBuffers(w.getPtr());
|
|
TracyGpuCollect;
|
|
}
|
|
|
|
void Renderer::reloadShaders(const pass::VoxelProgram::options& options) {
|
|
WorldPass = std::make_unique<pass::WorldProgram>(options);
|
|
EntityPass = std::make_unique<pass::EntityProgram>(options);
|
|
}
|
|
void Renderer::reloadTextures(const std::string& texturePath, float mipMapLOD, float anisotropy) {
|
|
unloadTextures();
|
|
loadTextures(texturePath, mipMapLOD, anisotropy);
|
|
}
|
|
|
|
void Renderer::unloadTextures() {
|
|
glDeleteTextures(1, &HOSAtlas);
|
|
glDeleteTextures(1, &NormalAtlas);
|
|
glDeleteTextures(1, &TextureAtlas);
|
|
}
|
|
void Renderer::loadTextures(const std::string& texturePath, float mipMapLOD, float anisotropy) {
|
|
std::vector<std::string> terrainTextures;
|
|
for(const auto& texture: world::materials::textures) {
|
|
terrainTextures.emplace_back(texturePath + "/terrain/" + texture);
|
|
}
|
|
const auto ani = anisotropy >= 1 ? (1 << (static_cast<int>(anisotropy)-1)) : 0;
|
|
TextureAtlas = pass::Program::loadTextureArray(terrainTextures, "", mipMapLOD, ani);
|
|
NormalAtlas = pass::Program::loadTextureArray(terrainTextures, ".nrm", mipMapLOD, ani);
|
|
HOSAtlas = pass::Program::loadTextureArray(terrainTextures, ".hos", mipMapLOD, ani);
|
|
|
|
Skybox = pass::Program::loadTextureCube(texturePath + "/sky/Space_tray");
|
|
}
|
|
|
|
void Renderer::lookFrom(const Camera& camera) {
|
|
ProjectionMatrix = camera.getProjectionMatrix();
|
|
ViewMatrix = camera.getViewMatrix();
|
|
FogDepth = camera.getDepth();
|
|
}
|
|
|
|
void Renderer::setClearColor(glm::vec4 c) {
|
|
FogColor = c;
|
|
glClearColor(c.r, c.g, c.b, c.a);
|
|
}
|
|
void Renderer::setCurvature(glm::vec4 sp, float c) {
|
|
SphereProj = sp;
|
|
Curvature = c;
|
|
} |