feat: deferred lighting (WIP)
This commit is contained in:
parent
2ad076bec3
commit
e849d5e9b7
@ -14,6 +14,10 @@
|
|||||||
{
|
{
|
||||||
"name": "ssao",
|
"name": "ssao",
|
||||||
"advanced": true
|
"advanced": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "deferred_lighting",
|
||||||
|
"advanced": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"textures": [
|
"textures": [
|
||||||
|
|||||||
@ -1,14 +1,14 @@
|
|||||||
local function configure_SSAO()
|
local function configure_SSAO()
|
||||||
local slot = gfx.posteffects.index("core:default")
|
local slot = gfx.posteffects.index("core:default")
|
||||||
gfx.posteffects.set_effect(slot, "ssao")
|
gfx.posteffects.set_effect(slot, "ssao")
|
||||||
gfx.posteffects.set_intensity(slot, 1.0)
|
-- gfx.posteffects.set_intensity(slot, 1.0)
|
||||||
|
|
||||||
-- Generating random SSAO samples
|
-- Generating random SSAO samples
|
||||||
local buffer = Bytearray(0)
|
local buffer = Bytearray(0)
|
||||||
for i = 0, 63 do
|
for i = 0, 63 do
|
||||||
local x = math.random() * 2.0 - 1.0
|
local x = math.random() * 2.0 - 1.0
|
||||||
local y = math.random() * 2.0 - 1.0
|
local y = math.random() * 2.0 - 1.0
|
||||||
local z = math.random()
|
local z = math.random() * 2.0
|
||||||
local len = math.sqrt(x * x + y * y + z * z)
|
local len = math.sqrt(x * x + y * y + z * z)
|
||||||
if len > 0 then
|
if len > 0 then
|
||||||
x = x / len
|
x = x / len
|
||||||
@ -77,4 +77,6 @@ function on_hud_open()
|
|||||||
player.set_vel(pid, 0, 1, 0)
|
player.set_vel(pid, 0, 1, 0)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
configure_SSAO()
|
||||||
end
|
end
|
||||||
|
|||||||
@ -5,6 +5,7 @@ uniform sampler2D u_screen;
|
|||||||
uniform sampler2D u_position;
|
uniform sampler2D u_position;
|
||||||
uniform sampler2D u_normal;
|
uniform sampler2D u_normal;
|
||||||
uniform sampler2D u_noise;
|
uniform sampler2D u_noise;
|
||||||
|
uniform sampler2D u_ssao;
|
||||||
uniform sampler2D u_shadows;
|
uniform sampler2D u_shadows;
|
||||||
|
|
||||||
uniform ivec2 u_screenSize;
|
uniform ivec2 u_screenSize;
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
vec4 effect() {
|
vec4 effect() {
|
||||||
//return vec4(vec3(pow(texture(u_shadows, v_uv).r, 5.0) * 1000.0), 1.0);
|
|
||||||
return texture(u_screen, v_uv);
|
return texture(u_screen, v_uv);
|
||||||
}
|
}
|
||||||
|
|||||||
11
res/shaders/effects/deferred_lighting.glsl
Normal file
11
res/shaders/effects/deferred_lighting.glsl
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
vec4 effect() {
|
||||||
|
float ssao = 0.0;
|
||||||
|
for (int y = -1; y <= 1; y++) {
|
||||||
|
for (int x = -1; x <= 1; x++) {
|
||||||
|
vec2 offset = vec2(x, y) / u_screenSize;
|
||||||
|
ssao += texture(u_ssao, v_uv + offset * 2.0).r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ssao /= 9.0;
|
||||||
|
return vec4(texture(u_screen, v_uv).rgb * mix(1.0, ssao, 1.0), 1.0);
|
||||||
|
}
|
||||||
@ -1,13 +1,12 @@
|
|||||||
#param vec3 u_ssaoSamples[64]
|
#param vec3 u_ssaoSamples[64]
|
||||||
#param int u_kernelSize = 16
|
#param int u_kernelSize = 16
|
||||||
#param float u_radius = 0.25
|
#param float u_radius = 0.2
|
||||||
#param float u_bias = 0.025
|
#param float u_bias = 0.006
|
||||||
|
|
||||||
vec4 effect() {
|
vec4 effect() {
|
||||||
vec2 noiseScale = u_screenSize / 4.0;
|
vec2 noiseScale = u_screenSize / 4.0;
|
||||||
|
|
||||||
vec3 position = texture(u_position, v_uv).xyz;
|
vec3 position = texture(u_position, v_uv).xyz;
|
||||||
vec3 color = texture(u_screen, v_uv).rgb;
|
|
||||||
vec3 normal = texture(u_normal, v_uv).xyz;
|
vec3 normal = texture(u_normal, v_uv).xyz;
|
||||||
vec3 randomVec = normalize(texture(u_noise, v_uv * noiseScale).xyz);
|
vec3 randomVec = normalize(texture(u_noise, v_uv * noiseScale).xyz);
|
||||||
|
|
||||||
@ -31,7 +30,7 @@ vec4 effect() {
|
|||||||
}
|
}
|
||||||
occlusion = min(1.0, 1.05 - (occlusion / u_kernelSize));
|
occlusion = min(1.0, 1.05 - (occlusion / u_kernelSize));
|
||||||
|
|
||||||
float z = -position.z * 0.02;
|
float z = -position.z * 0.01;
|
||||||
z = max(0.0, 1.0 - z);
|
z = max(0.0, 1.0 - z);
|
||||||
return vec4(color * mix(1.0, occlusion, z), 1.0);
|
return vec4(occlusion, 0.0, 0.0, 1.0);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -84,6 +84,26 @@ void GBuffer::createDepthBuffer() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GBuffer::createSSAOBuffer() {
|
||||||
|
glGenTextures(1, &ssaoBuffer);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, ssaoBuffer);
|
||||||
|
glTexImage2D(
|
||||||
|
GL_TEXTURE_2D,
|
||||||
|
0,
|
||||||
|
GL_R16F,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
0,
|
||||||
|
GL_RED,
|
||||||
|
GL_FLOAT,
|
||||||
|
nullptr
|
||||||
|
);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
}
|
||||||
|
|
||||||
GBuffer::GBuffer(uint width, uint height) : width(width), height(height) {
|
GBuffer::GBuffer(uint width, uint height) : width(width), height(height) {
|
||||||
glGenFramebuffers(1, &fbo);
|
glGenFramebuffers(1, &fbo);
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||||
@ -100,7 +120,20 @@ GBuffer::GBuffer(uint width, uint height) : width(width), height(height) {
|
|||||||
createDepthBuffer();
|
createDepthBuffer();
|
||||||
|
|
||||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
||||||
logger.error() << "framebuffer is not complete!";
|
logger.error() << "gbuffer is not complete!";
|
||||||
|
}
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
|
||||||
|
glGenFramebuffers(1, &ssaoFbo);
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, ssaoFbo);
|
||||||
|
createSSAOBuffer();
|
||||||
|
glFramebufferTexture2D(
|
||||||
|
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ssaoBuffer, 0
|
||||||
|
);
|
||||||
|
GLenum ssaoAttachments[1] = {GL_COLOR_ATTACHMENT0};
|
||||||
|
glDrawBuffers(1, ssaoAttachments);
|
||||||
|
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
||||||
|
logger.error() << "SSAO framebuffer is not complete!";
|
||||||
}
|
}
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
}
|
}
|
||||||
@ -109,8 +142,10 @@ GBuffer::~GBuffer() {
|
|||||||
glDeleteTextures(1, &colorBuffer);
|
glDeleteTextures(1, &colorBuffer);
|
||||||
glDeleteTextures(1, &positionsBuffer);
|
glDeleteTextures(1, &positionsBuffer);
|
||||||
glDeleteTextures(1, &normalsBuffer);
|
glDeleteTextures(1, &normalsBuffer);
|
||||||
|
glDeleteTextures(1, &ssaoBuffer);
|
||||||
glDeleteRenderbuffers(1, &depthBuffer);
|
glDeleteRenderbuffers(1, &depthBuffer);
|
||||||
glDeleteFramebuffers(1, &fbo);
|
glDeleteFramebuffers(1, &fbo);
|
||||||
|
glDeleteFramebuffers(1, &ssaoFbo);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GBuffer::bind() {
|
void GBuffer::bind() {
|
||||||
@ -118,6 +153,11 @@ void GBuffer::bind() {
|
|||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GBuffer::bindSSAO() const {
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, ssaoFbo);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
void GBuffer::unbind() {
|
void GBuffer::unbind() {
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
}
|
}
|
||||||
@ -133,6 +173,10 @@ void GBuffer::bindBuffers() const {
|
|||||||
glBindTexture(GL_TEXTURE_2D, colorBuffer);
|
glBindTexture(GL_TEXTURE_2D, colorBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GBuffer::bindSSAOBuffer() const {
|
||||||
|
glBindTexture(GL_TEXTURE_2D, ssaoBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
void GBuffer::resize(uint width, uint height) {
|
void GBuffer::resize(uint width, uint height) {
|
||||||
if (this->width == width && this->height == height) {
|
if (this->width == width && this->height == height) {
|
||||||
return;
|
return;
|
||||||
@ -180,6 +224,17 @@ void GBuffer::resize(uint width, uint height) {
|
|||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, ssaoFbo);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, ssaoBuffer);
|
||||||
|
glTexImage2D(
|
||||||
|
GL_TEXTURE_2D, 0, GL_R16F, width, height, 0, GL_RED, GL_FLOAT, nullptr
|
||||||
|
);
|
||||||
|
glFramebufferTexture2D(
|
||||||
|
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ssaoBuffer, 0
|
||||||
|
);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<ImageData> GBuffer::toImage() const {
|
std::unique_ptr<ImageData> GBuffer::toImage() const {
|
||||||
|
|||||||
@ -10,9 +10,11 @@ public:
|
|||||||
~GBuffer() override;
|
~GBuffer() override;
|
||||||
|
|
||||||
void bind() override;
|
void bind() override;
|
||||||
|
void bindSSAO() const;
|
||||||
void unbind() override;
|
void unbind() override;
|
||||||
|
|
||||||
void bindBuffers() const;
|
void bindBuffers() const;
|
||||||
|
void bindSSAOBuffer() const;
|
||||||
|
|
||||||
void resize(uint width, uint height);
|
void resize(uint width, uint height);
|
||||||
|
|
||||||
@ -29,9 +31,12 @@ private:
|
|||||||
uint positionsBuffer;
|
uint positionsBuffer;
|
||||||
uint normalsBuffer;
|
uint normalsBuffer;
|
||||||
uint depthBuffer;
|
uint depthBuffer;
|
||||||
|
uint ssaoFbo;
|
||||||
|
uint ssaoBuffer;
|
||||||
|
|
||||||
void createColorBuffer();
|
void createColorBuffer();
|
||||||
void createPositionsBuffer();
|
void createPositionsBuffer();
|
||||||
void createNormalsBuffer();
|
void createNormalsBuffer();
|
||||||
void createDepthBuffer();
|
void createDepthBuffer();
|
||||||
|
void createSSAOBuffer();
|
||||||
};
|
};
|
||||||
|
|||||||
@ -88,7 +88,9 @@ void PostProcessing::configureEffect(
|
|||||||
shader.uniform1i("u_position", 1);
|
shader.uniform1i("u_position", 1);
|
||||||
shader.uniform1i("u_normal", 2);
|
shader.uniform1i("u_normal", 2);
|
||||||
}
|
}
|
||||||
shader.uniform1i("u_noise", 3);
|
shader.uniform1i("u_noise", 3); // used in SSAO pass
|
||||||
|
shader.uniform1i("u_ssao", 3);
|
||||||
|
|
||||||
shader.uniform1i("u_shadows", 4);
|
shader.uniform1i("u_shadows", 4);
|
||||||
shader.uniform2i("u_screenSize", viewport);
|
shader.uniform2i("u_screenSize", viewport);
|
||||||
shader.uniform1f("u_timer", timer);
|
shader.uniform1f("u_timer", timer);
|
||||||
@ -126,13 +128,25 @@ void PostProcessing::render(
|
|||||||
glBindTexture(GL_TEXTURE_2D, noiseTexture);
|
glBindTexture(GL_TEXTURE_2D, noiseTexture);
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
|
||||||
|
auto& ssaoEffect = assets.require<PostEffect>("ssao");
|
||||||
|
auto& shader = ssaoEffect.use();
|
||||||
|
configureEffect(context, ssaoEffect, shader, timer, camera, shadowMap);
|
||||||
|
gbuffer->bindSSAO();
|
||||||
|
quadMesh->draw();
|
||||||
|
gbuffer->unbind();
|
||||||
|
|
||||||
|
glActiveTexture(GL_TEXTURE3);
|
||||||
|
gbuffer->bindSSAOBuffer();
|
||||||
} else {
|
} else {
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
fbo->getTexture()->bind();
|
fbo->getTexture()->bind();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (totalPasses == 0) {
|
if (totalPasses == 0) {
|
||||||
auto& effect = assets.require<PostEffect>("default");
|
auto& effect = assets.require<PostEffect>(
|
||||||
|
gbuffer ? "deferred_lighting" : "default"
|
||||||
|
);
|
||||||
auto& shader = effect.use();
|
auto& shader = effect.use();
|
||||||
configureEffect(context, effect, shader, timer, camera, shadowMap);
|
configureEffect(context, effect, shader, timer, camera, shadowMap);
|
||||||
quadMesh->draw();
|
quadMesh->draw();
|
||||||
|
|||||||
@ -17,7 +17,10 @@ static int l_set_effect(lua::State* L) {
|
|||||||
size_t index = static_cast<size_t>(lua::tointeger(L, 1));
|
size_t index = static_cast<size_t>(lua::tointeger(L, 1));
|
||||||
auto name = lua::require_string(L, 2);
|
auto name = lua::require_string(L, 2);
|
||||||
auto& assets = *engine->getAssets();
|
auto& assets = *engine->getAssets();
|
||||||
auto effect = std::make_shared<PostEffect>(assets.require<PostEffect>(name));
|
auto effect = assets.getShared<PostEffect>(name);
|
||||||
|
if (effect == nullptr) {
|
||||||
|
throw std::runtime_error(std::string("post-effect '") + name + "' not found");
|
||||||
|
}
|
||||||
post_processing->setEffect(index, std::move(effect));
|
post_processing->setEffect(index, std::move(effect));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user