#include "Renderer.hpp" #include "UI.hpp" #include "../../../core/world/materials.hpp" #include "../../control/Camera.hpp" #include "../../Window.hpp" #include "../../../core/utils/logger.hpp" #include #include 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(); SkyEnable = options.skybox; IndicatorPass = std::make_unique(); 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 Renderer::beginWorldPass() { WorldPass->useIt(); WorldPass->start(this); return [&](glm::mat4 model) { return WorldPass->setup(this, model); }; } std::function &)> Renderer::beginEntityPass() { EntityPass->useIt(); EntityPass->start(this); return [&](const std::vector& 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(options); EntityPass = std::make_unique(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 terrainTextures; for(const auto& texture: world::materials::textures) { terrainTextures.emplace_back(texturePath + "/terrain/" + texture); } const auto ani = anisotropy >= 1 ? (1 << (static_cast(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; }