|
@@ -1,12 +1,39 @@
|
|
|
#include "client/rendering/Engine.h"
|
|
|
+#include "client/Game.h"
|
|
|
+#include "client/rendering/Framebuffers.h"
|
|
|
+#include "client/rendering/Mesh.h"
|
|
|
+#include "client/rendering/NoiseTexture.h"
|
|
|
+#include "client/rendering/Renderer.h"
|
|
|
#include "client/rendering/ShaderMatrix.h"
|
|
|
+#include "client/rendering/Shaders.h"
|
|
|
+#include "math/Frustum.h"
|
|
|
+#include "rendering/Window.h"
|
|
|
+#include "utils/Logger.h"
|
|
|
#include "wrapper/GL.h"
|
|
|
|
|
|
-Engine::Engine(Shaders& shaders, Framebuffers& fb, const Size& size,
|
|
|
- RenderSettings& renderSettings, Game& game)
|
|
|
- : shaders(shaders), framebuffers(fb), lastSize(size), size(size),
|
|
|
- renderSettings(renderSettings), game(game),
|
|
|
- frustum(60.0f, 0.1f, 1000.0f, size) {
|
|
|
+static Window window;
|
|
|
+static Shaders shaders;
|
|
|
+static Framebuffers framebuffers;
|
|
|
+static Size lastSize{0, 0};
|
|
|
+static Frustum frustum{60.0f, 0.1f, 1000.0f, window.getSize()};
|
|
|
+static MatrixStack<16> model;
|
|
|
+static Renderer renderer;
|
|
|
+static NoiseTexture ssaoNoise;
|
|
|
+static Mesh rectangle;
|
|
|
+static Matrix worldProj;
|
|
|
+static Matrix worldView;
|
|
|
+static Matrix worldShadowProj;
|
|
|
+static Matrix worldShadowView;
|
|
|
+static Matrix worldShadowProjView;
|
|
|
+static bool useSsao = true;
|
|
|
+static bool useShadows = false;
|
|
|
+static float shadowRadius = 0.01f;
|
|
|
+static float shadowBias = 0.0002f;
|
|
|
+
|
|
|
+static bool initRectangle() {
|
|
|
+ if(rectangle.init()) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
TypedBuffer<Triangle> buffer(2);
|
|
|
buffer.add(
|
|
|
Triangle(Vertex(Vector3(-1.0f, -1.0f, 0.0f), Vector2(0, 0.0f)),
|
|
@@ -17,39 +44,34 @@ Engine::Engine(Shaders& shaders, Framebuffers& fb, const Size& size,
|
|
|
Vertex(Vector3(1.0f, -1.0f, 0.0f), Vector2(1.0f, 0.0f)),
|
|
|
Vertex(Vector3(1.0f, 1.0f, 0.0f), Vector2(1.0f, 1.0f))));
|
|
|
rectangle.build(buffer);
|
|
|
+ return false;
|
|
|
}
|
|
|
|
|
|
-void Engine::render(float lag) {
|
|
|
- if(size.width != lastSize.width || size.height != lastSize.height) {
|
|
|
- GL::setViewport(size.width, size.height);
|
|
|
- framebuffers.resize(size);
|
|
|
- lastSize = size;
|
|
|
+bool Engine::init() {
|
|
|
+ WindowOptions options(4, 0, {1024, 620}, false, "test");
|
|
|
+ Error error = window.open(options);
|
|
|
+ if(error.has()) {
|
|
|
+ LOG_ERROR(error.message);
|
|
|
+ return true;
|
|
|
}
|
|
|
- GL::printError("loop error");
|
|
|
-
|
|
|
- updateWorldProjection();
|
|
|
- updateWorldView();
|
|
|
-
|
|
|
- if(renderSettings.shadows) {
|
|
|
- renderShadow(lag);
|
|
|
+ lastSize = window.getSize();
|
|
|
+ error = shaders.init();
|
|
|
+ if(error.has()) {
|
|
|
+ LOG_ERROR(error.message);
|
|
|
+ return true;
|
|
|
}
|
|
|
- renderWorld(lag);
|
|
|
- if(renderSettings.ssao) {
|
|
|
- renderSSAO();
|
|
|
+ error = framebuffers.init(window.getSize());
|
|
|
+ if(error.has()) {
|
|
|
+ LOG_ERROR(error.message);
|
|
|
+ return true;
|
|
|
}
|
|
|
- renderPostWorld();
|
|
|
- renderOverlay(lag);
|
|
|
-}
|
|
|
-
|
|
|
-void Engine::tick() {
|
|
|
- game.tick();
|
|
|
-}
|
|
|
-
|
|
|
-bool Engine::isRunning() const {
|
|
|
- return game.isRunning();
|
|
|
+ if(renderer.init() || ssaoNoise.init() || initRectangle()) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
}
|
|
|
|
|
|
-void Engine::renderShadow(float lag) {
|
|
|
+static void renderShadow(float lag) {
|
|
|
framebuffers.shadow.bindAndClear();
|
|
|
GL::enableDepthTesting();
|
|
|
shaders.shadow.use();
|
|
@@ -59,10 +81,10 @@ void Engine::renderShadow(float lag) {
|
|
|
model.clear();
|
|
|
shaders.shadow.setMatrix("model", model.peek().getValues());
|
|
|
ShaderMatrix sm(shaders.shadow, model, worldView);
|
|
|
- game.renderWorld(lag, sm);
|
|
|
+ Game::game->renderWorld(lag, sm);
|
|
|
}
|
|
|
|
|
|
-void Engine::renderWorld(float lag) {
|
|
|
+static void renderWorld(float lag) {
|
|
|
framebuffers.world.bindAndClear();
|
|
|
GL::enableDepthTesting();
|
|
|
shaders.world.use();
|
|
@@ -78,14 +100,14 @@ void Engine::renderWorld(float lag) {
|
|
|
model.clear();
|
|
|
shaders.world.setMatrix("model", model.peek().getValues());
|
|
|
framebuffers.shadow.bindTextureTo(0, 1);
|
|
|
- shaders.world.setInt("shadows", renderSettings.shadows);
|
|
|
- shaders.world.setFloat("radius", renderSettings.testRadius);
|
|
|
- shaders.world.setFloat("zbias", renderSettings.testBias);
|
|
|
+ shaders.world.setInt("shadows", useShadows);
|
|
|
+ shaders.world.setFloat("radius", shadowRadius);
|
|
|
+ shaders.world.setFloat("zbias", shadowBias);
|
|
|
ShaderMatrix sm(shaders.world, model, worldView);
|
|
|
- game.renderWorld(lag, sm);
|
|
|
+ Game::game->renderWorld(lag, sm);
|
|
|
}
|
|
|
|
|
|
-void Engine::renderSSAO() {
|
|
|
+static void renderSSAO() {
|
|
|
shaders.ssao.use();
|
|
|
|
|
|
Matrix rProj;
|
|
@@ -93,6 +115,7 @@ void Engine::renderSSAO() {
|
|
|
rProj *= worldProj;
|
|
|
|
|
|
shaders.ssao.setMatrix("proj", rProj.getValues());
|
|
|
+ const Size& size = window.getSize();
|
|
|
shaders.ssao.setInt("width", size.width);
|
|
|
shaders.ssao.setInt("height", size.height);
|
|
|
framebuffers.world.bindTextureTo(0, 0);
|
|
@@ -107,7 +130,7 @@ void Engine::renderSSAO() {
|
|
|
rectangle.draw();
|
|
|
}
|
|
|
|
|
|
-void Engine::renderPostWorld() {
|
|
|
+static void renderPostWorld() {
|
|
|
GL::bindMainFramebuffer();
|
|
|
GL::clear();
|
|
|
shaders.postWorld.use();
|
|
@@ -115,15 +138,16 @@ void Engine::renderPostWorld() {
|
|
|
framebuffers.ssaoBlur.bindTextureTo(0, 1);
|
|
|
framebuffers.world.bindTextureTo(3, 2);
|
|
|
framebuffers.world.bindTextureTo(1, 3);
|
|
|
- shaders.postWorld.setInt("ssao", renderSettings.ssao);
|
|
|
- shaders.postWorld.setInt("shadows", renderSettings.shadows);
|
|
|
+ shaders.postWorld.setInt("ssao", useSsao);
|
|
|
+ shaders.postWorld.setInt("shadows", useShadows);
|
|
|
rectangle.draw();
|
|
|
}
|
|
|
|
|
|
-void Engine::renderOverlay(float lag) {
|
|
|
+static void renderOverlay(float lag) {
|
|
|
GL::disableDepthTesting();
|
|
|
shaders.overlay.use();
|
|
|
|
|
|
+ const Size& size = window.getSize();
|
|
|
Matrix m;
|
|
|
m.scale(Vector3(2.0f / size.width, -2.0f / size.height, 1.0f))
|
|
|
.translate(Vector3(-1.0f, 1.0f, 0.0f));
|
|
@@ -133,14 +157,14 @@ void Engine::renderOverlay(float lag) {
|
|
|
|
|
|
GL::enableBlending();
|
|
|
ShaderMatrix sm(shaders.overlay, model, m);
|
|
|
- game.renderOverlay(lag, sm, renderer);
|
|
|
+ Game::game->renderOverlay(lag, sm, renderer);
|
|
|
GL::disableBlending();
|
|
|
}
|
|
|
|
|
|
-void Engine::updateWorldProjection() {
|
|
|
+static void updateWorldProjection() {
|
|
|
worldProj = frustum.updateProjection();
|
|
|
|
|
|
- if(!renderSettings.shadows) {
|
|
|
+ if(!useShadows) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
@@ -150,8 +174,8 @@ void Engine::updateWorldProjection() {
|
|
|
worldShadowProj.set(3, Vector4(0.0f, 0.0f, 0.0f, 1.0f));
|
|
|
}
|
|
|
|
|
|
-void Engine::updateWorldView() {
|
|
|
- if(!renderSettings.shadows) {
|
|
|
+static void updateWorldView() {
|
|
|
+ if(!useShadows) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
@@ -166,4 +190,73 @@ void Engine::updateWorldView() {
|
|
|
worldShadowView.set(2,
|
|
|
Vector4(back[0], back[1], back[2], back.dot(-center)));
|
|
|
worldShadowView.set(3, Vector4(0.0f, 0.0f, 0.0f, 1.0f));
|
|
|
+}
|
|
|
+
|
|
|
+static void startRender(float lag) {
|
|
|
+ const Size& size = window.getSize();
|
|
|
+ if(size.width != lastSize.width || size.height != lastSize.height) {
|
|
|
+ GL::setViewport(size.width, size.height);
|
|
|
+ framebuffers.resize(size);
|
|
|
+ lastSize = size;
|
|
|
+ }
|
|
|
+ GL::printError("loop error");
|
|
|
+
|
|
|
+ updateWorldProjection();
|
|
|
+ updateWorldView();
|
|
|
+
|
|
|
+ if(useShadows) {
|
|
|
+ renderShadow(lag);
|
|
|
+ }
|
|
|
+ renderWorld(lag);
|
|
|
+ if(useSsao) {
|
|
|
+ renderSSAO();
|
|
|
+ }
|
|
|
+ renderPostWorld();
|
|
|
+ renderOverlay(lag);
|
|
|
+}
|
|
|
+
|
|
|
+struct Loop final {
|
|
|
+ void render(float lag) {
|
|
|
+ startRender(lag);
|
|
|
+ }
|
|
|
+
|
|
|
+ void tick() {
|
|
|
+ Game::game->tick();
|
|
|
+ }
|
|
|
+
|
|
|
+ bool isRunning() const {
|
|
|
+ return Game::game->isRunning();
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+void Engine::run() {
|
|
|
+ Loop loop;
|
|
|
+ window.run(loop, 50'000'000);
|
|
|
+}
|
|
|
+
|
|
|
+void Engine::setTextInput(TextInput* input) {
|
|
|
+ window.textInput = input;
|
|
|
+ if(input != nullptr) {
|
|
|
+ input->setActive(true);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+bool Engine::isActiveTextInput(TextInput* input) {
|
|
|
+ return window.textInput == input;
|
|
|
+}
|
|
|
+
|
|
|
+Buttons& Engine::getButtons() {
|
|
|
+ return window.buttons;
|
|
|
+}
|
|
|
+
|
|
|
+const Size& Engine::getSize() {
|
|
|
+ return window.getSize();
|
|
|
+}
|
|
|
+
|
|
|
+const Clock& Engine::getFrameClock() {
|
|
|
+ return window.getFrameClock();
|
|
|
+}
|
|
|
+
|
|
|
+const Clock& Engine::getTickClock() {
|
|
|
+ return window.getTickClock();
|
|
|
}
|