Skip to content

Commit

Permalink
Implement 3D shadows in the GL Compatibility renderer
Browse files Browse the repository at this point in the history
  • Loading branch information
clayjohn committed Sep 28, 2023
1 parent ec62b8a commit cb7200b
Show file tree
Hide file tree
Showing 10 changed files with 2,360 additions and 371 deletions.
10 changes: 10 additions & 0 deletions drivers/gles3/effects/copy_effects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,16 @@ void CopyEffects::copy_screen() {
draw_screen_triangle();
}

void CopyEffects::copy_cube_to_rect(const Rect2 &p_rect) {
bool success = copy.shader.version_bind_shader(copy.shader_version, CopyShaderGLES3::MODE_CUBE_TO_OCTAHEDRAL);
if (!success) {
return;
}

copy.shader.version_set_uniform(CopyShaderGLES3::COPY_SECTION, p_rect.position.x, p_rect.position.y, p_rect.size.x, p_rect.size.y, copy.shader_version, CopyShaderGLES3::MODE_COPY_SECTION);
draw_screen_quad();
}

// Intended for efficiently mipmapping textures.
void CopyEffects::bilinear_blur(GLuint p_source_texture, int p_mipmap_count, const Rect2i &p_region) {
GLuint framebuffers[2];
Expand Down
1 change: 1 addition & 0 deletions drivers/gles3/effects/copy_effects.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ class CopyEffects {
// These functions assume that a framebuffer and texture are bound already. They only manage the shader, uniforms, and vertex array.
void copy_to_rect(const Rect2 &p_rect);
void copy_screen();
void copy_cube_to_rect(const Rect2 &p_rect);
void bilinear_blur(GLuint p_source_texture, int p_mipmap_count, const Rect2i &p_region);
void gaussian_blur(GLuint p_source_texture, int p_mipmap_count, const Rect2i &p_region, const Size2i &p_size);
void set_color(const Color &p_color, const Rect2i &p_region);
Expand Down
1,190 changes: 914 additions & 276 deletions drivers/gles3/rasterizer_scene_gles3.cpp

Large diffs are not rendered by default.

79 changes: 66 additions & 13 deletions drivers/gles3/rasterizer_scene_gles3.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ enum RenderListType {
enum PassMode {
PASS_MODE_COLOR,
PASS_MODE_COLOR_TRANSPARENT,
PASS_MODE_COLOR_ADDITIVE,
PASS_MODE_SHADOW,
PASS_MODE_DEPTH,
};
Expand All @@ -75,6 +74,8 @@ enum SceneUniformLocation {
SCENE_SPOTLIGHT_UNIFORM_LOCATION,
SCENE_DIRECTIONAL_LIGHT_UNIFORM_LOCATION,
SCENE_MULTIVIEW_UNIFORM_LOCATION,
SCENE_POSITIONAL_SHADOW_UNIFORM_LOCATION,
SCENE_DIRECTIONAL_SHADOW_UNIFORM_LOCATION,
};

enum SkyUniformLocation {
Expand Down Expand Up @@ -109,17 +110,24 @@ struct RenderDataGLES3 {
const PagedArray<RID> *reflection_probes = nullptr;
RID environment;
RID camera_attributes;
RID shadow_atlas;
RID reflection_probe;
int reflection_probe_pass = 0;

float lod_distance_multiplier = 0.0;
float screen_mesh_lod_threshold = 0.0;

uint32_t directional_light_count = 0;
uint32_t directional_shadow_count = 0;

uint32_t spot_light_count = 0;
uint32_t omni_light_count = 0;

RenderingMethod::RenderInfo *render_info = nullptr;

/* Shadow data */
const RendererSceneRender::RenderShadowData *render_shadows = nullptr;
int render_shadow_count = 0;
};

class RasterizerCanvasGLES3;
Expand Down Expand Up @@ -173,11 +181,36 @@ class RasterizerSceneGLES3 : public RendererSceneRender {
float size;

uint32_t enabled; // For use by SkyShaders
float pad[2];
float pad;
float shadow_opacity;
float specular;
};
static_assert(sizeof(DirectionalLightData) % 16 == 0, "DirectionalLightData size must be a multiple of 16 bytes");

struct ShadowData {
float shadow_matrix[16];

float light_position[3];
float shadow_normal_bias;

float pad[3];
float shadow_atlas_pixel_size;
};
static_assert(sizeof(ShadowData) % 16 == 0, "ShadowData size must be a multiple of 16 bytes");

struct DirectionalShadowData {
float direction[3];
float shadow_atlas_pixel_size;
float shadow_normal_bias[4];
float shadow_split_offsets[4];
float shadow_matrices[4][16];
float fade_from;
float fade_to;
uint32_t blend_splits; // Not exposed to the shader.
uint32_t pad;
};
static_assert(sizeof(DirectionalShadowData) % 16 == 0, "DirectionalShadowData size must be a multiple of 16 bytes");

class GeometryInstanceGLES3;

// Cached data for drawing surfaces
Expand Down Expand Up @@ -221,6 +254,8 @@ class RasterizerSceneGLES3 : public RendererSceneRender {
uint32_t surface_index = 0;
uint32_t lod_index = 0;
uint32_t index_count = 0;
int32_t light_pass_index = -1;
bool finished_base_pass = false;

void *surface = nullptr;
GLES3::SceneShaderData *shader = nullptr;
Expand All @@ -245,14 +280,23 @@ class RasterizerSceneGLES3 : public RendererSceneRender {
bool using_projectors = false;
bool using_softshadows = false;

uint32_t omni_light_count = 0;
LocalVector<RID> omni_lights;
uint32_t spot_light_count = 0;
LocalVector<RID> spot_lights;
struct LightPass {
int32_t light_id = -1; // Position in the light uniform buffer.
int32_t shadow_id = -1; // Position in the shadow uniform buffer.
RID light_instance_rid;
bool is_omni = false;
};

LocalVector<LightPass> light_passes;

uint32_t paired_omni_light_count = 0;
uint32_t paired_spot_light_count = 0;
LocalVector<RID> paired_omni_lights;
LocalVector<RID> paired_spot_lights;
LocalVector<uint32_t> omni_light_gl_cache;
LocalVector<uint32_t> spot_light_gl_cache;

//used during setup
// Used during setup.
GeometryInstanceSurface *surface_caches = nullptr;
SelfList<GeometryInstanceGLES3> dirty_list_element;

Expand Down Expand Up @@ -336,10 +380,11 @@ class RasterizerSceneGLES3 : public RendererSceneRender {

float fog_light_color[3];
float fog_sun_scatter;

float shadow_bias;
float pad;
uint32_t camera_visible_layers;
uint32_t pad1;
uint32_t pad2;
uint32_t pad3;
bool pancake_shadows;
};
static_assert(sizeof(UBO) % 16 == 0, "Scene UBO size must be a multiple of 16 bytes");

Expand Down Expand Up @@ -378,16 +423,22 @@ class RasterizerSceneGLES3 : public RendererSceneRender {

LightData *omni_lights = nullptr;
LightData *spot_lights = nullptr;
ShadowData *positional_shadows = nullptr;

InstanceSort<GLES3::LightInstance> *omni_light_sort;
InstanceSort<GLES3::LightInstance> *spot_light_sort;
GLuint omni_light_buffer = 0;
GLuint spot_light_buffer = 0;
GLuint positional_shadow_buffer = 0;
uint32_t omni_light_count = 0;
uint32_t spot_light_count = 0;
RS::ShadowQuality positional_shadow_quality = RS::ShadowQuality::SHADOW_QUALITY_SOFT_LOW;

DirectionalLightData *directional_lights = nullptr;
GLuint directional_light_buffer = 0;
DirectionalShadowData *directional_shadows = nullptr;
GLuint directional_shadow_buffer = 0;
RS::ShadowQuality directional_shadow_quality = RS::ShadowQuality::SHADOW_QUALITY_SOFT_LOW;
} scene_state;

struct RenderListParameters {
Expand Down Expand Up @@ -462,9 +513,11 @@ class RasterizerSceneGLES3 : public RendererSceneRender {

RenderList render_list[RENDER_LIST_MAX];

void _setup_lights(const RenderDataGLES3 *p_render_data, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_omni_light_count, uint32_t &r_spot_light_count);
void _setup_environment(const RenderDataGLES3 *p_render_data, bool p_no_fog, const Size2i &p_screen_size, bool p_flip_y, const Color &p_default_bg_color, bool p_pancake_shadows);
void _setup_lights(const RenderDataGLES3 *p_render_data, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_omni_light_count, uint32_t &r_spot_light_count, uint32_t &r_directional_shadow_count);
void _setup_environment(const RenderDataGLES3 *p_render_data, bool p_no_fog, const Size2i &p_screen_size, bool p_flip_y, const Color &p_default_bg_color, bool p_pancake_shadows, float p_shadow_bias = 0.0);
void _fill_render_list(RenderListType p_render_list, const RenderDataGLES3 *p_render_data, PassMode p_pass_mode, bool p_append = false);
void _render_shadows(const RenderDataGLES3 *p_render_data);
void _render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_mesh_lod_threshold = 0.0, RenderingMethod::RenderInfo *p_render_info = nullptr);

template <PassMode p_pass_mode>
_FORCE_INLINE_ void _render_list_template(RenderListParameters *p_params, const RenderDataGLES3 *p_render_data, uint32_t p_from_element, uint32_t p_to_element, bool p_alpha_pass = false);
Expand All @@ -477,7 +530,7 @@ class RasterizerSceneGLES3 : public RendererSceneRender {
float screen_space_roughness_limiter_amount = 0.25;
float screen_space_roughness_limiter_limit = 0.18;

void _render_buffers_debug_draw(Ref<RenderSceneBuffersGLES3> p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer);
void _render_buffers_debug_draw(Ref<RenderSceneBuffersGLES3> p_render_buffers, RID p_shadow_atlas);

/* Camera Attributes */

Expand Down
20 changes: 20 additions & 0 deletions drivers/gles3/shaders/copy.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ mode_copy_section = #define USE_COPY_SECTION \n#define MODE_SIMPLE_COPY
mode_gaussian_blur = #define MODE_GAUSSIAN_BLUR
mode_mipmap = #define MODE_MIPMAP
mode_simple_color = #define MODE_SIMPLE_COLOR \n#define USE_COPY_SECTION
mode_cube_to_octahedral = #define CUBE_TO_OCTAHEDRAL \n#define USE_COPY_SECTION

#[specializations]

Expand Down Expand Up @@ -50,8 +51,20 @@ uniform vec4 color_in;
uniform highp vec2 pixel_size;
#endif

#ifdef CUBE_TO_OCTAHEDRAL
uniform samplerCube source_cube; // texunit:0

vec3 oct_to_vec3(vec2 e) {
vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));
float t = max(-v.z, 0.0);
v.xy += t * -sign(v.xy);
return normalize(v);
}
#else
uniform sampler2D source; // texunit:0

#endif

layout(location = 0) out vec4 frag_color;

void main() {
Expand Down Expand Up @@ -90,4 +103,11 @@ void main() {
frag_color += (F + G + L + K) * lesser_weight;
frag_color += (G + H + M + L) * lesser_weight;
#endif

#ifdef CUBE_TO_OCTAHEDRAL
// Treat the UV coordinates as 0-1 encoded octahedral coordinates.
vec3 dir = oct_to_vec3(uv_interp * 2.0 - 1.0);
frag_color = texture(source_cube, dir);

#endif
}
Loading

0 comments on commit cb7200b

Please sign in to comment.