671 lines
19 KiB
C++
671 lines
19 KiB
C++
#include "GameState.hpp"
|
|
|
|
#include <algorithm>
|
|
#include <chrono>
|
|
#include <cstdio>
|
|
#include <iomanip>
|
|
#include <memory>
|
|
#include <sstream>
|
|
#include <thread>
|
|
|
|
#include <glm/gtc/matrix_transform.hpp>
|
|
#include <glm/gtc/type_ptr.hpp>
|
|
|
|
#include "Audio.hpp"
|
|
#include "CaveGenerator.hpp"
|
|
#include "Chatbox.hpp"
|
|
#include "Clouds.hpp"
|
|
#include "content/Registry.hpp"
|
|
#include "content/texture/TextureLoader.hpp"
|
|
#include "EscMenu.hpp"
|
|
#include "Game.hpp"
|
|
#include "GlobalProperties.hpp"
|
|
#include "KeyBinds.hpp"
|
|
#include "LocalPlayer.hpp"
|
|
#include "network/msgtypes/BlockUpdate.hpp"
|
|
#include "network/msgtypes/PlayerJoin.hpp"
|
|
#include "network/msgtypes/PlayerUpdate.hpp"
|
|
#include "network/NetHelper.hpp"
|
|
#include "Particles.hpp"
|
|
#include "render/gl/FBO.hpp"
|
|
#include "render/gl/ProgramManager.hpp"
|
|
#include "render/Renderer.hpp"
|
|
#include "scripting/lua/State.hpp"
|
|
#include "Skybox.hpp"
|
|
#include "ui/FontManager.hpp"
|
|
#include "ui/Manager.hpp"
|
|
#include "util/MemoryTracker.hpp"
|
|
|
|
using std::unique_ptr;
|
|
|
|
namespace Diggler {
|
|
|
|
GameState::GameState(GameWindow *GW) :
|
|
GW(GW),
|
|
CMH(*this),
|
|
bloom(*GW->G) {
|
|
G = GW->G;
|
|
int w = GW->getW(),
|
|
h = GW->getH();
|
|
|
|
// Initialized in setupUI
|
|
m_chatBox = nullptr;
|
|
|
|
float coords[6*3*2*3] = {
|
|
-1.0f,-1.0f,-1.0f,
|
|
-1.0f,-1.0f, 1.0f,
|
|
-1.0f, 1.0f, 1.0f,
|
|
1.0f, 1.0f,-1.0f,
|
|
-1.0f,-1.0f,-1.0f,
|
|
-1.0f, 1.0f,-1.0f,
|
|
|
|
1.0f,-1.0f, 1.0f,
|
|
-1.0f,-1.0f,-1.0f,
|
|
1.0f,-1.0f,-1.0f,
|
|
1.0f, 1.0f,-1.0f,
|
|
1.0f,-1.0f,-1.0f,
|
|
-1.0f,-1.0f,-1.0f,
|
|
|
|
-1.0f,-1.0f,-1.0f,
|
|
-1.0f, 1.0f, 1.0f,
|
|
-1.0f, 1.0f,-1.0f,
|
|
1.0f,-1.0f, 1.0f,
|
|
-1.0f,-1.0f, 1.0f,
|
|
-1.0f,-1.0f,-1.0f,
|
|
|
|
-1.0f, 1.0f, 1.0f,
|
|
-1.0f,-1.0f, 1.0f,
|
|
1.0f,-1.0f, 1.0f,
|
|
1.0f, 1.0f, 1.0f,
|
|
1.0f,-1.0f,-1.0f,
|
|
1.0f, 1.0f,-1.0f,
|
|
|
|
1.0f,-1.0f,-1.0f,
|
|
1.0f, 1.0f, 1.0f,
|
|
1.0f,-1.0f, 1.0f,
|
|
1.0f, 1.0f, 1.0f,
|
|
1.0f, 1.0f,-1.0f,
|
|
-1.0f, 1.0f,-1.0f,
|
|
|
|
1.0f, 1.0f, 1.0f,
|
|
-1.0f, 1.0f,-1.0f,
|
|
-1.0f, 1.0f, 1.0f,
|
|
1.0f, 1.0f, 1.0f,
|
|
-1.0f, 1.0f, 1.0f,
|
|
1.0f,-1.0f, 1.0f,
|
|
};
|
|
m_highlightBox.vbo.setData(coords, 6*3*2*3);
|
|
m_highlightBox.program = G->PM->getProgram("3d");
|
|
m_highlightBox.att_coord = m_highlightBox.program->att("coord");
|
|
m_highlightBox.uni_unicolor = m_highlightBox.program->uni("unicolor");
|
|
m_highlightBox.uni_mvp = m_highlightBox.program->uni("mvp");
|
|
{ Render::gl::VAO::Config cfg = m_highlightBox.vao.configure();
|
|
cfg.vertexAttrib(m_highlightBox.vbo, m_highlightBox.att_coord, 3, GL_FLOAT, 0);
|
|
cfg.commit();
|
|
}
|
|
|
|
m_3dFbo = new Render::gl::FBO(w, h, PixelFormat::RGB, true);
|
|
m_3dFbo->tex->setWrapping(Texture::Wrapping::ClampEdge);
|
|
m_3dRenderVBO = new Render::gl::VBO();
|
|
m_clouds = new Clouds(G, 32, 32, 4);
|
|
//m_sky = new Skybox(G, getAssetPath("alpine"));
|
|
m_3dFboRenderer = G->PM->getProgram("2d", "texture0", "texcoord0"); //getSpecialProgram("effect3dRender");
|
|
m_3dFboRenderer_coord = m_3dFboRenderer->att("coord");
|
|
m_3dFboRenderer_texcoord = m_3dFboRenderer->att("texcoord");
|
|
m_3dFboRenderer_mvp = m_3dFboRenderer->uni("mvp");
|
|
|
|
Coord2DTex renderQuad[6] = {
|
|
{0, 0, 0, 0},
|
|
{1, 0, 1, 0},
|
|
{0, 1, 0, 1},
|
|
|
|
{1, 1, 1, 1},
|
|
{0, 1, 0, 1},
|
|
{1, 0, 1, 0}
|
|
};
|
|
m_3dRenderVBO->setData(renderQuad, 6*sizeof(Coord2DTex));
|
|
|
|
m_crossHair.tex = Content::Texture::TextureLoader::load(*G, Content::Image::ImageFormats::PNG,
|
|
getAssetPath("crosshair.png"), PixelFormat::RGBA)->texture;
|
|
|
|
//"\f0H\f1e\f2l\f3l\f4l\f5o \f6d\f7e\f8m\f9b\faa\fbz\fcz\fde\fes\ff,\n\f0ye see,it werks purrfektly :D\n(and also; it's optimized)"
|
|
|
|
debugInfo.show = false;
|
|
|
|
m_mouseLocked = false;
|
|
nextNetUpdate = 0;
|
|
}
|
|
|
|
GameState::Bloom::Bloom(Game &G) {
|
|
enable = true;
|
|
scale = 4;
|
|
|
|
extractor.fbo = new Render::gl::FBO(G.GW->getW()/scale, G.GW->getH()/scale, PixelFormat::RGBA);
|
|
extractor.fbo->tex->setFiltering(Texture::Filter::Linear, Texture::Filter::Linear);
|
|
extractor.fbo->tex->setWrapping(Texture::Wrapping::ClampEdge);
|
|
extractor.prog = G.PM->getProgram("bloomExtractor");
|
|
extractor.att_coord = extractor.prog->att("coord");
|
|
extractor.att_texcoord = extractor.prog->att("texcoord");
|
|
extractor.uni_mvp = extractor.prog->uni("mvp");
|
|
|
|
renderer.fbo = new Render::gl::FBO(G.GW->getW()/scale, G.GW->getH()/scale, PixelFormat::RGBA);
|
|
renderer.fbo->tex->setFiltering(Texture::Filter::Linear, Texture::Filter::Linear);
|
|
renderer.fbo->tex->setWrapping(Texture::Wrapping::ClampEdge);
|
|
renderer.prog = G.PM->getProgram("bloom");
|
|
renderer.att_coord = renderer.prog->att("coord");
|
|
renderer.att_texcoord = renderer.prog->att("texcoord");
|
|
renderer.uni_mvp = renderer.prog->uni("mvp");
|
|
renderer.uni_pixshift = renderer.prog->uni("pixshift");
|
|
}
|
|
|
|
GameState::Bloom::~Bloom() {
|
|
delete extractor.fbo;
|
|
delete renderer.fbo;
|
|
}
|
|
|
|
void GameState::setupUI() {
|
|
UI.FPS = G->UIM->add<UI::Text>();
|
|
UI.FPS->setUpdateFrequencyHint(Render::FontRendererTextBufferUsage::Dynamic);
|
|
UI.FPS->setScale(2, 2);
|
|
|
|
UI.DebugInfo = G->UIM->add<UI::Text>();
|
|
UI.DebugInfo->setUpdateFrequencyHint(Render::FontRendererTextBufferUsage::Stream);
|
|
UI.DebugInfo->setVisible(false);
|
|
|
|
UI.EM = G->UIM->add<EscMenu>();
|
|
UI.EM->setVisible(false);
|
|
|
|
m_chatBox = new Chatbox(G);
|
|
|
|
updateViewport();
|
|
}
|
|
|
|
GameState::~GameState() {
|
|
delete m_clouds;
|
|
delete m_chatBox;
|
|
//delete m_sky;
|
|
}
|
|
|
|
void GameState::onChar(char32 unichar) {
|
|
if (m_chatIgnFirstKey) {
|
|
m_chatIgnFirstKey = false;
|
|
return;
|
|
}
|
|
if (m_chatBox->isChatting()) {
|
|
m_chatBox->handleChar(unichar);
|
|
}
|
|
}
|
|
|
|
void GameState::onKey(int key, int scancode, int action, int mods) {
|
|
if (!(action == GLFW_PRESS || action == GLFW_RELEASE))
|
|
return;
|
|
|
|
switch (key) {
|
|
case GLFW_KEY_ESCAPE:
|
|
if (mods & GLFW_MOD_SHIFT)
|
|
glfwSetWindowShouldClose(*G->GW, true);
|
|
break;
|
|
case GLFW_KEY_F1:
|
|
if (action == GLFW_PRESS)
|
|
bloom.enable = !bloom.enable;
|
|
break;
|
|
case GLFW_KEY_F5:
|
|
if (action == GLFW_PRESS) {
|
|
debugInfo.show = !debugInfo.show;
|
|
UI.DebugInfo->setVisible(debugInfo.show);
|
|
}
|
|
break;
|
|
case GLFW_KEY_F6:
|
|
if (action == GLFW_PRESS) {
|
|
unlockMouse();
|
|
}
|
|
break;
|
|
case GLFW_KEY_F7:
|
|
if (action == GLFW_PRESS) {
|
|
G->RP->wavingLiquids = !G->RP->wavingLiquids;
|
|
// TODO: better way
|
|
G->U->getWorld(0)->onRenderPropertiesChanged();
|
|
}
|
|
break;
|
|
case GLFW_KEY_F8:
|
|
if (action == GLFW_PRESS) {
|
|
G->U->getWorld(0)->refresh();
|
|
}
|
|
break;
|
|
case GLFW_KEY_F12:
|
|
if (action == GLFW_PRESS && (mods & GLFW_MOD_SHIFT)) {
|
|
::abort();
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (m_chatBox && m_chatBox->isChatting()) {
|
|
switch (key) {
|
|
case GLFW_KEY_ENTER:
|
|
if (action == GLFW_PRESS) {
|
|
std::string str = m_chatBox->getChatString();
|
|
if (str.size() > 0) {
|
|
NetHelper::SendChat(G, str);
|
|
}
|
|
m_chatBox->setIsChatting(false);
|
|
}
|
|
break;
|
|
case GLFW_KEY_ESCAPE:
|
|
if (action == GLFW_PRESS)
|
|
m_chatBox->setIsChatting(false);
|
|
break;
|
|
default:
|
|
m_chatBox->handleKey(key, scancode, action, mods);
|
|
break;
|
|
}
|
|
} else {
|
|
bool isMenuToggled = UI.EM->isVisible();
|
|
if (key == G->KB->gameMenu && action == GLFW_PRESS) {
|
|
isMenuToggled = !isMenuToggled;
|
|
UI.EM->setVisible(isMenuToggled);
|
|
if (isMenuToggled) {
|
|
unlockMouse();
|
|
G->LP->goForward(false);
|
|
G->LP->goBackward(false);
|
|
G->LP->goLeft(false);
|
|
G->LP->goRight(false);
|
|
} else {
|
|
lockMouse();
|
|
}
|
|
}
|
|
if (!isMenuToggled) {
|
|
if (key == G->KB->forward) {
|
|
G->LP->goForward(action == GLFW_PRESS);
|
|
} else if (key == G->KB->backward) {
|
|
G->LP->goBackward(action == GLFW_PRESS);
|
|
} else if (key == G->KB->left) {
|
|
G->LP->goLeft(action == GLFW_PRESS);
|
|
} else if (key == G->KB->right) {
|
|
G->LP->goRight(action == GLFW_PRESS);
|
|
} else if (key == G->KB->jump) {
|
|
if (action == GLFW_PRESS)
|
|
G->LP->jump();
|
|
} else if (key == G->KB->chat) {
|
|
if (action == GLFW_PRESS) {
|
|
m_chatBox->setIsChatting(true);
|
|
m_chatIgnFirstKey = true;
|
|
}
|
|
} else if (key == GLFW_KEY_V) {
|
|
G->LP->setHasNoclip(true);
|
|
} else if (key == GLFW_KEY_B) {
|
|
G->LP->setHasNoclip(false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void GameState::lockMouse() {
|
|
glfwSetInputMode(*GW, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
|
double x, y;
|
|
glfwGetCursorPos(*GW, &x, &y);
|
|
cX = static_cast<int>(x); cY = static_cast<int>(y);
|
|
m_mouseLocked = true;
|
|
}
|
|
|
|
void GameState::unlockMouse() {
|
|
m_mouseLocked = false;
|
|
glfwSetInputMode(*GW, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
|
}
|
|
|
|
|
|
void GameState::onMouseButton(int key, int action, int mods) {
|
|
(void) mods;
|
|
|
|
if (!m_mouseLocked && action == GLFW_PRESS && !UI.EM->isVisible()) {
|
|
lockMouse();
|
|
}
|
|
|
|
if (action == GLFW_PRESS) {
|
|
glm::ivec3 pointed, face;
|
|
if (G->LP->raytracePointed(32, &pointed, &face)) {
|
|
Net::OutMessage msg;
|
|
if (key == GLFW_MOUSE_BUTTON_LEFT) {
|
|
Net::MsgTypes::BlockUpdateBreak bub;
|
|
bub.worldId = G->LP->W->id;
|
|
bub.pos = pointed;
|
|
bub.writeToMsg(msg);
|
|
} else {
|
|
Net::MsgTypes::BlockUpdatePlace bup;
|
|
bup.worldId = G->LP->W->id;
|
|
bup.pos = face;
|
|
bup.id = 2; //Content::BlockUnknownId;
|
|
bup.data = 0;
|
|
bup.writeToMsg(msg);
|
|
}
|
|
sendMsg(msg, Net::Tfer::Rel, Net::Channels::MapUpdate);
|
|
}
|
|
}
|
|
}
|
|
|
|
void GameState::onCursorPos(double x, double y) {
|
|
if (!m_mouseLocked) {
|
|
return;
|
|
}
|
|
int cx = static_cast<int>(x), dx = cx-cX, cy = static_cast<int>(y), dy = cy-cY;
|
|
const float mousespeed = 0.003f;
|
|
|
|
angles.x -= dx * mousespeed;
|
|
angles.y -= dy * mousespeed;
|
|
|
|
if(angles.x < -M_PI)
|
|
angles.x += M_PI * 2;
|
|
else if(angles.x > M_PI)
|
|
angles.x -= M_PI * 2;
|
|
|
|
if(angles.y < -M_PI / 2)
|
|
angles.y = -M_PI / 2 + 0.001;
|
|
if(angles.y > M_PI / 2)
|
|
angles.y = M_PI / 2 - 0.001;
|
|
|
|
G->LP->angle = angles.x;
|
|
lookat.x = sinf(angles.x) * cosf(angles.y);
|
|
lookat.y = sinf(angles.y);
|
|
lookat.z = cosf(angles.x) * cosf(angles.y);
|
|
|
|
G->LP->lookAt(lookat);
|
|
|
|
cX = cx; cY = cy;
|
|
}
|
|
|
|
void GameState::onResize(int w, int h) {
|
|
updateViewport();
|
|
}
|
|
|
|
void GameState::onMouseScroll(double x, double y) {
|
|
(void) x; (void) y;
|
|
}
|
|
|
|
void GameState::updateViewport() {
|
|
int w = GW->getW(), h = GW->getH();
|
|
UI::Manager &UIM = *G->UIM;
|
|
G->LP->camera.setPersp((float)M_PI/180*75.0f, (float)w / h, 0.1f, 32.0f);
|
|
m_3dFbo->resize(w, h);
|
|
bloom.extractor.fbo->resize(w/bloom.scale, h/bloom.scale);
|
|
//bloom.extractor.fbo->tex->setFiltering(Texture::Filter::Linear, Texture::Filter::Linear);
|
|
bloom.renderer.fbo->resize(w/bloom.scale, h/bloom.scale);
|
|
//bloom.renderer.fb->tex->setFiltering(Texture::Filter::Linear, Texture::Filter::Linear);
|
|
|
|
{ int tw = 5*UIM.scale, th = 5*UIM.scale;
|
|
m_crossHair.mat = glm::scale(glm::translate(*UIM.PM,
|
|
glm::vec3((w-tw)/2, (h-th)/2, 0)),
|
|
glm::vec3(tw, tw, 0));
|
|
}
|
|
|
|
int lineHeight = G->FM->getDefaultFont()->getHeight()*UIM.scale;
|
|
|
|
UI.FPS->setPos(16, 16);
|
|
UI.DebugInfo->setPos(0, h-(lineHeight+UI.DebugInfo->getSize().y));
|
|
const int menuWidth = G->UIM->scale*128;
|
|
UI.EM->setArea(UI::Element::Area(w - menuWidth, 0, menuWidth, h));
|
|
|
|
m_chatBox->setPosition(4, 64);
|
|
updateUI();
|
|
}
|
|
|
|
void GameState::sendMsg(Net::OutMessage &msg, Net::Tfer mode, Net::Channels chan) {
|
|
G->H.send(*G->NS, msg, mode, chan);
|
|
}
|
|
|
|
void GameState::onStart() {
|
|
setupUI();
|
|
|
|
fpsCounter = 0;
|
|
fpsNextSampling = 1.;
|
|
|
|
LocalPlayer *LP = G->LP;
|
|
LP->position = glm::vec3(-2, 2, -2);
|
|
angles.x = M_PI/4; angles.y = M_PI/4;
|
|
lookat.x = sinf(angles.x) * cosf(angles.y);
|
|
lookat.y = sinf(angles.y);
|
|
lookat.z = cosf(angles.x) * cosf(angles.y);
|
|
LP->lookAt(lookat);
|
|
LP->forceCameraUpdate();
|
|
G->A->update();
|
|
LP->setHasNoclip(true);
|
|
}
|
|
|
|
void GameState::onLogicTick() {
|
|
if (!processNetwork()) return;
|
|
|
|
G->updateTime(runTime());
|
|
if (runTime() > fpsNextSampling) {
|
|
char str[10]; std::snprintf(str, 10, "FPS: %-4d", fpsCounter);
|
|
UI.FPS->setText(std::string(str));
|
|
fpsNextSampling = runTime() + 1;
|
|
fpsCounter = 0;
|
|
}
|
|
}
|
|
|
|
void GameState::onFrameTick() {
|
|
std::chrono::time_point<std::chrono::steady_clock> frameStart, frameEnd;
|
|
|
|
G->R->beginFrame();
|
|
frameStart = std::chrono::steady_clock::now();
|
|
|
|
LocalPlayer *LP = G->LP;
|
|
double T = G->Time;
|
|
if (runTime() > nextNetUpdate) {
|
|
Net::MsgTypes::PlayerUpdateMove pum;
|
|
pum.position = LP->position;
|
|
if (LP->velocity != glm::vec3()) {
|
|
pum.velocity = LP->velocity;
|
|
pum.accel = LP->accel;
|
|
}
|
|
pum.angle = LP->angle;
|
|
Net::OutMessage msg; pum.writeToMsg(msg);
|
|
sendMsg(msg, Net::Tfer::Unrel, Net::Channels::Movement);
|
|
nextNetUpdate = T+1.0/G->PlayerPosUpdateFreq;
|
|
}
|
|
|
|
if (bloom.enable) {
|
|
m_3dFbo->bind();
|
|
glClearColor(0.0, 0.0, 0.0, 1.0);
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
}
|
|
|
|
double deltaT = deltaTime();
|
|
LP->update(deltaT);
|
|
|
|
glm::mat4 m_transform = LP->getPVMatrix();
|
|
|
|
/*** 3D PART ***/
|
|
// TODO: multiworld
|
|
WorldRef WR = G->U->getWorld(0);
|
|
World &W = *WR;
|
|
/*glm::mat4 cloudmat = glm::scale(glm::translate(m_transform, glm::vec3(0.f, W.cloudsHeight, 0.f)), glm::vec3(4*CX, 1, 4*CZ));
|
|
m_clouds->render(cloudmat);*/
|
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
glEnable(GL_CULL_FACE);
|
|
|
|
Render::RenderParams rp;
|
|
rp.world = WR.get();
|
|
rp.transform = m_transform;
|
|
rp.frustum = G->LP->camera.frustum;
|
|
G->R->renderers.world->render(rp);
|
|
for (Player &p : G->players) {
|
|
p.update(deltaT);
|
|
if (G->LP->camera.frustum.sphereInFrustum(p.position, 2))
|
|
p.render(m_transform);
|
|
}
|
|
//W.renderTransparent(m_transform);
|
|
|
|
/*static ParticleEmitter pe(G);
|
|
pe.posAmpl = glm::vec3(1, 1, 1);
|
|
pe.pTemplate.color = glm::vec4(0, 0.4, 0.9, 1);
|
|
pe.pTemplate.size = 0.07;
|
|
pe.velAmpl = glm::vec3(0, 1, 0);
|
|
pe.pTemplate.accel = glm::vec3(0, -.7, 0);
|
|
pe.pTemplate.decay = 4;
|
|
pe.decayAmpl = 2;
|
|
|
|
pe.setMaxCount(4*4*800);
|
|
pe.posAmpl = glm::vec3(2*16, 1, 2*16);
|
|
pe.pos = glm::vec3(2*16, 4*16+4, 2*16);
|
|
pe.pTemplate.vel = glm::vec3(0, -4, 0);
|
|
pe.velAmpl = glm::vec3(0, 2, 0); rain
|
|
|
|
pe.update(deltaT);
|
|
Render::RenderParams rp;
|
|
rp.transform = m_transform;
|
|
G->R->PR->render(rp);*/
|
|
|
|
// TODO: replace harcoded 32 viewdistance
|
|
if (G->LP->raytracePointed(32, &m_pointedBlock, &m_pointedFacing)) {
|
|
m_highlightBox.program->bind();
|
|
m_highlightBox.vao.bind();
|
|
|
|
glUniform4f(m_highlightBox.uni_unicolor, 1.f, 1.f, 1.f, .1f);
|
|
glUniformMatrix4fv(m_highlightBox.uni_mvp, 1, GL_FALSE, glm::value_ptr(
|
|
glm::scale(glm::translate(m_transform, glm::vec3(m_pointedBlock)+glm::vec3(.5f)), glm::vec3(0.5f*1.03f))));
|
|
glDrawArrays(GL_TRIANGLES, 0, 6*2*3);
|
|
|
|
m_highlightBox.vao.unbind();
|
|
}
|
|
|
|
glDisable(GL_CULL_FACE);
|
|
glDisable(GL_DEPTH_TEST);
|
|
G->LP->render(m_transform);
|
|
|
|
if (bloom.enable) {
|
|
m_3dFbo->unbind();
|
|
G->UIM->drawFullTexV(*m_3dFbo->tex);
|
|
|
|
m_3dFbo->tex->setFiltering(Texture::Filter::Linear, Texture::Filter::Linear);
|
|
bloom.extractor.fbo->bind();
|
|
glViewport(0, 0, GW->getW()/bloom.scale, GW->getH()/bloom.scale);
|
|
glClearColor(0.f, 0.f, 0.f, 0.f);
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
if (!bloom.vao) {
|
|
bloom.vao = std::make_unique<Render::gl::VAO>();
|
|
Render::gl::VAO::Config cfg = bloom.vao->configure();
|
|
cfg.vertexAttrib(*m_3dRenderVBO, bloom.extractor.att_coord, 2, GL_SHORT, sizeof(Coord2DTex), 0);
|
|
cfg.vertexAttrib(*m_3dRenderVBO, bloom.extractor.att_texcoord, 2, GL_BYTE, sizeof(Coord2DTex), offsetof(Coord2DTex, u));
|
|
cfg.commit();
|
|
}
|
|
bloom.extractor.prog->bind();
|
|
bloom.vao->bind();
|
|
glUniformMatrix4fv(bloom.extractor.uni_mvp, 1, GL_FALSE, glm::value_ptr(*G->UIM->PM1));
|
|
glDrawArrays(GL_TRIANGLES, 0, 6);
|
|
m_3dFbo->tex->setFiltering(Texture::Filter::Nearest, Texture::Filter::Nearest);
|
|
|
|
bloom.renderer.fbo->bind();
|
|
glClearColor(0.f, 0.f, 0.f, 0.f);
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
bloom.extractor.fbo->tex->bind();
|
|
bloom.renderer.prog->bind();
|
|
glUniformMatrix4fv(bloom.renderer.uni_mvp, 1, GL_FALSE, glm::value_ptr(*G->UIM->PM1));
|
|
glUniform2f(bloom.renderer.uni_pixshift, 1.f/(GW->getW()/bloom.scale), 1.f/(GW->getH()/bloom.scale));
|
|
glDrawArrays(GL_TRIANGLES, 0, 6);
|
|
bloom.renderer.fbo->unbind();
|
|
|
|
// render to real surface
|
|
glViewport(0, 0, GW->getW(), GW->getH());
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
|
bloom.extractor.fbo->tex->bind();
|
|
bloom.extractor.fbo->tex->setFiltering(Texture::Filter::Linear, Texture::Filter::Linear);
|
|
glDrawArrays(GL_TRIANGLES, 0, 6);
|
|
bloom.vao->unbind();
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
}
|
|
|
|
/*** 2D PART ***/
|
|
G->UIM->drawFullRect(glm::vec4(1.f, 0.f, 0.f, 1-G->LP->health));
|
|
updateUI();
|
|
drawUI();
|
|
|
|
G->R->endFrame();
|
|
frameEnd = std::chrono::steady_clock::now();
|
|
frameTime = std::chrono::duration_cast<std::chrono::duration<uint64, std::micro>>(frameEnd - frameStart).count();
|
|
|
|
fpsCounter++;
|
|
}
|
|
|
|
void GameState::onStop() {
|
|
Net::OutMessage quit(Net::MessageType::PlayerQuit);
|
|
sendMsg(quit, Net::Tfer::Rel);
|
|
|
|
G->LS->finalize();
|
|
}
|
|
|
|
void GameState::gameLoop() {
|
|
double lastT, deltaT, T, fpsT = 0; int frames = 0;
|
|
LocalPlayer *LP = G->LP;
|
|
}
|
|
|
|
void GameState::renderDeathScreen() {
|
|
double red = std::max(1-(G->Time-G->LP->deathTime), 0.0);
|
|
glClearColor(red, 0.0, 0.0, 1.0);
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
}
|
|
|
|
void GameState::updateUI() {
|
|
LocalPlayer &LP = *G->LP;
|
|
if (debugInfo.show) {
|
|
WorldRef w;
|
|
int chunkMem = 0, maxChunkMem = 0;
|
|
for (const std::pair<int, WorldWeakRef> &wr : *G->U)
|
|
if ((w = wr.second.lock()))
|
|
for (std::pair<const glm::ivec3, ChunkWeakRef> &cr : *w) {
|
|
ChunkRef c(cr.second.lock());
|
|
if (c) {
|
|
chunkMem += c->blkMem;
|
|
maxChunkMem += Chunk::AllocaSize;
|
|
}
|
|
}
|
|
constexpr auto CX = Chunk::CX, CY = Chunk::CY, CZ = Chunk::CZ;
|
|
std::ostringstream oss;
|
|
oss << std::setprecision(3) <<
|
|
"HP: " << LP.health << std::endl <<
|
|
"x: " << LP.position.x << std::endl <<
|
|
"y: " << LP.position.y << std::endl <<
|
|
"z: " << LP.position.z << std::endl <<
|
|
"vy: " << LP.velocity.y << std::endl <<
|
|
"r: " << LP.angle << std::endl <<
|
|
// TODO reintroduce "chunk tris: " << lastVertCount / 3 << std::endl <<
|
|
"chunk mem: " << chunkMem / 1024 << " kib / " << (chunkMem*100/maxChunkMem) << '%' <<
|
|
std::endl <<
|
|
"Pointing at: " << LP.W->getBlockId(m_pointedBlock.x, m_pointedBlock.y, m_pointedBlock.z) <<
|
|
" @ " << m_pointedBlock.x << ' ' << m_pointedBlock.y << ' ' << m_pointedBlock.z <<
|
|
" C: " << divrd(m_pointedBlock.x, CX) << ' ' << divrd(m_pointedBlock.y, CY) << ' ' <<
|
|
divrd(m_pointedBlock.z, CZ) << std::endl <<
|
|
"RX: " << G->H.getRxBytes() << std::endl <<
|
|
"TX: " << G->H.getTxBytes() << std::endl <<
|
|
"Frame time: " << frameTime;
|
|
oss << std::endl;
|
|
for (auto stats : Util::MemoryTracker::categoryStats()) {
|
|
oss << stats.name << ' ' << stats.bytesUsed << std::endl;
|
|
}
|
|
UI.DebugInfo->setText(oss.str());
|
|
}
|
|
}
|
|
|
|
void GameState::drawUI() {
|
|
G->UIM->render();
|
|
m_chatBox->render();
|
|
|
|
G->UIM->drawTex(m_crossHair.mat, *m_crossHair.tex);
|
|
// TODO render weapon
|
|
|
|
G->UIM->drawTex(*G->UIM->PM, UI::Element::Area{0,0,128,128}, *G->CR->getAtlas());
|
|
}
|
|
|
|
bool GameState::processNetwork() {
|
|
while (G->H.recv(m_msg, 0)) {
|
|
if (!CMH.handleMessage(m_msg)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
}
|