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

Split rendering of shadowmaps into a static and dynamic pass #77683

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
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
13 changes: 13 additions & 0 deletions doc/classes/GeometryInstance3D.xml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@
The material override for the whole geometry.
If a material is assigned to this property, it will be used instead of any material set in any material slot of the mesh.
</member>
<member name="render_shadow" type="int" setter="set_shadow_render_setting" getter="get_shadow_render_setting" enum="GeometryInstance3D.ShadowRenderSetting" default="0">
Sets the render mode for shadow maps.
</member>
<member name="transparency" type="float" setter="set_transparency" getter="get_transparency" default="0.0">
The transparency applied to the whole geometry (as a multiplier of the materials' existing transparency). [code]0.0[/code] is fully opaque, while [code]1.0[/code] is fully transparent. Values greater than [code]0.0[/code] (exclusive) will force the geometry's materials to go through the transparent pipeline, which is slower to render and can exhibit rendering issues due to incorrect transparency sorting. However, unlike using a transparent material, setting [member transparency] to a value greater than [code]0.0[/code] (exclusive) will [i]not[/i] disable shadow rendering.
In spatial shaders, [code]1.0 - transparency[/code] is set as the default value of the [code]ALPHA[/code] built-in.
Expand Down Expand Up @@ -100,6 +103,16 @@
Will only show the shadows casted from this object.
In other words, the actual mesh will not be visible, only the shadows casted from the mesh will be.
</constant>
<constant name="SHADOW_RENDER_AUTO" value="0" enum="ShadowRenderSetting">
Let Godot determine whether this instance is dynamic. Objects are determined to be dynamic when altered after being rendered to a static shadow map.
</constant>
<constant name="SHADOW_RENDER_STATIC_MAP" value="1" enum="ShadowRenderSetting">
This instance is rendered to static shadow maps. This speeds up shadow map rendering for objects that do not move.
Note: if the objects position or orientation changes, its shadow will not be updated.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Note: if the objects position or orientation changes, its shadow will not be updated.
[b]Note:[/b] If the objects position or orientation changes, its shadow will not be updated.

</constant>
<constant name="SHADOW_RENDER_DYNAMIC_MAP" value="2" enum="ShadowRenderSetting">
This instance is rendered to dynamic shadow maps. You must select this if the object changes position or orientation.
</constant>
<constant name="GI_MODE_DISABLED" value="0" enum="GIMode">
Disabled global illumination mode. Use for dynamic objects that do not contribute to global illumination (such as characters). When using [VoxelGI] and SDFGI, the geometry will [i]receive[/i] indirect lighting and reflections but the geometry will not be considered in GI baking. When using [LightmapGI], the object will receive indirect lighting using lightmap probes instead of using the baked lightmap texture.
</constant>
Expand Down
2 changes: 2 additions & 0 deletions doc/classes/ProjectSettings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2456,6 +2456,8 @@
<member name="rendering/lights_and_shadows/positional_shadow/soft_shadow_filter_quality.mobile" type="int" setter="" getter="" default="0">
Lower-end override for [member rendering/lights_and_shadows/positional_shadow/soft_shadow_filter_quality] on mobile devices, due to performance concerns or driver support.
</member>
<member name="rendering/lights_and_shadows/positional_shadow/split_static_and_dynamic_shadows" type="bool" setter="" getter="" default="false">
</member>
<member name="rendering/lights_and_shadows/use_physical_light_units" type="bool" setter="" getter="" default="false">
Enables the use of physically based units for light sources. Physically based units tend to be much larger than the arbitrary units used by Godot, but they can be used to match lighting within Godot to real-world lighting. Due to the large dynamic range of lighting conditions present in nature, Godot bakes exposure into the various lighting quantities before rendering. Most light sources bake exposure automatically at run time based on the active [CameraAttributes] resource, but [LightmapGI] and [VoxelGI] require a [CameraAttributes] resource to be set at bake time to reduce the dynamic range. At run time, Godot will automatically reconcile the baked exposure with the active exposure to ensure lighting remains consistent.
</member>
Expand Down
17 changes: 17 additions & 0 deletions doc/classes/RenderingServer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1679,6 +1679,14 @@
Sets the per-instance shader uniform on the specified 3D geometry instance. Equivalent to [method GeometryInstance3D.set_instance_shader_parameter].
</description>
</method>
<method name="instance_geometry_set_shadow_mode">
<return type="void" />
<param index="0" name="instance" type="RID" />
<param index="1" name="shadow_mode" type="int" enum="RenderingServer.ShadowDynamicMode" />
<description>
Sets the shadow mode on the specified 3D geometry instance.
</description>
</method>
<method name="instance_geometry_set_transparency">
<return type="void" />
<param index="0" name="instance" type="RID" />
Expand Down Expand Up @@ -5021,6 +5029,15 @@
<constant name="SHADOW_CASTING_SETTING_SHADOWS_ONLY" value="3" enum="ShadowCastingSetting">
Only render the shadows from the object. The object itself will not be drawn.
</constant>
<constant name="SHADOW_MODE_AUTO" value="0" enum="ShadowDynamicMode">
Shadow mode is automatically determined by changes to an instance.
</constant>
<constant name="SHADOW_MODE_STATIC" value="1" enum="ShadowDynamicMode">
Instance will be rendered to a static shadow map if applicable.
</constant>
<constant name="SHADOW_MODE_DYNAMIC" value="2" enum="ShadowDynamicMode">
Instance will be rendered to a dynamic shadow map if applicable.
</constant>
<constant name="VISIBILITY_RANGE_FADE_DISABLED" value="0" enum="VisibilityRangeFadeMode">
Disable visibility range fading for the given instance.
</constant>
Expand Down
1 change: 1 addition & 0 deletions drivers/gles3/storage/light_storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,7 @@ class LightStorage : public RendererLightStorage {

/* SHADOW ATLAS API */

virtual bool shadow_atlas_get_split_shadows() const override { return false; }
virtual RID shadow_atlas_create() override;
virtual void shadow_atlas_free(RID p_atlas) override;
virtual void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits = true) override;
Expand Down
28 changes: 28 additions & 0 deletions scene/3d/visual_instance_3d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,26 @@ GeometryInstance3D::ShadowCastingSetting GeometryInstance3D::get_cast_shadows_se
return shadow_casting_setting;
}

void GeometryInstance3D::set_shadow_render_setting(ShadowRenderSetting p_shadow_render_setting) {
shadow_render_setting = p_shadow_render_setting;

switch (p_shadow_render_setting) {
case SHADOW_RENDER_STATIC_MAP: {
RS::get_singleton()->instance_geometry_set_shadow_mode(get_instance(), RS::SHADOW_MODE_STATIC);
} break;
case SHADOW_RENDER_DYNAMIC_MAP: {
RS::get_singleton()->instance_geometry_set_shadow_mode(get_instance(), RS::SHADOW_MODE_DYNAMIC);
} break;
default: {
RS::get_singleton()->instance_geometry_set_shadow_mode(get_instance(), RS::SHADOW_MODE_AUTO);
} break;
}
}

GeometryInstance3D::ShadowRenderSetting GeometryInstance3D::get_shadow_render_setting() const {
return shadow_render_setting;
}

void GeometryInstance3D::set_extra_cull_margin(float p_margin) {
ERR_FAIL_COND(p_margin < 0);
extra_cull_margin = p_margin;
Expand Down Expand Up @@ -459,6 +479,9 @@ void GeometryInstance3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_cast_shadows_setting", "shadow_casting_setting"), &GeometryInstance3D::set_cast_shadows_setting);
ClassDB::bind_method(D_METHOD("get_cast_shadows_setting"), &GeometryInstance3D::get_cast_shadows_setting);

ClassDB::bind_method(D_METHOD("set_shadow_render_setting", "shadow_render_setting"), &GeometryInstance3D::set_shadow_render_setting);
ClassDB::bind_method(D_METHOD("get_shadow_render_setting"), &GeometryInstance3D::get_shadow_render_setting);

ClassDB::bind_method(D_METHOD("set_lod_bias", "bias"), &GeometryInstance3D::set_lod_bias);
ClassDB::bind_method(D_METHOD("get_lod_bias"), &GeometryInstance3D::get_lod_bias);

Expand Down Expand Up @@ -505,6 +528,7 @@ void GeometryInstance3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material_overlay", PROPERTY_HINT_RESOURCE_TYPE, "BaseMaterial3D,ShaderMaterial", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DEFERRED_SET_RESOURCE), "set_material_overlay", "get_material_overlay");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "transparency", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"), "set_transparency", "get_transparency");
ADD_PROPERTY(PropertyInfo(Variant::INT, "cast_shadow", PROPERTY_HINT_ENUM, "Off,On,Double-Sided,Shadows Only"), "set_cast_shadows_setting", "get_cast_shadows_setting");
ADD_PROPERTY(PropertyInfo(Variant::INT, "render_shadow", PROPERTY_HINT_ENUM, "Auto,Static,Dynamic"), "set_shadow_render_setting", "get_shadow_render_setting");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "extra_cull_margin", PROPERTY_HINT_RANGE, "0,16384,0.01,suffix:m"), "set_extra_cull_margin", "get_extra_cull_margin");
ADD_PROPERTY(PropertyInfo(Variant::AABB, "custom_aabb", PROPERTY_HINT_NONE, "suffix:m"), "set_custom_aabb", "get_custom_aabb");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lod_bias", PROPERTY_HINT_RANGE, "0.001,128,0.001"), "set_lod_bias", "get_lod_bias");
Expand All @@ -526,6 +550,10 @@ void GeometryInstance3D::_bind_methods() {
BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_DOUBLE_SIDED);
BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_SHADOWS_ONLY);

BIND_ENUM_CONSTANT(SHADOW_RENDER_AUTO);
BIND_ENUM_CONSTANT(SHADOW_RENDER_STATIC_MAP);
BIND_ENUM_CONSTANT(SHADOW_RENDER_DYNAMIC_MAP);

BIND_ENUM_CONSTANT(GI_MODE_DISABLED);
BIND_ENUM_CONSTANT(GI_MODE_STATIC);
BIND_ENUM_CONSTANT(GI_MODE_DYNAMIC);
Expand Down
12 changes: 12 additions & 0 deletions scene/3d/visual_instance_3d.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,13 @@ class GeometryInstance3D : public VisualInstance3D {
SHADOW_CASTING_SETTING_SHADOWS_ONLY = RS::SHADOW_CASTING_SETTING_SHADOWS_ONLY
};

enum ShadowRenderSetting {
SHADOW_RENDER_AUTO,
SHADOW_RENDER_STATIC_MAP,
SHADOW_RENDER_DYNAMIC_MAP,
SHADOW_RENDER_MAX
};

enum GIMode {
GI_MODE_DISABLED,
GI_MODE_STATIC,
Expand All @@ -113,6 +120,7 @@ class GeometryInstance3D : public VisualInstance3D {

private:
ShadowCastingSetting shadow_casting_setting = SHADOW_CASTING_SETTING_ON;
ShadowRenderSetting shadow_render_setting = SHADOW_RENDER_AUTO;
Ref<Material> material_override;
Ref<Material> material_overlay;

Expand Down Expand Up @@ -149,6 +157,9 @@ class GeometryInstance3D : public VisualInstance3D {
void set_cast_shadows_setting(ShadowCastingSetting p_shadow_casting_setting);
ShadowCastingSetting get_cast_shadows_setting() const;

void set_shadow_render_setting(ShadowRenderSetting p_shadow_render_setting);
ShadowRenderSetting get_shadow_render_setting() const;

void set_transparency(float p_transparency);
float get_transparency() const;

Expand Down Expand Up @@ -200,6 +211,7 @@ class GeometryInstance3D : public VisualInstance3D {
};

VARIANT_ENUM_CAST(GeometryInstance3D::ShadowCastingSetting);
VARIANT_ENUM_CAST(GeometryInstance3D::ShadowRenderSetting);
VARIANT_ENUM_CAST(GeometryInstance3D::LightmapScale);
VARIANT_ENUM_CAST(GeometryInstance3D::GIMode);
VARIANT_ENUM_CAST(GeometryInstance3D::VisibilityRangeFadeMode);
Expand Down
1 change: 1 addition & 0 deletions servers/rendering/dummy/storage/light_storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ class LightStorage : public RendererLightStorage {
void lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) override {}

/* SHADOW ATLAS API */
virtual bool shadow_atlas_get_split_shadows() const override { return false; }
virtual RID shadow_atlas_create() override { return RID(); }
virtual void shadow_atlas_free(RID p_atlas) override {}
virtual void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits = true) override {}
Expand Down
14 changes: 10 additions & 4 deletions servers/rendering/renderer_rd/effects/copy_effects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,11 +137,15 @@ CopyEffects::CopyEffects(bool p_prefer_raster_effects) {

cube_to_dp.shader_version = cube_to_dp.shader.version_create();
RID shader = cube_to_dp.shader.version_get_shader(cube_to_dp.shader_version, 0);

RD::PipelineDepthStencilState dss;
dss.enable_depth_test = true;
dss.depth_compare_operator = RD::COMPARE_OP_ALWAYS;
dss.enable_depth_write = true;
cube_to_dp.pipeline.setup(shader, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), dss, RD::PipelineColorBlendState(), 0);
cube_to_dp.pipelines[COPY_TO_DP_STATIC].setup(shader, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), dss, RD::PipelineColorBlendState(), 0);

dss.depth_compare_operator = RD::COMPARE_OP_LESS;
cube_to_dp.pipelines[COPY_TO_DP_DYNAMIC].setup(shader, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), dss, RD::PipelineColorBlendState(), 0);
}

{
Expand Down Expand Up @@ -625,7 +629,7 @@ void CopyEffects::copy_raster(RID p_source_texture, RID p_dest_framebuffer) {
RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));

RD::get_singleton()->draw_list_draw(draw_list, true);
RD::get_singleton()->draw_list_end();
RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_RASTER);
}

void CopyEffects::gaussian_blur(RID p_source_rd_texture, RID p_texture, const Rect2i &p_region, const Size2i &p_size, bool p_8bit_dst) {
Expand Down Expand Up @@ -958,7 +962,7 @@ void CopyEffects::set_color_raster(RID p_dest_texture, const Color &p_color, con
RD::get_singleton()->draw_list_end();
}

void CopyEffects::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuffer, const Rect2 &p_rect, const Vector2 &p_dst_size, float p_z_near, float p_z_far, bool p_dp_flip, BitField<RD::BarrierMask> p_post_barrier) {
void CopyEffects::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuffer, const Rect2 &p_rect, const Vector2 &p_dst_size, float p_z_near, float p_z_far, bool p_dp_flip, bool p_is_static, BitField<RD::BarrierMask> p_post_barrier) {
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
ERR_FAIL_NULL(uniform_set_cache);
MaterialStorage *material_storage = MaterialStorage::get_singleton();
Expand All @@ -983,8 +987,10 @@ void CopyEffects::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuf
RID shader = cube_to_dp.shader.version_get_shader(cube_to_dp.shader_version, 0);
ERR_FAIL_COND(shader.is_null());

CopyToDPMode mode = p_is_static ? COPY_TO_DP_STATIC : COPY_TO_DP_DYNAMIC;

RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dst_framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ);
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, cube_to_dp.pipeline.get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dst_framebuffer)));
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, cube_to_dp.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dst_framebuffer)));
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());

Expand Down
10 changes: 8 additions & 2 deletions servers/rendering/renderer_rd/effects/copy_effects.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,12 @@ class CopyEffects {

// Copy to DP

enum CopyToDPMode {
COPY_TO_DP_STATIC,
COPY_TO_DP_DYNAMIC,
COPY_TO_DP_MAX
};

struct CopyToDPPushConstant {
float z_far;
float z_near;
Expand All @@ -219,7 +225,7 @@ class CopyEffects {
struct CopyToDP {
CubeToDpShaderRD shader;
RID shader_version;
PipelineCacheRD pipeline;
PipelineCacheRD pipelines[COPY_TO_DP_MAX];
} cube_to_dp;

// Cubemap effects
Expand Down Expand Up @@ -341,7 +347,7 @@ class CopyEffects {
void set_color(RID p_dest_texture, const Color &p_color, const Rect2i &p_region, bool p_8bit_dst = false);
void set_color_raster(RID p_dest_texture, const Color &p_color, const Rect2i &p_region);

void copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuffer, const Rect2 &p_rect, const Vector2 &p_dst_size, float p_z_near, float p_z_far, bool p_dp_flip, BitField<RD::BarrierMask> p_post_barrier = RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_TRANSFER);
void copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuffer, const Rect2 &p_rect, const Vector2 &p_dst_size, float p_z_near, float p_z_far, bool p_dp_flip, bool p_is_static, BitField<RD::BarrierMask> p_post_barrier = RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_TRANSFER);
void cubemap_downsample(RID p_source_cubemap, RID p_dest_cubemap, const Size2i &p_size);
void cubemap_downsample_raster(RID p_source_cubemap, RID p_dest_framebuffer, uint32_t p_face_id, const Size2i &p_size);
void cubemap_filter(RID p_source_cubemap, Vector<RID> p_dest_cubemap, bool p_use_array);
Expand Down
36 changes: 36 additions & 0 deletions servers/rendering/renderer_rd/effects/debug_effects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,17 @@ DebugEffects::DebugEffects() {
raster_state.wireframe = true;
shadow_frustum.pipelines[SFP_WIREFRAME].setup(shadow_frustum.shader.version_get_shader(shadow_frustum.shader_version, 0), RD::RENDER_PRIMITIVE_LINES, raster_state, RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
}

{
// Combined shadow map debug shader

Vector<String> modes;
modes.push_back("");

combined_shadow_map.shader.initialize(modes);
combined_shadow_map.shader_version = combined_shadow_map.shader.version_create();
combined_shadow_map.pipeline.setup(combined_shadow_map.shader.version_get_shader(combined_shadow_map.shader_version, 0), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_blend(), 0);
}
}

void DebugEffects::_create_frustum_arrays() {
Expand Down Expand Up @@ -148,6 +159,7 @@ void DebugEffects::_create_frustum_arrays() {

DebugEffects::~DebugEffects() {
shadow_frustum.shader.version_free(shadow_frustum.shader_version);
combined_shadow_map.shader.version_free(combined_shadow_map.shader_version);

// Destroy vertex buffer and array.
if (frustum.vertex_buffer.is_valid()) {
Expand Down Expand Up @@ -326,3 +338,27 @@ void DebugEffects::draw_shadow_frustum(RID p_light, const Projection &p_cam_proj
}
}
}

void DebugEffects::draw_combined_shadow_map(RID p_static_texture, RID p_dynamic_texture, RID p_dest_fb, const Rect2 p_rect) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
void DebugEffects::draw_combined_shadow_map(RID p_static_texture, RID p_dynamic_texture, RID p_dest_fb, const Rect2 p_rect) {
void DebugEffects::draw_combined_shadow_map(RID p_static_texture, RID p_dynamic_texture, RID p_dest_fb, const Rect2 &p_rect) {

UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
ERR_FAIL_NULL(uniform_set_cache);
MaterialStorage *material_storage = MaterialStorage::get_singleton();
ERR_FAIL_NULL(material_storage);

// setup our uniforms
RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);

RD::Uniform u_static_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_static_texture }));
RD::Uniform u_dynamic_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_dynamic_texture }));

RID shader = combined_shadow_map.shader.version_get_shader(combined_shadow_map.shader_version, 0);
ERR_FAIL_COND(shader.is_null());

RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_fb, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, p_rect);
RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, combined_shadow_map.pipeline.get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_fb)));
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_static_texture), 0);
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_dynamic_texture), 1);
RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
RD::get_singleton()->draw_list_draw(draw_list, true);
RD::get_singleton()->draw_list_end();
}
Loading