1
0
Fork 0
Univerxel/src/client/render/gl/Renderer.cpp

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;
}