day-night loop, dynamic skybox, clock on debug panel

This commit is contained in:
MihailRis
2023-11-28 11:01:22 +03:00
parent 4a9a4ddd14
commit c08c31b0ad
24 changed files with 599 additions and 48 deletions
+2
View File
@@ -110,6 +110,8 @@ void AssetsLoader::addDefaults(AssetsLoader& loader) {
loader.add(ASSET_SHADER, resdir/path(SHADERS_FOLDER"/main"), "main");
loader.add(ASSET_SHADER, resdir/path(SHADERS_FOLDER"/lines"), "lines");
loader.add(ASSET_SHADER, resdir/path(SHADERS_FOLDER"/ui"), "ui");
loader.add(ASSET_SHADER, resdir/path(SHADERS_FOLDER"/background"), "background");
loader.add(ASSET_SHADER, resdir/path(SHADERS_FOLDER"/skybox_gen"), "skybox_gen");
loader.add(ASSET_ATLAS, resdir/path(TEXTURES_FOLDER"/blocks"), "blocks");
loader.add(ASSET_TEXTURE, resdir/path(TEXTURES_FOLDER"/menubg.png"), "menubg");
+10 -1
View File
@@ -27,6 +27,7 @@
#define PLAYER_FLAG_NOCLIP 0x2
#define WORLD_SECTION_MAIN 1
#define WORLD_SECTION_DAYNIGHT 2
using glm::ivec2;
using glm::vec3;
@@ -235,11 +236,15 @@ void WorldFiles::writeWorldInfo(const WorldInfo& info) {
BinaryWriter out;
out.putCStr(WORLD_FORMAT_MAGIC);
out.put(WORLD_FORMAT_VERSION);
out.put(WORLD_SECTION_MAIN);
out.putInt64(info.seed);
out.put(info.name);
out.put(WORLD_SECTION_DAYNIGHT);
out.putFloat32(info.daytime);
out.putFloat32(info.daytimeSpeed);
files::write_bytes(getWorldFile(), (const char*)out.data(), out.size());
}
@@ -260,6 +265,10 @@ bool WorldFiles::readWorldInfo(WorldInfo& info) {
info.seed = inp.getInt64();
info.name = inp.getString();
break;
case WORLD_SECTION_DAYNIGHT:
info.daytime = inp.getFloat32();
info.daytimeSpeed = inp.getFloat32();
break;
}
}
return false;
+2
View File
@@ -36,6 +36,8 @@ struct WorldInfo {
std::string name;
std::filesystem::path directory;
uint64_t seed;
float daytime;
float daytimeSpeed;
};
class WorldFiles {
+111
View File
@@ -0,0 +1,111 @@
#include "Skybox.h"
#include <GL/glew.h>
#include <iostream>
#include <glm/glm.hpp>
#include "../../graphics/Shader.h"
#include "../../graphics/Mesh.h"
#include "../../window/Window.h"
using glm::vec3;
Skybox::Skybox(uint size, Shader* shader) : size(size), shader(shader) {
glGenTextures(1, &cubemap);
glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap);
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
for (uint face = 0; face < 6; face++) {
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, GL_RGB, size, size, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
}
glGenFramebuffers(1, &fbo);
float vertices[] {
-1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f
};
vattr attrs[] {2, 0};
mesh = new Mesh(vertices, 6, attrs);
}
Skybox::~Skybox() {
glDeleteTextures(1, &cubemap);
glDeleteFramebuffers(1, &fbo);
delete mesh;
}
void Skybox::draw(Shader* shader) {
shader->uniform1i("u_cubemap", 1);
bind();
mesh->draw();
unbind();
}
void Skybox::refresh(float t, float mie, uint quality) {
ready = true;
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap);
shader->use();
Window::viewport(0,0, size,size);
const vec3 xaxs[] = {
{0.0f, 0.0f, -1.0f},
{0.0f, 0.0f, 1.0f},
{-1.0f, 0.0f, 0.0f},
{-1.0f, 0.0f, 0.0f},
{-1.0f, 0.0f, 0.0f},
{1.0f, 0.0f, 0.0f},
};
const vec3 yaxs[] = {
{0.0f, 1.0f, 0.0f},
{0.0f, 1.0f, 0.0f},
{0.0f, 0.0f, -1.0f},
{0.0f, 0.0f, 1.0f},
{0.0f, 1.0f, 0.0f},
{0.0f, 1.0f, 0.0f},
};
const vec3 zaxs[] = {
{1.0f, 0.0f, 0.0f},
{-1.0f, 0.0f, 0.0f},
{0.0f, -1.0f, 0.0f},
{0.0f, 1.0f, 0.0f},
{0.0f, 0.0f, -1.0f},
{0.0f, 0.0f, 1.0f},
};
t *= M_PI*2.0f;
shader->uniform1i("u_quality", quality);
shader->uniform1f("u_mie", mie);
shader->uniform3f("u_lightDir", glm::normalize(vec3(sin(t), -cos(t), 0.7f)));
for (uint face = 0; face < 6; face++) {
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, cubemap, 0);
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
shader->uniform3f("u_xaxis", xaxs[face]);
shader->uniform3f("u_yaxis", yaxs[face]);
shader->uniform3f("u_zaxis", zaxs[face]);
mesh->draw(GL_TRIANGLES);
}
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
glActiveTexture(GL_TEXTURE0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
Window::viewport(0, 0, Window::width, Window::height);
}
void Skybox::bind() const {
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap);
glActiveTexture(GL_TEXTURE0);
}
void Skybox::unbind() const {
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
glActiveTexture(GL_TEXTURE0);
}
+30
View File
@@ -0,0 +1,30 @@
#ifndef FRONTEND_GRAPHICS_SKYBOX_H_
#define FRONTEND_GRAPHICS_SKYBOX_H_
#include "../../typedefs.h"
class Mesh;
class Shader;
class Skybox {
uint fbo;
uint cubemap;
uint size;
Mesh* mesh;
Shader* shader;
bool ready = false;
public:
Skybox(uint size, Shader* shader);
~Skybox();
void draw(Shader* shader);
void refresh(float t, float mie, uint quality);
void bind() const;
void unbind() const;
bool isReady() const {
return ready;
}
};
#endif // FRONTEND_GRAPHICS_SKYBOX_H_
+13 -3
View File
@@ -11,6 +11,7 @@
#include "../typedefs.h"
#include "../content/Content.h"
#include "../util/stringutil.h"
#include "../util/timeutil.h"
#include "../assets/Assets.h"
#include "../graphics/Shader.h"
#include "../graphics/Batch2D.h"
@@ -128,13 +129,22 @@ HudRenderer::HudRenderer(Engine* engine,
sub->add(box);
panel->add(sub);
}
panel->add(shared_ptr<Label>(create_label([this](){
int hour, minute, second;
timeutil::from_value(this->level->world->daytime, hour, minute, second);
std::wstring timeString =
util::lfill(std::to_wstring(hour), 2, L'0') + L":" +
util::lfill(std::to_wstring(minute), 2, L'0');
return L"time: "+timeString;
})));
{
TrackBar* bar = new TrackBar(0.0f, 1.0f, 1.0f, 0.02f, 2);
TrackBar* bar = new TrackBar(0.0f, 1.0f, 1.0f, 0.005f, 8);
bar->supplier([=]() {
return renderer->skyLightMutliplier;
return level->world->daytime;
});
bar->consumer([=](double val) {
renderer->skyLightMutliplier = val;
level->world->daytime = val;
});
panel->add(bar);
}
+3
View File
@@ -136,6 +136,9 @@ void LevelScreen::update(float delta) {
level->chunks->saveAndClear();
backlight = settings.graphics.backlight;
}
if (!hud->isPause()) {
level->world->updateTimers(delta);
}
level->updatePlayer(delta, !inputLocked, hud->isPause(), !inputLocked);
level->update();
+23 -13
View File
@@ -28,6 +28,7 @@
#include "../settings.h"
#include "../engine.h"
#include "ContentGfxCache.h"
#include "graphics/Skybox.h"
using glm::vec3;
using std::string;
@@ -35,15 +36,19 @@ using std::shared_ptr;
WorldRenderer::WorldRenderer(Engine* engine, Level* level, const ContentGfxCache* cache)
: engine(engine), level(level) {
EngineSettings& settings = engine->getSettings();
lineBatch = new LineBatch(4096);
renderer = new ChunksRenderer(level, cache, engine->getSettings());
renderer = new ChunksRenderer(level, cache, settings);
frustumCulling = new Frustum();
level->events->listen(EVT_CHUNK_HIDDEN, [this](lvl_event_type type, Chunk* chunk) {
renderer->unload(chunk);
});
skybox = new Skybox(64, engine->getAssets()->getShader("skybox_gen"));
}
WorldRenderer::~WorldRenderer() {
delete skybox;
delete lineBatch;
delete renderer;
delete frustumCulling;
@@ -100,6 +105,10 @@ void WorldRenderer::drawChunks(Chunks* chunks,
void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool occlusion){
EngineSettings& settings = engine->getSettings();
skybox->refresh(level->world->daytime,
fmax(1.0f, 18.0f/settings.chunks.loadDistance), 4);
const Content* content = level->content;
const ContentIndices* contentIds = content->indices;
Assets* assets = engine->getAssets();
@@ -110,32 +119,32 @@ void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool occlusion)
const Viewport& viewport = pctx.getViewport();
int displayWidth = viewport.getWidth();
int displayHeight = viewport.getHeight();
Window::clearDepth();
Window::viewport(0, 0, displayWidth, displayHeight);
Shader* backShader = assets->getShader("background");
backShader->use();
backShader->uniformMatrix("u_view", camera->getView(false));
backShader->uniform1f("u_zoom", camera->zoom);
backShader->uniform1f("u_ar", (float)Window::width/(float)Window::height);
skybox->draw(backShader);
{
GfxContext ctx = pctx.sub();
ctx.depthTest(true);
ctx.cullFace(true);
EngineSettings& settings = engine->getSettings();
vec3 skyColor(0.7f, 0.81f, 1.0f);
skyColor *= skyLightMutliplier;
Window::setBgColor(skyColor);
Window::clear();
Window::viewport(0, 0, displayWidth, displayHeight);
float fogFactor = 18.0f / (float)settings.chunks.loadDistance;
shader->use();
skybox->bind();
shader->uniformMatrix("u_proj", camera->getProjection());
shader->uniformMatrix("u_view", camera->getView());
shader->uniform1f("u_gamma", 1.0f);
shader->uniform3f("u_skyLightColor", vec3(1.1f) * skyLightMutliplier);
shader->uniform3f("u_fogColor", skyColor);
shader->uniform1f("u_fogFactor", fogFactor);
shader->uniform1f("u_fogCurve", settings.graphics.fogCurve);
shader->uniform3f("u_cameraPos", camera->position);
shader->uniform1i("u_cubemap", 1);
Block* cblock = contentIds->getBlockDef(level->player->choosenBlock);
assert(cblock != nullptr);
@@ -168,6 +177,7 @@ void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool occlusion)
}
lineBatch->render();
}
skybox->unbind();
}
if (level->player->debug) {
@@ -175,7 +185,7 @@ void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool occlusion)
ctx.depthTest(true);
linesShader->use();
if (engine->getSettings().debug.showChunkBorders){
if (settings.debug.showChunkBorders){
linesShader->uniformMatrix("u_projview", camera->getProjView());
vec3 coord = level->player->camera->position;
if (coord.x < 0) coord.x--;
+2 -2
View File
@@ -22,6 +22,7 @@ class Frustum;
class Engine;
class Chunks;
class ContentGfxCache;
class Skybox;
class WorldRenderer {
Engine* engine;
@@ -29,11 +30,10 @@ class WorldRenderer {
Frustum* frustumCulling;
LineBatch* lineBatch;
ChunksRenderer* renderer;
Skybox* skybox;
bool drawChunk(size_t index, Camera* camera, Shader* shader, bool occlusion);
void drawChunks(Chunks* chunks, Camera* camera, Shader* shader, bool occlusion);
public:
float skyLightMutliplier = 1.0f; // will be replaced with day-night cycle
WorldRenderer(Engine* engine, Level* level, const ContentGfxCache* cache);
~WorldRenderer();
+14
View File
@@ -0,0 +1,14 @@
#include "timeutil.h"
float timeutil::time_value(float hour, float minute, float second) {
return (hour + (minute + second / 60.0f) / 60.0f) / 24.0f;
}
void timeutil::from_value(float value, int& hour, int& minute, int& second) {
value *= 24;
hour = value;
value *= 60;
minute = int(value) % 60;
value *= 60;
second = int(value) % 60;
}
+9
View File
@@ -0,0 +1,9 @@
#ifndef UTIL_TIMEUTIL_H_
#define UTIL_TIMEUTIL_H_
namespace timeutil {
float time_value(float hour, float minute, float second);
void from_value(float value, int& hour, int& minute, int& second);
}
#endif // UTIL_TIMEUTIL_H_
+8 -3
View File
@@ -42,11 +42,16 @@ mat4 Camera::getProjection(){
return glm::ortho(0.0f, fov*aspect, 0.0f, fov);
}
mat4 Camera::getView(){
if (perspective)
mat4 Camera::getView(bool pos){
vec3 position = this->position;
if (!pos) {
position = vec3(0.0f);
}
if (perspective) {
return glm::lookAt(position, position+front, up);
else
} else {
return glm::translate(glm::mat4(1.0f), position);
}
}
mat4 Camera::getProjView(){
+1 -1
View File
@@ -24,7 +24,7 @@ public:
void rotate(float x, float y, float z);
mat4 getProjection();
mat4 getView();
mat4 getView(bool position=true);
mat4 getProjView();
};
+9
View File
@@ -127,6 +127,10 @@ int Window::initialize(DisplaySettings& settings){
glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, GLFW_DONT_CARE);
}
glfwSwapInterval(settings.swapInterval);
const GLubyte* vendor = glGetString(GL_VENDOR);
const GLubyte* renderer = glGetString(GL_RENDERER);
std::cout << "GL Vendor: " << (char*)vendor << std::endl;
std::cout << "GL Renderer: " << (char*)renderer << std::endl;
return 0;
}
@@ -134,6 +138,10 @@ void Window::clear() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
void Window::clearDepth() {
glClear(GL_DEPTH_BUFFER_BIT);
}
void Window::setBgColor(glm::vec3 color) {
glClearColor(color.r, color.g, color.b, 1.0f);
}
@@ -252,6 +260,7 @@ DisplaySettings* Window::getSettings() {
ImageData* Window::takeScreenshot() {
ubyte* data = new ubyte[width * height * 3];
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, data);
return new ImageData(ImageFormat::rgb888, width, height, data);
}
+1
View File
@@ -44,6 +44,7 @@ public:
static void resetScissor();
static void clear();
static void clearDepth();
static void setBgColor(glm::vec3 color);
static double time();
static DisplaySettings* getSettings();
+9 -2
View File
@@ -29,6 +29,11 @@ World::~World(){
delete wfile;
}
void World::updateTimers(float delta) {
daytime += delta * daytimeSpeed;
daytime = fmod(daytime, 1.0f);
}
void World::write(Level* level) {
const Content* content = level->content;
@@ -41,15 +46,17 @@ void World::write(Level* level) {
wfile->put(chunk.get());
}
wfile->write(WorldInfo {name, wfile->directory, seed}, content);
wfile->write(WorldInfo {name, wfile->directory, seed, daytime, daytimeSpeed}, content);
wfile->writePlayer(level->player);
}
Level* World::load(EngineSettings& settings, const Content* content) {
WorldInfo info {name, wfile->directory, seed};
WorldInfo info {name, wfile->directory, seed, daytime, daytimeSpeed};
wfile->readWorldInfo(info);
seed = info.seed;
name = info.name;
daytime = info.daytime;
daytimeSpeed = info.daytimeSpeed;
vec3 playerPosition = vec3(0, 100, 0);
Camera* camera = new Camera(playerPosition, glm::radians(90.0f));
+9
View File
@@ -5,6 +5,7 @@
#include <filesystem>
#include "../typedefs.h"
#include "../settings.h"
#include "../util/timeutil.h"
class Content;
class WorldFiles;
@@ -18,12 +19,20 @@ public:
WorldFiles* wfile;
uint64_t seed;
/* Day/night loop timer in range 0..1
0.0 - is midnight
0.5 - is noon
*/
float daytime = timeutil::time_value(10, 00, 00);
float daytimeSpeed = 1.0f/60.0f/24.0f;
World(std::string name,
std::filesystem::path directory,
uint64_t seed,
EngineSettings& settings);
~World();
void updateTimers(float delta);
void write(Level* level);
Level* load(EngineSettings& settings, const Content* content);
};