This commit is contained in:
MihailRis 2024-02-26 01:27:27 +03:00
parent e06350915e
commit 925ef426de
6 changed files with 240 additions and 233 deletions

View File

@ -15,18 +15,19 @@ class Content;
class ContentGfxCache; class ContentGfxCache;
class BlocksPreview { class BlocksPreview {
public:
static ImageData* draw( static ImageData* draw(
const ContentGfxCache* cache, const ContentGfxCache* cache,
Framebuffer* framebuffer, Framebuffer* framebuffer,
Batch3D* batch, Batch3D* batch,
const Block* block, const Block* block,
int size); int size
);
public:
static std::unique_ptr<Atlas> build( static std::unique_ptr<Atlas> build(
const ContentGfxCache* cache, const ContentGfxCache* cache,
Assets* assets, Assets* assets,
const Content* content); const Content* content
);
}; };
#endif // FRONTEND_BLOCKS_PREVIEW_H_ #endif // FRONTEND_BLOCKS_PREVIEW_H_

View File

@ -34,167 +34,172 @@
#include "graphics/Skybox.h" #include "graphics/Skybox.h"
#include "graphics/ChunksRenderer.h" #include "graphics/ChunksRenderer.h"
using glm::vec3;
using glm::vec4;
using glm::mat4;
WorldRenderer::WorldRenderer(Engine* engine, LevelFrontend* frontend) WorldRenderer::WorldRenderer(Engine* engine, LevelFrontend* frontend)
: engine(engine), : engine(engine),
level(frontend->getLevel()), level(frontend->getLevel())
frustumCulling(new Frustum()), {
lineBatch(new LineBatch()), frustumCulling = std::make_unique<Frustum>();
renderer(new ChunksRenderer(level, lineBatch = std::make_unique<LineBatch>();
frontend->getContentGfxCache(), renderer = std::make_unique<ChunksRenderer>(
engine->getSettings())), level,
batch3d(new Batch3D(4096)) { frontend->getContentGfxCache(),
engine->getSettings()
);
batch3d = std::make_unique<Batch3D>(4096);
auto& settings = engine->getSettings(); auto& settings = engine->getSettings();
level->events->listen(EVT_CHUNK_HIDDEN, level->events->listen(EVT_CHUNK_HIDDEN,
[this](lvl_event_type type, Chunk* chunk) { [this](lvl_event_type type, Chunk* chunk) {
renderer->unload(chunk); renderer->unload(chunk);
} }
); );
auto assets = engine->getAssets(); auto assets = engine->getAssets();
skybox = new Skybox(settings.graphics.skyboxResolution, skybox = std::make_unique<Skybox>(
assets->getShader("skybox_gen")); settings.graphics.skyboxResolution,
assets->getShader("skybox_gen")
);
} }
WorldRenderer::~WorldRenderer() { WorldRenderer::~WorldRenderer() {
delete skybox;
delete lineBatch;
delete renderer;
delete frustumCulling;
} }
bool WorldRenderer::drawChunk(size_t index, bool WorldRenderer::drawChunk(
Camera* camera, size_t index,
Shader* shader, Camera* camera,
bool culling){ Shader* shader,
auto chunk = level->chunks->chunks[index]; bool culling
if (!chunk->isLighted()) { ){
return false; auto chunk = level->chunks->chunks[index];
} if (!chunk->isLighted()) {
return false;
}
float distance = glm::distance( float distance = glm::distance(
camera->position, camera->position,
glm::vec3((chunk->x + 0.5f) * CHUNK_W, camera->position.y, (chunk->z + 0.5f) * CHUNK_D) glm::vec3((chunk->x + 0.5f) * CHUNK_W,
camera->position.y,
(chunk->z + 0.5f) * CHUNK_D)
); );
auto mesh = renderer->getOrRender(chunk, distance < CHUNK_W*1.5f); auto mesh = renderer->getOrRender(chunk, distance < CHUNK_W*1.5f);
if (mesh == nullptr) { if (mesh == nullptr) {
return false; return false;
} }
if (culling){ if (culling){
vec3 min(chunk->x * CHUNK_W, glm::vec3 min(
chunk->bottom, chunk->x * CHUNK_W,
chunk->z * CHUNK_D); chunk->bottom,
vec3 max(chunk->x * CHUNK_W + CHUNK_W, chunk->z * CHUNK_D
chunk->top, );
chunk->z * CHUNK_D + CHUNK_D); glm::vec3 max(
chunk->x * CHUNK_W + CHUNK_W,
chunk->top,
chunk->z * CHUNK_D + CHUNK_D
);
if (!frustumCulling->IsBoxVisible(min, max)) return false; if (!frustumCulling->IsBoxVisible(min, max))
} return false;
vec3 coord = vec3(chunk->x*CHUNK_W+0.5f, 0.5f, chunk->z*CHUNK_D+0.5f); }
mat4 model = glm::translate(mat4(1.0f), coord); glm::vec3 coord(chunk->x*CHUNK_W+0.5f, 0.5f, chunk->z*CHUNK_D+0.5f);
shader->uniformMatrix("u_model", model); glm::mat4 model = glm::translate(glm::mat4(1.0f), coord);
mesh->draw(); shader->uniformMatrix("u_model", model);
return true; mesh->draw();
return true;
} }
void WorldRenderer::drawChunks(Chunks* chunks, void WorldRenderer::drawChunks(Chunks* chunks, Camera* camera, Shader* shader) {
Camera* camera,
Shader* shader) {
renderer->update(); renderer->update();
std::vector<size_t> indices; std::vector<size_t> indices;
for (size_t i = 0; i < chunks->volume; i++){ for (size_t i = 0; i < chunks->volume; i++){
if (chunks->chunks[i] == nullptr) if (chunks->chunks[i] == nullptr)
continue; continue;
indices.push_back(i); indices.push_back(i);
} }
float px = camera->position.x / (float)CHUNK_W; float px = camera->position.x / (float)CHUNK_W;
float pz = camera->position.z / (float)CHUNK_D; float pz = camera->position.z / (float)CHUNK_D;
std::sort(indices.begin(), indices.end(), [chunks, px, pz](size_t i, size_t j) { std::sort(indices.begin(), indices.end(), [chunks, px, pz](size_t i, size_t j) {
auto a = chunks->chunks[i]; auto a = chunks->chunks[i];
auto b = chunks->chunks[j]; auto b = chunks->chunks[j];
return ((a->x + 0.5f - px)*(a->x + 0.5f - px) + return ((a->x + 0.5f - px)*(a->x + 0.5f - px) +
(a->z + 0.5f - pz)*(a->z + 0.5f - pz) (a->z + 0.5f - pz)*(a->z + 0.5f - pz)
> >
(b->x + 0.5f - px)*(b->x + 0.5f - px) + (b->x + 0.5f - px)*(b->x + 0.5f - px) +
(b->z + 0.5f - pz)*(b->z + 0.5f - pz)); (b->z + 0.5f - pz)*(b->z + 0.5f - pz));
}); });
bool culling = engine->getSettings().graphics.frustumCulling; bool culling = engine->getSettings().graphics.frustumCulling;
if (culling) { if (culling) {
frustumCulling->update(camera->getProjView()); frustumCulling->update(camera->getProjView());
} }
chunks->visible = 0; chunks->visible = 0;
for (size_t i = 0; i < indices.size(); i++){ for (size_t i = 0; i < indices.size(); i++){
chunks->visible += drawChunk(indices[i], camera, shader, culling); chunks->visible += drawChunk(indices[i], camera, shader, culling);
} }
} }
void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool hudVisible){ void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool hudVisible){
EngineSettings& settings = engine->getSettings();
Window::clearDepth(); Window::clearDepth();
EngineSettings& settings = engine->getSettings(); skybox->refresh(pctx, level->world->daytime, 1.0f+fog*2.0f, 4);
skybox->refresh(pctx, level->world->daytime, 1.0f+fog*2.0f, 4);
const Content* content = level->content; const Content* content = level->content;
auto indices = content->getIndices(); auto indices = content->getIndices();
Assets* assets = engine->getAssets(); Assets* assets = engine->getAssets();
Atlas* atlas = assets->getAtlas("blocks"); Atlas* atlas = assets->getAtlas("blocks");
Shader* shader = assets->getShader("main"); Shader* shader = assets->getShader("main");
const Viewport& viewport = pctx.getViewport(); const Viewport& viewport = pctx.getViewport();
int displayWidth = viewport.getWidth(); int displayWidth = viewport.getWidth();
int displayHeight = viewport.getHeight(); int displayHeight = viewport.getHeight();
// Drawing background sky plane // Drawing background sky plane
skybox->draw(pctx, camera, assets, level->getWorld()->daytime, fog); skybox->draw(pctx, camera, assets, level->getWorld()->daytime, fog);
Shader* linesShader = assets->getShader("lines"); Shader* linesShader = assets->getShader("lines");
{ {
GfxContext ctx = pctx.sub(); GfxContext ctx = pctx.sub();
ctx.depthTest(true); ctx.depthTest(true);
ctx.cullFace(true); ctx.cullFace(true);
float fogFactor = 15.0f / ((float)settings.chunks.loadDistance-2); float fogFactor = 15.0f / ((float)settings.chunks.loadDistance-2);
// Setting up main shader // Setting up main shader
shader->use(); shader->use();
shader->uniformMatrix("u_proj", camera->getProjection()); shader->uniformMatrix("u_proj", camera->getProjection());
shader->uniformMatrix("u_view", camera->getView()); shader->uniformMatrix("u_view", camera->getView());
shader->uniform1f("u_gamma", settings.graphics.gamma); shader->uniform1f("u_gamma", settings.graphics.gamma);
shader->uniform1f("u_fogFactor", fogFactor); shader->uniform1f("u_fogFactor", fogFactor);
shader->uniform1f("u_fogCurve", settings.graphics.fogCurve); shader->uniform1f("u_fogCurve", settings.graphics.fogCurve);
shader->uniform3f("u_cameraPos", camera->position); shader->uniform3f("u_cameraPos", camera->position);
shader->uniform1i("u_cubemap", 1); shader->uniform1i("u_cubemap", 1);
{ {
auto player = level->player; auto player = level->player;
auto inventory = player->getInventory(); auto inventory = player->getInventory();
ItemStack& stack = inventory->getSlot(player->getChosenSlot()); ItemStack& stack = inventory->getSlot(player->getChosenSlot());
ItemDef* item = indices->getItemDef(stack.getItemId()); ItemDef* item = indices->getItemDef(stack.getItemId());
assert(item != nullptr); assert(item != nullptr);
float multiplier = 0.5f; float multiplier = 0.5f;
shader->uniform3f("u_torchlightColor", shader->uniform3f("u_torchlightColor",
item->emission[0] / 15.0f * multiplier, item->emission[0] / 15.0f * multiplier,
item->emission[1] / 15.0f * multiplier, item->emission[1] / 15.0f * multiplier,
item->emission[2] / 15.0f * multiplier); item->emission[2] / 15.0f * multiplier);
shader->uniform1f("u_torchlightDistance", 6.0f); shader->uniform1f("u_torchlightDistance", 6.0f);
} }
// Binding main shader textures // Binding main shader textures
skybox->bind(); skybox->bind();
atlas->getTexture()->bind(); atlas->getTexture()->bind();
drawChunks(level->chunks, camera, shader); drawChunks(level->chunks, camera, shader);
// Selected block // Selected block
if (PlayerController::selectedBlockId != -1 && hudVisible){ if (PlayerController::selectedBlockId != -1 && hudVisible){
blockid_t id = PlayerController::selectedBlockId; blockid_t id = PlayerController::selectedBlockId;
Block* block = indices->getBlockDef(id); Block* block = indices->getBlockDef(id);
assert(block != nullptr); assert(block != nullptr);
const vec3 pos = PlayerController::selectedBlockPosition; const glm::vec3 pos = PlayerController::selectedBlockPosition;
const vec3 point = PlayerController::selectedPointPosition; const glm::vec3 point = PlayerController::selectedPointPosition;
const vec3 norm = PlayerController::selectedBlockNormal; const glm::vec3 norm = PlayerController::selectedBlockNormal;
std::vector<AABB>& hitboxes = block->rotatable std::vector<AABB>& hitboxes = block->rotatable
? block->rt.hitboxes[PlayerController::selectedBlockStates] ? block->rt.hitboxes[PlayerController::selectedBlockStates]
@ -204,95 +209,96 @@ void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool hudVisible
linesShader->uniformMatrix("u_projview", camera->getProjView()); linesShader->uniformMatrix("u_projview", camera->getProjView());
lineBatch->lineWidth(2.0f); lineBatch->lineWidth(2.0f);
for (auto& hitbox: hitboxes) { for (auto& hitbox: hitboxes) {
const vec3 center = pos + hitbox.center(); const glm::vec3 center = pos + hitbox.center();
const vec3 size = hitbox.size(); const glm::vec3 size = hitbox.size();
lineBatch->box(center, size + vec3(0.02), vec4(0.f, 0.f, 0.f, 0.5f)); lineBatch->box(center, size + glm::vec3(0.02), glm::vec4(0.f, 0.f, 0.f, 0.5f));
if (level->player->debug) if (level->player->debug) {
lineBatch->line(point, point+norm*0.5f, vec4(1.0f, 0.0f, 1.0f, 1.0f)); lineBatch->line(point, point+norm*0.5f, glm::vec4(1.0f, 0.0f, 1.0f, 1.0f));
}
} }
lineBatch->render(); lineBatch->render();
} }
skybox->unbind(); skybox->unbind();
} }
if (hudVisible && level->player->debug) { if (hudVisible && level->player->debug) {
GfxContext ctx = pctx.sub(); GfxContext ctx = pctx.sub();
ctx.depthTest(true); ctx.depthTest(true);
linesShader->use(); linesShader->use();
if (settings.debug.showChunkBorders){ if (settings.debug.showChunkBorders){
linesShader->uniformMatrix("u_projview", camera->getProjView()); linesShader->uniformMatrix("u_projview", camera->getProjView());
vec3 coord = level->player->camera->position; glm::vec3 coord = level->player->camera->position;
if (coord.x < 0) coord.x--; if (coord.x < 0) coord.x--;
if (coord.z < 0) coord.z--; if (coord.z < 0) coord.z--;
int cx = floordiv((int)coord.x, CHUNK_W); int cx = floordiv((int)coord.x, CHUNK_W);
int cz = floordiv((int)coord.z, CHUNK_D); int cz = floordiv((int)coord.z, CHUNK_D);
drawBorders(cx * CHUNK_W, 0, cz * CHUNK_D, drawBorders(cx * CHUNK_W, 0, cz * CHUNK_D,
(cx + 1) * CHUNK_W, CHUNK_H, (cz + 1) * CHUNK_D); (cx + 1) * CHUNK_W, CHUNK_H, (cz + 1) * CHUNK_D);
} }
float length = 40.f; float length = 40.f;
vec3 tsl = vec3(displayWidth/2, displayHeight/2, 0.f); glm::vec3 tsl(displayWidth/2, displayHeight/2, 0.f);
glm::mat4 model(glm::translate(glm::mat4(1.f), tsl)); glm::mat4 model(glm::translate(glm::mat4(1.f), tsl));
linesShader->uniformMatrix("u_projview", glm::ortho( linesShader->uniformMatrix("u_projview", glm::ortho(
0.f, (float)displayWidth, 0.f, (float)displayWidth,
0.f, (float)displayHeight, 0.f, (float)displayHeight,
-length, length) * model * glm::inverse(camera->rotation)); -length, length) * model * glm::inverse(camera->rotation));
ctx.depthTest(false); ctx.depthTest(false);
lineBatch->lineWidth(4.0f); lineBatch->lineWidth(4.0f);
lineBatch->line(0.f, 0.f, 0.f, length, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f); lineBatch->line(0.f, 0.f, 0.f, length, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f);
lineBatch->line(0.f, 0.f, 0.f, 0.f, length, 0.f, 0.f, 0.f, 0.f, 1.f); lineBatch->line(0.f, 0.f, 0.f, 0.f, length, 0.f, 0.f, 0.f, 0.f, 1.f);
lineBatch->line(0.f, 0.f, 0.f, 0.f, 0.f, length, 0.f, 0.f, 0.f, 1.f); lineBatch->line(0.f, 0.f, 0.f, 0.f, 0.f, length, 0.f, 0.f, 0.f, 1.f);
lineBatch->render(); lineBatch->render();
ctx.depthTest(true); ctx.depthTest(true);
lineBatch->lineWidth(2.0f); lineBatch->lineWidth(2.0f);
lineBatch->line(0.f, 0.f, 0.f, length, 0.f, 0.f, 1.f, 0.f, 0.f, 1.f); lineBatch->line(0.f, 0.f, 0.f, length, 0.f, 0.f, 1.f, 0.f, 0.f, 1.f);
lineBatch->line(0.f, 0.f, 0.f, 0.f, length, 0.f, 0.f, 1.f, 0.f, 1.f); lineBatch->line(0.f, 0.f, 0.f, 0.f, length, 0.f, 0.f, 1.f, 0.f, 1.f);
lineBatch->line(0.f, 0.f, 0.f, 0.f, 0.f, length, 0.f, 0.f, 1.f, 1.f); lineBatch->line(0.f, 0.f, 0.f, 0.f, 0.f, length, 0.f, 0.f, 1.f, 1.f);
lineBatch->render(); lineBatch->render();
} }
} }
void WorldRenderer::drawBorders(int sx, int sy, int sz, int ex, int ey, int ez) { void WorldRenderer::drawBorders(int sx, int sy, int sz, int ex, int ey, int ez) {
int ww = ex-sx; int ww = ex-sx;
int dd = ez-sz; int dd = ez-sz;
/*corner*/ { /*corner*/ {
lineBatch->line(sx, sy, sz, lineBatch->line(sx, sy, sz,
sx, ey, sz, 0.8f, 0, 0.8f, 1); sx, ey, sz, 0.8f, 0, 0.8f, 1);
lineBatch->line(sx, sy, ez, lineBatch->line(sx, sy, ez,
sx, ey, ez, 0.8f, 0, 0.8f, 1); sx, ey, ez, 0.8f, 0, 0.8f, 1);
lineBatch->line(ex, sy, sz, lineBatch->line(ex, sy, sz,
ex, ey, sz, 0.8f, 0, 0.8f, 1); ex, ey, sz, 0.8f, 0, 0.8f, 1);
lineBatch->line(ex, sy, ez, lineBatch->line(ex, sy, ez,
ex, ey, ez, 0.8f, 0, 0.8f, 1); ex, ey, ez, 0.8f, 0, 0.8f, 1);
} }
for (int i = 2; i < ww; i+=2) { for (int i = 2; i < ww; i+=2) {
lineBatch->line(sx + i, sy, sz, lineBatch->line(sx + i, sy, sz,
sx + i, ey, sz, 0, 0, 0.8f, 1); sx + i, ey, sz, 0, 0, 0.8f, 1);
lineBatch->line(sx + i, sy, ez, lineBatch->line(sx + i, sy, ez,
sx + i, ey, ez, 0, 0, 0.8f, 1); sx + i, ey, ez, 0, 0, 0.8f, 1);
} }
for (int i = 2; i < dd; i+=2) { for (int i = 2; i < dd; i+=2) {
lineBatch->line(sx, sy, sz + i, lineBatch->line(sx, sy, sz + i,
sx, ey, sz + i, 0.8f, 0, 0, 1); sx, ey, sz + i, 0.8f, 0, 0, 1);
lineBatch->line(ex, sy, sz + i, lineBatch->line(ex, sy, sz + i,
ex, ey, sz + i, 0.8f, 0, 0, 1); ex, ey, sz + i, 0.8f, 0, 0, 1);
} }
for (int i = sy; i < ey; i+=2){ for (int i = sy; i < ey; i+=2){
lineBatch->line(sx, i, sz, lineBatch->line(sx, i, sz,
sx, i, ez, 0, 0.8f, 0, 1); sx, i, ez, 0, 0.8f, 0, 1);
lineBatch->line(sx, i, ez, lineBatch->line(sx, i, ez,
ex, i, ez, 0, 0.8f, 0, 1); ex, i, ez, 0, 0.8f, 0, 1);
lineBatch->line(ex, i, ez, lineBatch->line(ex, i, ez,
ex, i, sz, 0, 0.8f, 0, 1); ex, i, sz, 0, 0.8f, 0, 1);
lineBatch->line(ex, i, sz, lineBatch->line(ex, i, sz,
sx, i, sz, 0, 0.8f, 0, 1); sx, i, sz, 0, 0.8f, 0, 1);
} }
lineBatch->render(); lineBatch->render();
} }
float WorldRenderer::fog = 0.0f; float WorldRenderer::fog = 0.0f;

View File

@ -27,24 +27,24 @@ class LevelFrontend;
class Skybox; class Skybox;
class WorldRenderer { class WorldRenderer {
Engine* engine; Engine* engine;
Level* level; Level* level;
Frustum* frustumCulling; std::unique_ptr<Frustum> frustumCulling;
LineBatch* lineBatch; std::unique_ptr<LineBatch> lineBatch;
ChunksRenderer* renderer; std::unique_ptr<ChunksRenderer> renderer;
Skybox* skybox; std::unique_ptr<Skybox> skybox;
std::unique_ptr<Batch3D> batch3d; std::unique_ptr<Batch3D> batch3d;
bool drawChunk(size_t index, Camera* camera, Shader* shader, bool culling); bool drawChunk(size_t index, Camera* camera, Shader* shader, bool culling);
void drawChunks(Chunks* chunks, Camera* camera, Shader* shader); void drawChunks(Chunks* chunks, Camera* camera, Shader* shader);
public: public:
WorldRenderer(Engine* engine, LevelFrontend* frontend); WorldRenderer(Engine* engine, LevelFrontend* frontend);
~WorldRenderer(); ~WorldRenderer();
void draw(const GfxContext& context, Camera* camera, bool hudVisible); void draw(const GfxContext& context, Camera* camera, bool hudVisible);
void drawDebug(const GfxContext& context, Camera* camera); void drawDebug(const GfxContext& context, Camera* camera);
void drawBorders(int sx, int sy, int sz, int ex, int ey, int ez); void drawBorders(int sx, int sy, int sz, int ex, int ey, int ez);
static float fog; static float fog;
}; };

View File

@ -106,7 +106,7 @@ int l_file_read_bytes(lua_State* L) {
lua_createtable(L, length, 0); lua_createtable(L, length, 0);
int newTable = lua_gettop(L); int newTable = lua_gettop(L);
for(int i = 0;i < length;i++) { for(size_t i = 0; i < length; i++) {
lua_pushnumber(L, bytes[i]); lua_pushnumber(L, bytes[i]);
lua_rawseti(L, newTable, i+1); lua_rawseti(L, newTable, i+1);
} }

View File

@ -11,14 +11,14 @@
#define BLOCK_ITEM_SUFFIX ".item" #define BLOCK_ITEM_SUFFIX ".item"
const uint FACE_MX = 0; inline constexpr uint FACE_MX = 0;
const uint FACE_PX = 1; inline constexpr uint FACE_PX = 1;
const uint FACE_MY = 2; inline constexpr uint FACE_MY = 2;
const uint FACE_PY = 3; inline constexpr uint FACE_PY = 3;
const uint FACE_MZ = 4; inline constexpr uint FACE_MZ = 4;
const uint FACE_PZ = 5; inline constexpr uint FACE_PZ = 5;
const uint BLOCK_AABB_GRID = 16; inline constexpr uint BLOCK_AABB_GRID = 16;
struct block_funcs_set { struct block_funcs_set {
bool init: 1; bool init: 1;

View File

@ -17,7 +17,7 @@ struct ChunkFlag {
static const int UNSAVED = 0x10; static const int UNSAVED = 0x10;
static const int LOADED_LIGHTS = 0x20; static const int LOADED_LIGHTS = 0x20;
}; };
constexpr int CHUNK_DATA_LEN = CHUNK_VOL*4; inline constexpr int CHUNK_DATA_LEN = CHUNK_VOL*4;
class Lightmap; class Lightmap;
class ContentLUT; class ContentLUT;