GfxContext, render refactor

This commit is contained in:
MihailRis 2023-11-19 20:18:44 +03:00
parent ea729760d4
commit e3743b8463
12 changed files with 270 additions and 103 deletions

View File

@ -44,9 +44,9 @@ inline Label* create_label(gui::wstringsupplier supplier) {
return label;
}
HudRenderer::HudRenderer(Engine* engine, Level* level) : level(level), assets(engine->getAssets()), guiController(engine->getGUI()) {
HudRenderer::HudRenderer(Engine* engine, Level* level) : level(level), assets(engine->getAssets()), gui(engine->getGUI()) {
batch = new Batch2D(1024);
uicamera = new Camera(vec3(), Window::height);
uicamera = new Camera(vec3(), 1);
uicamera->perspective = false;
uicamera->flipped = true;
@ -139,13 +139,13 @@ HudRenderer::HudRenderer(Engine* engine, Level* level) : level(level), assets(en
panel->add(shared_ptr<UINode>(button));
}
panel->visible(false);
guiController->add(this->debugPanel);
guiController->add(this->pauseMenu);
gui->add(this->debugPanel);
gui->add(this->pauseMenu);
}
HudRenderer::~HudRenderer() {
guiController->remove(debugPanel);
guiController->remove(pauseMenu);
gui->remove(debugPanel);
gui->remove(pauseMenu);
delete batch;
delete uicamera;
}
@ -157,7 +157,11 @@ void HudRenderer::drawDebug(int fps, bool occlusion){
fpsMax = max(fps, fpsMax);
}
void HudRenderer::drawInventory(Player* player) {
void HudRenderer::drawInventory(const GfxContext& ctx, Player* player) {
const Viewport& viewport = ctx.getViewport();
const uint width = viewport.getWidth();
const uint height = viewport.getHeight();
Texture* blocks = assets->getTexture("block_tex");
uint size = 48;
uint step = 64;
@ -165,15 +169,15 @@ void HudRenderer::drawInventory(Player* player) {
uint inv_rows = 8;
uint inv_w = step*inv_cols + size;
uint inv_h = step*inv_rows + size;
int inv_x = (Window::width - (inv_w)) / 2;
int inv_y = (Window::height - (inv_h)) / 2;
int xs = (Window::width - inv_w + step)/2;
int ys = (Window::height - inv_h + step)/2;
if (Window::width > inv_w*3){
inv_x = (Window::width + (inv_w)) / 2;
inv_y = (Window::height - (inv_h)) / 2;
xs = (Window::width + inv_w + step)/2;
ys = (Window::height - inv_h + step)/2;
int inv_x = (width - (inv_w)) / 2;
int inv_y = (height - (inv_h)) / 2;
int xs = (width - inv_w + step)/2;
int ys = (height - inv_h + step)/2;
if (width > inv_w*3){
inv_x = (width + (inv_w)) / 2;
inv_y = (height - (inv_h)) / 2;
xs = (width + inv_w + step)/2;
ys = (height - inv_h + step)/2;
}
vec4 tint = vec4(1.0f);
int mx = Events::x;
@ -234,17 +238,18 @@ void HudRenderer::drawInventory(Player* player) {
}
}
void HudRenderer::draw(){
void HudRenderer::draw(const GfxContext& ctx){
const Viewport& viewport = ctx.getViewport();
const uint width = viewport.getWidth();
const uint height = viewport.getHeight();
debugPanel->visible(level->player->debug);
pauseMenu->setCoord((Window::size() - pauseMenu->size()) / 2.0f);
pauseMenu->setCoord((viewport.size() - pauseMenu->size()) / 2.0f);
auto settingsPanel = guiController->get("settings");
settingsPanel->setCoord((Window::size() - settingsPanel->size()) / 2.0f);
auto settingsPanel = gui->get("settings");
settingsPanel->setCoord((viewport.size() - settingsPanel->size()) / 2.0f);
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
uicamera->fov = Window::height;
uicamera->fov = height;
Shader* uishader = assets->getShader("ui");
uishader->use();
@ -256,9 +261,7 @@ void HudRenderer::draw(){
batch->texture(nullptr);
batch->color = vec4(1.0f);
if (Events::_cursor_locked && !level->player->debug) {
glLineWidth(2);
const uint width = Window::width;
const uint height = Window::height;
batch->lineWidth(2);
batch->line(width/2, height/2-6, width/2, height/2+6, 0.2f, 0.2f, 0.2f, 1.0f);
batch->line(width/2+6, height/2, width/2-6, height/2, 0.2f, 0.2f, 0.2f, 1.0f);
batch->line(width/2-5, height/2-5, width/2+5, height/2+5, 0.9f, 0.9f, 0.9f, 1.0f);
@ -266,19 +269,19 @@ void HudRenderer::draw(){
}
Player* player = level->player;
batch->rect(Window::width/2-128-4, Window::height-80-4, 256+8, 64+8,
batch->rect(width/2-128-4, height-80-4, 256+8, 64+8,
0.95f, 0.95f, 0.95f, 0.85f, 0.85f, 0.85f,
0.7f, 0.7f, 0.7f,
0.55f, 0.55f, 0.55f, 0.45f, 0.45f, 0.45f, 4);
batch->rect(Window::width/2-128, Window::height - 80, 256, 64,
batch->rect(width/2-128, height - 80, 256, 64,
0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f,
0.75f, 0.75f, 0.75f,
0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 4);
batch->rect(Window::width/2-32+2, Window::height - 80+2, 60, 60,
batch->rect(width/2-32+2, height - 80+2, 60, 60,
0.45f, 0.45f, 0.45f, 0.55f, 0.55f, 0.55f,
0.7f, 0.7f, 0.7f,
0.85f, 0.85f, 0.85f, 0.95f, 0.95f, 0.95f, 2);
batch->rect(Window::width/2-32+4, Window::height - 80+4, 56, 56,
batch->rect(width/2-32+4, height - 80+4, 56, 56,
0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f,
0.75f, 0.75f, 0.75f,
0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 0.75f, 2);
@ -288,13 +291,13 @@ void HudRenderer::draw(){
{
Block* cblock = Block::blocks[player->choosenBlock];
if (cblock->model == BlockModel::block){
batch->blockSprite(Window::width/2-24, uicamera->fov - 72, 48, 48, 16, cblock->textureFaces, vec4(1.0f));
batch->blockSprite(width/2-24, uicamera->fov - 72, 48, 48, 16, cblock->textureFaces, vec4(1.0f));
} else if (cblock->model == BlockModel::xsprite){
batch->sprite(Window::width/2-24, uicamera->fov - 72, 48, 48, 16, cblock->textureFaces[3], vec4(1.0f));
batch->sprite(width/2-24, uicamera->fov - 72, 48, 48, 16, cblock->textureFaces[3], vec4(1.0f));
}
}
if (Events::jpressed(keycode::ESCAPE) && !guiController->isFocusCaught()) {
if (Events::jpressed(keycode::ESCAPE) && !gui->isFocusCaught()) {
if (pause) {
pause = false;
pauseMenu->visible(false);
@ -317,10 +320,10 @@ void HudRenderer::draw(){
if (pause || inventoryOpen) {
batch->texture(nullptr);
batch->color = vec4(0.0f, 0.0f, 0.0f, 0.5f);
batch->rect(0, 0, Window::width, Window::height);
batch->rect(0, 0, width, height);
}
if (inventoryOpen) {
drawInventory(player);
drawInventory(ctx, player);
}
batch->render();
}

View File

@ -4,6 +4,8 @@
#include <string>
#include <memory>
#include "../graphics/GfxContext.h"
class Batch2D;
class Camera;
class Level;
@ -33,12 +35,12 @@ class HudRenderer {
std::shared_ptr<gui::UINode> debugPanel;
std::shared_ptr<gui::UINode> pauseMenu;
gui::GUI* guiController;
gui::GUI* gui;
public:
HudRenderer(Engine* engine, Level* level);
~HudRenderer();
void drawInventory(Player* player);
void draw();
void drawInventory(const GfxContext& ctx, Player* player);
void draw(const GfxContext& context);
void drawDebug(int fps, bool occlusion);
bool isInventoryOpen() const;

View File

@ -13,6 +13,7 @@
#include "../window/input.h"
#include "../graphics/Shader.h"
#include "../graphics/Batch2D.h"
#include "../graphics/GfxContext.h"
#include "../assets/Assets.h"
#include "../world/Level.h"
#include "../world/World.h"
@ -356,8 +357,11 @@ void LevelScreen::update(float delta) {
void LevelScreen::draw(float delta) {
Camera* camera = level->player->camera;
worldRenderer->draw(camera, occlusion);
hud->draw();
Viewport viewport(Window::width, Window::height);
GfxContext ctx(nullptr, viewport, nullptr);
worldRenderer->draw(ctx, camera, occlusion);
hud->draw(ctx);
if (level->player->debug) {
hud->drawDebug( 1 / delta, occlusion);
}

View File

@ -60,51 +60,15 @@ bool WorldRenderer::drawChunk(size_t index, Camera* camera, Shader* shader, bool
}
mat4 model = glm::translate(mat4(1.0f), vec3(chunk->x*CHUNK_W, 0.0f, chunk->z*CHUNK_D+1));
shader->uniformMatrix("u_model", model);
mesh->draw(GL_TRIANGLES);
mesh->draw();
return true;
}
void WorldRenderer::draw(Camera* camera, bool occlusion){
EngineSettings& settings = engine->getSettings();
Assets* assets = engine->getAssets();
Chunks* chunks = level->chunks;
vec3 skyColor(0.7f, 0.81f, 1.0f);
Window::setBgColor(skyColor);
Window::clear();
Window::viewport(0, 0, Window::width, Window::height);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
float fogFactor = 18.0f / (float)settings.chunks.loadDistance;
Texture* texture = assets->getTexture("block");
Shader* shader = assets->getShader("main");
Shader* linesShader = assets->getShader("lines");
shader->use();
shader->uniformMatrix("u_proj", camera->getProjection());
shader->uniformMatrix("u_view", camera->getView());
shader->uniform1f("u_gamma", 1.6f);
shader->uniform3f("u_skyLightColor", 1.1f,1.1f,1.1f);
shader->uniform3f("u_fogColor", skyColor);
shader->uniform1f("u_fogFactor", fogFactor);
shader->uniform1f("u_fogCurve", settings.graphics.fogCurve);
shader->uniform3f("u_cameraPos", camera->position);
Block* cblock = Block::blocks[level->player->choosenBlock];
float multiplier = 0.5f;
shader->uniform3f("u_torchlightColor",
cblock->emission[0] / 15.0f * multiplier,
cblock->emission[1] / 15.0f * multiplier,
cblock->emission[2] / 15.0f * multiplier);
shader->uniform1f("u_torchlightDistance", 6.0f);
texture->bind();
void WorldRenderer::drawChunks(Chunks* chunks,
Camera* camera,
Shader* shader,
bool occlusion) {
std::vector<size_t> indices;
for (size_t i = 0; i < chunks->volume; i++){
shared_ptr<Chunk> chunk = chunks->chunks[i];
if (chunk == nullptr)
@ -126,34 +90,84 @@ void WorldRenderer::draw(Camera* camera, bool occlusion){
for (size_t i = 0; i < indices.size(); i++){
chunks->visible += drawChunk(indices[i], camera, shader, occlusion);
}
}
shader->uniformMatrix("u_model", mat4(1.0f));
if (level->playerController->selectedBlockId != -1){
Block* selectedBlock = Block::blocks[level->playerController->selectedBlockId];
vec3 pos = level->playerController->selectedBlockPosition;
linesShader->use();
linesShader->uniformMatrix("u_projview", camera->getProjection()*camera->getView());
glLineWidth(2.0f);
if (selectedBlock->model == BlockModel::block){
lineBatch->box(pos.x+0.5f, pos.y+0.5f, pos.z+0.5f, 1.005f,1.005f,1.005f, 0,0,0,0.5f);
} else if (selectedBlock->model == BlockModel::xsprite){
lineBatch->box(pos.x+0.5f, pos.y+0.35f, pos.z+0.5f, 0.805f,0.705f,0.805f, 0,0,0,0.5f);
void WorldRenderer::draw(const GfxContext& pctx, Camera* camera, bool occlusion){
Assets* assets = engine->getAssets();
Texture* texture = assets->getTexture("block");
Shader* shader = assets->getShader("main");
Shader* linesShader = assets->getShader("lines");
const Viewport& viewport = pctx.getViewport();
int displayWidth = viewport.getWidth();
int displayHeight = viewport.getHeight();
{
GfxContext ctx = pctx.sub();
ctx.depthTest(true);
ctx.cullFace(true);
EngineSettings& settings = engine->getSettings();
vec3 skyColor(0.7f, 0.81f, 1.0f);
Window::setBgColor(skyColor);
Window::clear();
Window::viewport(0, 0, displayWidth, displayHeight);
float fogFactor = 18.0f / (float)settings.chunks.loadDistance;
shader->use();
shader->uniformMatrix("u_proj", camera->getProjection());
shader->uniformMatrix("u_view", camera->getView());
shader->uniform1f("u_gamma", 1.6f);
shader->uniform3f("u_skyLightColor", 1.1f,1.1f,1.1f);
shader->uniform3f("u_fogColor", skyColor);
shader->uniform1f("u_fogFactor", fogFactor);
shader->uniform1f("u_fogCurve", settings.graphics.fogCurve);
shader->uniform3f("u_cameraPos", camera->position);
Block* cblock = Block::blocks[level->player->choosenBlock];
float multiplier = 0.5f;
shader->uniform3f("u_torchlightColor",
cblock->emission[0] / 15.0f * multiplier,
cblock->emission[1] / 15.0f * multiplier,
cblock->emission[2] / 15.0f * multiplier);
shader->uniform1f("u_torchlightDistance", 6.0f);
texture->bind();
Chunks* chunks = level->chunks;
drawChunks(chunks, camera, shader, occlusion);
shader->uniformMatrix("u_model", mat4(1.0f));
if (level->playerController->selectedBlockId != -1){
Block* block = Block::blocks[level->playerController->selectedBlockId];
vec3 pos = level->playerController->selectedBlockPosition;
linesShader->use();
linesShader->uniformMatrix("u_projview", camera->getProjView());
lineBatch->lineWidth(2.0f);
if (block->model == BlockModel::block){
lineBatch->box(pos.x+0.5f, pos.y+0.5f, pos.z+0.5f,
1.008f,1.008f,1.008f, 0,0,0,0.5f);
} else if (block->model == BlockModel::xsprite){
lineBatch->box(pos.x+0.5f, pos.y+0.35f, pos.z+0.5f,
0.805f,0.705f,0.805f, 0,0,0,0.5f);
}
lineBatch->render();
}
lineBatch->render();
}
glDisable(GL_DEPTH_TEST);
if (level->player->debug) {
float length = 40.f;
linesShader->use();
vec3 tsl = vec3(Window::width/2, -((int)Window::height)/2, 0.f);
// top-right: vec3 tsl = vec3(displayWidth - length - 4, -length - 4, 0.f);
vec3 tsl = vec3(displayWidth/2, -((int)displayHeight)/2, 0.f);
glm::mat4 model(glm::translate(glm::mat4(1.f), tsl));
linesShader->uniformMatrix("u_projview", glm::ortho(
0.f, (float)Window::width,
-(float)Window::height, 0.f,
0.f, (float)displayWidth,
-(float)displayHeight, 0.f,
-length, length) * model * glm::inverse(camera->rotation));
lineBatch->lineWidth(4.0f);

View File

@ -10,6 +10,8 @@
#include <glm/ext.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include "../graphics/GfxContext.h"
class Level;
class Camera;
class LineBatch;
@ -18,6 +20,7 @@ class Shader;
class Texture;
class Frustum;
class Engine;
class Chunks;
class WorldRenderer {
Engine* engine;
@ -26,12 +29,13 @@ class WorldRenderer {
LineBatch* lineBatch;
ChunksRenderer* renderer;
bool drawChunk(size_t index, Camera* camera, Shader* shader, bool occlusion);
void drawChunks(Chunks* chunks, Camera* camera, Shader* shader, bool occlusion);
public:
WorldRenderer(Engine* engine, Level* level);
~WorldRenderer();
void draw(Camera* camera, bool occlusion);
void draw(const GfxContext& context, Camera* camera, bool occlusion);
};

View File

@ -361,3 +361,7 @@ void Batch2D::render(unsigned int gl_primitive) {
void Batch2D::render() {
render(GL_TRIANGLES);
}
void Batch2D::lineWidth(float width) {
glLineWidth(width);
}

View File

@ -62,6 +62,8 @@ public:
float r4, float g4, float b4, int sh);
void render(unsigned int gl_primitive);
void render();
void lineWidth(float width);
};
#endif /* SRC_GRAPHICS_BATCH2D_H_ */

View File

@ -0,0 +1,59 @@
#include "GfxContext.h"
#include <GL/glew.h>
#include "Batch2D.h"
GfxContext::GfxContext(const GfxContext* parent, Viewport& viewport, Batch2D* g2d)
: parent(parent), viewport(viewport), g2d(g2d) {
}
GfxContext::~GfxContext() {
if (parent == nullptr)
return;
if (depthTest_ != parent->depthTest_) {
if (depthTest_) glDisable(GL_DEPTH_TEST);
else glEnable(GL_DEPTH_TEST);
}
if (cullFace_ != parent->cullFace_) {
if (cullFace_) glDisable(GL_CULL_FACE);
else glEnable(GL_CULL_FACE);
}
}
const Viewport& GfxContext::getViewport() const {
return viewport;
}
Batch2D* GfxContext::getBatch2D() const {
return g2d;
}
GfxContext GfxContext::sub() const {
auto ctx = GfxContext(this, viewport, g2d);
ctx.depthTest_ = depthTest_;
ctx.cullFace_ = cullFace_;
return ctx;
}
void GfxContext::depthTest(bool flag) {
if (depthTest_ == flag)
return;
depthTest_ = flag;
if (depthTest_) {
glEnable(GL_DEPTH_TEST);
} else {
glDisable(GL_DEPTH_TEST);
}
}
void GfxContext::cullFace(bool flag) {
if (cullFace_ == flag)
return;
cullFace_ = flag;
if (cullFace_) {
glEnable(GL_CULL_FACE);
} else {
glDisable(GL_CULL_FACE);
}
}

27
src/graphics/GfxContext.h Normal file
View File

@ -0,0 +1,27 @@
#ifndef GRAPHICS_GFX_CONTEXT_H_
#define GRAPHICS_GFX_CONTEXT_H_
#include "../typedefs.h"
#include "Viewport.h"
class Batch2D;
class GfxContext {
const GfxContext* parent;
Viewport& viewport;
Batch2D* const g2d;
bool depthTest_ = false;
bool cullFace_ = false;
public:
GfxContext(const GfxContext* parent, Viewport& viewport, Batch2D* g2d);
~GfxContext();
Batch2D* getBatch2D() const;
const Viewport& getViewport() const;
GfxContext sub() const;
void depthTest(bool flag);
void cullFace(bool flag);
};
#endif // GRAPHICS_GFX_CONTEXT_H_

13
src/graphics/Viewport.cpp Normal file
View File

@ -0,0 +1,13 @@
#include "Viewport.h"
Viewport::Viewport(uint width, uint height)
: width(width), height(height) {
}
uint Viewport::getWidth() const {
return width;
}
uint Viewport::getHeight() const {
return height;
}

22
src/graphics/Viewport.h Normal file
View File

@ -0,0 +1,22 @@
#ifndef GRAPHICS_VIEWPORT_H_
#define GRAPHICS_VIEWPORT_H_
#include <glm/glm.hpp>
#include "../typedefs.h"
class Viewport {
uint width;
uint height;
public:
Viewport(uint width, uint height);
virtual uint getWidth() const;
virtual uint getHeight() const;
glm::vec2 size() const {
return glm::vec2(width, height);
}
};
#endif // GRAPHICS_VIEWPORT_H_

View File

@ -215,8 +215,21 @@ void PlayerController::updateInteraction(){
Camera* camera = player->camera;
vec3 end;
vec3 norm;
bool xkey = Events::pressed(keycode::X);
bool lclick = Events::jclicked(mousecode::BUTTON_1) ||
(xkey && Events::clicked(mousecode::BUTTON_1));
bool rclick = Events::jclicked(mousecode::BUTTON_2) ||
(xkey && Events::clicked(mousecode::BUTTON_2));
float maxDistance = 10.0f;
if (xkey) {
maxDistance *= 20.0f;
}
vec3 iend;
voxel* vox = chunks->rayCast(camera->position, camera->front, 10.0f, end, norm, iend);
voxel* vox = chunks->rayCast(camera->position,
camera->front,
maxDistance,
end, norm, iend);
if (vox != nullptr){
player->selectedVoxel = *vox;
selectedBlockId = vox->id;
@ -238,11 +251,11 @@ void PlayerController::updateInteraction(){
}
Block* block = Block::blocks[vox->id];
if (Events::jclicked(mousecode::BUTTON_1) && block->breakable){
if (lclick && block->breakable){
chunks->set(x,y,z, 0, 0);
lighting->onBlockSet(x,y,z, 0);
}
if (Events::jclicked(mousecode::BUTTON_2)){
if (rclick){
if (block->model != BlockModel::xsprite){
x = (int)(iend.x)+(int)(norm.x);
y = (int)(iend.y)+(int)(norm.y);