Skip to content

Commit cb7200b

Browse files
committed
Implement 3D shadows in the GL Compatibility renderer
1 parent ec62b8a commit cb7200b

File tree

10 files changed

+2360
-371
lines changed

10 files changed

+2360
-371
lines changed

drivers/gles3/effects/copy_effects.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,16 @@ void CopyEffects::copy_screen() {
134134
draw_screen_triangle();
135135
}
136136

137+
void CopyEffects::copy_cube_to_rect(const Rect2 &p_rect) {
138+
bool success = copy.shader.version_bind_shader(copy.shader_version, CopyShaderGLES3::MODE_CUBE_TO_OCTAHEDRAL);
139+
if (!success) {
140+
return;
141+
}
142+
143+
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);
144+
draw_screen_quad();
145+
}
146+
137147
// Intended for efficiently mipmapping textures.
138148
void CopyEffects::bilinear_blur(GLuint p_source_texture, int p_mipmap_count, const Rect2i &p_region) {
139149
GLuint framebuffers[2];

drivers/gles3/effects/copy_effects.h

+1
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ class CopyEffects {
6363
// These functions assume that a framebuffer and texture are bound already. They only manage the shader, uniforms, and vertex array.
6464
void copy_to_rect(const Rect2 &p_rect);
6565
void copy_screen();
66+
void copy_cube_to_rect(const Rect2 &p_rect);
6667
void bilinear_blur(GLuint p_source_texture, int p_mipmap_count, const Rect2i &p_region);
6768
void gaussian_blur(GLuint p_source_texture, int p_mipmap_count, const Rect2i &p_region, const Size2i &p_size);
6869
void set_color(const Color &p_color, const Rect2i &p_region);

drivers/gles3/rasterizer_scene_gles3.cpp

+914-276
Large diffs are not rendered by default.

drivers/gles3/rasterizer_scene_gles3.h

+66-13
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ enum RenderListType {
5959
enum PassMode {
6060
PASS_MODE_COLOR,
6161
PASS_MODE_COLOR_TRANSPARENT,
62-
PASS_MODE_COLOR_ADDITIVE,
6362
PASS_MODE_SHADOW,
6463
PASS_MODE_DEPTH,
6564
};
@@ -75,6 +74,8 @@ enum SceneUniformLocation {
7574
SCENE_SPOTLIGHT_UNIFORM_LOCATION,
7675
SCENE_DIRECTIONAL_LIGHT_UNIFORM_LOCATION,
7776
SCENE_MULTIVIEW_UNIFORM_LOCATION,
77+
SCENE_POSITIONAL_SHADOW_UNIFORM_LOCATION,
78+
SCENE_DIRECTIONAL_SHADOW_UNIFORM_LOCATION,
7879
};
7980

8081
enum SkyUniformLocation {
@@ -109,17 +110,24 @@ struct RenderDataGLES3 {
109110
const PagedArray<RID> *reflection_probes = nullptr;
110111
RID environment;
111112
RID camera_attributes;
113+
RID shadow_atlas;
112114
RID reflection_probe;
113115
int reflection_probe_pass = 0;
114116

115117
float lod_distance_multiplier = 0.0;
116118
float screen_mesh_lod_threshold = 0.0;
117119

118120
uint32_t directional_light_count = 0;
121+
uint32_t directional_shadow_count = 0;
122+
119123
uint32_t spot_light_count = 0;
120124
uint32_t omni_light_count = 0;
121125

122126
RenderingMethod::RenderInfo *render_info = nullptr;
127+
128+
/* Shadow data */
129+
const RendererSceneRender::RenderShadowData *render_shadows = nullptr;
130+
int render_shadow_count = 0;
123131
};
124132

125133
class RasterizerCanvasGLES3;
@@ -173,11 +181,36 @@ class RasterizerSceneGLES3 : public RendererSceneRender {
173181
float size;
174182

175183
uint32_t enabled; // For use by SkyShaders
176-
float pad[2];
184+
float pad;
185+
float shadow_opacity;
177186
float specular;
178187
};
179188
static_assert(sizeof(DirectionalLightData) % 16 == 0, "DirectionalLightData size must be a multiple of 16 bytes");
180189

190+
struct ShadowData {
191+
float shadow_matrix[16];
192+
193+
float light_position[3];
194+
float shadow_normal_bias;
195+
196+
float pad[3];
197+
float shadow_atlas_pixel_size;
198+
};
199+
static_assert(sizeof(ShadowData) % 16 == 0, "ShadowData size must be a multiple of 16 bytes");
200+
201+
struct DirectionalShadowData {
202+
float direction[3];
203+
float shadow_atlas_pixel_size;
204+
float shadow_normal_bias[4];
205+
float shadow_split_offsets[4];
206+
float shadow_matrices[4][16];
207+
float fade_from;
208+
float fade_to;
209+
uint32_t blend_splits; // Not exposed to the shader.
210+
uint32_t pad;
211+
};
212+
static_assert(sizeof(DirectionalShadowData) % 16 == 0, "DirectionalShadowData size must be a multiple of 16 bytes");
213+
181214
class GeometryInstanceGLES3;
182215

183216
// Cached data for drawing surfaces
@@ -221,6 +254,8 @@ class RasterizerSceneGLES3 : public RendererSceneRender {
221254
uint32_t surface_index = 0;
222255
uint32_t lod_index = 0;
223256
uint32_t index_count = 0;
257+
int32_t light_pass_index = -1;
258+
bool finished_base_pass = false;
224259

225260
void *surface = nullptr;
226261
GLES3::SceneShaderData *shader = nullptr;
@@ -245,14 +280,23 @@ class RasterizerSceneGLES3 : public RendererSceneRender {
245280
bool using_projectors = false;
246281
bool using_softshadows = false;
247282

248-
uint32_t omni_light_count = 0;
249-
LocalVector<RID> omni_lights;
250-
uint32_t spot_light_count = 0;
251-
LocalVector<RID> spot_lights;
283+
struct LightPass {
284+
int32_t light_id = -1; // Position in the light uniform buffer.
285+
int32_t shadow_id = -1; // Position in the shadow uniform buffer.
286+
RID light_instance_rid;
287+
bool is_omni = false;
288+
};
289+
290+
LocalVector<LightPass> light_passes;
291+
292+
uint32_t paired_omni_light_count = 0;
293+
uint32_t paired_spot_light_count = 0;
294+
LocalVector<RID> paired_omni_lights;
295+
LocalVector<RID> paired_spot_lights;
252296
LocalVector<uint32_t> omni_light_gl_cache;
253297
LocalVector<uint32_t> spot_light_gl_cache;
254298

255-
//used during setup
299+
// Used during setup.
256300
GeometryInstanceSurface *surface_caches = nullptr;
257301
SelfList<GeometryInstanceGLES3> dirty_list_element;
258302

@@ -336,10 +380,11 @@ class RasterizerSceneGLES3 : public RendererSceneRender {
336380

337381
float fog_light_color[3];
338382
float fog_sun_scatter;
383+
384+
float shadow_bias;
385+
float pad;
339386
uint32_t camera_visible_layers;
340-
uint32_t pad1;
341-
uint32_t pad2;
342-
uint32_t pad3;
387+
bool pancake_shadows;
343388
};
344389
static_assert(sizeof(UBO) % 16 == 0, "Scene UBO size must be a multiple of 16 bytes");
345390

@@ -378,16 +423,22 @@ class RasterizerSceneGLES3 : public RendererSceneRender {
378423

379424
LightData *omni_lights = nullptr;
380425
LightData *spot_lights = nullptr;
426+
ShadowData *positional_shadows = nullptr;
381427

382428
InstanceSort<GLES3::LightInstance> *omni_light_sort;
383429
InstanceSort<GLES3::LightInstance> *spot_light_sort;
384430
GLuint omni_light_buffer = 0;
385431
GLuint spot_light_buffer = 0;
432+
GLuint positional_shadow_buffer = 0;
386433
uint32_t omni_light_count = 0;
387434
uint32_t spot_light_count = 0;
435+
RS::ShadowQuality positional_shadow_quality = RS::ShadowQuality::SHADOW_QUALITY_SOFT_LOW;
388436

389437
DirectionalLightData *directional_lights = nullptr;
390438
GLuint directional_light_buffer = 0;
439+
DirectionalShadowData *directional_shadows = nullptr;
440+
GLuint directional_shadow_buffer = 0;
441+
RS::ShadowQuality directional_shadow_quality = RS::ShadowQuality::SHADOW_QUALITY_SOFT_LOW;
391442
} scene_state;
392443

393444
struct RenderListParameters {
@@ -462,9 +513,11 @@ class RasterizerSceneGLES3 : public RendererSceneRender {
462513

463514
RenderList render_list[RENDER_LIST_MAX];
464515

465-
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);
466-
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);
516+
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);
517+
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);
467518
void _fill_render_list(RenderListType p_render_list, const RenderDataGLES3 *p_render_data, PassMode p_pass_mode, bool p_append = false);
519+
void _render_shadows(const RenderDataGLES3 *p_render_data);
520+
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);
468521

469522
template <PassMode p_pass_mode>
470523
_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);
@@ -477,7 +530,7 @@ class RasterizerSceneGLES3 : public RendererSceneRender {
477530
float screen_space_roughness_limiter_amount = 0.25;
478531
float screen_space_roughness_limiter_limit = 0.18;
479532

480-
void _render_buffers_debug_draw(Ref<RenderSceneBuffersGLES3> p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer);
533+
void _render_buffers_debug_draw(Ref<RenderSceneBuffersGLES3> p_render_buffers, RID p_shadow_atlas);
481534

482535
/* Camera Attributes */
483536

drivers/gles3/shaders/copy.glsl

+20
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ mode_copy_section = #define USE_COPY_SECTION \n#define MODE_SIMPLE_COPY
66
mode_gaussian_blur = #define MODE_GAUSSIAN_BLUR
77
mode_mipmap = #define MODE_MIPMAP
88
mode_simple_color = #define MODE_SIMPLE_COLOR \n#define USE_COPY_SECTION
9+
mode_cube_to_octahedral = #define CUBE_TO_OCTAHEDRAL \n#define USE_COPY_SECTION
910

1011
#[specializations]
1112

@@ -50,8 +51,20 @@ uniform vec4 color_in;
5051
uniform highp vec2 pixel_size;
5152
#endif
5253

54+
#ifdef CUBE_TO_OCTAHEDRAL
55+
uniform samplerCube source_cube; // texunit:0
56+
57+
vec3 oct_to_vec3(vec2 e) {
58+
vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));
59+
float t = max(-v.z, 0.0);
60+
v.xy += t * -sign(v.xy);
61+
return normalize(v);
62+
}
63+
#else
5364
uniform sampler2D source; // texunit:0
5465

66+
#endif
67+
5568
layout(location = 0) out vec4 frag_color;
5669

5770
void main() {
@@ -90,4 +103,11 @@ void main() {
90103
frag_color += (F + G + L + K) * lesser_weight;
91104
frag_color += (G + H + M + L) * lesser_weight;
92105
#endif
106+
107+
#ifdef CUBE_TO_OCTAHEDRAL
108+
// Treat the UV coordinates as 0-1 encoded octahedral coordinates.
109+
vec3 dir = oct_to_vec3(uv_interp * 2.0 - 1.0);
110+
frag_color = texture(source_cube, dir);
111+
112+
#endif
93113
}

0 commit comments

Comments
 (0)