feat: deferred shading (day 2)

This commit is contained in:
MihailRis
2025-07-08 23:56:22 +03:00
parent a585b52aa2
commit 0bd901d1a6
23 changed files with 236 additions and 92 deletions
+15 -3
View File
@@ -4,6 +4,8 @@
#include "debug/Logger.hpp"
using namespace advanced_pipeline;
static debug::Logger logger("gl-gbuffer");
void GBuffer::createColorBuffer() {
@@ -162,20 +164,30 @@ void GBuffer::unbind() {
}
void GBuffer::bindBuffers() const {
glActiveTexture(GL_TEXTURE2);
glActiveTexture(GL_TEXTURE0 + TARGET_NORMALS);
glBindTexture(GL_TEXTURE_2D, normalsBuffer);
glActiveTexture(GL_TEXTURE1);
glActiveTexture(GL_TEXTURE0 + TARGET_POSITIONS);
glBindTexture(GL_TEXTURE_2D, positionsBuffer);
glActiveTexture(GL_TEXTURE0);
glActiveTexture(GL_TEXTURE0 + TARGET_COLOR);
glBindTexture(GL_TEXTURE_2D, colorBuffer);
if (TARGET_COLOR != 0)
glActiveTexture(GL_TEXTURE0);
}
void GBuffer::bindSSAOBuffer() const {
glBindTexture(GL_TEXTURE_2D, ssaoBuffer);
}
void GBuffer::bindDepthBuffer() {
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBlitFramebuffer(0, 0, width, height, 0, 0, width, height,
GL_DEPTH_BUFFER_BIT, GL_NEAREST);
}
void GBuffer::resize(uint width, uint height) {
if (this->width == width && this->height == height) {
return;
+2
View File
@@ -16,6 +16,8 @@ public:
void bindBuffers() const;
void bindSSAOBuffer() const;
void bindDepthBuffer();
void resize(uint width, uint height);
uint getWidth() const;
+4
View File
@@ -100,6 +100,10 @@ Shader& PostEffect::use() {
return *shader;
}
Shader& PostEffect::getShader() {
return *shader;
}
float PostEffect::getIntensity() const {
return intensity;
}
+2
View File
@@ -48,6 +48,8 @@ public:
Shader& use();
Shader& getShader();
float getIntensity() const;
void setIntensity(float value);
+75 -14
View File
@@ -12,6 +12,8 @@
#include <stdexcept>
#include <random>
using namespace advanced_pipeline;
PostProcessing::PostProcessing(size_t effectSlotsCount)
: effectSlots(effectSlotsCount) {
// Fullscreen quad mesh bulding
@@ -74,28 +76,46 @@ void PostProcessing::refreshFbos(uint width, uint height) {
}
}
void PostProcessing::bindDepthBuffer() {
gbuffer->bindDepthBuffer();
}
void PostProcessing::configureEffect(
const DrawContext& context,
PostEffect& effect,
Shader& shader,
float timer,
const Camera& camera,
uint shadowMap
uint shadowMap,
uint shadowMap2,
const glm::mat4& shadowMatrix,
const glm::mat4& shadowMatrix2,
uint shadowMapResolution
) {
const auto& viewport = context.getViewport();
shader.uniform1i("u_screen", 0);
shader.uniform1i("u_screen", TARGET_COLOR);
shader.uniform1i("u_skybox", TARGET_SKYBOX);
if (gbuffer) {
shader.uniform1i("u_position", 1);
shader.uniform1i("u_normal", 2);
shader.uniform1i("u_position", TARGET_POSITIONS);
shader.uniform1i("u_normal", TARGET_NORMALS);
}
shader.uniform1i("u_noise", 3); // used in SSAO pass
shader.uniform1i("u_ssao", 3);
shader.uniform1i("u_noise", TARGET_SSAO); // used in SSAO pass
shader.uniform1i("u_ssao", TARGET_SSAO);
shader.uniform1i("u_shadows", 4);
shader.uniform1i("u_shadows[0]", TARGET_SHADOWS0);
shader.uniform1i("u_shadows[1]", TARGET_SHADOWS1);
shader.uniformMatrix("u_shadowsMatrix[0]", shadowMatrix);
shader.uniformMatrix("u_shadowsMatrix[1]", shadowMatrix2);
shader.uniform1f("u_shadowsOpacity", 1.0f);
shader.uniform1f("u_shadowsSoftness", 1.0f);
shader.uniform1i("u_shadowsRes", shadowMapResolution);
shader.uniform2i("u_screenSize", viewport);
shader.uniform3f("u_cameraPos", camera.position);
shader.uniform1f("u_timer", timer);
shader.uniform1i("u_enableShadows", shadowMap != 0);
shader.uniformMatrix("u_projection", camera.getProjection());
shader.uniformMatrix("u_view", camera.getView());
shader.uniformMatrix("u_inverseView", glm::inverse(camera.getView()));
}
void PostProcessing::render(
@@ -103,7 +123,11 @@ void PostProcessing::render(
const Assets& assets,
float timer,
const Camera& camera,
uint shadowMap
uint shadowMap,
uint shadowMap2,
const glm::mat4& shadowMatrix,
const glm::mat4& shadowMatrix2,
uint shadowMapResolution
) {
if (fbo == nullptr && gbuffer == nullptr) {
throw std::runtime_error("'use(...)' was never called");
@@ -118,25 +142,40 @@ void PostProcessing::render(
const auto& vp = context.getViewport();
refreshFbos(vp.x, vp.y);
glActiveTexture(GL_TEXTURE4);
glActiveTexture(GL_TEXTURE0 + TARGET_SHADOWS0);
glBindTexture(GL_TEXTURE_2D, shadowMap);
glActiveTexture(GL_TEXTURE0 + TARGET_SHADOWS1);
glBindTexture(GL_TEXTURE_2D, shadowMap2);
// Generating ssao
if (gbuffer) {
gbuffer->bindBuffers();
glActiveTexture(GL_TEXTURE3);
glActiveTexture(GL_TEXTURE0 + TARGET_SSAO);
glBindTexture(GL_TEXTURE_2D, noiseTexture);
glActiveTexture(GL_TEXTURE0);
auto& ssaoEffect = assets.require<PostEffect>("ssao");
auto& shader = ssaoEffect.use();
configureEffect(context, ssaoEffect, shader, timer, camera, shadowMap);
configureEffect(
context,
ssaoEffect,
shader,
timer,
camera,
shadowMap,
shadowMap2,
shadowMatrix,
shadowMatrix2,
shadowMapResolution
);
gbuffer->bindSSAO();
quadMesh->draw();
gbuffer->unbind();
glActiveTexture(GL_TEXTURE3);
glActiveTexture(GL_TEXTURE0 + TARGET_SSAO);
gbuffer->bindSSAOBuffer();
} else {
glActiveTexture(GL_TEXTURE0);
@@ -148,7 +187,18 @@ void PostProcessing::render(
gbuffer ? "deferred_lighting" : "default"
);
auto& shader = effect.use();
configureEffect(context, effect, shader, timer, camera, shadowMap);
configureEffect(
context,
effect,
shader,
timer,
camera,
shadowMap,
shadowMap2,
shadowMatrix,
shadowMatrix2,
shadowMapResolution
);
quadMesh->draw();
return;
}
@@ -162,7 +212,18 @@ void PostProcessing::render(
continue;
}
auto& shader = effect->use();
configureEffect(context, *effect, shader, timer, camera, shadowMap);
configureEffect(
context,
*effect,
shader,
timer,
camera,
shadowMap,
shadowMap2,
shadowMatrix,
shadowMatrix2,
shadowMapResolution
);
if (currentPass > 1) {
fbo->getTexture()->bind();
+11 -2
View File
@@ -44,7 +44,11 @@ public:
const Assets& assets,
float timer,
const Camera& camera,
uint shadowMap
uint shadowMap,
uint shadowMap2,
const glm::mat4& shadowMatrix,
const glm::mat4& shadowMatrix2,
uint shadowMapResolution
);
void setEffect(size_t slot, std::shared_ptr<PostEffect> effect);
@@ -55,6 +59,7 @@ public:
std::unique_ptr<ImageData> toImage();
Framebuffer* getFramebuffer() const;
void bindDepthBuffer();
private:
void configureEffect(
const DrawContext& context,
@@ -62,7 +67,11 @@ private:
Shader& shader,
float timer,
const Camera& camera,
uint shadowMap
uint shadowMap,
uint shadowMap2,
const glm::mat4& shadowMatrix,
const glm::mat4& shadowMatrix2,
uint shadowMapResolution
);
void refreshFbos(uint width, uint height);
+6
View File
@@ -51,6 +51,12 @@ void Shader::uniformMatrix(const std::string& name, const glm::mat4& matrix) {
);
}
void Shader::uniformMatrix(const std::string& name, const glm::mat3& matrix) {
glUniformMatrix3fv(
getUniformLocation(name), 1, GL_FALSE, glm::value_ptr(matrix)
);
}
void Shader::uniform1i(const std::string& name, int x){
glUniform1i(getUniformLocation(name), x);
}
+1
View File
@@ -33,6 +33,7 @@ public:
void use();
void uniformMatrix(const std::string&, const glm::mat4& matrix);
void uniformMatrix(const std::string&, const glm::mat3& matrix);
void uniform1i(const std::string& name, int x);
void uniform1f(const std::string& name, float x);
void uniform2f(const std::string& name, float x, float y);
+10
View File
@@ -50,6 +50,16 @@ enum class CursorShape {
LAST=NOT_ALLOWED
};
namespace advanced_pipeline {
inline constexpr int TARGET_COLOR = 0;
inline constexpr int TARGET_SKYBOX = 1;
inline constexpr int TARGET_POSITIONS = 2;
inline constexpr int TARGET_NORMALS = 3;
inline constexpr int TARGET_SSAO = 4;
inline constexpr int TARGET_SHADOWS0 = 5;
inline constexpr int TARGET_SHADOWS1 = 6;
}
VC_ENUM_METADATA(CursorShape)
{"arrow", CursorShape::ARROW},
{"text", CursorShape::TEXT},
+21 -20
View File
@@ -18,9 +18,7 @@
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/constants.hpp>
#ifndef M_PI
#define M_PI 3.141592
#endif // M_PI
using namespace advanced_pipeline;
const int STARS_COUNT = 3000;
const int STARS_SEED = 632;
@@ -47,14 +45,6 @@ Skybox::Skybox(uint size, Shader& shader)
mesh = std::make_unique<Mesh<SkyboxVertex>>(vertices, 6);
sprites.push_back(SkySprite {
"misc/moon_flare",
glm::pi<float>() * 0.5f,
0.5f,
false,
glm::pi<float>() * 0.25f,
});
sprites.push_back(SkySprite {
"misc/moon",
glm::pi<float>() * 0.5f,
@@ -62,6 +52,14 @@ Skybox::Skybox(uint size, Shader& shader)
false,
glm::pi<float>() * 0.25f,
});
sprites.push_back(SkySprite {
"misc/moon_flare",
glm::pi<float>() * 0.5f,
0.5f,
false,
glm::pi<float>() * 0.25f,
});
sprites.push_back(SkySprite {
"misc/sun",
@@ -118,6 +116,8 @@ void Skybox::draw(
{
const glm::uvec2& viewport = pctx.getViewport();
glActiveTexture(GL_TEXTURE0);
drawBackground(camera, assets, viewport.x, viewport.y);
DrawContext ctx = pctx.sub();
@@ -130,22 +130,23 @@ void Skybox::draw(
batch3d->begin();
float angle = daytime * glm::pi<float>() * 2.0f;
float opacity = glm::pow(1.0f-fog, 7.0f);
float opacity = glm::pow(1.0f - fog, 7.0f);
float depthScale = 1e3;
for (auto& sprite : sprites) {
batch3d->texture(assets.get<Texture>(sprite.texture));
float sangle = daytime * glm::pi<float>() * 2.0 + sprite.phase;
float distance = sprite.distance;
float distance = sprite.distance * depthScale;
glm::mat4 rotation = glm::rotate(glm::mat4(1.0f), -sangle + glm::pi<float>() * 0.5f, glm::vec3(0, 0, -1));
rotation = glm::rotate(rotation, sprite.altitude, glm::vec3(1, 0, 0));
glm::vec3 pos = glm::vec4(0, distance, 0, 1) * rotation;
glm::vec3 up = glm::vec4(1, 0, 0, 1) * rotation;
glm::vec3 right = glm::vec4(0, 0, 1, 1) * rotation;
glm::vec3 up = glm::vec4(depthScale, 0, 0, 1) * rotation;
glm::vec3 right = glm::vec4(0, 0, depthScale, 1) * rotation;
glm::vec4 tint (1,1,1, opacity);
if (!sprite.emissive) {
tint *= 0.6f+std::cos(angle)*0.4;
tint *= 0.6f + std::cos(angle)*0.4;
}
batch3d->sprite(pos, right,
up, 1, 1, UVRegion(), tint);
@@ -167,10 +168,10 @@ void Skybox::refresh(const DrawContext& pctx, float t, float mie, uint quality)
assert(cubemap != nullptr);
ready = true;
glActiveTexture(GL_TEXTURE1);
glActiveTexture(GL_TEXTURE0 + TARGET_SKYBOX);
cubemap->bind();
shader.use();
t *= glm::pi<float>()*2.0f;
t *= glm::two_pi<float>();
lightDir = glm::normalize(glm::vec3(sin(t), -cos(t), 0.0f));
shader.uniform1i("u_quality", quality);
@@ -237,13 +238,13 @@ void Skybox::refreshFace(uint face, Cubemap* cubemap) {
}
void Skybox::bind() const {
glActiveTexture(GL_TEXTURE1);
glActiveTexture(GL_TEXTURE0 + TARGET_SKYBOX);
fbo->getTexture()->bind();
glActiveTexture(GL_TEXTURE0);
}
void Skybox::unbind() const {
glActiveTexture(GL_TEXTURE1);
glActiveTexture(GL_TEXTURE0 + TARGET_SKYBOX);
fbo->getTexture()->unbind();
glActiveTexture(GL_TEXTURE0);
}
+32 -15
View File
@@ -54,8 +54,11 @@
#include "Emitter.hpp"
#include "TextNote.hpp"
using namespace advanced_pipeline;
inline constexpr size_t BATCH3D_CAPACITY = 4096;
inline constexpr size_t MODEL_BATCH_CAPACITY = 20'000;
inline constexpr GLenum TEXTURE_MAIN = GL_TEXTURE0;
bool WorldRenderer::showChunkBorders = false;
bool WorldRenderer::showEntitiesDebug = false;
@@ -141,15 +144,15 @@ void WorldRenderer::setupWorldShader(
shader.uniform1f("u_shadowsOpacity", 1.0f - cloudsIntensity); // TODO: make it configurable
shader.uniform1f("u_shadowsSoftness", 1.0f + cloudsIntensity * 4); // TODO: make it configurable
glActiveTexture(GL_TEXTURE4);
shader.uniform1i("u_shadows[0]", 4);
glActiveTexture(GL_TEXTURE0 + TARGET_SHADOWS0);
shader.uniform1i("u_shadows[0]", TARGET_SHADOWS0);
glBindTexture(GL_TEXTURE_2D, shadowMap->getDepthMap());
glActiveTexture(GL_TEXTURE5);
shader.uniform1i("u_shadows[1]", 5);
glActiveTexture(GL_TEXTURE0 + TARGET_SHADOWS1);
shader.uniform1i("u_shadows[1]", TARGET_SHADOWS1);
glBindTexture(GL_TEXTURE_2D, wideShadowMap->getDepthMap());
glActiveTexture(GL_TEXTURE0);
glActiveTexture(TEXTURE_MAIN);
}
auto indices = level.content.getIndices();
@@ -438,9 +441,11 @@ void WorldRenderer::draw(
auto& mainShader = assets.require<Shader>("main");
auto& entityShader = assets.require<Shader>("entity");
auto& deferredShader = assets.require<PostEffect>("deferred_lighting").getShader();
const auto& settings = engine.getSettings();
gbufferPipeline = settings.graphics.advancedRender.get();
int shadowsQuality = settings.graphics.shadowsQuality.get();
int shadowsQuality = settings.graphics.shadowsQuality.get() * gbufferPipeline;
int resolution = 512 << shadowsQuality;
if (shadowsQuality > 0 && !shadows) {
shadowMap = std::make_unique<ShadowMap>(resolution);
@@ -449,6 +454,7 @@ void WorldRenderer::draw(
Shader::preprocessor->define("ENABLE_SHADOWS", "true");
mainShader.recompile();
entityShader.recompile();
deferredShader.recompile();
} else if (shadowsQuality == 0 && shadows) {
shadowMap.reset();
wideShadowMap.reset();
@@ -456,6 +462,7 @@ void WorldRenderer::draw(
Shader::preprocessor->undefine("ENABLE_SHADOWS");
mainShader.recompile();
entityShader.recompile();
deferredShader.recompile();
}
if (shadows && shadowMap->getResolution() != resolution) {
shadowMap = std::make_unique<ShadowMap>(resolution);
@@ -489,9 +496,6 @@ void WorldRenderer::draw(
display::clearDepth();
// Drawing background sky plane
skybox->draw(pctx, camera, assets, worldInfo.daytime, clouds);
/* Actually world render with depth buffer on */ {
DrawContext ctx = wctx.sub();
ctx.setDepthTest(true);
@@ -506,19 +510,32 @@ void WorldRenderer::draw(
}
}
}
{
DrawContext ctx = wctx.sub();
texts->render(ctx, camera, settings, hudVisible, true);
}
texts->render(pctx, camera, settings, hudVisible, true);
}
skybox->bind();
deferredShader.use();
float fogFactor =
15.0f / static_cast<float>(settings.chunks.loadDistance.get() - 2);
setupWorldShader(deferredShader, camera, settings, fogFactor);
postProcessing.render(
pctx,
assets,
timer,
camera,
shadows ? shadowMap->getDepthMap() : 0
shadows ? shadowMap->getDepthMap() : 0,
shadows ? wideShadowMap->getDepthMap() : 0,
shadowCamera.getProjView(),
wideShadowCamera.getProjView(),
shadows ? shadowMap->getResolution() : 0
);
{
DrawContext ctx = pctx.sub();
ctx.setDepthTest(true);
postProcessing.bindDepthBuffer();
// Drawing background sky plane
skybox->draw(ctx, camera, assets, worldInfo.daytime, clouds);
}
skybox->unbind();
if (player.currentCamera == player.fpCamera) {
DrawContext ctx = pctx.sub();
ctx.setDepthTest(true);
+1 -1
View File
@@ -19,7 +19,7 @@ public:
bool perspective = true;
bool flipped = false;
float near = 0.05f;
float far = 1500.0f;
float far = 1e4f;
bool projset = false;
glm::mat4 projection;