initial commit
This commit is contained in:
parent
27b194816b
commit
fc46b7c434
@ -6,10 +6,12 @@
|
||||
"lines",
|
||||
"entity",
|
||||
"background",
|
||||
"skybox_gen"
|
||||
"skybox_gen",
|
||||
"shadows"
|
||||
],
|
||||
"post-effects": [
|
||||
"default"
|
||||
"default",
|
||||
"ssao"
|
||||
],
|
||||
"textures": [
|
||||
"gui/menubg",
|
||||
|
||||
@ -4,5 +4,8 @@
|
||||
"third-person-front",
|
||||
"third-person-back",
|
||||
"cinematic"
|
||||
],
|
||||
"post-effect-slot": [
|
||||
"default"
|
||||
]
|
||||
}
|
||||
|
||||
@ -55,4 +55,8 @@ function on_hud_open()
|
||||
player.set_vel(pid, 0, 1, 0)
|
||||
end
|
||||
end)
|
||||
|
||||
local slot = gfx.posteffects.index("core:default")
|
||||
gfx.posteffects.set_effect(slot, "ssao")
|
||||
--gfx.posteffects.set_intensity(slot, 1.0)
|
||||
end
|
||||
|
||||
@ -1,9 +1,13 @@
|
||||
in vec3 v_coord;
|
||||
out vec4 f_color;
|
||||
layout (location = 0) out vec4 f_color;
|
||||
layout (location = 1) out vec4 f_position;
|
||||
layout (location = 2) out vec4 f_normal;
|
||||
|
||||
uniform samplerCube u_cubemap;
|
||||
|
||||
void main(){
|
||||
vec3 dir = normalize(v_coord);
|
||||
f_position = vec4(100000.0);
|
||||
f_normal = vec4(0.0);
|
||||
f_color = texture(u_cubemap, dir);
|
||||
}
|
||||
|
||||
@ -2,8 +2,15 @@ in vec2 v_uv;
|
||||
out vec4 f_color;
|
||||
|
||||
uniform sampler2D u_screen;
|
||||
uniform sampler2D u_position;
|
||||
uniform sampler2D u_normal;
|
||||
uniform sampler2D u_noise;
|
||||
uniform sampler2D u_shadows;
|
||||
|
||||
uniform ivec2 u_screenSize;
|
||||
uniform float u_intensity;
|
||||
uniform float u_timer;
|
||||
uniform mat4 u_projection;
|
||||
|
||||
#include <__effect__>
|
||||
|
||||
|
||||
@ -1,3 +1,50 @@
|
||||
vec4 effect() {
|
||||
return texture(u_screen, v_uv);
|
||||
uniform vec3 samples[64];
|
||||
|
||||
int kernelSize = 32;
|
||||
float radius = 0.25;
|
||||
float bias = 0.025;
|
||||
|
||||
float near_plane = 0.5f;
|
||||
float far_plane = 200.0f;
|
||||
|
||||
// required when using a perspective projection matrix
|
||||
float linearize_depth(float depth) {
|
||||
float z = depth * 2.0 - 1.0; // Back to NDC
|
||||
return (2.0 * near_plane * far_plane) / (far_plane + near_plane - z * (far_plane - near_plane));
|
||||
}
|
||||
|
||||
float fmod(float x, float y) {
|
||||
return x - y * floor(x/y);
|
||||
}
|
||||
|
||||
vec4 effect() {
|
||||
vec2 noiseScale = u_screenSize / 4.0;
|
||||
|
||||
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 randomVec = normalize(texture(u_noise, v_uv * noiseScale).xyz);
|
||||
|
||||
vec3 tangent = normalize(randomVec - normal * dot(randomVec, normal));
|
||||
vec3 bitangent = cross(normal, tangent);
|
||||
mat3 TBN = mat3(tangent, bitangent, normal);
|
||||
|
||||
float occlusion = 0.0;
|
||||
for(int i = 0; i < kernelSize; ++i)
|
||||
{
|
||||
vec3 samplePos = TBN * samples[i];
|
||||
samplePos = position + samplePos * radius;
|
||||
|
||||
vec4 offset = vec4(samplePos, 1.0);
|
||||
offset = u_projection * offset;
|
||||
offset.xyz /= offset.w;
|
||||
offset.xyz = offset.xyz * 0.5 + 0.5;
|
||||
|
||||
float sampleDepth = texture(u_position, offset.xy).z;
|
||||
float rangeCheck = smoothstep(0.0, 1.0, radius / abs(position.z - sampleDepth));
|
||||
occlusion += (sampleDepth >= samplePos.z + bias ? 1.0 : 0.0) * rangeCheck;
|
||||
}
|
||||
occlusion = 1.1 - (occlusion / kernelSize);
|
||||
float d = texture(u_shadows, v_uv).r;
|
||||
return vec4(color * occlusion, 1.0);
|
||||
}
|
||||
|
||||
11
res/shaders/effects/ssao.glsl
Normal file
11
res/shaders/effects/ssao.glsl
Normal file
@ -0,0 +1,11 @@
|
||||
uniform vec3 samples[64];
|
||||
|
||||
vec4 effect() {
|
||||
vec2 noiseScale = u_screenSize / 4.0;
|
||||
|
||||
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 randomVec = texture(u_noise, v_uv * noiseScale).xyz;
|
||||
return vec4(randomVec, 1.0);
|
||||
}
|
||||
@ -1,8 +1,13 @@
|
||||
in vec4 a_color;
|
||||
in vec2 a_texCoord;
|
||||
in vec3 a_position;
|
||||
in vec3 a_dir;
|
||||
in vec3 a_normal;
|
||||
in float a_fog;
|
||||
out vec4 f_color;
|
||||
|
||||
layout (location = 0) out vec4 f_color;
|
||||
layout (location = 1) out vec4 f_position;
|
||||
layout (location = 2) out vec4 f_normal;
|
||||
|
||||
uniform sampler2D u_texture0;
|
||||
uniform samplerCube u_cubemap;
|
||||
@ -20,4 +25,6 @@ void main() {
|
||||
discard;
|
||||
f_color = mix(a_color * tex_color, vec4(fogColor,1.0), a_fog);
|
||||
f_color.a = alpha;
|
||||
f_position = vec4(a_position, 1.0);
|
||||
f_normal = vec4(a_normal, 1.0);
|
||||
}
|
||||
|
||||
@ -7,7 +7,9 @@ layout (location = 3) in vec4 v_light;
|
||||
|
||||
out vec4 a_color;
|
||||
out vec2 a_texCoord;
|
||||
out vec3 a_normal;
|
||||
out float a_fog;
|
||||
out vec3 a_position;
|
||||
out vec3 a_dir;
|
||||
|
||||
uniform mat4 u_model;
|
||||
@ -31,6 +33,8 @@ void main() {
|
||||
vec3 pos3d = modelpos.xyz - u_cameraPos;
|
||||
modelpos.xyz = apply_planet_curvature(modelpos.xyz, pos3d);
|
||||
|
||||
a_normal = vec3(0.0, 1.0, 0.0);//v_normal.xyz * 2.0 - 1.0;
|
||||
|
||||
vec3 light = v_light.rgb;
|
||||
float torchlight = max(0.0, 1.0-distance(u_cameraPos, modelpos.xyz) /
|
||||
u_torchlightDistance);
|
||||
@ -48,4 +52,6 @@ void main() {
|
||||
a_fog = min(1.0, max(pow(depth * u_fogFactor, u_fogCurve),
|
||||
min(pow(depth * u_weatherFogDencity, u_weatherFogCurve), u_weatherFogOpacity)));
|
||||
gl_Position = u_proj * u_view * modelpos;
|
||||
|
||||
a_position = (u_view * modelpos).xyz;
|
||||
}
|
||||
|
||||
@ -1,19 +1,53 @@
|
||||
layout (location = 0) out vec4 f_color;
|
||||
layout (location = 1) out vec4 f_position;
|
||||
layout (location = 2) out vec4 f_normal;
|
||||
|
||||
in vec4 a_color;
|
||||
in vec2 a_texCoord;
|
||||
in float a_fog;
|
||||
in vec3 a_position;
|
||||
in vec3 a_dir;
|
||||
out vec4 f_color;
|
||||
in vec3 a_normal;
|
||||
in vec3 a_realnormal;
|
||||
in vec4 a_modelpos;
|
||||
|
||||
uniform sampler2D u_texture0;
|
||||
uniform samplerCube u_cubemap;
|
||||
uniform sampler2DShadow u_shadows;
|
||||
|
||||
// flags
|
||||
uniform bool u_alphaClip;
|
||||
uniform bool u_debugLights;
|
||||
uniform bool u_debugNormals;
|
||||
uniform bool u_enableShadows;
|
||||
|
||||
uniform mat4 u_shadowsMatrix;
|
||||
|
||||
const int BLUR_SAMPLES = 6;
|
||||
|
||||
void main() {
|
||||
float shadow = 1.0;
|
||||
if (u_enableShadows) {
|
||||
vec4 mpos = u_shadowsMatrix * vec4(a_modelpos.xyz, 1.0);
|
||||
vec3 projCoords = mpos.xyz / mpos.w;
|
||||
projCoords = projCoords * 0.5 + 0.5;
|
||||
projCoords.z -= 0.0001;
|
||||
|
||||
shadow = 0.0;
|
||||
|
||||
for (int i = 0; i < BLUR_SAMPLES; i++) {
|
||||
shadow += texture(u_shadows, projCoords.xyz + vec3(
|
||||
-0.002*(i%2==0?1:0)*i/BLUR_SAMPLES,
|
||||
-0.002*(i%2==0?0:1)*i/BLUR_SAMPLES,
|
||||
-0.0005 * i/BLUR_SAMPLES));
|
||||
}
|
||||
shadow /= BLUR_SAMPLES;
|
||||
shadow += 0.5;
|
||||
shadow = shadow * 0.7 + 0.3;
|
||||
}
|
||||
|
||||
vec3 fogColor = texture(u_cubemap, a_dir).rgb;
|
||||
vec4 tex_color = texture(u_texture0, a_texCoord);
|
||||
if (u_debugLights)
|
||||
tex_color.rgb = vec3(1.0);
|
||||
float alpha = a_color.a * tex_color.a;
|
||||
if (u_alphaClip) {
|
||||
if (alpha < 0.2f)
|
||||
@ -23,6 +57,14 @@ void main() {
|
||||
if (alpha < 0.002f)
|
||||
discard;
|
||||
}
|
||||
if (u_debugLights)
|
||||
tex_color.rgb = u_debugNormals ? (a_normal * 0.5 + 0.5) : vec3(1.0);
|
||||
else if (u_debugNormals) {
|
||||
tex_color.rgb *= a_normal * 0.5 + 0.5;
|
||||
}
|
||||
f_color = mix(a_color * tex_color, vec4(fogColor,1.0), a_fog);
|
||||
f_color.rgb *= shadow;
|
||||
f_color.a = alpha;
|
||||
f_position = vec4(a_position, 1.0);
|
||||
f_normal = vec4(a_normal, 1.0);
|
||||
}
|
||||
|
||||
@ -3,12 +3,17 @@
|
||||
layout (location = 0) in vec3 v_position;
|
||||
layout (location = 1) in vec2 v_texCoord;
|
||||
layout (location = 2) in vec4 v_light;
|
||||
layout (location = 3) in vec4 v_normal;
|
||||
|
||||
out vec4 a_color;
|
||||
out vec2 a_texCoord;
|
||||
out vec3 a_normal;
|
||||
out float a_distance;
|
||||
out float a_fog;
|
||||
out vec3 a_position;
|
||||
out vec4 a_modelpos;
|
||||
out vec3 a_dir;
|
||||
out vec3 a_realnormal;
|
||||
|
||||
uniform mat4 u_model;
|
||||
uniform mat4 u_proj;
|
||||
@ -25,12 +30,19 @@ uniform samplerCube u_cubemap;
|
||||
|
||||
uniform vec3 u_torchlightColor;
|
||||
uniform float u_torchlightDistance;
|
||||
uniform bool u_enableShadows;
|
||||
|
||||
void main() {
|
||||
vec4 modelpos = u_model * vec4(v_position, 1.0f);
|
||||
vec3 pos3d = modelpos.xyz-u_cameraPos;
|
||||
modelpos.xyz = apply_planet_curvature(modelpos.xyz, pos3d);
|
||||
|
||||
a_realnormal = v_normal.xyz;
|
||||
mat3 normalMatrix = transpose(inverse(mat3(u_view * u_model)));
|
||||
a_normal = v_normal.xyz * 2.0 - 1.0;
|
||||
a_normal = normalMatrix * (false ? -a_normal : a_normal);
|
||||
//a_normal = v_normal.xyz * 2.0 - 1.0;
|
||||
|
||||
vec3 light = v_light.rgb;
|
||||
float torchlight = max(0.0, 1.0-distance(u_cameraPos, modelpos.xyz) /
|
||||
u_torchlightDistance);
|
||||
@ -47,4 +59,7 @@ void main() {
|
||||
a_fog = min(1.0, max(pow(depth * u_fogFactor, u_fogCurve),
|
||||
min(pow(depth * u_weatherFogDencity, u_weatherFogCurve), u_weatherFogOpacity)));
|
||||
gl_Position = u_proj * u_view * modelpos;
|
||||
|
||||
a_position = (u_view * modelpos).xyz;
|
||||
a_modelpos = modelpos;
|
||||
}
|
||||
|
||||
11
res/shaders/shadows.glslf
Normal file
11
res/shaders/shadows.glslf
Normal file
@ -0,0 +1,11 @@
|
||||
in vec2 a_texCoord;
|
||||
|
||||
uniform sampler2D u_texture0;
|
||||
|
||||
void main() {
|
||||
vec4 tex_color = texture(u_texture0, a_texCoord);
|
||||
if (tex_color.a < 0.5) {
|
||||
discard;
|
||||
}
|
||||
// depth will be written anyway
|
||||
}
|
||||
17
res/shaders/shadows.glslv
Normal file
17
res/shaders/shadows.glslv
Normal file
@ -0,0 +1,17 @@
|
||||
#include <commons>
|
||||
|
||||
layout (location = 0) in vec3 v_position;
|
||||
layout (location = 1) in vec2 v_texCoord;
|
||||
layout (location = 2) in vec4 v_light;
|
||||
layout (location = 3) in vec4 v_normal;
|
||||
|
||||
out vec2 a_texCoord;
|
||||
|
||||
uniform mat4 u_model;
|
||||
uniform mat4 u_proj;
|
||||
uniform mat4 u_view;
|
||||
|
||||
void main() {
|
||||
a_texCoord = v_texCoord;
|
||||
gl_Position = u_proj * u_view * u_model * vec4(v_position, 1.0f);
|
||||
}
|
||||
@ -178,6 +178,8 @@ Hud::Hud(Engine& engine, LevelFrontend& frontend, Player& player)
|
||||
uicamera = std::make_unique<Camera>(glm::vec3(), 1);
|
||||
uicamera->perspective = false;
|
||||
uicamera->flipped = true;
|
||||
uicamera->near = -1.0f;
|
||||
uicamera->far = 1.0f;
|
||||
|
||||
debugPanel = create_debug_panel(
|
||||
engine, frontend.getLevel(), player, allowDebugCheats
|
||||
|
||||
@ -22,6 +22,8 @@ MenuScreen::MenuScreen(Engine& engine) : Screen(engine) {
|
||||
uicamera =
|
||||
std::make_unique<Camera>(glm::vec3(), engine.getWindow().getSize().y);
|
||||
uicamera->perspective = false;
|
||||
uicamera->near = -1.0f;
|
||||
uicamera->far = 1.0f;
|
||||
uicamera->flipped = true;
|
||||
}
|
||||
|
||||
|
||||
@ -100,7 +100,7 @@ void DrawContext::setViewport(const glm::uvec2& viewport) {
|
||||
glViewport(0, 0, viewport.x, viewport.y);
|
||||
}
|
||||
|
||||
void DrawContext::setFramebuffer(Framebuffer* fbo) {
|
||||
void DrawContext::setFramebuffer(Bindable* fbo) {
|
||||
if (this->fbo == fbo)
|
||||
return;
|
||||
this->fbo = fbo;
|
||||
|
||||
@ -16,7 +16,7 @@ class DrawContext {
|
||||
glm::uvec2 viewport;
|
||||
Batch2D* g2d;
|
||||
Flushable* flushable = nullptr;
|
||||
Framebuffer* fbo = nullptr;
|
||||
Bindable* fbo = nullptr;
|
||||
bool depthMask = true;
|
||||
bool depthTest = false;
|
||||
bool cullFace = false;
|
||||
@ -37,7 +37,7 @@ public:
|
||||
DrawContext sub(Flushable* flushable=nullptr) const;
|
||||
|
||||
void setViewport(const glm::uvec2& viewport);
|
||||
void setFramebuffer(Framebuffer* fbo);
|
||||
void setFramebuffer(Bindable* fbo);
|
||||
void setDepthMask(bool flag);
|
||||
void setDepthTest(bool flag);
|
||||
void setCullFace(bool flag);
|
||||
|
||||
@ -2,6 +2,9 @@
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include "Texture.hpp"
|
||||
#include "debug/Logger.hpp"
|
||||
|
||||
static debug::Logger logger("gl-framebuffer");
|
||||
|
||||
Framebuffer::Framebuffer(uint fbo, uint depth, std::unique_ptr<Texture> texture)
|
||||
: fbo(fbo), depth(depth), texture(std::move(texture))
|
||||
@ -39,17 +42,40 @@ Framebuffer::Framebuffer(uint width, uint height, bool alpha)
|
||||
// Setup color attachment (texture)
|
||||
texture = create_texture(width, height, format);
|
||||
|
||||
glGenTextures(1, &positions);
|
||||
glBindTexture(GL_TEXTURE_2D, positions);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, NULL);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, positions, 0);
|
||||
|
||||
glGenTextures(1, &normals);
|
||||
glBindTexture(GL_TEXTURE_2D, normals);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, NULL);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, normals, 0);
|
||||
|
||||
unsigned int attachments[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
|
||||
glDrawBuffers(3, attachments);
|
||||
|
||||
// Setup depth attachment
|
||||
glGenRenderbuffers(1, &depth);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, depth);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth);
|
||||
|
||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
||||
logger.error() << "framebuffer is not complete!";
|
||||
}
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
Framebuffer::~Framebuffer() {
|
||||
glDeleteFramebuffers(1, &fbo);
|
||||
glDeleteRenderbuffers(1, &depth);
|
||||
glDeleteTextures(1, &normals);
|
||||
glDeleteTextures(1, &depth);
|
||||
}
|
||||
|
||||
void Framebuffer::bind() {
|
||||
@ -60,6 +86,19 @@ void Framebuffer::unbind() {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
void Framebuffer::bindBuffers() {
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, texture->getId());
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, positions);
|
||||
|
||||
glActiveTexture(GL_TEXTURE2);
|
||||
glBindTexture(GL_TEXTURE_2D, normals);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
|
||||
void Framebuffer::resize(uint width, uint height) {
|
||||
if (this->width == width && this->height == height) {
|
||||
return;
|
||||
@ -67,11 +106,22 @@ void Framebuffer::resize(uint width, uint height) {
|
||||
this->width = width;
|
||||
this->height = height;
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, depth);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
glBindTexture(GL_TEXTURE_2D, positions);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, width, height, 0, GL_RGB, GL_FLOAT, NULL);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, positions, 0);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, normals);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, width, height, 0, GL_RGB, GL_FLOAT, NULL);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, normals, 0);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
texture = create_texture(width, height, format);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
@ -1,14 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include "typedefs.hpp"
|
||||
#include "commons.hpp"
|
||||
|
||||
#include <memory>
|
||||
|
||||
class Texture;
|
||||
|
||||
class Framebuffer {
|
||||
class Framebuffer : public Bindable {
|
||||
uint fbo;
|
||||
uint depth;
|
||||
uint positions;
|
||||
uint normals;
|
||||
uint width;
|
||||
uint height;
|
||||
uint format;
|
||||
@ -19,10 +22,12 @@ public:
|
||||
~Framebuffer();
|
||||
|
||||
/// @brief Use framebuffer
|
||||
void bind();
|
||||
void bind() override;
|
||||
|
||||
/// @brief Stop using framebuffer
|
||||
void unbind();
|
||||
void unbind() override;
|
||||
|
||||
void bindBuffers();
|
||||
|
||||
/// @brief Update framebuffer texture size
|
||||
/// @param width new width
|
||||
|
||||
186
src/graphics/core/GBuffer.cpp
Normal file
186
src/graphics/core/GBuffer.cpp
Normal file
@ -0,0 +1,186 @@
|
||||
#include "GBuffer.hpp"
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
||||
#include "debug/Logger.hpp"
|
||||
|
||||
static debug::Logger logger("gl-gbuffer");
|
||||
|
||||
void GBuffer::createColorBuffer() {
|
||||
glGenTextures(1, &colorBuffer);
|
||||
glBindTexture(GL_TEXTURE_2D, colorBuffer);
|
||||
glTexImage2D(
|
||||
GL_TEXTURE_2D,
|
||||
0,
|
||||
GL_RGB,
|
||||
width,
|
||||
height,
|
||||
0,
|
||||
GL_RGB,
|
||||
GL_UNSIGNED_BYTE,
|
||||
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);
|
||||
glFramebufferTexture2D(
|
||||
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBuffer, 0
|
||||
);
|
||||
}
|
||||
|
||||
void GBuffer::createPositionsBuffer() {
|
||||
glGenTextures(1, &positionsBuffer);
|
||||
glBindTexture(GL_TEXTURE_2D, positionsBuffer);
|
||||
glTexImage2D(
|
||||
GL_TEXTURE_2D,
|
||||
0,
|
||||
GL_RGBA16F,
|
||||
width,
|
||||
height,
|
||||
0,
|
||||
GL_RGBA,
|
||||
GL_FLOAT,
|
||||
nullptr
|
||||
);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glFramebufferTexture2D(
|
||||
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, positionsBuffer, 0
|
||||
);
|
||||
}
|
||||
|
||||
void GBuffer::createNormalsBuffer() {
|
||||
glGenTextures(1, &normalsBuffer);
|
||||
glBindTexture(GL_TEXTURE_2D, normalsBuffer);
|
||||
glTexImage2D(
|
||||
GL_TEXTURE_2D,
|
||||
0,
|
||||
GL_RGBA16F,
|
||||
width,
|
||||
height,
|
||||
0,
|
||||
GL_RGBA,
|
||||
GL_FLOAT,
|
||||
nullptr
|
||||
);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glFramebufferTexture2D(
|
||||
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, normalsBuffer, 0
|
||||
);
|
||||
}
|
||||
|
||||
void GBuffer::createDepthBuffer() {
|
||||
glGenRenderbuffers(1, &depthBuffer);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height);
|
||||
glFramebufferRenderbuffer(
|
||||
GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer
|
||||
);
|
||||
}
|
||||
|
||||
GBuffer::GBuffer(uint width, uint height) : width(width), height(height) {
|
||||
glGenFramebuffers(1, &fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
|
||||
createColorBuffer();
|
||||
createPositionsBuffer();
|
||||
createNormalsBuffer();
|
||||
|
||||
GLenum attachments[3] = {
|
||||
GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2
|
||||
};
|
||||
glDrawBuffers(3, attachments);
|
||||
|
||||
createDepthBuffer();
|
||||
|
||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
||||
logger.error() << "framebuffer is not complete!";
|
||||
}
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
GBuffer::~GBuffer() {
|
||||
glDeleteTextures(1, &colorBuffer);
|
||||
glDeleteTextures(1, &positionsBuffer);
|
||||
glDeleteTextures(1, &normalsBuffer);
|
||||
glDeleteRenderbuffers(1, &depthBuffer);
|
||||
glDeleteFramebuffers(1, &fbo);
|
||||
}
|
||||
|
||||
void GBuffer::bind() {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
}
|
||||
|
||||
void GBuffer::unbind() {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
void GBuffer::bindBuffers() {
|
||||
glActiveTexture(GL_TEXTURE2);
|
||||
glBindTexture(GL_TEXTURE_2D, normalsBuffer);
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, positionsBuffer);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, colorBuffer);
|
||||
}
|
||||
|
||||
void GBuffer::resize(uint width, uint height) {
|
||||
if (this->width == width && this->height == height) {
|
||||
return;
|
||||
}
|
||||
this->width = width;
|
||||
this->height = height;
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, colorBuffer);
|
||||
glTexImage2D(
|
||||
GL_TEXTURE_2D,
|
||||
0,
|
||||
GL_RGB,
|
||||
width,
|
||||
height,
|
||||
0,
|
||||
GL_RGB,
|
||||
GL_UNSIGNED_BYTE,
|
||||
nullptr
|
||||
);
|
||||
glFramebufferTexture2D(
|
||||
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBuffer, 0
|
||||
);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, positionsBuffer);
|
||||
glTexImage2D(
|
||||
GL_TEXTURE_2D, 0, GL_RGB16F, width, height, 0, GL_RGB, GL_FLOAT, nullptr
|
||||
);
|
||||
glFramebufferTexture2D(
|
||||
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, positionsBuffer, 0
|
||||
);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, normalsBuffer);
|
||||
glTexImage2D(
|
||||
GL_TEXTURE_2D, 0, GL_RGB16F, width, height, 0, GL_RGB, GL_FLOAT, nullptr
|
||||
);
|
||||
glFramebufferTexture2D(
|
||||
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, normalsBuffer, 0
|
||||
);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
uint GBuffer::getWidth() const {
|
||||
return width;
|
||||
}
|
||||
|
||||
uint GBuffer::getHeight() const {
|
||||
return height;
|
||||
}
|
||||
34
src/graphics/core/GBuffer.hpp
Normal file
34
src/graphics/core/GBuffer.hpp
Normal file
@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include "typedefs.hpp"
|
||||
#include "commons.hpp"
|
||||
|
||||
class GBuffer : public Bindable{
|
||||
public:
|
||||
GBuffer(uint width, uint height);
|
||||
~GBuffer();
|
||||
|
||||
void bind() override;
|
||||
void unbind() override;
|
||||
|
||||
void bindBuffers();
|
||||
|
||||
void resize(uint width, uint height);
|
||||
|
||||
uint getWidth() const;
|
||||
uint getHeight() const;
|
||||
private:
|
||||
uint width;
|
||||
uint height;
|
||||
|
||||
uint fbo;
|
||||
uint colorBuffer;
|
||||
uint positionsBuffer;
|
||||
uint normalsBuffer;
|
||||
uint depthBuffer;
|
||||
|
||||
void createColorBuffer();
|
||||
void createPositionsBuffer();
|
||||
void createNormalsBuffer();
|
||||
void createDepthBuffer();
|
||||
};
|
||||
@ -6,22 +6,56 @@
|
||||
#include "DrawContext.hpp"
|
||||
#include "PostEffect.hpp"
|
||||
#include "assets/Assets.hpp"
|
||||
#include "window/Camera.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <random>
|
||||
|
||||
PostProcessing::PostProcessing(size_t effectSlotsCount)
|
||||
: effectSlots(effectSlotsCount) {
|
||||
// Fullscreen quad mesh bulding
|
||||
PostProcessingVertex meshData[]{
|
||||
{{-1.0f, -1.0f}},
|
||||
{{-1.0f, 1.0f}},
|
||||
{{1.0f, 1.0f}},
|
||||
{{-1.0f, -1.0f}},
|
||||
{{1.0f, 1.0f}},
|
||||
{{1.0f, -1.0f}},
|
||||
PostProcessingVertex meshData[] {
|
||||
{{-1.0f, -1.0f}},
|
||||
{{-1.0f, 1.0f}},
|
||||
{{1.0f, 1.0f}},
|
||||
{{-1.0f, -1.0f}},
|
||||
{{1.0f, 1.0f}},
|
||||
{{1.0f, -1.0f}},
|
||||
};
|
||||
|
||||
quadMesh = std::make_unique<Mesh<PostProcessingVertex>>(meshData, 6);
|
||||
|
||||
std::vector<glm::vec3> ssaoNoise;
|
||||
for (unsigned int i = 0; i < 16; i++)
|
||||
{
|
||||
glm::vec3 noise(
|
||||
(rand() / static_cast<float>(RAND_MAX)) * 2.0 - 1.0,
|
||||
(rand() / static_cast<float>(RAND_MAX)) * 2.0 - 1.0,
|
||||
0.0f);
|
||||
ssaoNoise.push_back(noise);
|
||||
}
|
||||
glGenTextures(1, &noiseTexture);
|
||||
glBindTexture(GL_TEXTURE_2D, noiseTexture);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, 4, 4, 0, GL_RGB, GL_FLOAT, ssaoNoise.data());
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
std::uniform_real_distribution<float> randomFloats(0.0, 1.0);
|
||||
std::default_random_engine generator;
|
||||
for (unsigned int i = 0; i < 64; ++i)
|
||||
{
|
||||
glm::vec3 sample(
|
||||
randomFloats(generator) * 2.0 - 1.0,
|
||||
randomFloats(generator) * 2.0 - 1.0,
|
||||
randomFloats(generator)
|
||||
);
|
||||
sample = glm::normalize(sample);
|
||||
sample *= randomFloats(generator);
|
||||
ssaoKernel.push_back(sample);
|
||||
}
|
||||
}
|
||||
|
||||
PostProcessing::~PostProcessing() = default;
|
||||
@ -39,7 +73,7 @@ void PostProcessing::use(DrawContext& context) {
|
||||
}
|
||||
|
||||
void PostProcessing::render(
|
||||
const DrawContext& context, const Assets& assets, float timer
|
||||
const DrawContext& context, const Assets& assets, float timer, const Camera& camera, uint depthMap
|
||||
) {
|
||||
if (fbo == nullptr) {
|
||||
throw std::runtime_error("'use(...)' was never called");
|
||||
@ -51,8 +85,38 @@ void PostProcessing::render(
|
||||
|
||||
if (totalPasses == 0) {
|
||||
auto& effect = assets.require<PostEffect>("default");
|
||||
effect.use();
|
||||
fbo->getTexture()->bind();
|
||||
fbo->bindBuffers();
|
||||
|
||||
glActiveTexture(GL_TEXTURE3);
|
||||
glBindTexture(GL_TEXTURE_2D, noiseTexture);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
glActiveTexture(GL_TEXTURE4);
|
||||
glBindTexture(GL_TEXTURE_2D, depthMap);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
const auto& viewport = context.getViewport();
|
||||
|
||||
auto& shader = effect.use();
|
||||
if (!ssaoConfigured) {
|
||||
for (unsigned int i = 0; i < 64; ++i) {
|
||||
auto name = "samples["+ std::to_string(i) + "]";
|
||||
shader.uniform3f(name, ssaoKernel[i]);
|
||||
}
|
||||
ssaoConfigured = true;
|
||||
}
|
||||
shader.uniform1i("u_screen", 0);
|
||||
shader.uniform1i("u_position", 1);
|
||||
shader.uniform1i("u_normal", 2);
|
||||
shader.uniform1i("u_noise", 3);
|
||||
shader.uniform1i("u_shadows", 4);
|
||||
shader.uniform2i("u_screenSize", viewport);
|
||||
shader.uniform1f("u_timer", timer);
|
||||
shader.uniform1f("near_plane", camera.near);
|
||||
shader.uniform1f("far_plane", camera.far);
|
||||
shader.uniformMatrix("u_projection", camera.getProjection());
|
||||
|
||||
quadMesh->draw();
|
||||
return;
|
||||
}
|
||||
@ -64,15 +128,25 @@ void PostProcessing::render(
|
||||
}
|
||||
auto& shader = effect->use();
|
||||
|
||||
for (unsigned int i = 0; i < 64; ++i) {
|
||||
shader.uniform3f("samples["+ std::to_string(i) + "]", ssaoKernel[i]);
|
||||
}
|
||||
|
||||
const auto& viewport = context.getViewport();
|
||||
shader.uniform1i("u_screen", 0);
|
||||
shader.uniform1i("u_position", 1);
|
||||
shader.uniform1i("u_normal", 2);
|
||||
shader.uniform1i("u_noise", 3);
|
||||
shader.uniform2i("u_screenSize", viewport);
|
||||
shader.uniform1f("u_timer", timer);
|
||||
|
||||
shader.uniformMatrix("u_projection", camera.getProjView(false));
|
||||
fbo->getTexture()->bind();
|
||||
fbo->bindBuffers();
|
||||
|
||||
if (currentPass < totalPasses) {
|
||||
fboSecond->bind();
|
||||
}
|
||||
|
||||
quadMesh->draw();
|
||||
if (currentPass < totalPasses) {
|
||||
fboSecond->unbind();
|
||||
|
||||
@ -11,6 +11,7 @@ class Framebuffer;
|
||||
class DrawContext;
|
||||
class ImageData;
|
||||
class PostEffect;
|
||||
class Camera;
|
||||
|
||||
struct PostProcessingVertex {
|
||||
glm::vec2 position;
|
||||
@ -30,6 +31,10 @@ class PostProcessing {
|
||||
/// @brief Fullscreen quad mesh as the post-processing canvas
|
||||
std::unique_ptr<Mesh<PostProcessingVertex>> quadMesh;
|
||||
std::vector<std::shared_ptr<PostEffect>> effectSlots;
|
||||
|
||||
std::vector<glm::vec3> ssaoKernel;
|
||||
uint noiseTexture;
|
||||
bool ssaoConfigured = false;
|
||||
public:
|
||||
PostProcessing(size_t effectSlotsCount);
|
||||
~PostProcessing();
|
||||
@ -42,7 +47,7 @@ public:
|
||||
/// with framebuffer texture bound
|
||||
/// @param context graphics context
|
||||
/// @throws std::runtime_error if use(...) wasn't called before
|
||||
void render(const DrawContext& context, const Assets& assets, float timer);
|
||||
void render(const DrawContext& context, const Assets& assets, float timer, const Camera& camera, uint depthMap);
|
||||
|
||||
void setEffect(size_t slot, std::shared_ptr<PostEffect> effect);
|
||||
|
||||
|
||||
47
src/graphics/core/ShadowMap.cpp
Normal file
47
src/graphics/core/ShadowMap.cpp
Normal file
@ -0,0 +1,47 @@
|
||||
#include "ShadowMap.hpp"
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
||||
ShadowMap::ShadowMap(int resolution) : resolution(resolution) {
|
||||
glGenTextures(1, &depthMap);
|
||||
glBindTexture(GL_TEXTURE_2D, depthMap);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT,
|
||||
resolution, resolution, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_BORDER);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
|
||||
float border[4] {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
glTexParameterfv(GL_TEXTURE_2D,GL_TEXTURE_BORDER_COLOR, border);
|
||||
|
||||
glGenFramebuffers(1, &fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthMap, 0);
|
||||
glDrawBuffer(GL_NONE);
|
||||
glReadBuffer(GL_NONE);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
ShadowMap::~ShadowMap() {
|
||||
glDeleteFramebuffers(1, &fbo);
|
||||
glDeleteTextures(1, &depthMap);
|
||||
}
|
||||
|
||||
void ShadowMap::bind() {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
void ShadowMap::unbind() {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
uint ShadowMap::getDepthMap() const {
|
||||
return depthMap;
|
||||
}
|
||||
|
||||
int ShadowMap::getResolution() const {
|
||||
return resolution;
|
||||
}
|
||||
18
src/graphics/core/ShadowMap.hpp
Normal file
18
src/graphics/core/ShadowMap.hpp
Normal file
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include "typedefs.hpp"
|
||||
|
||||
class ShadowMap {
|
||||
public:
|
||||
ShadowMap(int resolution);
|
||||
~ShadowMap();
|
||||
|
||||
void bind();
|
||||
void unbind();
|
||||
uint getDepthMap() const;
|
||||
int getResolution() const;
|
||||
private:
|
||||
uint fbo;
|
||||
uint depthMap;
|
||||
int resolution;
|
||||
};
|
||||
@ -69,3 +69,11 @@ public:
|
||||
|
||||
virtual void flush() = 0;
|
||||
};
|
||||
|
||||
class Bindable {
|
||||
public:
|
||||
virtual ~Bindable() = default;
|
||||
|
||||
virtual void bind() = 0;
|
||||
virtual void unbind() = 0;
|
||||
};
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
#include "frontend/ContentGfxCache.hpp"
|
||||
|
||||
const glm::vec3 BlocksRenderer::SUN_VECTOR(0.528265f, 0.833149f, -0.163704f);
|
||||
const float DIRECTIONAL_LIGHT_FACTOR = 0.3f;
|
||||
const float DIRECTIONAL_LIGHT_FACTOR = 0.2f;
|
||||
|
||||
BlocksRenderer::BlocksRenderer(
|
||||
size_t capacity,
|
||||
@ -39,13 +39,17 @@ BlocksRenderer::~BlocksRenderer() {
|
||||
|
||||
/// Basic vertex add method
|
||||
void BlocksRenderer::vertex(
|
||||
const glm::vec3& coord, float u, float v, const glm::vec4& light
|
||||
const glm::vec3& coord, float u, float v, const glm::vec4& light, const glm::vec3& normal
|
||||
) {
|
||||
|
||||
vertexBuffer[vertexCount].position = coord;
|
||||
|
||||
vertexBuffer[vertexCount].uv = {u,v};
|
||||
|
||||
vertexBuffer[vertexCount].normal[0] = static_cast<uint8_t>(normal.r * 127 + 128);
|
||||
vertexBuffer[vertexCount].normal[1] = static_cast<uint8_t>(normal.g * 127 + 128);
|
||||
vertexBuffer[vertexCount].normal[2] = static_cast<uint8_t>(normal.b * 127 + 128);
|
||||
|
||||
vertexBuffer[vertexCount].color[0] = static_cast<uint8_t>(light.r * 255);
|
||||
vertexBuffer[vertexCount].color[1] = static_cast<uint8_t>(light.g * 255);
|
||||
vertexBuffer[vertexCount].color[2] = static_cast<uint8_t>(light.b * 255);
|
||||
@ -82,10 +86,10 @@ void BlocksRenderer::face(
|
||||
auto Y = axisY * h;
|
||||
auto Z = axisZ * d;
|
||||
float s = 0.5f;
|
||||
vertex(coord + (-X - Y + Z) * s, region.u1, region.v1, lights[0] * tint);
|
||||
vertex(coord + ( X - Y + Z) * s, region.u2, region.v1, lights[1] * tint);
|
||||
vertex(coord + ( X + Y + Z) * s, region.u2, region.v2, lights[2] * tint);
|
||||
vertex(coord + (-X + Y + Z) * s, region.u1, region.v2, lights[3] * tint);
|
||||
vertex(coord + (-X - Y + Z) * s, region.u1, region.v1, lights[0] * tint, axisZ);
|
||||
vertex(coord + ( X - Y + Z) * s, region.u2, region.v1, lights[1] * tint, axisZ);
|
||||
vertex(coord + ( X + Y + Z) * s, region.u2, region.v2, lights[2] * tint, axisZ);
|
||||
vertex(coord + (-X + Y + Z) * s, region.u1, region.v2, lights[3] * tint, axisZ);
|
||||
index(0, 1, 3, 1, 2, 3);
|
||||
}
|
||||
|
||||
@ -103,7 +107,7 @@ void BlocksRenderer::vertexAO(
|
||||
axisX,
|
||||
axisY
|
||||
);
|
||||
vertex(coord, u, v, light * tint);
|
||||
vertex(coord, u, v, light * tint, axisZ);
|
||||
}
|
||||
|
||||
void BlocksRenderer::faceAO(
|
||||
@ -134,11 +138,12 @@ void BlocksRenderer::faceAO(
|
||||
vertexAO(coord + ( X + Y + Z) * s, region.u2, region.v2, tint, axisX, axisY, axisZ);
|
||||
vertexAO(coord + (-X + Y + Z) * s, region.u1, region.v2, tint, axisX, axisY, axisZ);
|
||||
} else {
|
||||
auto axisZ = glm::normalize(Z);
|
||||
glm::vec4 tint(1.0f);
|
||||
vertex(coord + (-X - Y + Z) * s, region.u1, region.v1, tint);
|
||||
vertex(coord + ( X - Y + Z) * s, region.u2, region.v1, tint);
|
||||
vertex(coord + ( X + Y + Z) * s, region.u2, region.v2, tint);
|
||||
vertex(coord + (-X + Y + Z) * s, region.u1, region.v2, tint);
|
||||
vertex(coord + (-X - Y + Z) * s, region.u1, region.v1, tint, axisZ);
|
||||
vertex(coord + ( X - Y + Z) * s, region.u2, region.v1, tint, axisZ);
|
||||
vertex(coord + ( X + Y + Z) * s, region.u2, region.v2, tint, axisZ);
|
||||
vertex(coord + (-X + Y + Z) * s, region.u1, region.v2, tint, axisZ);
|
||||
}
|
||||
index(0, 1, 2, 0, 2, 3);
|
||||
}
|
||||
@ -163,10 +168,10 @@ void BlocksRenderer::face(
|
||||
d = (1.0f - DIRECTIONAL_LIGHT_FACTOR) + d * DIRECTIONAL_LIGHT_FACTOR;
|
||||
tint *= d;
|
||||
}
|
||||
vertex(coord + (-X - Y + Z) * s, region.u1, region.v1, tint);
|
||||
vertex(coord + ( X - Y + Z) * s, region.u2, region.v1, tint);
|
||||
vertex(coord + ( X + Y + Z) * s, region.u2, region.v2, tint);
|
||||
vertex(coord + (-X + Y + Z) * s, region.u1, region.v2, tint);
|
||||
vertex(coord + (-X - Y + Z) * s, region.u1, region.v1, tint, Z);
|
||||
vertex(coord + ( X - Y + Z) * s, region.u2, region.v1, tint, Z);
|
||||
vertex(coord + ( X + Y + Z) * s, region.u2, region.v2, tint, Z);
|
||||
vertex(coord + (-X + Y + Z) * s, region.u1, region.v2, tint, Z);
|
||||
index(0, 1, 2, 0, 2, 3);
|
||||
}
|
||||
|
||||
@ -337,7 +342,8 @@ void BlocksRenderer::blockCustomModel(
|
||||
coord + vcoord.x * X + vcoord.y * Y + vcoord.z * Z,
|
||||
vertex.uv.x,
|
||||
vertex.uv.y,
|
||||
glm::vec4(d, d, d, d) * aoColor
|
||||
glm::vec4(d, d, d, d) * aoColor,
|
||||
n
|
||||
);
|
||||
indexBuffer[indexCount++] = vertexOffset++;
|
||||
}
|
||||
|
||||
@ -44,7 +44,7 @@ class BlocksRenderer {
|
||||
|
||||
SortingMeshData sortingMesh;
|
||||
|
||||
void vertex(const glm::vec3& coord, float u, float v, const glm::vec4& light);
|
||||
void vertex(const glm::vec3& coord, float u, float v, const glm::vec4& light, const glm::vec3& normal);
|
||||
void index(uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint32_t e, uint32_t f);
|
||||
|
||||
void vertexAO(
|
||||
|
||||
@ -143,7 +143,7 @@ void ChunksRenderer::update() {
|
||||
}
|
||||
|
||||
const Mesh<ChunkVertex>* ChunksRenderer::retrieveChunk(
|
||||
size_t index, const Camera& camera, Shader& shader, bool culling
|
||||
size_t index, const Camera& camera, bool culling
|
||||
) {
|
||||
auto chunk = chunks.getChunks()[index];
|
||||
if (chunk == nullptr) {
|
||||
@ -219,7 +219,7 @@ void ChunksRenderer::drawChunks(
|
||||
// TODO: minimize draw calls number
|
||||
for (int i = indices.size()-1; i >= 0; i--) {
|
||||
auto& chunk = chunks.getChunks()[indices[i].index];
|
||||
auto mesh = retrieveChunk(indices[i].index, camera, shader, culling);
|
||||
auto mesh = retrieveChunk(indices[i].index, camera, culling);
|
||||
|
||||
if (mesh) {
|
||||
glm::vec3 coord(
|
||||
|
||||
@ -50,7 +50,7 @@ class ChunksRenderer {
|
||||
std::vector<ChunksSortEntry> indices;
|
||||
util::ThreadPool<std::shared_ptr<Chunk>, RendererResult> threadPool;
|
||||
const Mesh<ChunkVertex>* retrieveChunk(
|
||||
size_t index, const Camera& camera, Shader& shader, bool culling
|
||||
size_t index, const Camera& camera, bool culling
|
||||
);
|
||||
public:
|
||||
ChunksRenderer(
|
||||
|
||||
@ -136,8 +136,8 @@ void Skybox::draw(
|
||||
batch3d->sprite(pos, glm::vec3(0, 0, 1),
|
||||
up, 1, 1, UVRegion(), tint);
|
||||
}
|
||||
|
||||
drawStars(angle, opacity);
|
||||
batch3d->flush();
|
||||
//drawStars(angle, opacity);
|
||||
}
|
||||
|
||||
void Skybox::refresh(const DrawContext& pctx, float t, float mie, uint quality) {
|
||||
|
||||
@ -41,6 +41,8 @@
|
||||
#include "graphics/core/Shader.hpp"
|
||||
#include "graphics/core/Texture.hpp"
|
||||
#include "graphics/core/Font.hpp"
|
||||
#include "graphics/core/ShadowMap.hpp"
|
||||
#include "graphics/core/GBuffer.hpp"
|
||||
#include "BlockWrapsRenderer.hpp"
|
||||
#include "ParticlesRenderer.hpp"
|
||||
#include "PrecipitationRenderer.hpp"
|
||||
@ -100,6 +102,10 @@ WorldRenderer::WorldRenderer(
|
||||
settings.graphics.skyboxResolution.get(),
|
||||
assets->require<Shader>("skybox_gen")
|
||||
);
|
||||
|
||||
shadowMap = std::make_unique<ShadowMap>(1024);
|
||||
|
||||
shadowCamera = std::make_unique<Camera>();
|
||||
}
|
||||
|
||||
WorldRenderer::~WorldRenderer() = default;
|
||||
@ -119,6 +125,7 @@ void WorldRenderer::setupWorldShader(
|
||||
shader.uniform1f("u_fogFactor", fogFactor);
|
||||
shader.uniform1f("u_fogCurve", settings.graphics.fogCurve.get());
|
||||
shader.uniform1i("u_debugLights", lightsDebug);
|
||||
shader.uniform1i("u_debugNormals", false);
|
||||
shader.uniform1f("u_weatherFogOpacity", weather.fogOpacity());
|
||||
shader.uniform1f("u_weatherFogDencity", weather.fogDencity());
|
||||
shader.uniform1f("u_weatherFogCurve", weather.fogCurve());
|
||||
@ -126,6 +133,15 @@ void WorldRenderer::setupWorldShader(
|
||||
shader.uniform2f("u_lightDir", skybox->getLightDir());
|
||||
shader.uniform3f("u_cameraPos", camera.position);
|
||||
shader.uniform1i("u_cubemap", 1);
|
||||
shader.uniform1i("u_enableShadows", gbufferPipeline);
|
||||
|
||||
if (gbufferPipeline) {
|
||||
shader.uniformMatrix("u_shadowsMatrix", shadowCamera->getProjView());
|
||||
glActiveTexture(GL_TEXTURE4);
|
||||
shader.uniform1i("u_shadows", 4);
|
||||
glBindTexture(GL_TEXTURE_2D, shadowMap->getDepthMap());
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
|
||||
auto indices = level.content.getIndices();
|
||||
// Light emission when an emissive item is chosen
|
||||
@ -354,10 +370,52 @@ void WorldRenderer::draw(
|
||||
|
||||
const auto& assets = *engine.getAssets();
|
||||
auto& linesShader = assets.require<Shader>("lines");
|
||||
auto& shadowsShader = assets.require<Shader>("shadows");
|
||||
|
||||
if (gbufferPipeline) {
|
||||
float shadowMapScale = 0.05f;
|
||||
float shadowMapSize = shadowMap->getResolution() * shadowMapScale;
|
||||
*shadowCamera = Camera(camera.position, shadowMapSize);
|
||||
shadowCamera->near = 0.5f;
|
||||
shadowCamera->far = 600.0f;
|
||||
shadowCamera->perspective = false;
|
||||
shadowCamera->setAspectRatio(1.0f);
|
||||
shadowCamera->rotate(glm::radians(-65.0f), glm::radians(-35.0f), glm::radians(-35.0f));
|
||||
//shadowCamera.perspective = false;
|
||||
/*shadowCamera.rotation = //glm::inverse(
|
||||
glm::lookAt({}, glm::normalize(shadowCamera.position-camera.position), glm::vec3(0, 1, 0));
|
||||
//);*/
|
||||
shadowCamera->updateVectors();
|
||||
//shadowCamera->position += camera.dir * shadowMapSize * 0.5f;
|
||||
shadowCamera->position -= shadowCamera->front * 100.0f;
|
||||
shadowCamera->position -= shadowCamera->right * (shadowMap->getResolution() * shadowMapScale) * 0.5f;
|
||||
shadowCamera->position -= shadowCamera->up * (shadowMap->getResolution() * shadowMapScale) * 0.5f;
|
||||
shadowCamera->position = glm::floor(shadowCamera->position);
|
||||
{
|
||||
frustumCulling->update(shadowCamera->getProjView());
|
||||
auto sctx = pctx.sub();
|
||||
sctx.setDepthTest(true);
|
||||
sctx.setCullFace(true);
|
||||
sctx.setViewport({shadowMap->getResolution(), shadowMap->getResolution()});
|
||||
shadowMap->bind();
|
||||
setupWorldShader(shadowsShader, *shadowCamera, settings, 0.0f);
|
||||
chunks->drawChunks(*shadowCamera, shadowsShader);
|
||||
shadowMap->unbind();
|
||||
}
|
||||
}
|
||||
|
||||
/* World render scope with diegetic HUD included */ {
|
||||
DrawContext wctx = pctx.sub();
|
||||
postProcessing.use(wctx);
|
||||
if (gbufferPipeline) {
|
||||
if (gbuffer == nullptr) {
|
||||
gbuffer = std::make_unique<GBuffer>(vp.x, vp.y);
|
||||
} else {
|
||||
gbuffer->resize(vp.x, vp.y);
|
||||
}
|
||||
wctx.setFramebuffer(gbuffer.get());
|
||||
} else {
|
||||
postProcessing.use(wctx);
|
||||
}
|
||||
|
||||
display::clearDepth();
|
||||
|
||||
@ -370,25 +428,25 @@ void WorldRenderer::draw(
|
||||
ctx.setCullFace(true);
|
||||
renderLevel(ctx, camera, settings, uiDelta, pause, hudVisible);
|
||||
// Debug lines
|
||||
if (hudVisible) {
|
||||
if (debug) {
|
||||
guides->renderDebugLines(
|
||||
ctx, camera, *lineBatch, linesShader, showChunkBorders
|
||||
);
|
||||
}
|
||||
if (player.currentCamera == player.fpCamera) {
|
||||
renderHands(camera, delta);
|
||||
}
|
||||
}
|
||||
// if (hudVisible) {
|
||||
// if (debug) {
|
||||
// guides->renderDebugLines(
|
||||
// ctx, camera, *lineBatch, linesShader, showChunkBorders
|
||||
// );
|
||||
// }
|
||||
// if (player.currentCamera == player.fpCamera) {
|
||||
// renderHands(camera, delta);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
{
|
||||
DrawContext ctx = wctx.sub();
|
||||
texts->render(ctx, camera, settings, hudVisible, true);
|
||||
}
|
||||
renderBlockOverlay(wctx);
|
||||
// {
|
||||
// DrawContext ctx = wctx.sub();
|
||||
// texts->render(ctx, camera, settings, hudVisible, true);
|
||||
// }
|
||||
//renderBlockOverlay(wctx);
|
||||
}
|
||||
|
||||
postProcessing.render(pctx, assets, timer);
|
||||
postProcessing.render(pctx, assets, timer, camera, shadowMap->getDepthMap());
|
||||
}
|
||||
|
||||
void WorldRenderer::renderBlockOverlay(const DrawContext& wctx) {
|
||||
|
||||
@ -30,6 +30,8 @@ class PostProcessing;
|
||||
class DrawContext;
|
||||
class ModelBatch;
|
||||
class Assets;
|
||||
class ShadowMap;
|
||||
class GBuffer;
|
||||
struct EngineSettings;
|
||||
|
||||
class WorldRenderer {
|
||||
@ -44,12 +46,18 @@ class WorldRenderer {
|
||||
std::unique_ptr<GuidesRenderer> guides;
|
||||
std::unique_ptr<ChunksRenderer> chunks;
|
||||
std::unique_ptr<Skybox> skybox;
|
||||
std::unique_ptr<ShadowMap> shadowMap;
|
||||
Weather weather {};
|
||||
|
||||
std::unique_ptr<Camera> shadowCamera;
|
||||
|
||||
float timer = 0.0f;
|
||||
bool debug = false;
|
||||
bool lightsDebug = false;
|
||||
|
||||
std::unique_ptr<GBuffer> gbuffer;
|
||||
bool gbufferPipeline = false;
|
||||
|
||||
/// @brief Render block selection lines
|
||||
void renderBlockSelection();
|
||||
|
||||
|
||||
@ -14,11 +14,13 @@ struct ChunkVertex {
|
||||
glm::vec3 position;
|
||||
glm::vec2 uv;
|
||||
std::array<uint8_t, 4> color;
|
||||
std::array<uint8_t, 4> normal;
|
||||
|
||||
static constexpr VertexAttribute ATTRIBUTES[] = {
|
||||
{VertexAttribute::Type::FLOAT, false, 3},
|
||||
{VertexAttribute::Type::FLOAT, false, 2},
|
||||
{VertexAttribute::Type::UNSIGNED_BYTE, true, 4},
|
||||
{VertexAttribute::Type::UNSIGNED_BYTE, true, 4},
|
||||
{{}, 0}};
|
||||
};
|
||||
|
||||
|
||||
@ -38,6 +38,8 @@ GUI::GUI(Engine& engine)
|
||||
std::make_unique<Camera>(glm::vec3(), engine.getWindow().getSize().y);
|
||||
uicamera->perspective = false;
|
||||
uicamera->flipped = true;
|
||||
uicamera->near = -1.0f;
|
||||
uicamera->far = 1.0f;
|
||||
|
||||
menu = std::make_shared<Menu>(*this);
|
||||
menu->setId("menu");
|
||||
|
||||
@ -31,9 +31,9 @@ glm::mat4 Camera::getProjection() const {
|
||||
if (perspective) {
|
||||
return glm::perspective(fov * zoom, ar, near, far);
|
||||
} else if (flipped) {
|
||||
return glm::ortho(0.0f, fov * ar, fov, 0.0f);
|
||||
return glm::ortho(0.0f, fov * ar, fov, 0.0f, near, far);
|
||||
} else {
|
||||
return glm::ortho(0.0f, fov * ar, 0.0f, fov);
|
||||
return glm::ortho(0.0f, fov * ar, 0.0f, fov, near, far);
|
||||
}
|
||||
}
|
||||
|
||||
@ -45,7 +45,8 @@ glm::mat4 Camera::getView(bool pos) const {
|
||||
if (perspective) {
|
||||
return glm::lookAt(camera_pos, camera_pos + front, up);
|
||||
} else {
|
||||
return glm::translate(glm::mat4(1.0f), camera_pos);
|
||||
return glm::lookAt(camera_pos, camera_pos + front, up);
|
||||
//return glm::translate(glm::mat4(1.0f), camera_pos);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user