#include #include #include "client/rendering/Engine.h" #include "client/rendering/wrapper/GLFWWrapper.h" #include "client/rendering/wrapper/GLWrapper.h" #include "client/rendering/Renderer.h" #include "client/math/Plane.h" Engine::Engine(Shaders& shaders, Framebuffers& fb, const WindowSize& size, RenderSettings& renderSettings) : shaders(shaders), framebuffers(fb), size(size), renderSettings(renderSettings), frustum(60.0f, 0.1f, 1000.0f) { rectangle.add(Triangle( Vertex(Vector3(-1, -1, 0), Vector2(0, 0)), Vertex(Vector3(1, 1, 0), Vector2(1, 1)), Vertex(Vector3(-1, 1, 0), Vector2(0, 1)))); rectangle.add(Triangle( Vertex(Vector3(-1, -1, 0), Vector2(0, 0)), Vertex(Vector3(1, -1, 0), Vector2(1, 0)), Vertex(Vector3(1, 1, 0), Vector2(1, 1)))); rectangle.build(); } void Engine::renderTick(float lag, const Game& game) { if(renderSettings.dirtyFactor) { framebuffers.setFactor(renderSettings.factor); } updateWorldProjection(); updateWorldView(); if(renderSettings.shadows) { renderShadow(lag, game); } renderWorld(lag, game); if(renderSettings.ssao) { renderSSAO(); } renderPostWorld(); renderTextOverlay(lag, game); } void Engine::renderShadow(float lag, const Game& game) { framebuffers.shadow.bind(); GLWrapper::enableDepthTesting(); shaders.shadow.use(); worldShadowProjView.set(worldShadowProj).mul(worldShadowView); shaders.shadow.setMatrix("projView", worldShadowProjView.getValues()); model.clear(); shaders.shadow.setMatrix("model", model.get().getValues()); Renderer renderer(shaders.shadow, model, worldView); game.renderWorld(lag, renderer); } void Engine::renderWorld(float lag, const Game& game) { framebuffers.world.bind(); GLWrapper::enableDepthTesting(); shaders.world.use(); Matrix rWorldShadowProjView; rWorldShadowProjView.translate(0.5f, 0.5f, 0.5f).scale(0.5f).mul(worldShadowProjView); shaders.world.setMatrix("projViewShadow", rWorldShadowProjView.getValues()); shaders.world.setMatrix("proj", worldProj.getValues()); shaders.world.setMatrix("view", worldView.setToIdentity().getValues()); model.clear(); shaders.world.setMatrix("model", model.get().getValues()); framebuffers.shadow.bindDepthTexture(1); shaders.world.setInt("shadows", renderSettings.shadows); shaders.world.setFloat("radius", renderSettings.testRadius); shaders.world.setFloat("zbias", renderSettings.testBias); Renderer renderer(shaders.world, model, worldView); game.renderWorld(lag, renderer); shaders.worldLines.use(); shaders.worldLines.setMatrix("proj", worldProj.getValues()); shaders.worldLines.setMatrix("view", worldView.getValues()); model.clear(); shaders.worldLines.setMatrix("model", model.get().getValues()); Renderer lineRenderer(shaders.worldLines, model, worldView); game.renderWorldLines(lag, lineRenderer); } void Engine::renderSSAO() { shaders.ssao.use(); Matrix rProj; rProj.translate(0.5f, 0.5f, 0.5f).scale(0.5f).mul(worldProj); shaders.ssao.setMatrix("proj", rProj.getValues()); shaders.ssao.setInt("width", size.width * renderSettings.factor); shaders.ssao.setInt("height", size.height * renderSettings.factor); framebuffers.world.bindPositionTexture(0); framebuffers.world.bindNormalTexture(1); framebuffers.world.bindColorTexture(2); framebuffers.world.bindDepthTexture(3); ssaoNoise.bind(4); framebuffers.ssao.bind(); rectangle.draw(); shaders.ssaoBlur.use(); framebuffers.ssao.bindRedTexture(0); framebuffers.ssaoBlur.bind(); rectangle.draw(); } void Engine::renderPostWorld() { framebuffers.antialias.bind(); shaders.postWorld.use(); framebuffers.world.bindColorTexture(0); framebuffers.ssaoBlur.bindRedTexture(1); framebuffers.world.bindRedTexture(2); framebuffers.world.bindNormalTexture(3); shaders.postWorld.setInt("ssao", renderSettings.ssao); shaders.postWorld.setInt("shadows", renderSettings.shadows); shaders.postWorld.setFloat("bump", renderSettings.bump); rectangle.draw(); GLWrapper::prepareMainFramebuffer(); glViewport(0, 0, size.width, size.height); shaders.antialias.use(); shaders.antialias.setInt("radius", renderSettings.factor); framebuffers.antialias.bindColorTexture(0); rectangle.draw(); } void Engine::renderTextOverlay(float lag, const Game& game) { GLWrapper::disableDepthTesting(); shaders.text.use(); Matrix m; shaders.text.setMatrix("proj", m.getValues()); m.translate(-1.0f, 1.0f, 0.0f).scale(2.0f / size.width, -2.0f / size.height, 1.0f); shaders.text.setMatrix("view", m.getValues()); model.clear(); shaders.text.setMatrix("model", model.get().getValues()); GLWrapper::enableBlending(); Renderer renderer(shaders.text, model, m); game.renderTextOverlay(lag, renderer, fontRenderer); GLWrapper::disableBlending(); } void Engine::updateWorldProjection() { frustum.setProjection(worldProj, size.width, size.height); if(!renderSettings.shadows) { return; } worldShadowProj.setToIdentity(); worldShadowProj.set(0, 2.0f / 40.0f); worldShadowProj.set(5, 2.0f / 30.0f); worldShadowProj.set(10, -2.0f / frustum.getClipDifference()); } void Engine::updateWorldView() { if(!renderSettings.shadows) { return; } Vector3 right(0.939693f, 0.0f, -0.34202f); Vector3 back(0.280166f, 0.573576f, 0.769751f); Vector3 up(-0.196175f, 0.819152f, -0.538986f); Vector3 center(16.0f, 24.0f, 24.0f); worldShadowView.set(0, right[0]); worldShadowView.set(1, up[0]); worldShadowView.set(2, back[0]); worldShadowView.set(4, right[1]); worldShadowView.set(5, up[1]); worldShadowView.set(6, back[1]); worldShadowView.set(8, right[2]); worldShadowView.set(9, up[2]); worldShadowView.set(10, back[2]); worldShadowView.set(12, right.dot(-center)); worldShadowView.set(13, up.dot(-center)); worldShadowView.set(14, back.dot(-center)); }