Split client server
This commit is contained in:
parent
f0f12da614
commit
0dcff4b885
|
@ -0,0 +1,184 @@
|
|||
#include "Client.hpp"
|
||||
|
||||
#include "render/gl/Renderer.hpp"
|
||||
#include "render/gl/UI.hpp"
|
||||
#include "render/gl/Pipeline.hpp"
|
||||
#include "InputMap.hpp"
|
||||
|
||||
Client::Client() { }
|
||||
Client::~Client() { }
|
||||
|
||||
void Client::run() {
|
||||
if (!render::gl::Renderer::Load(window, {options.renderer.clear_color}))
|
||||
return;
|
||||
|
||||
window.setTargetFPS(options.target_fps);
|
||||
|
||||
|
||||
InputMap inputs(window.getPtr());
|
||||
Controllable player(window.getPtr(), inputs, options.control);
|
||||
Camera camera(&player, options.camera);
|
||||
|
||||
auto *pipeline = static_cast<render::gl::Pipeline*>(render::Renderer::Get()->createPipeline(options.renderer));
|
||||
pipeline->LightInvDir = glm::normalize(glm::vec3(-.5f, 2, -2));
|
||||
render::Renderer::Get()->loadUI(window);
|
||||
|
||||
//TODO: extract to server
|
||||
world::Universe world = world::Universe(options.world);
|
||||
world.setContouring(contouring::load(options.contouring_idx, options.contouring_data));
|
||||
state.contouring = world.getContouring();
|
||||
|
||||
//TODO: loop
|
||||
do {
|
||||
window.startFrame();
|
||||
{ // Update
|
||||
ZoneScopedN("Update");
|
||||
static double lastTime = window.getTime();
|
||||
const double partTime = window.getTime();
|
||||
const float deltaTime = partTime - lastTime;
|
||||
inputs.toggle(state.capture_mouse, Input::Mouse);
|
||||
inputs.toggle(options.show_debug_menu, Input::Debug);
|
||||
|
||||
player.capture(state.capture_mouse, !render::UI::IsFocus(), deltaTime);
|
||||
if(player.velocity != glm::vec3(0) && (
|
||||
!options.control.collide ||
|
||||
!world.collide(player.position, player.velocity, options.voxel_density, 1))
|
||||
) {
|
||||
player.position += player.velocity;
|
||||
state.position = player.position;
|
||||
}
|
||||
camera.update();
|
||||
pipeline->lookFrom(camera);
|
||||
pipeline->LightInvDir = glm::vec3(glm::rotate(glm::mat4(1), deltaTime * .1f, glm::vec3(1, .5, .1)) * glm::vec4(pipeline->LightInvDir, 0));
|
||||
|
||||
{
|
||||
const auto ray_result = world.raycast(camera.getRay() * options.voxel_density);
|
||||
if(auto target = std::get_if<world::Universe::ray_target>(&ray_result)) {
|
||||
state.look_at = *target;
|
||||
} else {
|
||||
state.look_at = {};
|
||||
}
|
||||
}
|
||||
if (state.capture_mouse) {
|
||||
if (state.look_at.has_value()) {
|
||||
ZoneScopedN("Edit");
|
||||
if (inputs.isPressing(Mouse::Left))
|
||||
world.setCube(state.look_at.value().pos, world::Voxel(world::materials::AIR, options.tool.empty_air * world::Voxel::DENSITY_MAX), options.tool.radius);
|
||||
else if (inputs.isPressing(Mouse::Right))
|
||||
world.setCube(state.look_at.value().pos, world::Voxel(options.tool.material, world::Voxel::DENSITY_MAX), options.tool.radius);
|
||||
}
|
||||
if (inputs.isDown(Input::Throw)) {
|
||||
world.addEntity(entity_id(0), {state.position * options.voxel_density, glm::vec3(10, 0, 0)});
|
||||
}
|
||||
}
|
||||
world.update((state.position * options.voxel_density).as_voxel(), deltaTime);
|
||||
inputs.saveKeys();
|
||||
lastTime = partTime;
|
||||
}
|
||||
|
||||
{
|
||||
ZoneScopedN("UI");
|
||||
const auto actions = render::UI::Get()->draw(options, state, reports);
|
||||
if (actions && render::UI::Actions::FPS) {
|
||||
window.setTargetFPS(options.target_fps);
|
||||
}
|
||||
if (actions && render::UI::Actions::FullScreen) {
|
||||
window.setFullscreen(options.fullscreen);
|
||||
}
|
||||
if(actions && render::UI::Actions::ClearColor) {
|
||||
pipeline->setClearColor(options.renderer.clear_color);
|
||||
}
|
||||
if(actions && render::UI::Actions::RendererSharders) {
|
||||
pipeline->reloadShaders(options.renderer.voxel);
|
||||
}
|
||||
if(actions && render::UI::Actions::RendererTextures) {
|
||||
pipeline->reloadTextures(options.renderer.textures, options.renderer.mipMapLOD, options.renderer.anisotropy);
|
||||
}
|
||||
if(actions && render::UI::Actions::World) {
|
||||
world.setOptions(options.world);
|
||||
}
|
||||
if(actions && render::UI::Actions::Camera) {
|
||||
camera.setOptions(options.camera);
|
||||
}
|
||||
if(actions && render::UI::Actions::Control) {
|
||||
player.setOptions(options.control);
|
||||
}
|
||||
if(actions && render::UI::Actions::ChangeContouring) {
|
||||
state.contouring = NULL;
|
||||
world.setContouring(contouring::load(options.contouring_idx, options.contouring_data));
|
||||
state.contouring = world.getContouring();
|
||||
}
|
||||
pipeline->SkyEnable = options.renderer.skybox;
|
||||
}
|
||||
{ // Rendering
|
||||
ZoneScopedN("Render");
|
||||
pipeline->beginFrame();
|
||||
|
||||
reports.models_count = 0;
|
||||
reports.tris_count = 0;
|
||||
std::optional<geometry::Frustum> frustum;
|
||||
if(options.culling >= 0) {
|
||||
frustum = {camera.getFrustum()};
|
||||
}
|
||||
const auto offset = state.position.raw_as_long();
|
||||
{ // Chunks
|
||||
const auto pass = pipeline->beginWorldPass();
|
||||
const auto draw = [&](glm::mat4 model, buffer::Abstract *const buffer, const contouring::Abstract::area_info &area, const voxel_pos &pos) {
|
||||
pipeline->SphereProj = glm::vec4(pos, std::get<1>(area));
|
||||
pipeline->Curvature = std::get<2>(area);
|
||||
reports.models_count++;
|
||||
reports.tris_count += buffer->draw(pass(model));
|
||||
};
|
||||
if (options.culling > 0) {
|
||||
std::vector<glm::vec3> occlusion;
|
||||
const auto ratio = options.culling * 2;
|
||||
occlusion.reserve(glm::pow2(ratio * 2 - 1));
|
||||
const auto [ch, cv] = player.getAngles();
|
||||
const auto max_v = tan(options.camera.fov / 2.), max_h = Window::RATIO * max_v;
|
||||
for(int iv = -ratio + 1; iv < ratio; iv++) {
|
||||
const auto v = cv + max_v * iv / ratio;
|
||||
for(int ih = -ratio + 1; ih < ratio; ih++) {
|
||||
const auto h = ch + max_h * ih / ratio;
|
||||
occlusion.emplace_back(cos(v) * sin(h), sin(v), cos(v) * cos(h));
|
||||
}
|
||||
}
|
||||
world.getContouring()->getModels(draw, player.position, options.camera.far, occlusion, offset, options.voxel_density);
|
||||
} else {
|
||||
world.getContouring()->getModels(draw, frustum, offset, options.voxel_density);
|
||||
}
|
||||
}
|
||||
{ // Entities
|
||||
const auto pass = pipeline->beginEntityPass();
|
||||
const auto draw = [&](const std::vector<glm::mat4>& models, buffer::Abstract *const buffer) {
|
||||
reports.models_count += models.size();
|
||||
reports.tris_count += buffer->draw(pass(models));
|
||||
};
|
||||
world.getEntitiesModels(draw, frustum, offset, options.voxel_density);
|
||||
}
|
||||
if(state.look_at.has_value()) { // Indicator
|
||||
const auto model = glm::scale(glm::translate(glm::scale(glm::mat4(1), 1.f / glm::vec3(options.voxel_density)), glm::vec3(state.look_at.value().pos.second + state.look_at.value().offset - offset * glm::llvec3(options.voxel_density)) - glm::vec3(.5 + options.tool.radius)), glm::vec3(1 + options.tool.radius * 2));
|
||||
reports.models_count++;
|
||||
reports.tris_count += pipeline->drawIndicatorCube(model);
|
||||
}
|
||||
pipeline->endPass();
|
||||
|
||||
render::UI::Get()->render();
|
||||
}
|
||||
|
||||
{ // Swap buffers
|
||||
ZoneScopedN("Swap");
|
||||
pipeline->swapBuffer(window.getPtr());
|
||||
inputs.poll();
|
||||
FrameMark;
|
||||
}
|
||||
|
||||
window.waitTargetFPS();
|
||||
} while (!(inputs.isDown(Input::Quit) || window.shouldClose()));
|
||||
|
||||
render::UI::Unload();
|
||||
render::Renderer::Unload();
|
||||
window.destroy();
|
||||
|
||||
contouring::save(options.contouring_idx, state.contouring, options.contouring_data);
|
||||
options.save();
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
#pragma once
|
||||
|
||||
#include "state.h"
|
||||
#include "Window.hpp"
|
||||
|
||||
namespace render {
|
||||
class Renderer;
|
||||
};
|
||||
|
||||
/// Client view
|
||||
class Client {
|
||||
public:
|
||||
Client();
|
||||
~Client();
|
||||
|
||||
void run();
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
config::options options;
|
||||
config::state state;
|
||||
config::reports reports;
|
||||
|
||||
Window window;
|
||||
};
|
|
@ -49,4 +49,6 @@ bool InputMap::isPressing(Mouse input) const {
|
|||
}
|
||||
bool InputMap::isReleasing(Mouse input) const {
|
||||
return !isDown(input) && wasDown(input);
|
||||
}
|
||||
}
|
||||
|
||||
void InputMap::poll() const { glfwPollEvents(); }
|
|
@ -3,12 +3,11 @@
|
|||
#include <robin_hood.h>
|
||||
#include <vector>
|
||||
|
||||
#include <GL/gl3w.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
enum class Input {
|
||||
Forward, Backward, Left, Right, Up, Down,
|
||||
Mouse, Debug, Throw
|
||||
Mouse, Debug, Throw, Quit
|
||||
};
|
||||
enum class Mouse {
|
||||
Left = GLFW_MOUSE_BUTTON_LEFT,
|
||||
|
@ -35,6 +34,8 @@ public:
|
|||
bool isPressing(Mouse input) const;
|
||||
bool isReleasing(Mouse input) const;
|
||||
|
||||
void poll() const;
|
||||
|
||||
private:
|
||||
GLFWwindow *window;
|
||||
robin_hood::unordered_map<Input, int> Map = {
|
||||
|
@ -46,7 +47,8 @@ private:
|
|||
{Input::Down, GLFW_KEY_LEFT_SHIFT},
|
||||
{Input::Mouse, GLFW_KEY_E},
|
||||
{Input::Debug, GLFW_KEY_F3},
|
||||
{Input::Throw, GLFW_KEY_B}
|
||||
{Input::Throw, GLFW_KEY_B},
|
||||
{Input::Quit, GLFW_KEY_ESCAPE}
|
||||
};
|
||||
const std::vector<Input> Toggles = {
|
||||
Input::Mouse, Input::Debug, Input::Throw
|
|
@ -0,0 +1,121 @@
|
|||
#include "Window.hpp"
|
||||
|
||||
#include <GL/gl3w.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <exception>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include "../core/utils/logger.hpp"
|
||||
|
||||
/// Default floating window width
|
||||
constexpr auto DEFAULT_WIDTH = 1280;
|
||||
/// Default floating window height
|
||||
constexpr auto DEFAULT_HEIGHT = 720;
|
||||
|
||||
constexpr auto MIN_WIDTH = 854;
|
||||
constexpr auto MIN_HEIGHT = 480;
|
||||
|
||||
constexpr auto APP_NAME = "Univerxel";
|
||||
|
||||
Window::Window() : ptr(nullptr), targetFPS(60) {
|
||||
if (!glfwInit()) {
|
||||
FATAL("Failed to initialize GLFW");
|
||||
}
|
||||
}
|
||||
Window::~Window() {
|
||||
glfwTerminate();
|
||||
}
|
||||
|
||||
bool Window::create(const CreateInfo &opt) {
|
||||
if(isReady()) {
|
||||
LOG_W("Previous window in use");
|
||||
return false;
|
||||
}
|
||||
|
||||
glfwWindowHint(GLFW_SAMPLES, opt.samples);
|
||||
switch (opt.client.type) {
|
||||
case CreateInfo::Client::Type::GL:
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, opt.client.major);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, opt.client.minor);
|
||||
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // To make MacOS happy; should not be needed
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
break;
|
||||
|
||||
default:
|
||||
FATAL("Unsupported client type");
|
||||
break;
|
||||
}
|
||||
|
||||
#if FIXED_WINDOW
|
||||
glfwWindowHint(GLFW_RESIZABLE, false); //Note: Dev-only: Force floating on i3
|
||||
#endif
|
||||
|
||||
ptr = glfwCreateWindow(DEFAULT_WIDTH, DEFAULT_HEIGHT, APP_NAME, NULL, NULL);
|
||||
if (ptr == NULL) {
|
||||
LOG_E("Failed to open GLFW window");
|
||||
return false;
|
||||
}
|
||||
glfwMakeContextCurrent(ptr);
|
||||
|
||||
// Ensure we can capture the escape key being pressed below
|
||||
glfwSetInputMode(ptr, GLFW_STICKY_KEYS, GL_TRUE);
|
||||
// Hide the mouse and enable unlimited mouvement
|
||||
glfwSetInputMode(ptr, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
|
||||
// Set the mouse at the center of the screen
|
||||
// TODO: move to input manager
|
||||
glfwPollEvents();
|
||||
glfwSetCursorPos(ptr, DEFAULT_WIDTH / 2, DEFAULT_HEIGHT / 2);
|
||||
|
||||
// Force aspect ratio
|
||||
glfwSetWindowSizeLimits(ptr, MIN_WIDTH, MIN_HEIGHT, GLFW_DONT_CARE, GLFW_DONT_CARE);
|
||||
glfwSetWindowAspectRatio(ptr, RATIO_WIDTH, RATIO_HEIGHT);
|
||||
|
||||
glfwSetFramebufferSizeCallback(ptr, opt.pfnResize);
|
||||
|
||||
glfwSetWindowTitle(ptr, APP_NAME);
|
||||
glfwSetWindowAttrib(ptr, GLFW_RESIZABLE, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Window::isReady() const { return ptr != nullptr; }
|
||||
|
||||
void Window::setTargetFPS(int val) {
|
||||
targetFPS = val;
|
||||
glfwSwapInterval(static_cast<int>(val < MIN_FPS));
|
||||
}
|
||||
|
||||
double Window::getTime() const {
|
||||
return glfwGetTime();
|
||||
}
|
||||
void Window::startFrame() {
|
||||
frameStart = getTime();
|
||||
}
|
||||
void Window::waitTargetFPS() {
|
||||
if (targetFPS >= MIN_FPS && targetFPS <= MAX_FPS) {
|
||||
while (glfwGetTime() < frameStart + 1.0 / targetFPS) {
|
||||
std::this_thread::sleep_for(std::chrono::microseconds(100));
|
||||
}
|
||||
}
|
||||
}
|
||||
void Window::destroy() {
|
||||
glfwDestroyWindow(ptr);
|
||||
}
|
||||
|
||||
bool Window::shouldClose() { return glfwWindowShouldClose(ptr); }
|
||||
|
||||
void Window::setFullscreen(bool val) {
|
||||
// MAYBE: real fullscreen
|
||||
if(fullscreen != val) {
|
||||
fullscreen = val;
|
||||
if (val) {
|
||||
GLFWmonitor *monitor = glfwGetPrimaryMonitor();
|
||||
const GLFWvidmode *mode = glfwGetVideoMode(monitor);
|
||||
glfwSetWindowMonitor(ptr, monitor, 0, 0, mode->width, mode->height, mode->refreshRate);
|
||||
} else {
|
||||
glfwSetWindowMonitor(ptr, nullptr, 0, 0, DEFAULT_WIDTH, DEFAULT_HEIGHT, GLFW_DONT_CARE);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
#pragma once
|
||||
|
||||
#include "../core/flags.hpp"
|
||||
|
||||
typedef struct GLFWwindow GLFWwindow;
|
||||
typedef void (*GLFWframebuffersizefun)(GLFWwindow*, int, int);
|
||||
|
||||
|
||||
/// GLFW context and window
|
||||
class Window {
|
||||
public:
|
||||
Window();
|
||||
~Window();
|
||||
|
||||
static constexpr auto MIN_FPS = 24;
|
||||
static constexpr auto MAX_FPS = 240;
|
||||
|
||||
static constexpr auto RATIO_WIDTH = 16;
|
||||
static constexpr auto RATIO_HEIGHT = 9;
|
||||
/// Fixed window ratio
|
||||
static constexpr auto RATIO = RATIO_WIDTH / (RATIO_HEIGHT * 1.0f);
|
||||
|
||||
struct CreateInfo {
|
||||
GLFWframebuffersizefun pfnResize;
|
||||
struct Client {
|
||||
enum class Type { GL, VK } type;
|
||||
int major;
|
||||
int minor;
|
||||
} client;
|
||||
int samples;
|
||||
};
|
||||
bool create(const CreateInfo &opt);
|
||||
void destroy();
|
||||
bool isReady() const;
|
||||
|
||||
void setTargetFPS(int val);
|
||||
void setFullscreen(bool val);
|
||||
|
||||
_FORCE_INLINE_ GLFWwindow *getPtr() { return ptr; }
|
||||
|
||||
void startFrame();
|
||||
void waitTargetFPS();
|
||||
|
||||
bool shouldClose();
|
||||
|
||||
double getTime() const;
|
||||
|
||||
private:
|
||||
GLFWwindow *ptr;
|
||||
int targetFPS;
|
||||
bool fullscreen;
|
||||
double frameStart;
|
||||
};
|
|
@ -1,7 +1,7 @@
|
|||
#include "Camera.hpp"
|
||||
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include "../render/window.hpp"
|
||||
#include "../Window.hpp"
|
||||
|
||||
Camera::Camera(const Controllable* origin, const Camera::options& opt): origin(origin), o(opt) {
|
||||
updateProjection();
|
||||
|
@ -9,7 +9,7 @@ Camera::Camera(const Controllable* origin, const Camera::options& opt): origin(o
|
|||
Camera::~Camera() { }
|
||||
|
||||
void Camera::updateProjection() {
|
||||
ProjectionMatrix = glm::perspective(o.fov, RATIO, o.near, o.far);
|
||||
ProjectionMatrix = glm::perspective(o.fov, Window::RATIO, o.near, o.far);
|
||||
}
|
||||
|
||||
void Camera::update() {
|
|
@ -1,8 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include "Controllable.hpp"
|
||||
#include "../data/geometry/Frustum.hpp"
|
||||
#include "../data/geometry/Ray.hpp"
|
||||
#include "../../core/geometry/Frustum.hpp"
|
||||
#include "../../core/geometry/Ray.hpp"
|
||||
|
||||
/// Moving perspective camera
|
||||
class Camera {
|
|
@ -1,6 +1,6 @@
|
|||
#include "Controllable.hpp"
|
||||
|
||||
Controllable::Controllable(GLFWwindow *window, const InputMap& inputs, const Controllable::options& opt): position(voxel_pos(0), 1), window(window), inputs(inputs), o(opt){ }
|
||||
Controllable::Controllable(GLFWwindow *window, const InputMap& inputs, const Controllable::options& opt): position(voxel_pos(100, 0, 0), 1), window(window), inputs(inputs), o(opt){ }
|
||||
Controllable::~Controllable() { }
|
||||
|
||||
Controllable::axis Controllable::getAxis() const {
|
|
@ -1,11 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
#include "InputMap.hpp"
|
||||
#include "../InputMap.hpp"
|
||||
|
||||
#include <GL/gl3w.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include "../data/glm.hpp"
|
||||
#include "../world/position.h"
|
||||
#include "../../core/data/glm.hpp"
|
||||
#include "../../core/world/position.h"
|
||||
|
||||
/// Player controller moving entity
|
||||
struct Controllable {
|
|
@ -0,0 +1,45 @@
|
|||
#pragma once
|
||||
|
||||
#include "gl/pass/VoxelProgram.hpp"
|
||||
|
||||
struct GLFWwindow;
|
||||
class Camera;
|
||||
|
||||
namespace render {
|
||||
|
||||
/// Handle rendering passes and params
|
||||
class Pipeline {
|
||||
public:
|
||||
/// Rendering options
|
||||
struct options {
|
||||
/// Voxel passes
|
||||
pass::VoxelProgram::options voxel;
|
||||
/// Display skybox
|
||||
bool skybox = true;
|
||||
/// Display only wires
|
||||
bool wireframe = false;
|
||||
/// Texture pack name
|
||||
std::string textures = "1024-realistic";
|
||||
/// Textures quality
|
||||
float mipMapLOD = -.5;
|
||||
/// Textures anisotropic mapping
|
||||
int anisotropy = 0;
|
||||
/// Depth color
|
||||
glm::vec4 clear_color;
|
||||
};
|
||||
|
||||
virtual ~Pipeline() { }
|
||||
|
||||
/// Start new frame and setup
|
||||
virtual void beginFrame() = 0;
|
||||
/// Apply postprocessing
|
||||
virtual void endPass() = 0;
|
||||
/// Swap displayed image
|
||||
virtual void swapBuffer(GLFWwindow*) = 0;
|
||||
|
||||
/// Apply camera matrices
|
||||
virtual void lookFrom(const Camera&) = 0;
|
||||
|
||||
virtual void setClearColor(glm::vec4) = 0;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
#include "Renderer.hpp"
|
||||
|
||||
using namespace render;
|
||||
|
||||
Renderer *Renderer::sInstance = nullptr;
|
||||
|
||||
void Renderer::Unload() {
|
||||
delete sInstance;
|
||||
sInstance = nullptr;
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
#pragma once
|
||||
|
||||
#include "../Window.hpp"
|
||||
#include "Pipeline.hpp"
|
||||
#include <cassert>
|
||||
|
||||
namespace render {
|
||||
|
||||
/// Rendering plateform interface
|
||||
class Renderer {
|
||||
public:
|
||||
virtual ~Renderer() { }
|
||||
|
||||
virtual Pipeline* createPipeline(const Pipeline::options&) = 0;
|
||||
|
||||
virtual void loadUI(Window&) = 0;
|
||||
|
||||
static _FORCE_INLINE_ Renderer *Get() {
|
||||
assert(sInstance != nullptr && "Uninitialized renderer");
|
||||
return sInstance;
|
||||
}
|
||||
static void Unload();
|
||||
|
||||
protected:
|
||||
static Renderer *sInstance;
|
||||
};
|
||||
}
|
|
@ -1,33 +1,25 @@
|
|||
#include "UI.hpp"
|
||||
|
||||
#include <imgui.h>
|
||||
#include <imgui_impl_glfw.h>
|
||||
#include <imgui_impl_opengl3.h>
|
||||
#include "../state.h"
|
||||
#include "../contouring/Abstract.hpp"
|
||||
#include "../world/materials.hpp"
|
||||
#include "../../core/world/materials.hpp"
|
||||
|
||||
void UI::setup(GLFWwindow* window) {
|
||||
using namespace render;
|
||||
|
||||
UI *UI::sInstance = nullptr;
|
||||
|
||||
UI::UI() {
|
||||
// Setup Dear ImGui context
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGui::StyleColorsDark();
|
||||
|
||||
// Setup Platform/Renderer bindings
|
||||
ImGui_ImplGlfw_InitForOpenGL(window, true);
|
||||
ImGui_ImplOpenGL3_Init("#version 130");
|
||||
}
|
||||
void UI::unload() {
|
||||
ImGui_ImplGlfw_Shutdown();
|
||||
ImGui_ImplOpenGL3_Shutdown();
|
||||
|
||||
UI::~UI() {
|
||||
ImGui::DestroyContext();
|
||||
}
|
||||
|
||||
UI::Actions UI::draw(options &options, state &state, const reports &reports, GLuint aim) {
|
||||
UI::Actions UI::draw(config::options &options, config::state &state, const config::reports &reports, intptr_t aim) {
|
||||
auto actions = Actions::None;
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
ImGui_ImplGlfw_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
const ImGuiIO &io = ImGui::GetIO();
|
||||
|
@ -35,7 +27,7 @@ UI::Actions UI::draw(options &options, state &state, const reports &reports, GLu
|
|||
if(state.capture_mouse) {
|
||||
ImGui::SetNextWindowPos(ImVec2(io.DisplaySize.x / 2, io.DisplaySize.y / 2), ImGuiCond_Always, ImVec2(.5f, .5f));
|
||||
ImGui::Begin("Aim", NULL, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoInputs);
|
||||
ImGui::Image((void *)(intptr_t)aim, ImVec2(32, 32));
|
||||
ImGui::Image((void *)aim, ImVec2(32, 32));
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
|
@ -60,7 +52,7 @@ UI::Actions UI::draw(options &options, state &state, const reports &reports, GLu
|
|||
ImGui::Text("Tris: %ld (%ld models)", reports.tris_count, reports.models_count);
|
||||
ImGui::Separator();
|
||||
ImGui::Checkbox("Overlay", &options.overlay_show);
|
||||
if (ImGui::SliderInt("FPS", &options.target_fps, MIN_FPS-1, MAX_FPS+1, options.target_fps > MIN_FPS ? (options.target_fps < MAX_FPS ? "%d" : "UNLIMITED") : "VSYNC")){
|
||||
if (ImGui::SliderInt("FPS", &options.target_fps, Window::MIN_FPS-1, Window::MAX_FPS+1, options.target_fps > Window::MIN_FPS ? (options.target_fps < Window::MAX_FPS ? "%d" : "UNLIMITED") : "VSYNC")){
|
||||
actions |= Actions::FPS;
|
||||
}
|
||||
|
||||
|
@ -279,10 +271,12 @@ UI::Actions UI::draw(options &options, state &state, const reports &reports, GLu
|
|||
ImGui::Render();
|
||||
return actions;
|
||||
}
|
||||
void UI::render() {
|
||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
|
||||
bool UI::IsFocus() {
|
||||
return ImGui::IsAnyItemActive();
|
||||
}
|
||||
|
||||
bool UI::isFocus() {
|
||||
return ImGui::IsAnyItemActive();
|
||||
void UI::Unload() {
|
||||
delete sInstance;
|
||||
sInstance = nullptr;
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cassert>
|
||||
#include "../../core/flags.hpp"
|
||||
|
||||
namespace config {
|
||||
|
||||
struct options;
|
||||
struct state;
|
||||
struct reports;
|
||||
|
||||
}
|
||||
namespace render {
|
||||
|
||||
//TODO: rewrite as static with function pointers
|
||||
|
||||
/// ImGui interface
|
||||
class UI {
|
||||
protected:
|
||||
UI();
|
||||
public:
|
||||
virtual ~UI();
|
||||
|
||||
/// Retro actions to state
|
||||
enum class Actions {
|
||||
None = 0,
|
||||
FPS = 1 << 0,
|
||||
FullScreen = 1 << 1,
|
||||
ClearColor = 1 << 2,
|
||||
RendererSharders = 1 << 3,
|
||||
RendererTextures = 1 << 4,
|
||||
World = 1 << 5,
|
||||
Camera = 1 << 6,
|
||||
Control = 1 << 7,
|
||||
ChangeContouring = 1 << 8,
|
||||
};
|
||||
friend inline void operator|=(Actions& a, Actions b) {
|
||||
a = static_cast<Actions>(static_cast<int>(a) | static_cast<int>(b));
|
||||
}
|
||||
friend inline bool operator&&(Actions a, Actions b) {
|
||||
return static_cast<int>(a) & static_cast<int>(b);
|
||||
}
|
||||
|
||||
/// Compute UI
|
||||
virtual Actions draw(config::options&, config::state&, const config::reports&) = 0;
|
||||
|
||||
/// Display UI
|
||||
virtual void render() = 0;
|
||||
|
||||
/// Is UI in focus
|
||||
static bool IsFocus();
|
||||
|
||||
static _FORCE_INLINE_ UI *Get() {
|
||||
assert(sInstance != nullptr && "Uninitialized ui");
|
||||
return sInstance;
|
||||
}
|
||||
static void Unload();
|
||||
|
||||
protected:
|
||||
static Actions draw(config::options &, config::state &, const config::reports &, intptr_t aim);
|
||||
|
||||
static UI* sInstance;
|
||||
};
|
||||
|
||||
};
|
|
@ -1,10 +1,10 @@
|
|||
#pragma once
|
||||
|
||||
#include "../render/buffer/Abstract.hpp"
|
||||
#include "../world/forward.h"
|
||||
#include "../data/geometry/Frustum.hpp"
|
||||
#include "../data/geometry/Ray.hpp"
|
||||
#include "../data/geometry/Faces.hpp"
|
||||
#include "../gl/buffer/Abstract.hpp"
|
||||
#include "../../../server/world/forward.h"
|
||||
#include "../../../core/geometry/Frustum.hpp"
|
||||
#include "../../../core/geometry/Ray.hpp"
|
||||
#include "../../../core/geometry/Faces.hpp"
|
||||
|
||||
/// Mesh creation
|
||||
namespace contouring {
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
#include <imgui.h> // NOLINT
|
||||
#include <toml.h>
|
||||
#include "../world/Chunk.hpp"
|
||||
#include "../world/Area.hpp"
|
||||
#include "../../../server/world/Chunk.hpp"
|
||||
#include "../../../server/world/Area.hpp"
|
||||
|
||||
namespace contouring {
|
||||
size_t AbstractFlat::clear(const voxel_pos& pos, const world::area_map& areas) {
|
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "Abstract.hpp"
|
||||
#include "../data/math.hpp"
|
||||
#include "../../../core/data/math.hpp"
|
||||
|
||||
namespace contouring {
|
||||
/// Generating mesh for chunks 1:1
|
|
@ -1,8 +1,8 @@
|
|||
#include "FlatDualMC.hpp"
|
||||
|
||||
#include "../world/Chunk.hpp"
|
||||
#include "../world/Area.hpp"
|
||||
#include "../world/materials.hpp"
|
||||
#include "../../../server/world/Chunk.hpp"
|
||||
#include "../../../server/world/Area.hpp"
|
||||
#include "../../../core/world/materials.hpp"
|
||||
#include <Tracy.hpp> // NOLINT
|
||||
#include <common/TracySystem.hpp> // NOLINT
|
||||
#include <imgui.h> // NOLINT
|
|
@ -3,10 +3,10 @@
|
|||
#include "AbstractFlat.hpp"
|
||||
#include "surrounding.hpp"
|
||||
|
||||
#include "../data/safe_queue.hpp"
|
||||
#include "../data/safe_priority_queue.hpp"
|
||||
#include "../data/circular_buffer.hpp"
|
||||
#include "../render/buffer/LodShortIndexed.hpp"
|
||||
#include "../../../core/data/safe_queue.hpp"
|
||||
#include "../../../core/data/safe_priority_queue.hpp"
|
||||
#include "../../../core/data/circular_buffer.hpp"
|
||||
#include "../gl/buffer/LodShortIndexed.hpp"
|
||||
#include <thread>
|
||||
|
||||
using namespace data;
|
|
@ -1,7 +1,7 @@
|
|||
#include "surrounding.hpp"
|
||||
|
||||
#include "../world/Area.hpp"
|
||||
#include "../data/math.hpp"
|
||||
#include "../../../server/world/Area.hpp"
|
||||
#include "../../../core/data/math.hpp"
|
||||
|
||||
using namespace geometry;
|
||||
namespace contouring::surrounding {
|
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "../data/geometry/Faces.hpp"
|
||||
#include "../world/forward.h"
|
||||
#include "../../../core/geometry/Faces.hpp"
|
||||
#include "../../../server/world/forward.h"
|
||||
|
||||
namespace world {
|
||||
class Chunk;
|
|
@ -1,9 +1,12 @@
|
|||
#include "Renderer.hpp"
|
||||
#include "Pipeline.hpp"
|
||||
|
||||
#include "../world/materials.hpp"
|
||||
#include "../control/Camera.hpp"
|
||||
#include "../../../core/world/materials.hpp"
|
||||
#include "../../control/Camera.hpp"
|
||||
#include <TracyOpenGL.hpp>
|
||||
|
||||
Renderer::Renderer(const Renderer::options& options):
|
||||
using namespace render::gl;
|
||||
|
||||
Pipeline::Pipeline(const Pipeline::options& 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),
|
||||
|
@ -43,16 +46,17 @@ Renderer::Renderer(const Renderer::options& options):
|
|||
loadTextures(options.textures, options.mipMapLOD, options.anisotropy);
|
||||
}
|
||||
|
||||
Renderer::~Renderer() {
|
||||
Pipeline::~Pipeline() {
|
||||
unloadTextures();
|
||||
glDeleteVertexArrays(1, &VertexArrayID);
|
||||
}
|
||||
|
||||
void Renderer::beginFrame() {
|
||||
void Pipeline::beginFrame() {
|
||||
TracyGpuZone("Render");
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
std::function<buffer::params(glm::mat4)> Renderer::beginWorldPass() {
|
||||
std::function<buffer::params(glm::mat4)> Pipeline::beginWorldPass() {
|
||||
WorldPass->useIt();
|
||||
WorldPass->start(this);
|
||||
return [&](glm::mat4 model) {
|
||||
|
@ -60,7 +64,7 @@ std::function<buffer::params(glm::mat4)> Renderer::beginWorldPass() {
|
|||
};
|
||||
}
|
||||
|
||||
std::function<buffer::params(const std::vector<glm::mat4> &)> Renderer::beginEntityPass() {
|
||||
std::function<buffer::params(const std::vector<glm::mat4> &)> Pipeline::beginEntityPass() {
|
||||
EntityPass->useIt();
|
||||
EntityPass->start(this);
|
||||
return [&](const std::vector<glm::mat4>& models) {
|
||||
|
@ -68,45 +72,57 @@ std::function<buffer::params(const std::vector<glm::mat4> &)> Renderer::beginEnt
|
|||
};
|
||||
}
|
||||
|
||||
size_t Renderer::drawIndicatorCube(glm::mat4 model) {
|
||||
size_t Pipeline::drawIndicatorCube(glm::mat4 model) {
|
||||
IndicatorPass->useIt();
|
||||
return IndicatorCubeBuffer.draw(IndicatorPass->setup(this, model));
|
||||
}
|
||||
|
||||
void Renderer::endFrame() {
|
||||
void Pipeline::endPass() {
|
||||
if(SkyEnable) {
|
||||
SkyPass->draw(this);
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::reloadShaders(const pass::VoxelProgram::options& options) {
|
||||
void Pipeline::swapBuffer(GLFWwindow* ptr) {
|
||||
TracyGpuZone("Swap");
|
||||
glfwSwapBuffers(ptr);
|
||||
TracyGpuCollect;
|
||||
}
|
||||
|
||||
void Pipeline::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) {
|
||||
void Pipeline::reloadTextures(const std::string& texturePath, float mipMapLOD, float anisotropy) {
|
||||
unloadTextures();
|
||||
loadTextures(texturePath, mipMapLOD, anisotropy);
|
||||
}
|
||||
|
||||
void Renderer::unloadTextures() {
|
||||
void Pipeline::unloadTextures() {
|
||||
glDeleteTextures(1, &HOSAtlas);
|
||||
glDeleteTextures(1, &NormalAtlas);
|
||||
glDeleteTextures(1, &TextureAtlas);
|
||||
}
|
||||
void Renderer::loadTextures(const std::string& texturePath, float mipMapLOD, float anisotropy) {
|
||||
void Pipeline::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);
|
||||
}
|
||||
TextureAtlas = pass::Program::loadTextureArray(terrainTextures, "", mipMapLOD, anisotropy * anisotropy);
|
||||
NormalAtlas = pass::Program::loadTextureArray(terrainTextures, ".nrm", mipMapLOD, anisotropy * anisotropy);
|
||||
HOSAtlas = pass::Program::loadTextureArray(terrainTextures, ".hos", mipMapLOD, anisotropy * anisotropy);
|
||||
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) {
|
||||
void Pipeline::lookFrom(const Camera& camera) {
|
||||
ProjectionMatrix = camera.getProjectionMatrix();
|
||||
ViewMatrix = camera.getViewMatrix();
|
||||
FogDepth = camera.getDepth();
|
||||
}
|
||||
|
||||
void Pipeline::setClearColor(glm::vec4 c) {
|
||||
FogColor = c;
|
||||
glClearColor(c.r, c.g, c.b, c.a);
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "../Pipeline.hpp"
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <GL/gl3w.h>
|
||||
|
@ -9,34 +10,17 @@
|
|||
#include "pass/ColorProgram.hpp"
|
||||
#include "buffer/Colored.hpp"
|
||||
|
||||
class Camera;
|
||||
/// Handle rendering passes and params
|
||||
class Renderer {
|
||||
public:
|
||||
/// Rendering options
|
||||
struct options {
|
||||
/// Voxel passes
|
||||
pass::VoxelProgram::options voxel;
|
||||
/// Display skybox
|
||||
bool skybox = true;
|
||||
/// Display only wires
|
||||
bool wireframe = false;
|
||||
/// Texture pack name
|
||||
std::string textures = "1024-realistic";
|
||||
/// Textures quality
|
||||
float mipMapLOD = -.5;
|
||||
/// Textures anisotropic mapping
|
||||
int anisotropy = 0;
|
||||
/// Depth color
|
||||
glm::vec4 clear_color;
|
||||
};
|
||||
namespace render::gl {
|
||||
|
||||
Renderer(const options&);
|
||||
Renderer(Renderer &&) = delete;
|
||||
Renderer(const Renderer &) = delete;
|
||||
Renderer &operator=(Renderer &&) = delete;
|
||||
Renderer &operator=(const Renderer &) = delete;
|
||||
~Renderer();
|
||||
/// Handle OpenGL rendering passes and params
|
||||
class Pipeline final: public render::Pipeline {
|
||||
public:
|
||||
Pipeline(const options&);
|
||||
Pipeline(Pipeline &&) = delete;
|
||||
Pipeline(const Pipeline &) = delete;
|
||||
Pipeline &operator=(Pipeline &&) = delete;
|
||||
Pipeline &operator=(const Pipeline &) = delete;
|
||||
~Pipeline();
|
||||
|
||||
glm::vec3 LightInvDir = glm::vec3(0.5f, 2, 2);
|
||||
glm::vec3 FogColor;
|
||||
|
@ -71,7 +55,7 @@ public:
|
|||
}
|
||||
|
||||
/// Start new frame and setup
|
||||
void beginFrame();
|
||||
void beginFrame() override;
|
||||
/// Get started world program
|
||||
std::function<buffer::params(glm::mat4)> beginWorldPass();
|
||||
/// Get started entity program
|
||||
|
@ -79,10 +63,13 @@ public:
|
|||
/// Draw cube indicator
|
||||
size_t drawIndicatorCube(glm::mat4 model);
|
||||
/// Apply postprocessing
|
||||
void endFrame();
|
||||
void endPass() override;
|
||||
void swapBuffer(GLFWwindow *) override;
|
||||
|
||||
void setClearColor(glm::vec4) override;
|
||||
|
||||
/// Apply camera matrices
|
||||
void lookFrom(const Camera&);
|
||||
void lookFrom(const Camera&) override;
|
||||
void reloadShaders(const pass::VoxelProgram::options &);
|
||||
void reloadTextures(const std::string &, float mipMapLOD, float anisotropy);
|
||||
|
||||
|
@ -106,3 +93,5 @@ private:
|
|||
void loadTextures(const std::string &, float mipMapLOD, float anisotropy);
|
||||
void unloadTextures();
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
#include "Renderer.hpp"
|
||||
|
||||
#include "UI.hpp"
|
||||
#include "Pipeline.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 Options& options): options(options) { }
|
||||
Renderer::~Renderer() { }
|
||||
|
||||
bool Renderer::Load(Window& window, const Options& options) {
|
||||
auto windowInfo = GetWindowInfo();
|
||||
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));
|
||||
sInstance = new Renderer(options);
|
||||
return true;
|
||||
}
|
||||
|
||||
void framebuffer_size_callback(GLFWwindow *, int width, int height) {
|
||||
glViewport(0, 0, width, height);
|
||||
}
|
||||
Window::CreateInfo Renderer::GetWindowInfo() {
|
||||
Window::CreateInfo windowInfo;
|
||||
windowInfo.pfnResize = framebuffer_size_callback;
|
||||
windowInfo.client = { Window::CreateInfo::Client::Type::GL, GL_MAJOR, GL_MINOR };
|
||||
return windowInfo;
|
||||
}
|
||||
|
||||
render::Pipeline *Renderer::createPipeline(const render::Pipeline::options &opt) {
|
||||
// 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(options.clear_color.x, options.clear_color.y, options.clear_color.z, options.clear_color.w);
|
||||
|
||||
TracyGpuContext;
|
||||
return new Pipeline(opt);
|
||||
}
|
||||
|
||||
void Renderer::loadUI(Window& w) {
|
||||
UI::Load(w);
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
#pragma once
|
||||
#include "../Renderer.hpp"
|
||||
|
||||
#include <glm/vec4.hpp>
|
||||
|
||||
namespace render::gl {
|
||||
|
||||
/// OpenGL rendering
|
||||
class Renderer final: public render::Renderer {
|
||||
public:
|
||||
virtual ~Renderer();
|
||||
|
||||
struct Options {
|
||||
/// Depth color
|
||||
glm::vec4 clear_color;
|
||||
};
|
||||
|
||||
static bool Load(Window& window, const Options &options);
|
||||
|
||||
render::Pipeline *createPipeline(const render::Pipeline::options &) override;
|
||||
|
||||
void loadUI(Window &) override;
|
||||
|
||||
static _FORCE_INLINE_ Renderer *Get() { return static_cast<Renderer*>(render::Renderer::Get()); }
|
||||
|
||||
private:
|
||||
Renderer(const Options &options);
|
||||
static Window::CreateInfo GetWindowInfo();
|
||||
|
||||
Options options;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
#include "Texture.hpp"
|
||||
|
||||
#include "texture.hpp"
|
||||
|
||||
using namespace render::gl;
|
||||
|
||||
GLuint Texture::CreatePtr(const std::string &name, bool linear) {
|
||||
return loadDDS("content/textures/" + name + ".dds", linear);
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
namespace render::gl {
|
||||
|
||||
class Texture {
|
||||
public:
|
||||
static GLuint CreatePtr(const std::string &name, bool linear);
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
#include "UI.hpp"
|
||||
|
||||
#include <imgui_impl_glfw.h>
|
||||
#include <imgui_impl_opengl3.h>
|
||||
#include "Texture.hpp"
|
||||
|
||||
using namespace render::gl;
|
||||
|
||||
UI::UI(GLFWwindow *window): render::UI() {
|
||||
// Setup Platform/Renderer bindings
|
||||
ImGui_ImplGlfw_InitForOpenGL(window, true);
|
||||
ImGui_ImplOpenGL3_Init("#version 130");
|
||||
aim = Texture::CreatePtr("ui/Aim", false);
|
||||
}
|
||||
UI::~UI() {
|
||||
ImGui_ImplGlfw_Shutdown();
|
||||
ImGui_ImplOpenGL3_Shutdown();
|
||||
}
|
||||
|
||||
UI::Actions UI::draw(config::options &o, config::state &s, const config::reports &r) {
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
ImGui_ImplGlfw_NewFrame();
|
||||
return render::UI::draw(o, s, r, aim);
|
||||
}
|
||||
void UI::render() {
|
||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
}
|
||||
|
||||
void UI::Load(Window& w) {
|
||||
UI::sInstance = new UI(w.getPtr());
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
#pragma once
|
||||
|
||||
#include "../UI.hpp"
|
||||
#include "../../Window.hpp"
|
||||
|
||||
namespace render::gl {
|
||||
|
||||
/// ImGui OpenGL/GLFW interface
|
||||
class UI final: public render::UI {
|
||||
private:
|
||||
UI(GLFWwindow *window);
|
||||
public:
|
||||
~UI();
|
||||
|
||||
static void Load(Window &);
|
||||
|
||||
Actions draw(config::options &, config::state &, const config::reports &) override;
|
||||
void render() override;
|
||||
|
||||
private:
|
||||
intptr_t aim;
|
||||
};
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
#include "ShortIndexed.hpp"
|
||||
|
||||
#include "vboindexer.hpp"
|
||||
#include "../../data/logger.hpp"
|
||||
#include "../../../../core/utils/logger.hpp"
|
||||
|
||||
using namespace buffer;
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
#include "ColorProgram.hpp"
|
||||
|
||||
#include "../Renderer.hpp"
|
||||
#include "../Pipeline.hpp"
|
||||
|
||||
using namespace pass;
|
||||
|
||||
|
@ -20,7 +20,7 @@ ColorProgram::~ColorProgram() { }
|
|||
std::string ColorProgram::getName() const {
|
||||
return "Color";
|
||||
}
|
||||
buffer::params ColorProgram::setup(Renderer *renderer, glm::mat4 modelMatrix) {
|
||||
buffer::params ColorProgram::setup(render::gl::Pipeline *renderer, glm::mat4 modelMatrix) {
|
||||
const auto mvp = renderer->getProjectionMatrix() * renderer->getViewMatrix() * modelMatrix;
|
||||
setMVP(&mvp[0][0]);
|
||||
return buffer::params{.vertexOnly = false};
|
|
@ -9,7 +9,7 @@ namespace pass {
|
|||
ColorProgram();
|
||||
~ColorProgram();
|
||||
|
||||
buffer::params setup(Renderer *, glm::mat4 modelMatrix);
|
||||
buffer::params setup(render::gl::Pipeline *, glm::mat4 modelMatrix);
|
||||
|
||||
protected:
|
||||
std::string getName() const override;
|
|
@ -1,6 +1,6 @@
|
|||
#include "EntityProgram.hpp"
|
||||
|
||||
#include "../Renderer.hpp"
|
||||
#include "../Pipeline.hpp"
|
||||
|
||||
using namespace pass;
|
||||
|
||||
|
@ -17,7 +17,7 @@ EntityProgram::EntityProgram(const EntityProgram::options &opts) : VoxelProgram(
|
|||
}
|
||||
EntityProgram::~EntityProgram() { }
|
||||
|
||||
buffer::params EntityProgram::setup(Renderer *renderer, const std::vector<glm::mat4>& modelsMatrices) {
|
||||
buffer::params EntityProgram::setup(render::gl::Pipeline *renderer, const std::vector<glm::mat4>& modelsMatrices) {
|
||||
setModels(&modelsMatrices[0][0][0], modelsMatrices.size());
|
||||
auto params = VoxelProgram::setup(renderer);
|
||||
params.instances = modelsMatrices.size();
|
|
@ -11,7 +11,7 @@ namespace pass {
|
|||
|
||||
static constexpr auto LOCATION = 6;
|
||||
|
||||
buffer::params setup(Renderer *, const std::vector<glm::mat4> &modelsMatrices);
|
||||
buffer::params setup(render::gl::Pipeline *, const std::vector<glm::mat4> &modelsMatrices);
|
||||
void disable();
|
||||
|
||||
protected:
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
#include "texture.hpp"
|
||||
#include "../texture.hpp"
|
||||
|
||||
#define CONTENT_DIR "content/"
|
||||
#define SHADER_DIR CONTENT_DIR "shaders/"
|
|
@ -8,7 +8,9 @@
|
|||
#include "Shader.hpp"
|
||||
#include "../buffer/Abstract.hpp"
|
||||
|
||||
class Renderer;
|
||||
namespace render::gl {
|
||||
class Pipeline;
|
||||
}
|
||||
/// OpenGL programs
|
||||
namespace pass {
|
||||
/// OpenGL shaders pipeline
|
|
@ -1,6 +1,6 @@
|
|||
#include "SkyProgram.hpp"
|
||||
|
||||
#include "../Renderer.hpp"
|
||||
#include "../Pipeline.hpp"
|
||||
|
||||
using namespace pass;
|
||||
|
||||
|
@ -65,7 +65,7 @@ SkyProgram::~SkyProgram() { }
|
|||
std::string SkyProgram::getName() const {
|
||||
return "Sky";
|
||||
}
|
||||
void SkyProgram::start(Renderer *renderer) {
|
||||
void SkyProgram::start(render::gl::Pipeline *renderer) {
|
||||
const auto fixedView = glm::mat4(glm::mat3(renderer->getViewMatrix()));
|
||||
setView(&fixedView[0][0]);
|
||||
setProjection(&renderer->getProjectionMatrix()[0][0]);
|
||||
|
@ -75,7 +75,7 @@ void SkyProgram::start(Renderer *renderer) {
|
|||
buffer::params SkyProgram::setup() {
|
||||
return buffer::params{.vertexOnly = true};
|
||||
}
|
||||
void SkyProgram::draw(Renderer *renderer) {
|
||||
void SkyProgram::draw(render::gl::Pipeline *renderer) {
|
||||
useIt();
|
||||
start(renderer);
|
||||
CubeBuffer.draw(setup());
|
|
@ -10,11 +10,11 @@ namespace pass {
|
|||
SkyProgram();
|
||||
~SkyProgram();
|
||||
|
||||
void start(Renderer *);
|
||||
void start(render::gl::Pipeline *);
|
||||
buffer::params setup();
|
||||
|
||||
/// Direct draw using internal buffer
|
||||
void draw(Renderer *);
|
||||
void draw(render::gl::Pipeline *);
|
||||
|
||||
protected:
|
||||
std::string getName() const override;
|
|
@ -1,6 +1,6 @@
|
|||
#include "VoxelProgram.hpp"
|
||||
|
||||
#include "../Renderer.hpp"
|
||||
#include "../Pipeline.hpp"
|
||||
|
||||
using namespace pass;
|
||||
|
||||
|
@ -53,7 +53,7 @@ VoxelProgram::~VoxelProgram() { }
|
|||
std::string VoxelProgram::getName() const {
|
||||
return "Voxel";
|
||||
}
|
||||
void VoxelProgram::start(Renderer *renderer) {
|
||||
void VoxelProgram::start(render::gl::Pipeline *renderer) {
|
||||
bindTexture(renderer->getTextureAtlas());
|
||||
bindNormal(renderer->getNormalAtlas());
|
||||
bindHOS(renderer->getHOSAtlas());
|
||||
|
@ -62,7 +62,7 @@ void VoxelProgram::start(Renderer *renderer) {
|
|||
setView(&renderer->getViewMatrix()[0][0]);
|
||||
setProj(&renderer->getProjectionMatrix()[0][0]);
|
||||
}
|
||||
buffer::params VoxelProgram::setup(Renderer *renderer) {
|
||||
buffer::params VoxelProgram::setup(render::gl::Pipeline *renderer) {
|
||||
setSphereProj(&renderer->SphereProj[0]);
|
||||
setCurvature(renderer->Curvature);
|
||||
return buffer::params{.vertexOnly = false};
|
|
@ -29,10 +29,10 @@ namespace pass {
|
|||
VoxelProgram(const options &opts, std::vector<std::string> flags = {});
|
||||
~VoxelProgram();
|
||||
|
||||
void start(Renderer *);
|
||||
void start(render::gl::Pipeline *);
|
||||
|
||||
protected:
|
||||
buffer::params setup(Renderer *);
|
||||
buffer::params setup(render::gl::Pipeline *);
|
||||
|
||||
std::string getName() const override;
|
||||
void setView(const GLfloat *matrix);
|
|
@ -1,6 +1,6 @@
|
|||
#include "WorldProgram.hpp"
|
||||
|
||||
#include "../Renderer.hpp"
|
||||
#include "../Pipeline.hpp"
|
||||
|
||||
using namespace pass;
|
||||
|
||||
|
@ -11,7 +11,7 @@ WorldProgram::WorldProgram(const WorldProgram::options& opts): VoxelProgram(opts
|
|||
|
||||
WorldProgram::~WorldProgram() { }
|
||||
|
||||
buffer::params WorldProgram::setup(Renderer *renderer, glm::mat4 modelMatrix) {
|
||||
buffer::params WorldProgram::setup(render::gl::Pipeline *renderer, glm::mat4 modelMatrix) {
|
||||
setModel(&modelMatrix[0][0]);
|
||||
return VoxelProgram::setup(renderer);
|
||||
}
|
|
@ -9,7 +9,7 @@ namespace pass {
|
|||
WorldProgram(const options &opts);
|
||||
~WorldProgram();
|
||||
|
||||
buffer::params setup(Renderer *, glm::mat4 modelMatrix);
|
||||
buffer::params setup(render::gl::Pipeline *, glm::mat4 modelMatrix);
|
||||
|
||||
protected:
|
||||
void setModel(const GLfloat *matrix);
|
|
@ -1,19 +1,19 @@
|
|||
#pragma once
|
||||
|
||||
#define UI_MARGIN 5
|
||||
#define MIN_FPS 24
|
||||
#define MAX_FPS 240
|
||||
|
||||
#include <toml.h>
|
||||
#include <fstream>
|
||||
#include <filesystem>
|
||||
#include <optional>
|
||||
#include "data/glm.hpp"
|
||||
#include "data/circular_buffer.hpp"
|
||||
#include <glm/vec4.hpp>
|
||||
#include "render/Renderer.hpp"
|
||||
#include "world/Universe.hpp"
|
||||
#include "render/Pipeline.hpp"
|
||||
#include "../server/world/Universe.hpp"
|
||||
#include "control/Camera.hpp"
|
||||
#include "contouring/index.hpp"
|
||||
#include "render/contouring/index.hpp"
|
||||
|
||||
namespace config {
|
||||
|
||||
inline glm::vec4 fromHex(const std::string& str) {
|
||||
std::array<int, 3> rgb = {UCHAR_MAX};
|
||||
|
@ -164,7 +164,7 @@ struct options {
|
|||
int target_fps;
|
||||
int samples;
|
||||
bool fullscreen;
|
||||
Renderer::options renderer;
|
||||
render::Pipeline::options renderer;
|
||||
|
||||
bool show_debug_world;
|
||||
world::Universe::options world;
|
||||
|
@ -208,4 +208,6 @@ struct state {
|
|||
struct reports {
|
||||
size_t tris_count = 0;
|
||||
size_t models_count = 0;
|
||||
};
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
#ifndef _ALWAYS_INLINE_
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ >= 4)
|
||||
#define _ALWAYS_INLINE_ __attribute__((always_inline)) inline
|
||||
#elif defined(__llvm__)
|
||||
#define _ALWAYS_INLINE_ __attribute__((always_inline)) inline
|
||||
#elif defined(_MSC_VER)
|
||||
#define _ALWAYS_INLINE_ __forceinline
|
||||
#else
|
||||
#define _ALWAYS_INLINE_ inline
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
//should always inline, except in some cases because it makes debugging harder
|
||||
#ifndef _FORCE_INLINE_
|
||||
|
||||
#ifdef DISABLE_FORCED_INLINE
|
||||
#define _FORCE_INLINE_ inline
|
||||
#else
|
||||
#define _FORCE_INLINE_ _ALWAYS_INLINE_
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,6 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "../../world/position.h"
|
||||
#include "../world/position.h"
|
||||
|
||||
/// Math utils
|
||||
namespace geometry {
|
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "IBox.hpp"
|
||||
#include "../../world/position.h"
|
||||
#include "../world/position.h"
|
||||
|
||||
namespace geometry {
|
||||
/// Raycast with distance
|
|
@ -10,6 +10,7 @@
|
|||
#define LOG_W(expr) _OUT("[" << YELLOW << logger::now() << END_COLOR << "] " << expr)
|
||||
#define LOG_I(expr) _OUT("[" << GREEN << logger::now() << END_COLOR << "] " << expr)
|
||||
#define LOG_D(expr) _OUT("[" << GREY << logger::now() << END_COLOR << "] " << expr)
|
||||
#define FATAL(expr) LOG_E(expr); exit(EXIT_FAILURE)
|
||||
|
||||
namespace logger {
|
||||
std::_Put_time<char> now();
|
212
src/main.cpp
212
src/main.cpp
|
@ -7,18 +7,8 @@
|
|||
* Univerxel main program.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <chrono>
|
||||
|
||||
#include "render/window.hpp"
|
||||
#include "render/UI.hpp"
|
||||
#include "control/InputMap.hpp" //TODO: add options
|
||||
|
||||
#include "state.h"
|
||||
#include "data/math.hpp"
|
||||
|
||||
#include "client/Client.hpp"
|
||||
#include <Tracy.hpp>
|
||||
#include <TracyOpenGL.hpp>
|
||||
|
||||
#if TRACY_MEMORY
|
||||
void *operator new(std::size_t count)
|
||||
|
@ -37,209 +27,13 @@ void operator delete(void *ptr) noexcept
|
|||
/// Entry point
|
||||
int main(int /*unused*/, char */*unused*/[]){
|
||||
LOG("Univerxel");
|
||||
options options;
|
||||
state state;
|
||||
reports reports;
|
||||
|
||||
GLFWwindow *window = createWindow(options.samples);
|
||||
if(window == nullptr)
|
||||
return 1;
|
||||
|
||||
glClearColor(options.renderer.clear_color.x, options.renderer.clear_color.y, options.renderer.clear_color.z, options.renderer.clear_color.w);
|
||||
glfwSwapInterval(static_cast<int>(options.target_fps < MIN_FPS));
|
||||
|
||||
InputMap inputs(window);
|
||||
Controllable player(window, inputs, options.control);
|
||||
Camera camera(&player, options.camera);
|
||||
|
||||
auto *renderer = new Renderer(options.renderer);
|
||||
renderer->LightInvDir = glm::normalize(glm::vec3(-.5f, 2, -2));
|
||||
UI::setup(window);
|
||||
|
||||
GLuint aimTexture = pass::Program::loadTexture("ui/Aim", false);
|
||||
|
||||
#if TRACY_ENABLE
|
||||
LOG("Profiling !");
|
||||
#endif
|
||||
TracyGpuContext;
|
||||
|
||||
world::Universe world = world::Universe(options.world);
|
||||
world.setContouring(contouring::load(options.contouring_idx, options.contouring_data));
|
||||
state.contouring = world.getContouring();
|
||||
|
||||
do {
|
||||
const double startTime = glfwGetTime();
|
||||
{ // Update
|
||||
ZoneScopedN("Update");
|
||||
static double lastTime = glfwGetTime();
|
||||
const double partTime = glfwGetTime();
|
||||
const float deltaTime = partTime - lastTime;
|
||||
inputs.toggle(state.capture_mouse, Input::Mouse);
|
||||
inputs.toggle(options.show_debug_menu, Input::Debug);
|
||||
|
||||
player.capture(state.capture_mouse, !UI::isFocus(), deltaTime);
|
||||
if(player.velocity != glm::vec3(0) && (
|
||||
!options.control.collide ||
|
||||
!world.collide(player.position, player.velocity, options.voxel_density, 1))
|
||||
) {
|
||||
player.position += player.velocity;
|
||||
state.position = player.position;
|
||||
}
|
||||
camera.update();
|
||||
renderer->lookFrom(camera);
|
||||
renderer->LightInvDir = glm::vec3(glm::rotate(glm::mat4(1), deltaTime * .1f, glm::vec3(1, .5, .1)) * glm::vec4(renderer->LightInvDir, 0));
|
||||
|
||||
{
|
||||
const auto ray_result = world.raycast(camera.getRay() * options.voxel_density);
|
||||
if(auto target = std::get_if<world::Universe::ray_target>(&ray_result)) {
|
||||
state.look_at = *target;
|
||||
} else {
|
||||
state.look_at = {};
|
||||
}
|
||||
}
|
||||
if (state.capture_mouse) {
|
||||
if (state.look_at.has_value()) {
|
||||
ZoneScopedN("Edit");
|
||||
if (inputs.isPressing(Mouse::Left))
|
||||
world.setCube(state.look_at.value().pos, world::Voxel(world::materials::AIR, options.tool.empty_air * world::Voxel::DENSITY_MAX), options.tool.radius);
|
||||
else if (inputs.isPressing(Mouse::Right))
|
||||
world.setCube(state.look_at.value().pos, world::Voxel(options.tool.material, world::Voxel::DENSITY_MAX), options.tool.radius);
|
||||
}
|
||||
if (inputs.isDown(Input::Throw)) {
|
||||
world.addEntity(entity_id(0), {state.position * options.voxel_density, glm::vec3(10, 0, 0)});
|
||||
}
|
||||
}
|
||||
world.update((state.position * options.voxel_density).as_voxel(), deltaTime);
|
||||
inputs.saveKeys();
|
||||
lastTime = partTime;
|
||||
}
|
||||
|
||||
{
|
||||
ZoneScopedN("UI");
|
||||
const auto actions = UI::draw(options, state, reports, aimTexture);
|
||||
if (actions && UI::Actions::FPS) {
|
||||
glfwSwapInterval(static_cast<int>(options.target_fps < MIN_FPS));
|
||||
}
|
||||
if (actions && UI::Actions::FullScreen) {
|
||||
// MAYBE: real fullscreen
|
||||
if(options.fullscreen) {
|
||||
GLFWmonitor *monitor = glfwGetPrimaryMonitor();
|
||||
const GLFWvidmode *mode = glfwGetVideoMode(monitor);
|
||||
glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, mode->refreshRate);
|
||||
} else {
|
||||
glfwSetWindowMonitor(window, nullptr, 0, 0, DEFAULT_WIDTH, DEFAULT_HEIGHT, GLFW_DONT_CARE);
|
||||
}
|
||||
}
|
||||
if(actions && UI::Actions::ClearColor) {
|
||||
renderer->FogColor = glm::vec3(options.renderer.clear_color.x, options.renderer.clear_color.y, options.renderer.clear_color.z);
|
||||
glClearColor(options.renderer.clear_color.x, options.renderer.clear_color.y, options.renderer.clear_color.z, options.renderer.clear_color.w);
|
||||
}
|
||||
if(actions && UI::Actions::RendererSharders) {
|
||||
renderer->reloadShaders(options.renderer.voxel);
|
||||
}
|
||||
if(actions && UI::Actions::RendererTextures) {
|
||||
renderer->reloadTextures(options.renderer.textures, options.renderer.mipMapLOD, options.renderer.anisotropy);
|
||||
}
|
||||
if(actions && UI::Actions::World) {
|
||||
world.setOptions(options.world);
|
||||
}
|
||||
if(actions && UI::Actions::Camera) {
|
||||
camera.setOptions(options.camera);
|
||||
}
|
||||
if(actions && UI::Actions::Control) {
|
||||
player.setOptions(options.control);
|
||||
}
|
||||
if(actions && UI::Actions::ChangeContouring) {
|
||||
state.contouring = NULL;
|
||||
world.setContouring(contouring::load(options.contouring_idx, options.contouring_data));
|
||||
state.contouring = world.getContouring();
|
||||
}
|
||||
renderer->SkyEnable = options.renderer.skybox;
|
||||
}
|
||||
{ // Rendering
|
||||
ZoneScopedN("Render");
|
||||
TracyGpuZone("Render");
|
||||
renderer->beginFrame();
|
||||
|
||||
reports.models_count = 0;
|
||||
reports.tris_count = 0;
|
||||
std::optional<geometry::Frustum> frustum;
|
||||
if(options.culling >= 0) {
|
||||
frustum = {camera.getFrustum()};
|
||||
}
|
||||
const auto offset = state.position.raw_as_long();
|
||||
{ // Chunks
|
||||
const auto pass = renderer->beginWorldPass();
|
||||
const auto draw = [&](glm::mat4 model, buffer::Abstract *const buffer, const contouring::Abstract::area_info &area, const voxel_pos &pos) {
|
||||
renderer->SphereProj = glm::vec4(pos, std::get<1>(area));
|
||||
renderer->Curvature = std::get<2>(area);
|
||||
reports.models_count++;
|
||||
reports.tris_count += buffer->draw(pass(model));
|
||||
};
|
||||
if (options.culling > 0) {
|
||||
std::vector<glm::vec3> occlusion;
|
||||
const auto ratio = options.culling * 2;
|
||||
occlusion.reserve(glm::pow2(ratio * 2 - 1));
|
||||
const auto [ch, cv] = player.getAngles();
|
||||
const auto max_v = tan(options.camera.fov / 2.), max_h = RATIO * max_v;
|
||||
for(int iv = -ratio + 1; iv < ratio; iv++) {
|
||||
const auto v = cv + max_v * iv / ratio;
|
||||
for(int ih = -ratio + 1; ih < ratio; ih++) {
|
||||
const auto h = ch + max_h * ih / ratio;
|
||||
occlusion.emplace_back(cos(v) * sin(h), sin(v), cos(v) * cos(h));
|
||||
}
|
||||
}
|
||||
world.getContouring()->getModels(draw, player.position, options.camera.far, occlusion, offset, options.voxel_density);
|
||||
} else {
|
||||
world.getContouring()->getModels(draw, frustum, offset, options.voxel_density);
|
||||
}
|
||||
}
|
||||
{ // Entities
|
||||
const auto pass = renderer->beginEntityPass();
|
||||
const auto draw = [&](const std::vector<glm::mat4>& models, buffer::Abstract *const buffer) {
|
||||
reports.models_count += models.size();
|
||||
reports.tris_count += buffer->draw(pass(models));
|
||||
};
|
||||
world.getEntitiesModels(draw, frustum, offset, options.voxel_density);
|
||||
}
|
||||
if(state.look_at.has_value()) { // Indicator
|
||||
const auto model = glm::scale(glm::translate(glm::scale(glm::mat4(1), 1.f / glm::vec3(options.voxel_density)), glm::vec3(state.look_at.value().pos.second + state.look_at.value().offset - offset * glm::llvec3(options.voxel_density)) - glm::vec3(.5 + options.tool.radius)), glm::vec3(1 + options.tool.radius * 2));
|
||||
reports.models_count++;
|
||||
reports.tris_count += renderer->drawIndicatorCube(model);
|
||||
}
|
||||
renderer->endFrame();
|
||||
|
||||
UI::render();
|
||||
}
|
||||
|
||||
{ // Swap buffers
|
||||
ZoneScopedN("Swap");
|
||||
TracyGpuZone("Swap");
|
||||
glfwSwapBuffers(window);
|
||||
glfwPollEvents();
|
||||
TracyGpuCollect;
|
||||
FrameMark;
|
||||
}
|
||||
|
||||
{ // Wait target fps
|
||||
if(options.target_fps >= MIN_FPS && options.target_fps <= MAX_FPS) {
|
||||
while (glfwGetTime() < startTime + 1.0 / options.target_fps) {
|
||||
std::this_thread::sleep_for(std::chrono::microseconds(100));
|
||||
}
|
||||
}
|
||||
}
|
||||
} // Check if the ESC key was pressed or the window was closed
|
||||
while (glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS &&
|
||||
glfwWindowShouldClose(window) == 0);
|
||||
|
||||
UI::unload();
|
||||
delete renderer;
|
||||
|
||||
// Close OpenGL window and terminate GLFW
|
||||
glfwTerminate();
|
||||
|
||||
contouring::save(options.contouring_idx, state.contouring, options.contouring_data);
|
||||
options.save();
|
||||
Client client;
|
||||
client.run();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <GL/gl3w.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
struct options;
|
||||
struct state;
|
||||
struct reports;
|
||||
namespace UI {
|
||||
/// Retro actions to state
|
||||
enum class Actions {
|
||||
None = 0,
|
||||
FPS = 1 << 0,
|
||||
FullScreen = 1 << 1,
|
||||
ClearColor = 1 << 2,
|
||||
RendererSharders = 1 << 3,
|
||||
RendererTextures = 1 << 4,
|
||||
World = 1 << 5,
|
||||
Camera = 1 << 6,
|
||||
Control = 1 << 7,
|
||||
ChangeContouring = 1 << 8,
|
||||
};
|
||||
inline void operator|=(Actions& a, Actions b) {
|
||||
a = static_cast<Actions>(static_cast<int>(a) | static_cast<int>(b));
|
||||
}
|
||||
inline bool operator&&(Actions a, Actions b) {
|
||||
return static_cast<int>(a) & static_cast<int>(b);
|
||||
}
|
||||
|
||||
/// Prepare UI
|
||||
void setup(GLFWwindow*);
|
||||
/// Release UI
|
||||
void unload();
|
||||
/// Compute UI
|
||||
Actions draw(options&, state&, const reports&, GLuint aim);
|
||||
|
||||
/// Is UI in focus
|
||||
bool isFocus();
|
||||
/// Display UI
|
||||
void render();
|
||||
};
|
|
@ -1,97 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "window.hpp"
|
||||
|
||||
#include <GL/gl3w.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#define MIN_WIDTH 854
|
||||
#define MIN_HEIGHT 480
|
||||
|
||||
#define GL_MAJOR 3
|
||||
#define GL_MINOR 3
|
||||
|
||||
void framebuffer_size_callback(GLFWwindow *, int width, int height) {
|
||||
glViewport(0, 0, width, height);
|
||||
}
|
||||
|
||||
GLFWwindow* createWindow(int samples) {
|
||||
GLFWwindow *window;
|
||||
|
||||
// Initialise GLFW
|
||||
if (!glfwInit()) {
|
||||
fprintf(stderr, "Failed to initialize GLFW\n");
|
||||
getchar();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
glfwWindowHint(GLFW_SAMPLES, samples);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, GL_MAJOR);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, GL_MINOR);
|
||||
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // To make MacOS happy; should not be needed
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
|
||||
#if FIXED_WINDOW
|
||||
glfwWindowHint(GLFW_RESIZABLE, false); //Note: Dev-only: Force floating on i3
|
||||
#endif
|
||||
|
||||
window = glfwCreateWindow(DEFAULT_WIDTH, DEFAULT_HEIGHT, "Univerxel", NULL, NULL);
|
||||
if (window == NULL) {
|
||||
fprintf(stderr, "Failed to open GLFW window.\n");
|
||||
getchar();
|
||||
glfwTerminate();
|
||||
return NULL;
|
||||
}
|
||||
glfwMakeContextCurrent(window);
|
||||
|
||||
// Initialize gl3w
|
||||
if (gl3wInit()) {
|
||||
fprintf(stderr, "failed to initialize OpenGL\n");
|
||||
glfwTerminate();
|
||||
return NULL;
|
||||
}
|
||||
if (!gl3wIsSupported(GL_MAJOR, GL_MINOR)) {
|
||||
fprintf(stderr, "OpenGL %d.%d not supported\n", GL_MAJOR, GL_MINOR);
|
||||
glfwTerminate();
|
||||
return NULL;
|
||||
}
|
||||
printf("OpenGL %s, GLSL %s\n", glGetString(GL_VERSION),
|
||||
glGetString(GL_SHADING_LANGUAGE_VERSION));
|
||||
|
||||
// Ensure we can capture the escape key being pressed below
|
||||
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
|
||||
// Hide the mouse and enable unlimited mouvement
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
|
||||
// Set the mouse at the center of the screen
|
||||
glfwPollEvents();
|
||||
glfwSetCursorPos(window, DEFAULT_WIDTH / 2, DEFAULT_HEIGHT / 2);
|
||||
|
||||
// Force aspect ratio
|
||||
glfwSetWindowSizeLimits(window, MIN_WIDTH, MIN_HEIGHT, GLFW_DONT_CARE, GLFW_DONT_CARE);
|
||||
glfwSetWindowAspectRatio(window, RATIO_WIDTH, RATIO_HEIGHT);
|
||||
|
||||
// Handle resize
|
||||
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
|
||||
|
||||
glfwSetWindowTitle(window, "Univerxel");
|
||||
glfwSetWindowAttrib(window, GLFW_RESIZABLE, true);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
return window;
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
#ifndef WINDOW_HPP
|
||||
#define WINDOW_HPP
|
||||
|
||||
#define RATIO_WIDTH 16
|
||||
#define RATIO_HEIGHT 9
|
||||
/// Fixed window ratio
|
||||
#define RATIO RATIO_WIDTH / (RATIO_HEIGHT * 1.0f)
|
||||
|
||||
/// Default floating window width
|
||||
#define DEFAULT_WIDTH 1280
|
||||
/// Default floating window height
|
||||
#define DEFAULT_HEIGHT 720
|
||||
|
||||
#include <GL/gl3w.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
/// Initialise glew and glfw, then create window
|
||||
GLFWwindow *createWindow(int samples);
|
||||
|
||||
#endif
|
|
@ -5,7 +5,7 @@
|
|||
using namespace libguarded;
|
||||
#include "region/index.hpp"
|
||||
#include "generator.hpp"
|
||||
#include "../data/geometry/IBox.hpp"
|
||||
#include "../../core/geometry/IBox.hpp"
|
||||
|
||||
namespace world {
|
||||
/// Chunk map with restricted access
|
|
@ -1,7 +1,7 @@
|
|||
#include "Chunk.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include "../data/math.hpp"
|
||||
#include "../../core/data/math.hpp"
|
||||
#include <Tracy.hpp>
|
||||
|
||||
using namespace world;
|
|
@ -4,8 +4,8 @@
|
|||
#include <sstream>
|
||||
#include "generator.hpp"
|
||||
#include "Voxel.hpp"
|
||||
#include "../data/geometry/Faces.hpp"
|
||||
#include "../data/math.hpp"
|
||||
#include "../../core/geometry/Faces.hpp"
|
||||
#include "../../core/data/math.hpp"
|
||||
|
||||
/// Chunk length
|
||||
namespace world {
|
|
@ -6,7 +6,7 @@
|
|||
#include <FastNoiseSIMD.h>
|
||||
#endif
|
||||
#include <memory>
|
||||
#include "position.h"
|
||||
#include "../../core/world/position.h"
|
||||
|
||||
namespace world {
|
||||
/// Noise handler
|
|
@ -5,10 +5,10 @@
|
|||
#include <filesystem>
|
||||
#include <random>
|
||||
|
||||
#include "../contouring/Dummy.hpp"
|
||||
#include "../../client/render/contouring/Dummy.hpp"
|
||||
#include "Chunk.hpp"
|
||||
|
||||
#include "../render/buffer/ShortIndexed.hpp"
|
||||
#include "../../client/render/gl/buffer/ShortIndexed.hpp"
|
||||
|
||||
using namespace world;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue