Skip to content

Commit

Permalink
[Graphic] ambient shadows
Browse files Browse the repository at this point in the history
  • Loading branch information
sarthou committed Jul 23, 2024
1 parent 3bddec9 commit ed7559d
Show file tree
Hide file tree
Showing 19 changed files with 486 additions and 73 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ owds_add_library(overworld_graphics_new
src/Engine/Graphics/OpenGL/Renderer.cpp
src/Engine/Graphics/OpenGL/Screen.cpp
src/Engine/Graphics/OpenGL/Shader.cpp
src/Engine/Graphics/OpenGL/Shadow.cpp
src/Engine/Graphics/OpenGL/Texture2D.cpp)
target_link_libraries(overworld_graphics_new PUBLIC overworld_engine_common overworld_glad assimp glfw)
target_compile_options(overworld_graphics_new PRIVATE $<$<CXX_COMPILER_ID:Clang>:-Wno-unused-function>)
Expand Down
8 changes: 8 additions & 0 deletions include/overworld/Engine/Graphics/OpenGL/Camera.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,20 +71,28 @@ namespace owds {
void finalize();
void setPositionAndOrientation(const std::array<float, 3>& position, const std::array<float, 3>& orientation);
void setPositionAndLookAt(const std::array<float, 3>& eye_position, const std::array<float, 3>& dst_position);
void setPositionAndDirection(const std::array<float, 3>& eye_position, const std::array<float, 3>& eye_direction);
void setDirectionAndLookAt(const std::array<float, 3>& eye_direction, const std::array<float, 3>& dst_position);

void recomputeDirectionVector();

std::vector<glm::vec4> getFrustumCornersWorldSpace();

void processUserKeyboardInput(float delta_time, int key, bool is_down);
void processUserMouseBtnInput(float delta_time, char btn, bool is_down);
void processUserMouseInput(float delta_time, float x, float y);
void processUserMouseScroll(float delta_time, float xoffset, float yoffset);
void update();

glm::vec3 getPosition() const { return world_eye_position_; }
glm::vec3 getFrontPose() const { return world_eye_position_ + world_eye_front_; }

glm::mat4 getViewMatrix() const { return view_matrix_; }
glm::mat4 getProjectionMatrix() const { return proj_matrix_; }

float getNearPlane() { return planes_[0]; }
float getFarPlane() { return planes_[1]; }

private:
glm::mat4 view_matrix_;
glm::mat4 proj_matrix_;
Expand Down
2 changes: 1 addition & 1 deletion include/overworld/Engine/Graphics/OpenGL/Cubemap.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace owds {
public:
bool init(const std::string& path);

void use(Shader& shader);
void draw(Shader& shader);

unsigned int getId() const { return texture_id_; }

Expand Down
6 changes: 3 additions & 3 deletions include/overworld/Engine/Graphics/OpenGL/MeshHandle.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,15 @@ namespace owds {
setupMesh();
}

void draw(Shader& shader) const
void draw(const Shader& shader, unsigned int texture_pose_offset = 0) const
{
unsigned int diffuse_nr = 1;
unsigned int specular_nr = 1;
unsigned int normal_nr = 1;
unsigned int height_nr = 1;
for(unsigned int i = 0; i < textures.size(); i++)
{
glActiveTexture(GL_TEXTURE0 + i); // active proper texture unit before binding
glActiveTexture(GL_TEXTURE0 + texture_pose_offset + i); // active proper texture unit before binding
std::string number;
std::string name;
if(textures[i].type_ == texture_diffuse)
Expand All @@ -67,7 +67,7 @@ namespace owds {
}

// now set the sampler to the correct texture unit
glUniform1i(glGetUniformLocation(shader.id_, (name + number).c_str()), i);
glUniform1i(glGetUniformLocation(shader.id_, (name + number).c_str()), texture_pose_offset + i);
// and finally bind the texture
glBindTexture(GL_TEXTURE_2D, textures[i].id_);
}
Expand Down
10 changes: 6 additions & 4 deletions include/overworld/Engine/Graphics/OpenGL/Renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,17 @@
#include "overworld/Engine/Common/Urdf/Actor.h"
#include "overworld/Engine/Graphics/Common/InstanceData.h"
#include "overworld/Engine/Graphics/OpenGL/Camera.h"
#include "overworld/Engine/Graphics/OpenGL/Cubemap.h"
#include "overworld/Engine/Graphics/OpenGL/MeshHandle.h"
#include "overworld/Engine/Graphics/OpenGL/Screen.h"
#include "overworld/Engine/Graphics/OpenGL/Shader.h"
#include "overworld/Engine/Graphics/OpenGL/Shadow.h"

namespace owds {
class Window;
class World;
class Camera;
class AmbientLight;
class PointLights;
class Cubemap;

class Renderer
{
Expand All @@ -42,7 +42,8 @@ namespace owds {
Camera render_camera_;
std::unordered_map<std::string, Shader> shaders_;
Screen screen_;
Cubemap* sky_;
Cubemap sky_;
Shadow shadow_;
float max_fps_ = 120;
float delta_time_;
float last_frame_;
Expand All @@ -62,8 +63,9 @@ namespace owds {
void loadInstance(const Model& model, const Material& material, const glm::mat4& model_mat);
void loadModel(const Model& model, const Material& material);
void render();
void renderModels(const Shader& shader, unsigned int texture_offset = 0);

void setLightsUniforms();
void setLightsUniforms(const Shader& shader);
void setAntiAliasing(ViewAntiAliasing_e setting);
};
} // namespace owds
Expand Down
2 changes: 1 addition & 1 deletion include/overworld/Engine/Graphics/OpenGL/Shader.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ namespace owds {
unsigned int id_;

// constructor reads and builds the shader
Shader(const std::string& vertex_path, const std::string& fragment_path);
Shader(const std::string& vertex_path, const std::string& fragment_path, const std::string& geometry_path = "");
// use/activate the shader
void use();
// utility uniform functions
Expand Down
37 changes: 37 additions & 0 deletions include/overworld/Engine/Graphics/OpenGL/Shadow.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#ifndef OWDS_GRAPHICS_OPNEGL_SHADOW_H
#define OWDS_GRAPHICS_OPNEGL_SHADOW_H

#include <array>

#include "overworld/Engine/Graphics/OpenGL/Camera.h"

namespace owds {
class Shader;

class Shadow
{
public:
void init(float near_plane, float far_plane);
void bindFrameBuffer() const;
void setUniforms(const Shader& shader, unsigned int texture_offset) const;
void setLighntMatrices();
void computeLightSpaceMatrices(Camera ref_cam, const glm::vec3& light_dir);

private:
std::vector<glm::mat4> lightspace_matrices_;

unsigned int matrices_uniform_buffer_;
unsigned int depth_framebuffer_;
unsigned int depth_maps_;
unsigned int resolution_ = 4096;

float near_plane_;
float far_plane_;
std::vector<float> shadow_cascade_levels_;

glm::mat4 getLightSpaceMatrix(Camera& ref_cam, const glm::vec3& light_dir, float near_plane, float far_plane);
};

} // namespace owds

#endif // OWDS_GRAPHICS_OPNEGL_SHADOW_H
5 changes: 5 additions & 0 deletions shaders/depth_shader.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#version 330 core

void main()
{
}
20 changes: 20 additions & 0 deletions shaders/depth_shader.gs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#version 410 core

layout(triangles, invocations = 5) in;
layout(triangle_strip, max_vertices = 3) out;

layout (std140) uniform LightSpaceMatrices
{
mat4 light_space_matrices[16];
};

void main()
{
for (int i = 0; i < 3; ++i)
{
gl_Position = light_space_matrices[gl_InvocationID] * gl_in[i].gl_Position;
gl_Layer = gl_InvocationID;
EmitVertex();
}
EndPrimitive();
}
9 changes: 9 additions & 0 deletions shaders/depth_shader.vs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#version 330 core
layout (location = 0) in vec3 aPos;

uniform mat4 model;

void main()
{
gl_Position = model * vec4(aPos, 1.0);
}
103 changes: 86 additions & 17 deletions shaders/light_shader.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,12 @@
out vec4 FragColor;

layout (location = 0) in vec3 FragPos;
layout (location = 1) in vec3 Normal;
layout (location = 1) in vec3 Normal;
layout (location = 2) in vec2 TexCoords;

struct Material {
sampler2D texture_diffuse1;
sampler2D texture_diffuse2;
sampler2D texture_diffuse3;
sampler2D texture_specular1;
sampler2D texture_specular2;
sampler2D emission;
float shininess;
float specular;
Expand Down Expand Up @@ -42,16 +39,21 @@ uniform float nb_point_lights;

uniform vec3 view_pose;

uniform mat4 view;

layout (std140) uniform LightSpaceMatrices
{
mat4 light_space_matrices[16];
};
uniform sampler2DArray shadow_maps;
uniform float cascade_planes_distances[16];
uniform int cascade_count;
uniform float far_plane;

vec4 calcDirLight(DirLight light, vec3 normal, vec3 viewDir);
vec4 calcPointLight(PointLight light, vec3 normal, vec3 viewDir);
float ShadowCalculation(vec3 fragPosWorldSpace);

float near = 0.1;
float far = 100.0;
float linearizeDepth(float depth)
{
float z = depth * 2.0 - 1.0; // back to NDC
return (2.0 * near * far) / (far + near - z * (far - near));
}

void main()
{
Expand All @@ -67,11 +69,8 @@ void main()
result += calcPointLight(point_lights[i], norm, viewDir);

FragColor = result;
//float gamma = 2.2;
//FragColor.rgb = pow(FragColor.rgb, vec3(1.0/gamma));

// float depth = linearizeDepth(gl_FragCoord.z) / far; // divide by far for demonstration
// FragColor = vec4(vec3(depth), 1.0);
float gamma = 2.2;
FragColor.rgb = pow(FragColor.rgb, vec3(1.0/gamma));
}

vec4 calcDirLight(DirLight light, vec3 normal, vec3 viewDir)
Expand All @@ -92,10 +91,12 @@ vec4 calcDirLight(DirLight light, vec3 normal, vec3 viewDir)
if(material.specular < 0)
mat_spec = vec4(texture(material.texture_specular1, TexCoords).r);

float shadow = ShadowCalculation(FragPos);

vec4 ambient = light.ambient * mat_ambient;
vec4 diffuse = light.diffuse * diff * mat_ambient;
vec4 specular = light.specular * spec * mat_spec;
return (ambient + diffuse + specular);
return (ambient + (1.0 - shadow) * (diffuse + specular));
}

vec4 calcPointLight(PointLight light, vec3 normal, vec3 viewDir)
Expand Down Expand Up @@ -127,4 +128,72 @@ vec4 calcPointLight(PointLight light, vec3 normal, vec3 viewDir)
diffuse *= attenuation;
specular *= attenuation;
return (ambient + diffuse + specular);
}

float ShadowCalculation(vec3 fragPosWorldSpace)
{
// select cascade layer
vec4 frag_pose_view_space = view * vec4(fragPosWorldSpace, 1.0);
float depth_value = abs(frag_pose_view_space.z);

int layer = -1;
for (int i = 0; i < cascade_count; ++i)
{
if (depth_value < cascade_planes_distances[i])
{
layer = i;
break;
}
}

if (layer == -1)
{
layer = cascade_count;
}

//return layer;

vec4 frag_pos_light_space = light_space_matrices[layer] * vec4(fragPosWorldSpace, 1.0);
// perform perspective divide
vec3 proj_coords = frag_pos_light_space.xyz / frag_pos_light_space.w;
// transform to [0,1] range
proj_coords = proj_coords * 0.5 + 0.5;

// get depth of current fragment from light's perspective
float current_depth = proj_coords.z;

// keep the shadow at 0.0 when outside the far_plane region of the light's frustum.
if (current_depth > 1.0)
{
return 0.0;
}

// calculate bias (based on depth map resolution and slope)
vec3 normal = normalize(Normal);
float bias = max(0.05 * (1.0 - dot(normal, dir_light.direction.xyz)), 0.005);
const float bias_modifier = 7.; // Can be tuned (increase reduce near to wall missing shadow)
// Increasing it too much will reduce the far quality
if (layer == cascade_count)
{
bias *= 1 / (far_plane * bias_modifier);
}
else
{
bias *= 1 / (cascade_planes_distances[layer] * bias_modifier);
}

// PCF
float shadow = 0.0;
vec2 texel_size = 1.0 / vec2(textureSize(shadow_maps, 0));
for(int x = -1; x <= 1; ++x)
{
for(int y = -1; y <= 1; ++y)
{
float pcf_depth = texture(shadow_maps, vec3(proj_coords.xy + vec2(x, y) * texel_size, layer)).r;
shadow += (current_depth - bias) > pcf_depth ? 1.0 : 0.0;
}
}
shadow /= 9.0;

return shadow;
}
3 changes: 2 additions & 1 deletion shaders/light_shader.vs
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@ void main()
Normal = mat3(transpose(inverse(model))) * aNormal;
TexCoords = aTexCoords;

gl_Position = projection * view * model * vec4(aPos, 1.0);
gl_Position = projection * view * vec4(FragPos, 1.0);
//gl_Position = projection * view * model * vec4(aPos, 1.0);
}
Loading

0 comments on commit ed7559d

Please sign in to comment.