Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement 3D shadows in the GL Compatibility renderer #77496

Merged
merged 1 commit into from
Sep 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading