added shadows

This commit is contained in:
Jay Robson 2024-02-25 21:54:51 +11:00
parent 787339ebee
commit 1b673127fe
11 changed files with 282 additions and 62 deletions

View File

@ -1,13 +1,13 @@
#version 460 core #version 460 core
in vec4 frag_pos; in vec3 frag_pos;
out vec4 frag_colour;
uniform float far_plane;
void main() void main()
{ {
float distance = length(frag_pos); float distance = length(frag_pos);
frag_colour = vec4(vec3(distance / 50.0f), 1); gl_FragDepth = distance / far_plane + 1e-4f;
gl_FragDepth = distance / 50.0f;
} }

View File

@ -6,18 +6,22 @@ layout (triangle_strip, max_vertices=18) out;
uniform mat4 shadow_mats[6]; uniform mat4 shadow_mats[6];
out vec4 frag_pos; in float emissive[];
out vec3 frag_pos;
void main() void main()
{ {
if(emissive[0] > 0) return;
for(int i = 0; i < 6; i++) for(int i = 0; i < 6; i++)
{ {
gl_Layer = i; gl_Layer = i;
for(int j = 0; j < 3; j++) for(int j = 0; j < 3; j++)
{ {
frag_pos = gl_in[j].gl_Position; vec4 fp = gl_in[j].gl_Position;
gl_Position = shadow_mats[i] * frag_pos; gl_Position = shadow_mats[i] * fp;
frag_pos = fp.xyz;
EmitVertex(); EmitVertex();
} }

View File

@ -2,12 +2,16 @@
#version 460 core #version 460 core
layout (location = 2) in vec4 aPos; layout (location = 2) in vec4 aPos;
layout (location = 5) in vec3 aMaterial;
uniform mat4 model; uniform mat4 model;
uniform mat4 camera; uniform mat4 camera;
out float emissive;
void main() void main()
{ {
gl_Position = camera * model * aPos; gl_Position = camera * model * aPos;
emissive = aMaterial[2];
} }

View File

@ -8,6 +8,18 @@ const float Epsilon = 0.00001;
// Constant normal incidence Fresnel factor for all dielectrics. // Constant normal incidence Fresnel factor for all dielectrics.
const vec3 Fdielectric = vec3(0.04); const vec3 Fdielectric = vec3(0.04);
const int SampleOffsetsLen = 8;
const vec3 SampleOffsets[SampleOffsetsLen] = {
vec3(-1.f,-1.f,-1.f),
vec3(-1.f,-1.f, 1.f),
vec3(-1.f, 1.f,-1.f),
vec3(-1.f, 1.f, 1.f),
vec3( 1.f,-1.f,-1.f),
vec3( 1.f,-1.f, 1.f),
vec3( 1.f, 1.f,-1.f),
vec3( 1.f, 1.f, 1.f),
};
in VS_OUT { in VS_OUT {
vec3 normal; vec3 normal;
vec4 colour; vec4 colour;
@ -27,52 +39,58 @@ layout(std140, binding = 1) buffer ssbo_lights
Light lights[]; Light lights[];
}; };
layout(std430, binding = 2) buffer ssbo_shadow_maps
{
samplerCube shadow_maps[];
};
in flat sampler2D frag_tex; in flat sampler2D frag_tex;
out vec4 frag_colour; out vec4 frag_colour;
uniform vec3 brightness; uniform vec3 brightness;
uniform vec3 camera_pos; uniform vec3 camera_pos;
uniform int lights_count; uniform int lights_count;
uniform float far_plane;
uniform bool shadows_enabled;
vec3 FresnelSchlick(float cosTheta, vec3 F0) vec3 FresnelSchlick(float cosTheta, vec3 F0)
{ {
return F0 + (1.0 - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0); return F0 + (1.0 - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0);
} }
float DistributionGGX(vec3 N, vec3 H, float roughness) float DistributionGGX(vec3 N, vec3 H, float roughness)
{ {
float a = roughness*roughness; float a = roughness*roughness;
float a2 = a*a; float a2 = a*a;
float NdotH = max(dot(N, H), 0.0); float NdotH = max(dot(N, H), 0.0);
float NdotH2 = NdotH*NdotH; float NdotH2 = NdotH*NdotH;
float num = a2; float num = a2;
float denom = (NdotH2 * (a2 - 1.0) + 1.0); float denom = (NdotH2 * (a2 - 1.0) + 1.0);
denom = PI * denom * denom; denom = PI * denom * denom;
return num / denom; return num / denom;
} }
float GeometrySchlickGGX(float NdotV, float roughness) float GeometrySchlickGGX(float NdotV, float roughness)
{ {
float r = (roughness + 1.0); float r = (roughness + 1.0);
float k = (r*r) / 8.0; float k = (r*r) / 8.0;
float num = NdotV; float num = NdotV;
float denom = NdotV * (1.0 - k) + k; float denom = NdotV * (1.0 - k) + k;
return num / denom; return num / denom;
} }
float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness) float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness)
{ {
float NdotV = max(dot(N, V), 0.0); float NdotV = max(dot(N, V), 0.0);
float NdotL = max(dot(N, L), 0.0); float NdotL = max(dot(N, L), 0.0);
float ggx2 = GeometrySchlickGGX(NdotV, roughness); float ggx2 = GeometrySchlickGGX(NdotV, roughness);
float ggx1 = GeometrySchlickGGX(NdotL, roughness); float ggx1 = GeometrySchlickGGX(NdotL, roughness);
return ggx1 * ggx2; return ggx1 * ggx2;
} }
vec3 LinRGB_To_sRGB(vec3 c) vec3 LinRGB_To_sRGB(vec3 c)
@ -121,21 +139,40 @@ void main()
vec3 radiance = l.colour.rgb * atten; vec3 radiance = l.colour.rgb * atten;
// cook-torrance brdf // cook-torrance brdf
float NDF = DistributionGGX(N, H, roughness); float NDF = DistributionGGX(N, H, roughness);
float G = GeometrySmith(N, V, L, roughness); float G = GeometrySmith(N, V, L, roughness);
vec3 F = FresnelSchlick(max(dot(H, V), 0.0), F0); vec3 F = FresnelSchlick(max(dot(H, V), 0.0), F0);
vec3 kS = F; vec3 kS = F;
vec3 kD = vec3(1.0) - kS; vec3 kD = vec3(1.0) - kS;
kD *= 1.0 - metalness; kD *= 1.0 - metalness;
vec3 numerator = NDF * G * F; vec3 numerator = NDF * G * F;
float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.0001; float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.0001;
vec3 specular = numerator / denominator; vec3 specular = numerator / denominator;
// add to outgoing radiance Lo float amount = 0;
float NdotL = max(dot(N, L), 0.0);
Lo += (kD * albedo_lin / PI + specular) * radiance * NdotL; if(shadows_enabled)
{
float texel_size = 1.f / textureSize(shadow_maps[i], 0)[0];
for(int j = 0; j < SampleOffsetsLen; j++)
{
amount += ((texture(shadow_maps[i], -L + SampleOffsets[j] * texel_size).r * far_plane > d) ? 1.f : 0.5f);
}
amount /= SampleOffsetsLen;
}
else
{
amount = 1.f;
}
// add to outgoing radiance Lo
float NdotL = max(dot(N, L), 0.0);
Lo += (kD * albedo_lin / PI + specular) * radiance * NdotL * amount;
} }
vec3 ambient = vec3(0.03f) * albedo_lin * brightness; vec3 ambient = vec3(0.03f) * albedo_lin * brightness;

View File

@ -0,0 +1,88 @@
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "gllight.hpp"
#include "../shader.hpp"
#include "../window.hpp"
#include "texture.hpp"
#include <glm/ext/matrix_transform.hpp>
#include <glm/ext/matrix_clip_space.hpp>
using namespace Sim::Graphics;
static glm::mat4 shadow_mats[6];
GLLight::GLLight(Light light) : light(light), size(4096)
{
glGenTextures(1, &id);
glBindTexture(GL_TEXTURE_CUBE_MAP, id);
for(int i = 0; i < 6; i++)
{
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_DEPTH_COMPONENT, size, size, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);
}
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, id, 0);
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
handle = glGetTextureHandleARB(id);
glMakeTextureHandleResidentARB(handle);
}
GLLight::GLLight(GLLight&& o) : light(o.light), size(o.size)
{
id = o.id;
handle = o.handle;
fbo = o.fbo;
o.id = 0;
o.handle = 0;
o.fbo = 0;
}
GLLight::~GLLight()
{
std::cout << "Destructor called for " << fbo << ":" << id << ":" << handle << "\n";
if(fbo)
glDeleteFramebuffers(1, &fbo);
if(id)
glDeleteTextures(1, &id);
}
void GLLight::render()
{
glm::mat4 camera_mat = glm::translate(glm::mat4(1), -light.pos);
glUniformMatrix4fv(Shader::LIGHT["camera"], 1, false, &camera_mat[0][0]);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glViewport(0, 0, size, size);
Window::render_scene();
}
void GLLight::init()
{
glm::mat4 shadow_proj = glm::perspective<float>(M_PI * 0.5f, 1.0f, 0.01f, 100.f);
shadow_mats[0] = shadow_proj * glm::lookAt(glm::vec3(0), { 1, 0, 0}, {0,-1, 0});
shadow_mats[1] = shadow_proj * glm::lookAt(glm::vec3(0), {-1, 0, 0}, {0,-1, 0});
shadow_mats[2] = shadow_proj * glm::lookAt(glm::vec3(0), { 0, 1, 0}, {0, 0, 1});
shadow_mats[3] = shadow_proj * glm::lookAt(glm::vec3(0), { 0,-1, 0}, {0, 0,-1});
shadow_mats[4] = shadow_proj * glm::lookAt(glm::vec3(0), { 0, 0, 1}, {0,-1, 0});
shadow_mats[5] = shadow_proj * glm::lookAt(glm::vec3(0), { 0, 0,-1}, {0,-1, 0});
glUniformMatrix4fv(Shader::LIGHT["shadow_mats"], 6, false, &shadow_mats[0][0][0]);
}

View File

@ -0,0 +1,28 @@
#pragma once
#include "light.hpp"
namespace Sim::Graphics
{
struct GLLight
{
const int size;
unsigned int id, fbo;
unsigned long handle;
Light light;
GLLight(Light light);
GLLight(GLLight&& o);
GLLight(const GLLight& o) = delete;
~GLLight();
static void init();
void render();
};
};

View File

@ -56,7 +56,7 @@ void GLMesh::bind()
void GLMesh::uniform() void GLMesh::uniform()
{ {
glUniformMatrix4fv(Shader::MAIN["model"], 1, false, &model_matrix[0][0]); glUniformMatrix4fv(Shader::ACTIVE->get("model"), 1, false, &model_matrix[0][0]);
} }
void GLMesh::set(const Mesh& m, int mode) void GLMesh::set(const Mesh& m, int mode)

View File

@ -14,6 +14,7 @@ using namespace Sim::Graphics;
Shader Shader::MAIN; Shader Shader::MAIN;
Shader Shader::BLUR; Shader Shader::BLUR;
Shader Shader::LIGHT; Shader Shader::LIGHT;
Shader* Shader::ACTIVE;
static int load_shader(const char* src, int type) static int load_shader(const char* src, int type)
{ {
@ -110,11 +111,14 @@ void Shader::load(const char* path, const char* file_vsh, const char* file_gsh,
glDeleteShader(gsh_id); glDeleteShader(gsh_id);
if(file_fsh) if(file_fsh)
glDeleteShader(fsh_id); glDeleteShader(fsh_id);
ACTIVE = this;
} }
void Shader::use() void Shader::use()
{ {
glUseProgram(prog_id); glUseProgram(prog_id);
ACTIVE = this;
} }
unsigned int Shader::operator [](const char* pos) unsigned int Shader::operator [](const char* pos)
@ -129,3 +133,8 @@ unsigned int Shader::operator [](const char* pos)
return uniform_locations[pos] = glGetUniformLocation(prog_id, pos); return uniform_locations[pos] = glGetUniformLocation(prog_id, pos);
} }
unsigned int Shader::get(const char* pos)
{
return operator[](pos);
}

View File

@ -18,6 +18,8 @@ public:
static Shader BLUR; static Shader BLUR;
static Shader LIGHT; static Shader LIGHT;
static Shader* ACTIVE;
Shader(); Shader();
Shader(const Shader& o) = delete; Shader(const Shader& o) = delete;
Shader(Shader&& o); Shader(Shader&& o);
@ -28,6 +30,7 @@ public:
void use(); void use();
unsigned int operator[](const char* pos); unsigned int operator[](const char* pos);
unsigned int get(const char* pos);
}; };
}; };

View File

@ -25,6 +25,7 @@
#include "monitor/secondary_loop.hpp" #include "monitor/secondary_loop.hpp"
#include "monitor/turbine.hpp" #include "monitor/turbine.hpp"
#include "mesh/texture.hpp" #include "mesh/texture.hpp"
#include "mesh/gllight.hpp"
#include "../system.hpp" #include "../system.hpp"
#include "../util/streams.hpp" #include "../util/streams.hpp"
#include "ui.hpp" #include "ui.hpp"
@ -34,6 +35,7 @@ using namespace Sim::Graphics;
static GLFWwindow* win; static GLFWwindow* win;
static bool win_should_close = false; static bool win_should_close = false;
static unsigned int ssbo_lights; static unsigned int ssbo_lights;
static unsigned int ssbo_shadow_maps;
static double secs_wait_at = 0; static double secs_wait_at = 0;
static double secs_wait_now = 0; static double secs_wait_now = 0;
@ -44,6 +46,8 @@ static GLMesh gm_dynamic_slow[2];
static GLMesh gm_dynamic_fast; static GLMesh gm_dynamic_fast;
static Mesh m_dynamic_fast; static Mesh m_dynamic_fast;
static std::vector<GLLight> lights;
static Monitor::Vessel monitor_vessel; static Monitor::Vessel monitor_vessel;
static Monitor::Core monitor_core; static Monitor::Core monitor_core;
static Monitor::PrimaryLoop monitor_primary_loop; static Monitor::PrimaryLoop monitor_primary_loop;
@ -54,7 +58,12 @@ glm::mat4 Window::projection_matrix;
static void GLAPIENTRY cb_debug_message(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam) static void GLAPIENTRY cb_debug_message(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam)
{ {
if(severity != GL_DEBUG_SEVERITY_NOTIFICATION) if(severity == GL_DEBUG_SEVERITY_HIGH)
{
throw std::runtime_error(message);
}
else if(severity != GL_DEBUG_SEVERITY_NOTIFICATION)
{ {
std::cout << "GL CALLBACK: " << message << "\n"; std::cout << "GL CALLBACK: " << message << "\n";
} }
@ -119,21 +128,23 @@ void Window::create()
Font::init(); Font::init();
UI::init(); UI::init();
Shader::LIGHT.load("../assets/shader", "light.vsh", "light.gsh", "light.fsh");
Shader::MAIN.load("../assets/shader", "main.vsh", "main.fsh"); Shader::MAIN.load("../assets/shader", "main.vsh", "main.fsh");
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
Sim::System& sys = *System::active; Sim::System& sys = *System::active;
Mesh m, m2; Mesh m_scene;
m.load_model("../assets", "scene.glb"); m_scene.load_model("../assets", "scene.glb");
m_scene.lights[0].pos.x = 6;
m_scene.lights[1].pos.x = 0;
// find the floor parts of the model and set them slightly transparent // find the floor parts of the model and set them slightly transparent
for(int i = 0; i < m.indices.size(); i += 3) for(int i = 0; i < m_scene.indices.size(); i += 3)
{ {
Arrays::Vertex& v1 = m.vertices[m.indices[i]]; Arrays::Vertex& v1 = m_scene.vertices[m_scene.indices[i]];
Arrays::Vertex& v2 = m.vertices[m.indices[i + 1]]; Arrays::Vertex& v2 = m_scene.vertices[m_scene.indices[i + 1]];
Arrays::Vertex& v3 = m.vertices[m.indices[i + 2]]; Arrays::Vertex& v3 = m_scene.vertices[m_scene.indices[i + 2]];
if(v1.pos.z <= 0 && v2.pos.z <= 0 && v3.pos.z <= 0) if(v1.pos.z <= 0 && v2.pos.z <= 0 && v3.pos.z <= 0)
{ {
@ -146,23 +157,51 @@ void Window::create()
// send all the light data // send all the light data
glGenBuffers(1, &ssbo_lights); glGenBuffers(1, &ssbo_lights);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo_lights); glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo_lights);
glBufferData(GL_SHADER_STORAGE_BUFFER, m.lights.size() * sizeof(m.lights[0]), &m.lights[0], GL_STATIC_DRAW); glBufferData(GL_SHADER_STORAGE_BUFFER, m_scene.lights.size() * sizeof(m_scene.lights[0]), &m_scene.lights[0], GL_STATIC_DRAW);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, ssbo_lights); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, ssbo_lights);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
glUniform1i(Shader::MAIN["lights_count"], m.lights.size()); glUniform1i(Shader::MAIN["lights_count"], m_scene.lights.size());
monitor_core.init(m); monitor_core.init(m_scene);
monitor_vessel.init(m); monitor_vessel.init(m_scene);
monitor_primary_loop.init(m); monitor_primary_loop.init(m_scene);
monitor_secondary_loop.init(m); monitor_secondary_loop.init(m_scene);
monitor_turbine.init(m); monitor_turbine.init(m_scene);
gm_scene.bind(); gm_scene.bind();
gm_scene.set(m, GL_STATIC_DRAW); gm_scene.set(m_scene, GL_STATIC_DRAW);
glfwShowWindow(win); glfwShowWindow(win);
glViewport(0, 0, 800, 600); /*
// setup lighting and prerender shadows
Shader::LIGHT.load("../assets/shader", "light.vsh", "light.gsh", "light.fsh");
glUniform1f(Shader::LIGHT["far_plane"], 100.0f);
GLLight::init();
std::vector<unsigned long> light_handles;
for(int i = 0; i < m_scene.lights.size(); i++)
{
GLLight light(m_scene.lights[i]);
light.render();
light_handles.push_back(light.handle);
lights.push_back(std::move(light));
}
for(int i = 0; i < lights.size(); i++)
{
std::cout << "handle " << i << ": " << light_handles[i] << "\n";
}
Shader::MAIN.use();*/
glUniform1f(Shader::MAIN["far_plane"], 100.0f);
/* // send all the light shadow map handles
glGenBuffers(1, &ssbo_shadow_maps);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo_shadow_maps);
glBufferData(GL_SHADER_STORAGE_BUFFER, light_handles.size() * sizeof(light_handles[0]), &light_handles[0], GL_STATIC_DRAW);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, ssbo_shadow_maps);*/
} }
void update_slow() void update_slow()
@ -217,7 +256,7 @@ void Window::update(double dt)
} }
} }
void render_scene() void Window::render_scene()
{ {
gm_scene.bind(); gm_scene.bind();
gm_scene.uniform(); gm_scene.uniform();
@ -242,11 +281,17 @@ void render_scene()
void Window::render() void Window::render()
{ {
glm::vec<2, int> size = Resize::get_size();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0, 0, size.x, size.y);
glm::vec3 camera_pos = Camera::get_pos(); glm::vec3 camera_pos = Camera::get_pos();
glm::mat4 mat_camera = Camera::get_matrix(); glm::mat4 mat_camera = Camera::get_matrix();
mat_camera = glm::scale(mat_camera, {1, 1, -1}); mat_camera = glm::scale(mat_camera, {1, 1, -1});
camera_pos.z *= -1; camera_pos.z *= -1;
Shader::MAIN.use();
glm::vec3 brightness = glm::vec3(System::active->grid.get_light_intensity()); glm::vec3 brightness = glm::vec3(System::active->grid.get_light_intensity());
glm::mat4 mat_projection = glm::perspective(glm::radians(90.0f), Resize::get_aspect(), 0.01f, 20.f); glm::mat4 mat_projection = glm::perspective(glm::radians(90.0f), Resize::get_aspect(), 0.01f, 20.f);
glUniformMatrix4fv(Shader::MAIN["projection"], 1, false, &mat_projection[0][0]); glUniformMatrix4fv(Shader::MAIN["projection"], 1, false, &mat_projection[0][0]);
@ -257,6 +302,7 @@ void Window::render()
glClearColor(0, 0, 0, 1.0f); glClearColor(0, 0, 0, 1.0f);
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glCullFace(GL_BACK);
glFrontFace(GL_CW); glFrontFace(GL_CW);
render_scene(); render_scene();

View File

@ -15,6 +15,7 @@ bool should_close();
void create(); void create();
void update(double dt); void update(double dt);
void render(); void render();
void render_scene();
void destroy(); void destroy();
void close(); void close();