|
@@ -3,6 +3,7 @@
|
|
#include <GLFW/glfw3.h>
|
|
#include <GLFW/glfw3.h>
|
|
#include <unordered_map>
|
|
#include <unordered_map>
|
|
#include <cmath>
|
|
#include <cmath>
|
|
|
|
+#include <cstring>
|
|
|
|
|
|
#include "common/utils/Types.h"
|
|
#include "common/utils/Types.h"
|
|
#include "client/GameClient.h"
|
|
#include "client/GameClient.h"
|
|
@@ -56,6 +57,7 @@ struct Shaders
|
|
world("resources/shader/worldVertex.vs", "resources/shader/worldFragment.fs"),
|
|
world("resources/shader/worldVertex.vs", "resources/shader/worldFragment.fs"),
|
|
ssao("resources/shader/ssaoVertex.vs", "resources/shader/ssaoFragment.fs"),
|
|
ssao("resources/shader/ssaoVertex.vs", "resources/shader/ssaoFragment.fs"),
|
|
ssaoBlur("resources/shader/ssaoBlurVertex.vs", "resources/shader/ssaoBlurFragment.fs"),
|
|
ssaoBlur("resources/shader/ssaoBlurVertex.vs", "resources/shader/ssaoBlurFragment.fs"),
|
|
|
|
+ postWorld("resources/shader/worldPostVertex.vs", "resources/shader/worldPostFragment.fs"),
|
|
text("resources/shader/textVertex.vs", "resources/shader/textFragment.fs")
|
|
text("resources/shader/textVertex.vs", "resources/shader/textFragment.fs")
|
|
{
|
|
{
|
|
}
|
|
}
|
|
@@ -63,11 +65,60 @@ struct Shaders
|
|
Shader world;
|
|
Shader world;
|
|
Shader ssao;
|
|
Shader ssao;
|
|
Shader ssaoBlur;
|
|
Shader ssaoBlur;
|
|
|
|
+ Shader postWorld;
|
|
Shader text;
|
|
Shader text;
|
|
|
|
|
|
|
|
+ float worldProj[16] =
|
|
|
|
+ {
|
|
|
|
+ 1.0f, 0.0f, 0.0f, 0.0f,
|
|
|
|
+ 0.0f, 1.0f, 0.0f, 0.0f,
|
|
|
|
+ 0.0f, 0.0f, 1.0f, -1.0f,
|
|
|
|
+ 0.0f, 0.0f, 1.0, 0.0f
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ float worldView[16]=
|
|
|
|
+ {
|
|
|
|
+ 1.0f, 0.0f, 0.0f, 0.0f,
|
|
|
|
+ 0.0f, 1.0f, 0.0f, 0.0f,
|
|
|
|
+ 0.0f, 0.0f, 1.0f, 0.0f,
|
|
|
|
+ 0.0f, 0.0f, 0.0f, 1.0f
|
|
|
|
+ };
|
|
|
|
+
|
|
bool isValid() const
|
|
bool isValid() const
|
|
{
|
|
{
|
|
- return world.isValid() && ssao.isValid() && ssaoBlur.isValid() && text.isValid();
|
|
+ return world.isValid() && ssao.isValid() && ssaoBlur.isValid() && postWorld.isValid() && text.isValid();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ void updateWorldProjection()
|
|
|
|
+ {
|
|
|
|
+ float tan = tanf((0.5f * fovY) * M_PI / 180.0f);
|
|
|
|
+ float q = 1.0f / tan;
|
|
|
|
+ float aspect = (float) width / height;
|
|
|
|
+ worldProj[0] = q / aspect;
|
|
|
|
+ worldProj[5] = q;
|
|
|
|
+ worldProj[10] = (nearClip + farClip) / (nearClip - farClip);
|
|
|
|
+ worldProj[14] = (2.0f * nearClip * farClip) / (nearClip - farClip);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ void updateWorldView(float lag, Camera& cam)
|
|
|
|
+ {
|
|
|
|
+ cam.update(lag);
|
|
|
|
+ const Vector right = cam.getRight();
|
|
|
|
+ const Vector up = cam.getUp();
|
|
|
|
+ const Vector back = cam.getBack();
|
|
|
|
+ const Vector pos = cam.getPosition();
|
|
|
|
+ worldView[0] = right.getX();
|
|
|
|
+ worldView[1] = up.getX();
|
|
|
|
+ worldView[2] = back.getX();
|
|
|
|
+ worldView[4] = right.getY();
|
|
|
|
+ worldView[5] = up.getY();
|
|
|
|
+ worldView[6] = back.getY();
|
|
|
|
+ worldView[8] = right.getZ();
|
|
|
|
+ worldView[9] = up.getZ();
|
|
|
|
+ worldView[10] = back.getZ();
|
|
|
|
+ worldView[12] = right.dotInverse(pos);
|
|
|
|
+ worldView[13] = up.dotInverse(pos);
|
|
|
|
+ worldView[14] = back.dotInverse(pos);
|
|
}
|
|
}
|
|
};
|
|
};
|
|
|
|
|
|
@@ -100,6 +151,13 @@ struct InternGame
|
|
{
|
|
{
|
|
InternGame() : ssaoNoise(4, 4)
|
|
InternGame() : ssaoNoise(4, 4)
|
|
{
|
|
{
|
|
|
|
+ rectangle.add({-1, -1, 0, 0, 0, 0, 0, 0});
|
|
|
|
+ rectangle.add({ 1, 1, 0, 1, 1, 0, 0, 0});
|
|
|
|
+ rectangle.add({-1, 1, 0, 0, 1, 0, 0, 0});
|
|
|
|
+ rectangle.add({-1, -1, 0, 0, 0, 0, 0, 0});
|
|
|
|
+ rectangle.add({ 1, -1, 0, 1, 0, 0, 0, 0});
|
|
|
|
+ rectangle.add({ 1, 1, 0, 1, 1, 0, 0, 0});
|
|
|
|
+ rectangle.build();
|
|
}
|
|
}
|
|
|
|
|
|
Game game;
|
|
Game game;
|
|
@@ -107,6 +165,7 @@ struct InternGame
|
|
MatrixStack model;
|
|
MatrixStack model;
|
|
FontRenderer fontRenderer;
|
|
FontRenderer fontRenderer;
|
|
NoiseTexture ssaoNoise;
|
|
NoiseTexture ssaoNoise;
|
|
|
|
+ Mesh rectangle;
|
|
};
|
|
};
|
|
|
|
|
|
static u64 getTimeNanos()
|
|
static u64 getTimeNanos()
|
|
@@ -211,48 +270,55 @@ static void tick(InternGame& game)
|
|
mButtons.postTick();
|
|
mButtons.postTick();
|
|
}
|
|
}
|
|
|
|
|
|
-static void renderWorld(float lag, Shaders& shaders, InternGame& game)
|
|
+static void renderWorld(float lag, Shaders& shaders, InternGame& game, Framebuffers& fb)
|
|
{
|
|
{
|
|
|
|
+ fb.worldBuffer.bind();
|
|
glEnable(GL_DEPTH_TEST);
|
|
glEnable(GL_DEPTH_TEST);
|
|
-
|
|
|
|
shaders.world.use();
|
|
shaders.world.use();
|
|
-
|
|
+ shaders.world.setMatrix("proj", shaders.worldProj);
|
|
- float tan = tanf((0.5f * fovY) * M_PI / 180.0f);
|
|
+ shaders.world.setMatrix("view", shaders.worldView);
|
|
- float q = 1.0f / tan;
|
|
|
|
- float aspect = (float) width / height;
|
|
|
|
- float proj[] =
|
|
|
|
- {
|
|
|
|
- q / aspect, 0.0f, 0.0f, 0.0f,
|
|
|
|
- 0.0f, q, 0.0f, 0.0f,
|
|
|
|
- 0.0f, 0.0f, (nearClip + farClip) / (nearClip - farClip), -1.0f,
|
|
|
|
- 0.0f, 0.0f, (2.0f * nearClip * farClip) / (nearClip - farClip), 0.0f
|
|
|
|
- };
|
|
|
|
- shaders.world.setMatrix("proj", proj);
|
|
|
|
-
|
|
|
|
- game.cam.update(lag);
|
|
|
|
- const Vector right = game.cam.getRight();
|
|
|
|
- const Vector up = game.cam.getUp();
|
|
|
|
- const Vector back = game.cam.getBack();
|
|
|
|
- const Vector pos = game.cam.getPosition();
|
|
|
|
- float view[] =
|
|
|
|
- {
|
|
|
|
- right.getX(), up.getX(), back.getX(), 0.0f,
|
|
|
|
- right.getY(), up.getY(), back.getY(), 0.0f,
|
|
|
|
- right.getZ(), up.getZ(), back.getZ(), 0.0f,
|
|
|
|
- right.dotInverse(pos), up.dotInverse(pos), back.dotInverse(pos), 1.0f
|
|
|
|
- };
|
|
|
|
- shaders.world.setMatrix("view", view);
|
|
|
|
-
|
|
|
|
game.model.clear();
|
|
game.model.clear();
|
|
shaders.world.setMatrix("model", game.model.get().getValues());
|
|
shaders.world.setMatrix("model", game.model.get().getValues());
|
|
-
|
|
|
|
game.game.renderWorld(lag, game.model, shaders.world);
|
|
game.game.renderWorld(lag, game.model, shaders.world);
|
|
|
|
+}
|
|
|
|
|
|
|
|
+static void renderSSAO(Shaders& shaders, InternGame& game, Framebuffers& fb)
|
|
|
|
+{
|
|
|
|
+
|
|
shaders.ssao.use();
|
|
shaders.ssao.use();
|
|
- shaders.ssao.setMatrix("view", view);
|
|
+ shaders.ssao.setMatrix("view", shaders.worldView);
|
|
- shaders.ssao.setMatrix("proj", proj);
|
|
+ shaders.ssao.setMatrix("proj", shaders.worldProj);
|
|
shaders.ssao.setInt("width", width);
|
|
shaders.ssao.setInt("width", width);
|
|
shaders.ssao.setInt("height", height);
|
|
shaders.ssao.setInt("height", height);
|
|
|
|
+ fb.worldBuffer.bindPositionTexture(0);
|
|
|
|
+ fb.worldBuffer.bindNormalTexture(1);
|
|
|
|
+ fb.worldBuffer.bindColorTexture(2);
|
|
|
|
+ fb.worldBuffer.bindDepthTexture(3);
|
|
|
|
+ game.ssaoNoise.bind(4);
|
|
|
|
+ fb.ssaoBuffer.bind();
|
|
|
|
+ game.rectangle.draw();
|
|
|
|
+
|
|
|
|
+ shaders.ssaoBlur.use();
|
|
|
|
+ fb.ssaoBuffer.bindRedTexture(0);
|
|
|
|
+ fb.worldBuffer.bindColorTexture(1);
|
|
|
|
+ fb.ssaoBlurBuffer.bind();
|
|
|
|
+ game.rectangle.draw();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void renderPostWorld(Shaders& shaders, InternGame& game, Framebuffers& fb)
|
|
|
|
+{
|
|
|
|
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
|
|
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
|
|
|
+ fb.worldBuffer.bindColorTexture(0);
|
|
|
|
+ fb.ssaoBlurBuffer.bindRedTexture(1);
|
|
|
|
+ shaders.postWorld.use();
|
|
|
|
+
|
|
|
|
+ glDisable(GL_DEPTH_TEST);
|
|
|
|
+ glEnable(GL_BLEND);
|
|
|
|
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
+ glBlendEquation(GL_FUNC_ADD);
|
|
|
|
+ game.rectangle.draw();
|
|
|
|
+ glDisable(GL_BLEND);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -283,8 +349,12 @@ static void renderTick(float lag, Shaders& shaders, InternGame& game, Framebuffe
|
|
fb.resize(width, height);
|
|
fb.resize(width, height);
|
|
resize = false;
|
|
resize = false;
|
|
}
|
|
}
|
|
- fb.worldBuffer.bind();
|
|
+ shaders.updateWorldProjection();
|
|
- renderWorld(lag, shaders, game);
|
|
+ shaders.updateWorldView(lag, game.cam);
|
|
|
|
+
|
|
|
|
+ renderWorld(lag, shaders, game, fb);
|
|
|
|
+ renderSSAO(shaders, game, fb);
|
|
|
|
+ renderPostWorld(shaders, game, fb);
|
|
}
|
|
}
|
|
|
|
|
|
static void loop()
|
|
static void loop()
|
|
@@ -301,47 +371,11 @@ static void loop()
|
|
}
|
|
}
|
|
InternGame game;
|
|
InternGame game;
|
|
|
|
|
|
- Shader sh("resources/shader/test2Vertex.vs", "resources/shader/test2Fragment.fs");
|
|
|
|
- Mesh m;
|
|
|
|
- m.add({-1, -1, 0, 0, 0, 0, 0, 0});
|
|
|
|
- m.add({ 1, 1, 0, 1, 1, 0, 0, 0});
|
|
|
|
- m.add({-1, 1, 0, 0, 1, 0, 0, 0});
|
|
|
|
- m.add({-1, -1, 0, 0, 0, 0, 0, 0});
|
|
|
|
- m.add({ 1, -1, 0, 1, 0, 0, 0, 0});
|
|
|
|
- m.add({ 1, 1, 0, 1, 1, 0, 0, 0});
|
|
|
|
- m.build();
|
|
|
|
-
|
|
|
|
u64 lastTime = getTimeNanos();
|
|
u64 lastTime = getTimeNanos();
|
|
u64 lag = 0;
|
|
u64 lag = 0;
|
|
while(!glfwWindowShouldClose(client.window))
|
|
while(!glfwWindowShouldClose(client.window))
|
|
{
|
|
{
|
|
renderTick(lag * lagFactor, shaders, game, fb);
|
|
renderTick(lag * lagFactor, shaders, game, fb);
|
|
-
|
|
|
|
- fb.worldBuffer.bindPositionTexture(0);
|
|
|
|
- fb.worldBuffer.bindNormalTexture(1);
|
|
|
|
- fb.worldBuffer.bindColorTexture(2);
|
|
|
|
- fb.worldBuffer.bindDepthTexture(3);
|
|
|
|
- game.ssaoNoise.bind(4);
|
|
|
|
- fb.ssaoBuffer.bind();
|
|
|
|
- m.draw();
|
|
|
|
-
|
|
|
|
- shaders.ssaoBlur.use();
|
|
|
|
- fb.ssaoBuffer.bindRedTexture(0);
|
|
|
|
- fb.worldBuffer.bindColorTexture(1);
|
|
|
|
- fb.ssaoBlurBuffer.bind();
|
|
|
|
- m.draw();
|
|
|
|
-
|
|
|
|
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
|
|
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
|
|
|
- fb.ssaoBlurBuffer.bindRedTexture(1);
|
|
|
|
- sh.use();
|
|
|
|
-
|
|
|
|
- glDisable(GL_DEPTH_TEST);
|
|
|
|
- glEnable(GL_BLEND);
|
|
|
|
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
- glBlendEquation(GL_FUNC_ADD);
|
|
|
|
- m.draw();
|
|
|
|
- glDisable(GL_BLEND);
|
|
|
|
glfwSwapBuffers(client.window);
|
|
glfwSwapBuffers(client.window);
|
|
|
|
|
|
u64 newTime = getTimeNanos();
|
|
u64 newTime = getTimeNanos();
|