Use specialization constants in clustered renderer
* Keep track of when projector, softshadow or directional sofshadow were enabled. * Enable them via specializaton constant where it makes sense. * Re-implements soft shadows. * Re-implements light projectors.
This commit is contained in:
parent
fc00a83901
commit
ad9f606ed8
22 changed files with 398 additions and 301 deletions
|
@ -4598,8 +4598,6 @@ RID RenderingDeviceVulkan::shader_create(const Vector<ShaderStageData> &p_stages
|
|||
}
|
||||
sconst.stage_flags = 1 << p_stages[i].shader_stage;
|
||||
|
||||
print_line("spec constant " + itos(i) + ": " + String(spec_constants[j]->name) + " type " + itos(spec_constants[j]->constant_type) + " id " + itos(spec_constants[j]->constant_id));
|
||||
|
||||
for (int k = 0; k < specialization_constants.size(); k++) {
|
||||
if (specialization_constants[k].constant.constant_id == sconst.constant.constant_id) {
|
||||
ERR_FAIL_COND_V_MSG(specialization_constants[k].constant.type != sconst.constant.type, RID(), "More than one specialization constant used for id (" + itos(sconst.constant.constant_id) + "), but their types differ.");
|
||||
|
@ -6047,7 +6045,7 @@ RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferForma
|
|||
const PipelineSpecializationConstant &psc = p_specialization_constants[j];
|
||||
if (psc.constant_id == sc.constant.constant_id) {
|
||||
ERR_FAIL_COND_V_MSG(psc.type != sc.constant.type, RID(), "Specialization constant provided for id (" + itos(sc.constant.constant_id) + ") is of the wrong type.");
|
||||
data_ptr[i] = sc.constant.int_value;
|
||||
data_ptr[i] = psc.int_value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -6070,14 +6068,14 @@ RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferForma
|
|||
}
|
||||
}
|
||||
|
||||
for (int k = 0; k < pipeline_stages.size(); k++) {
|
||||
if (specialization_map_entries[k].size()) {
|
||||
specialization_info.write[k].dataSize = specialization_constant_data.size() * sizeof(uint32_t);
|
||||
specialization_info.write[k].pData = data_ptr;
|
||||
specialization_info.write[k].mapEntryCount = specialization_map_entries[k].size();
|
||||
specialization_info.write[k].pMapEntries = specialization_map_entries[k].ptr();
|
||||
for (int i = 0; i < pipeline_stages.size(); i++) {
|
||||
if (specialization_map_entries[i].size()) {
|
||||
specialization_info.write[i].dataSize = specialization_constant_data.size() * sizeof(uint32_t);
|
||||
specialization_info.write[i].pData = data_ptr;
|
||||
specialization_info.write[i].mapEntryCount = specialization_map_entries[i].size();
|
||||
specialization_info.write[i].pMapEntries = specialization_map_entries[i].ptr();
|
||||
|
||||
pipeline_stages.write[k].pSpecializationInfo = specialization_info.ptr();
|
||||
pipeline_stages.write[i].pSpecializationInfo = specialization_info.ptr() + i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,6 +61,7 @@ public:
|
|||
void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override {}
|
||||
void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) override {}
|
||||
void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override {}
|
||||
void geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) override {}
|
||||
|
||||
void geometry_instance_free(GeometryInstance *p_geometry_instance) override {}
|
||||
|
||||
|
@ -413,6 +414,7 @@ public:
|
|||
RS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) override { return RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID; }
|
||||
|
||||
bool light_has_shadow(RID p_light) const override { return false; }
|
||||
bool light_has_projector(RID p_light) const override { return false; }
|
||||
|
||||
RS::LightType light_get_type(RID p_light) const override { return RS::LIGHT_OMNI; }
|
||||
AABB light_get_aabb(RID p_light) const override { return AABB(); }
|
||||
|
|
|
@ -318,11 +318,11 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
|
|||
RID prev_pipeline_rd;
|
||||
RID prev_xforms_uniform_set;
|
||||
|
||||
bool shadow_pass = (p_params->pass_mode == PASS_MODE_SHADOW) || (p_params->pass_mode == PASS_MODE_SHADOW_DP);
|
||||
bool shadow_pass = (p_pass_mode == PASS_MODE_SHADOW) || (p_pass_mode == PASS_MODE_SHADOW_DP);
|
||||
|
||||
SceneState::PushConstant push_constant;
|
||||
|
||||
if (p_params->pass_mode == PASS_MODE_DEPTH_MATERIAL) {
|
||||
if (p_pass_mode == PASS_MODE_DEPTH_MATERIAL) {
|
||||
push_constant.uv_offset = Math::make_half_float(p_params->uv_offset.y) << 16;
|
||||
push_constant.uv_offset |= Math::make_half_float(p_params->uv_offset.x);
|
||||
} else {
|
||||
|
@ -339,7 +339,7 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
|
|||
SceneShaderForwardClustered::ShaderData *shader;
|
||||
void *mesh_surface;
|
||||
|
||||
if (shadow_pass || p_params->pass_mode == PASS_MODE_DEPTH) { //regular depth pass can use these too
|
||||
if (shadow_pass || p_pass_mode == PASS_MODE_DEPTH) { //regular depth pass can use these too
|
||||
material_uniform_set = surf->material_uniform_set_shadow;
|
||||
shader = surf->shader_shadow;
|
||||
mesh_surface = surf->surface_shadow;
|
||||
|
@ -369,7 +369,7 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
|
|||
//find cull variant
|
||||
SceneShaderForwardClustered::ShaderData::CullVariant cull_variant;
|
||||
|
||||
if (p_params->pass_mode == PASS_MODE_DEPTH_MATERIAL || p_params->pass_mode == PASS_MODE_SDF || ((p_params->pass_mode == PASS_MODE_SHADOW || p_params->pass_mode == PASS_MODE_SHADOW_DP) && surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_DOUBLE_SIDED_SHADOWS)) {
|
||||
if (p_pass_mode == PASS_MODE_DEPTH_MATERIAL || p_pass_mode == PASS_MODE_SDF || ((p_pass_mode == PASS_MODE_SHADOW || p_pass_mode == PASS_MODE_SHADOW_DP) && surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_DOUBLE_SIDED_SHADOWS)) {
|
||||
cull_variant = SceneShaderForwardClustered::ShaderData::CULL_VARIANT_DOUBLE_SIDED;
|
||||
} else {
|
||||
bool mirror = surf->owner->mirror;
|
||||
|
@ -384,14 +384,30 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
|
|||
|
||||
SceneShaderForwardClustered::ShaderVersion shader_version = SceneShaderForwardClustered::SHADER_VERSION_MAX; // Assigned to silence wrong -Wmaybe-initialized.
|
||||
|
||||
switch (p_params->pass_mode) {
|
||||
uint32_t pipeline_specialization = 0;
|
||||
|
||||
if (p_pass_mode == PASS_MODE_COLOR || p_pass_mode == PASS_MODE_COLOR_TRANSPARENT || p_pass_mode == PASS_MODE_COLOR_SPECULAR) {
|
||||
if (element_info.uses_softshadow) {
|
||||
pipeline_specialization |= SceneShaderForwardClustered::SHADER_SPECIALIZATION_SOFT_SHADOWS;
|
||||
}
|
||||
if (element_info.uses_projector) {
|
||||
pipeline_specialization |= SceneShaderForwardClustered::SHADER_SPECIALIZATION_PROJECTOR;
|
||||
}
|
||||
|
||||
if (p_params->use_directional_soft_shadow) {
|
||||
pipeline_specialization |= SceneShaderForwardClustered::SHADER_SPECIALIZATION_DIRECTIONAL_SOFT_SHADOWS;
|
||||
}
|
||||
}
|
||||
|
||||
switch (p_pass_mode) {
|
||||
case PASS_MODE_COLOR:
|
||||
case PASS_MODE_COLOR_TRANSPARENT: {
|
||||
if (element_info.uses_lightmap) {
|
||||
shader_version = SceneShaderForwardClustered::SHADER_VERSION_LIGHTMAP_COLOR_PASS;
|
||||
} else if (element_info.uses_forward_gi) {
|
||||
shader_version = SceneShaderForwardClustered::SHADER_VERSION_COLOR_PASS_WITH_FORWARD_GI;
|
||||
} else {
|
||||
if (element_info.uses_forward_gi) {
|
||||
pipeline_specialization |= SceneShaderForwardClustered::SHADER_SPECIALIZATION_FORWARD_GI;
|
||||
}
|
||||
shader_version = SceneShaderForwardClustered::SHADER_VERSION_COLOR_PASS;
|
||||
}
|
||||
} break;
|
||||
|
@ -452,7 +468,7 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
|
|||
prev_index_array_rd = index_array_rd;
|
||||
}
|
||||
|
||||
RID pipeline_rd = pipeline->get_render_pipeline(vertex_format, framebuffer_format, p_params->force_wireframe);
|
||||
RID pipeline_rd = pipeline->get_render_pipeline(vertex_format, framebuffer_format, p_params->force_wireframe, 0, pipeline_specialization);
|
||||
|
||||
if (pipeline_rd != prev_pipeline_rd) {
|
||||
// checking with prev shader does not make so much sense, as
|
||||
|
@ -848,7 +864,7 @@ void RenderForwardClustered::_fill_instance_data(RenderListType p_render_list, i
|
|||
|
||||
bool cant_repeat = instance_data.flags & INSTANCE_DATA_FLAG_MULTIMESH || inst->mesh_instance.is_valid();
|
||||
|
||||
if (prev_surface != nullptr && !cant_repeat && prev_surface->sort.sort_key1 == surface->sort.sort_key1 && prev_surface->sort.sort_key2 == surface->sort.sort_key2) {
|
||||
if (prev_surface != nullptr && !cant_repeat && prev_surface->sort.sort_key1 == surface->sort.sort_key1 && prev_surface->sort.sort_key2 == surface->sort.sort_key2 && repeats < RenderElementInfo::MAX_REPEATS) {
|
||||
//this element is the same as the previous one, count repeats to draw it using instancing
|
||||
repeats++;
|
||||
} else {
|
||||
|
@ -868,6 +884,8 @@ void RenderForwardClustered::_fill_instance_data(RenderListType p_render_list, i
|
|||
element_info.lod_index = surface->sort.lod_index;
|
||||
element_info.uses_forward_gi = surface->sort.uses_forward_gi;
|
||||
element_info.uses_lightmap = surface->sort.uses_lightmap;
|
||||
element_info.uses_softshadow = surface->sort.uses_softshadow;
|
||||
element_info.uses_projector = surface->sort.uses_projector;
|
||||
|
||||
if (cant_repeat) {
|
||||
prev_surface = nullptr;
|
||||
|
@ -1375,7 +1393,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
|
|||
RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_OPAQUE, nullptr, RID());
|
||||
|
||||
bool finish_depth = using_ssao || using_sdfgi || using_voxelgi;
|
||||
RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, depth_pass_mode, render_buffer == nullptr, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold);
|
||||
RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, depth_pass_mode, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold);
|
||||
_render_list_with_threads(&render_list_params, depth_framebuffer, needs_pre_resolve ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, needs_pre_resolve ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_CLEAR, finish_depth ? RD::FINAL_ACTION_READ : RD::FINAL_ACTION_CONTINUE, needs_pre_resolve ? Vector<Color>() : depth_pass_clear);
|
||||
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
|
@ -1432,7 +1450,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
|
|||
}
|
||||
|
||||
RID framebuffer = using_separate_specular ? opaque_specular_framebuffer : opaque_framebuffer;
|
||||
RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, using_separate_specular ? PASS_MODE_COLOR_SPECULAR : PASS_MODE_COLOR, render_buffer == nullptr, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold);
|
||||
RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, using_separate_specular ? PASS_MODE_COLOR_SPECULAR : PASS_MODE_COLOR, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold);
|
||||
_render_list_with_threads(&render_list_params, framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, depth_pre_pass ? (continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP) : RD::INITIAL_ACTION_CLEAR, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0);
|
||||
if (will_continue_color && using_separate_specular) {
|
||||
// close the specular framebuffer, as it's no longer used
|
||||
|
@ -1529,7 +1547,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
|
|||
_setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false);
|
||||
|
||||
{
|
||||
RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), false, PASS_MODE_COLOR, render_buffer == nullptr, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold);
|
||||
RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), false, PASS_MODE_COLOR, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_lod_threshold);
|
||||
_render_list_with_threads(&render_list_params, alpha_framebuffer, can_continue_color ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, can_continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ);
|
||||
}
|
||||
|
||||
|
@ -1631,7 +1649,7 @@ void RenderForwardClustered::_render_shadow_end(uint32_t p_barrier) {
|
|||
|
||||
for (uint32_t i = 0; i < scene_state.shadow_passes.size(); i++) {
|
||||
SceneState::ShadowPass &shadow_pass = scene_state.shadow_passes[i];
|
||||
RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, true, shadow_pass.rp_uniform_set, false, Vector2(), shadow_pass.camera_plane, shadow_pass.lod_distance_multiplier, shadow_pass.screen_lod_threshold, shadow_pass.element_from, RD::BARRIER_MASK_NO_BARRIER);
|
||||
RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, true, false, shadow_pass.rp_uniform_set, false, Vector2(), shadow_pass.camera_plane, shadow_pass.lod_distance_multiplier, shadow_pass.screen_lod_threshold, shadow_pass.element_from, RD::BARRIER_MASK_NO_BARRIER);
|
||||
_render_list_with_threads(&render_list_parameters, shadow_pass.framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, shadow_pass.initial_depth_action, shadow_pass.final_depth_action, Vector<Color>(), 1.0, 0, shadow_pass.rect);
|
||||
}
|
||||
|
||||
|
@ -1672,7 +1690,7 @@ void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, con
|
|||
|
||||
{
|
||||
//regular forward for now
|
||||
RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), false, pass_mode, true, rp_uniform_set);
|
||||
RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), false, pass_mode, true, false, rp_uniform_set);
|
||||
_render_list_with_threads(&render_list_params, p_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ);
|
||||
}
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
|
@ -1707,7 +1725,7 @@ void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform
|
|||
RENDER_TIMESTAMP("Render Material");
|
||||
|
||||
{
|
||||
RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, true, rp_uniform_set);
|
||||
RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, true, false, rp_uniform_set);
|
||||
//regular forward for now
|
||||
Vector<Color> clear;
|
||||
clear.push_back(Color(0, 0, 0, 0));
|
||||
|
@ -1750,7 +1768,7 @@ void RenderForwardClustered::_render_uv2(const PagedArray<GeometryInstance *> &p
|
|||
RENDER_TIMESTAMP("Render Material");
|
||||
|
||||
{
|
||||
RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, true, rp_uniform_set, true);
|
||||
RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, true, false, rp_uniform_set, true);
|
||||
//regular forward for now
|
||||
Vector<Color> clear;
|
||||
clear.push_back(Color(0, 0, 0, 0));
|
||||
|
@ -1868,7 +1886,7 @@ void RenderForwardClustered::_render_sdfgi(RID p_render_buffers, const Vector3i
|
|||
E = sdfgi_framebuffer_size_cache.insert(fb_size, fb);
|
||||
}
|
||||
|
||||
RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, true, rp_uniform_set, false);
|
||||
RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), true, pass_mode, true, false, rp_uniform_set, false);
|
||||
_render_list_with_threads(&render_list_params, E->get(), RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, Vector<Color>(), 1.0, 0, Rect2(), sbs);
|
||||
}
|
||||
|
||||
|
@ -2511,12 +2529,14 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet
|
|||
sdcache->sort.sort_key2 = 0;
|
||||
|
||||
sdcache->sort.surface_index = p_surface;
|
||||
sdcache->sort.material_id_low = p_material_id & 0x3FFF;
|
||||
sdcache->sort.material_id_hi = p_material_id >> 14;
|
||||
sdcache->sort.material_id_low = p_material_id & 0xFFFF;
|
||||
sdcache->sort.material_id_hi = p_material_id >> 16;
|
||||
sdcache->sort.shader_id = p_shader_id;
|
||||
sdcache->sort.geometry_id = p_mesh.get_local_index(); //only meshes can repeat anyway
|
||||
sdcache->sort.uses_forward_gi = ginstance->can_sdfgi;
|
||||
sdcache->sort.priority = p_material->priority;
|
||||
sdcache->sort.uses_projector = ginstance->using_projectors;
|
||||
sdcache->sort.uses_softshadow = ginstance->using_softshadows;
|
||||
}
|
||||
|
||||
void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, RID p_material, RID p_mesh) {
|
||||
|
@ -2911,6 +2931,14 @@ void RenderForwardClustered::geometry_instance_pair_voxel_gi_instances(GeometryI
|
|||
}
|
||||
}
|
||||
|
||||
void RenderForwardClustered::geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) {
|
||||
GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
|
||||
ERR_FAIL_COND(!ginstance);
|
||||
ginstance->using_projectors = p_projector;
|
||||
ginstance->using_softshadows = p_softshadow;
|
||||
_geometry_instance_mark_dirty(ginstance);
|
||||
}
|
||||
|
||||
RenderForwardClustered::RenderForwardClustered(RendererStorageRD *p_storage) :
|
||||
RendererSceneRenderRD(p_storage) {
|
||||
singleton = this;
|
||||
|
|
|
@ -156,8 +156,9 @@ class RenderForwardClustered : public RendererSceneRenderRD {
|
|||
RD::FramebufferFormatID framebuffer_format = 0;
|
||||
uint32_t element_offset = 0;
|
||||
uint32_t barrier = RD::BARRIER_MASK_ALL;
|
||||
bool use_directional_soft_shadow = false;
|
||||
|
||||
RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL) {
|
||||
RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, bool p_use_directional_soft_shadows, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_lod_threshold = 0.0, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL) {
|
||||
elements = p_elements;
|
||||
element_info = p_element_info;
|
||||
element_count = p_element_count;
|
||||
|
@ -172,6 +173,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
|
|||
screen_lod_threshold = p_screen_lod_threshold;
|
||||
element_offset = p_element_offset;
|
||||
barrier = p_barrier;
|
||||
use_directional_soft_shadow = p_use_directional_soft_shadows;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -353,7 +355,10 @@ class RenderForwardClustered : public RendererSceneRenderRD {
|
|||
void _setup_lightmaps(const PagedArray<RID> &p_lightmaps, const Transform3D &p_cam_transform);
|
||||
|
||||
struct RenderElementInfo {
|
||||
uint32_t repeat : 22;
|
||||
enum { MAX_REPEATS = (1 << 20) - 1 };
|
||||
uint32_t repeat : 20;
|
||||
uint32_t uses_projector : 1;
|
||||
uint32_t uses_softshadow : 1;
|
||||
uint32_t uses_lightmap : 1;
|
||||
uint32_t uses_forward_gi : 1;
|
||||
uint32_t lod_index : 8;
|
||||
|
@ -402,12 +407,14 @@ class RenderForwardClustered : public RendererSceneRenderRD {
|
|||
union {
|
||||
struct {
|
||||
uint64_t lod_index : 8;
|
||||
uint64_t surface_index : 10;
|
||||
uint64_t surface_index : 8;
|
||||
uint64_t geometry_id : 32;
|
||||
uint64_t material_id_low : 14;
|
||||
uint64_t material_id_low : 16;
|
||||
|
||||
uint64_t material_id_hi : 18;
|
||||
uint64_t material_id_hi : 16;
|
||||
uint64_t shader_id : 32;
|
||||
uint64_t uses_softshadow : 1;
|
||||
uint64_t uses_projector : 1;
|
||||
uint64_t uses_forward_gi : 1;
|
||||
uint64_t uses_lightmap : 1;
|
||||
uint64_t depth_layer : 4;
|
||||
|
@ -455,6 +462,8 @@ class RenderForwardClustered : public RendererSceneRenderRD {
|
|||
uint32_t trail_steps = 1;
|
||||
RID mesh_instance;
|
||||
bool can_sdfgi = false;
|
||||
bool using_projectors = false;
|
||||
bool using_softshadows = false;
|
||||
//used during setup
|
||||
uint32_t base_flags = 0;
|
||||
Transform3D transform;
|
||||
|
@ -604,6 +613,8 @@ public:
|
|||
virtual void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) override;
|
||||
virtual void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override;
|
||||
|
||||
virtual void geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) override;
|
||||
|
||||
virtual bool free(RID p_rid) override;
|
||||
|
||||
RenderForwardClustered(RendererStorageRD *p_storage);
|
||||
|
|
|
@ -287,7 +287,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
|
|||
multisample_state.enable_alpha_to_one = true;
|
||||
}
|
||||
|
||||
if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_COLOR_PASS_WITH_FORWARD_GI || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS) {
|
||||
if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS) {
|
||||
blend_state = blend_state_blend;
|
||||
if (depth_draw == DEPTH_DRAW_OPAQUE) {
|
||||
depth_stencil.enable_depth_write = false; //alpha does not draw depth
|
||||
|
@ -305,7 +305,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
|
|||
continue; // do not use this version (will error if using it is attempted)
|
||||
}
|
||||
} else {
|
||||
if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_COLOR_PASS_WITH_FORWARD_GI || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS) {
|
||||
if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS) {
|
||||
blend_state = blend_state_opaque;
|
||||
} else if (k == SHADER_VERSION_DEPTH_PASS || k == SHADER_VERSION_DEPTH_PASS_DP) {
|
||||
//none, leave empty
|
||||
|
@ -483,7 +483,6 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
|
|||
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_MATERIAL\n"); // SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL
|
||||
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_SDF\n"); // SHADER_VERSION_DEPTH_PASS_WITH_SDF
|
||||
shader_versions.push_back(""); // SHADER_VERSION_COLOR_PASS
|
||||
shader_versions.push_back("\n#define USE_FORWARD_GI\n"); // SHADER_VERSION_COLOR_PASS_WITH_FORWARD_GI
|
||||
shader_versions.push_back("\n#define MODE_MULTIPLE_RENDER_TARGETS\n"); // SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR
|
||||
shader_versions.push_back("\n#define USE_LIGHTMAP\n"); // SHADER_VERSION_LIGHTMAP_COLOR_PASS
|
||||
shader_versions.push_back("\n#define MODE_MULTIPLE_RENDER_TARGETS\n#define USE_LIGHTMAP\n"); // SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR
|
||||
|
|
|
@ -52,7 +52,6 @@ public:
|
|||
SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL,
|
||||
SHADER_VERSION_DEPTH_PASS_WITH_SDF,
|
||||
SHADER_VERSION_COLOR_PASS,
|
||||
SHADER_VERSION_COLOR_PASS_WITH_FORWARD_GI,
|
||||
SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR,
|
||||
SHADER_VERSION_LIGHTMAP_COLOR_PASS,
|
||||
SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR,
|
||||
|
@ -60,6 +59,13 @@ public:
|
|||
SHADER_VERSION_MAX
|
||||
};
|
||||
|
||||
enum ShaderSpecializations {
|
||||
SHADER_SPECIALIZATION_FORWARD_GI = 1 << 0,
|
||||
SHADER_SPECIALIZATION_PROJECTOR = 1 << 1,
|
||||
SHADER_SPECIALIZATION_SOFT_SHADOWS = 1 << 2,
|
||||
SHADER_SPECIALIZATION_DIRECTIONAL_SOFT_SHADOWS = 1 << 3,
|
||||
};
|
||||
|
||||
struct ShaderData : public RendererStorageRD::ShaderData {
|
||||
enum BlendMode { //used internally
|
||||
BLEND_MODE_MIX,
|
||||
|
|
|
@ -1801,6 +1801,9 @@ void RenderForwardMobile::geometry_instance_pair_voxel_gi_instances(GeometryInst
|
|||
// We do not have this here!
|
||||
}
|
||||
|
||||
void RenderForwardMobile::geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) {
|
||||
}
|
||||
|
||||
void RenderForwardMobile::_geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance) {
|
||||
GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
|
||||
if (ginstance->dirty_list_element.in_list()) {
|
||||
|
|
|
@ -594,6 +594,8 @@ public:
|
|||
virtual void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) override;
|
||||
virtual void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override;
|
||||
|
||||
virtual void geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) override;
|
||||
|
||||
virtual bool free(RID p_rid) override;
|
||||
|
||||
virtual bool is_dynamic_gi_supported() const override;
|
||||
|
|
|
@ -31,14 +31,30 @@
|
|||
#include "pipeline_cache_rd.h"
|
||||
#include "core/os/memory.h"
|
||||
|
||||
RID PipelineCacheRD::_generate_version(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id, bool p_wireframe, uint32_t p_render_pass) {
|
||||
RID PipelineCacheRD::_generate_version(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id, bool p_wireframe, uint32_t p_render_pass, uint32_t p_bool_specializations) {
|
||||
RD::PipelineMultisampleState multisample_state_version = multisample_state;
|
||||
multisample_state_version.sample_count = RD::get_singleton()->framebuffer_format_get_texture_samples(p_framebuffer_format_id, p_render_pass);
|
||||
|
||||
RD::PipelineRasterizationState raster_state_version = rasterization_state;
|
||||
raster_state_version.wireframe = p_wireframe;
|
||||
|
||||
RID pipeline = RD::get_singleton()->render_pipeline_create(shader, p_framebuffer_format_id, p_vertex_format_id, render_primitive, raster_state_version, multisample_state_version, depth_stencil_state, blend_state, dynamic_state_flags, p_render_pass);
|
||||
Vector<RD::PipelineSpecializationConstant> specialization_constants = base_specialization_constants;
|
||||
|
||||
uint32_t bool_index = 0;
|
||||
uint32_t bool_specializations = p_bool_specializations;
|
||||
while (bool_specializations) {
|
||||
if (bool_specializations & (1 << bool_index)) {
|
||||
RD::PipelineSpecializationConstant sc;
|
||||
sc.bool_value = true;
|
||||
sc.constant_id = bool_index;
|
||||
sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL;
|
||||
specialization_constants.push_back(sc);
|
||||
bool_specializations &= ~(1 << bool_index);
|
||||
}
|
||||
bool_index++;
|
||||
}
|
||||
|
||||
RID pipeline = RD::get_singleton()->render_pipeline_create(shader, p_framebuffer_format_id, p_vertex_format_id, render_primitive, raster_state_version, multisample_state_version, depth_stencil_state, blend_state, dynamic_state_flags, p_render_pass, specialization_constants);
|
||||
ERR_FAIL_COND_V(pipeline.is_null(), RID());
|
||||
versions = (Version *)memrealloc(versions, sizeof(Version) * (version_count + 1));
|
||||
versions[version_count].framebuffer_id = p_framebuffer_format_id;
|
||||
|
@ -46,6 +62,7 @@ RID PipelineCacheRD::_generate_version(RD::VertexFormatID p_vertex_format_id, RD
|
|||
versions[version_count].wireframe = p_wireframe;
|
||||
versions[version_count].pipeline = pipeline;
|
||||
versions[version_count].render_pass = p_render_pass;
|
||||
versions[version_count].bool_specializations = p_bool_specializations;
|
||||
version_count++;
|
||||
return pipeline;
|
||||
}
|
||||
|
@ -64,7 +81,7 @@ void PipelineCacheRD::_clear() {
|
|||
}
|
||||
}
|
||||
|
||||
void PipelineCacheRD::setup(RID p_shader, RD::RenderPrimitive p_primitive, const RD::PipelineRasterizationState &p_rasterization_state, RD::PipelineMultisampleState p_multisample, const RD::PipelineDepthStencilState &p_depth_stencil_state, const RD::PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags) {
|
||||
void PipelineCacheRD::setup(RID p_shader, RD::RenderPrimitive p_primitive, const RD::PipelineRasterizationState &p_rasterization_state, RD::PipelineMultisampleState p_multisample, const RD::PipelineDepthStencilState &p_depth_stencil_state, const RD::PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags, const Vector<RD::PipelineSpecializationConstant> &p_base_specialization_constants) {
|
||||
ERR_FAIL_COND(p_shader.is_null());
|
||||
_clear();
|
||||
shader = p_shader;
|
||||
|
@ -75,6 +92,7 @@ void PipelineCacheRD::setup(RID p_shader, RD::RenderPrimitive p_primitive, const
|
|||
depth_stencil_state = p_depth_stencil_state;
|
||||
blend_state = p_blend_state;
|
||||
dynamic_state_flags = p_dynamic_state_flags;
|
||||
base_specialization_constants = p_base_specialization_constants;
|
||||
}
|
||||
|
||||
void PipelineCacheRD::update_shader(RID p_shader) {
|
||||
|
|
|
@ -46,27 +46,29 @@ class PipelineCacheRD {
|
|||
RD::PipelineDepthStencilState depth_stencil_state;
|
||||
RD::PipelineColorBlendState blend_state;
|
||||
int dynamic_state_flags;
|
||||
Vector<RD::PipelineSpecializationConstant> base_specialization_constants;
|
||||
|
||||
struct Version {
|
||||
RD::VertexFormatID vertex_id;
|
||||
RD::FramebufferFormatID framebuffer_id;
|
||||
uint32_t render_pass;
|
||||
bool wireframe;
|
||||
uint32_t bool_specializations;
|
||||
RID pipeline;
|
||||
};
|
||||
|
||||
Version *versions;
|
||||
uint32_t version_count;
|
||||
|
||||
RID _generate_version(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id, bool p_wireframe, uint32_t p_render_pass);
|
||||
RID _generate_version(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id, bool p_wireframe, uint32_t p_render_pass, uint32_t p_bool_specializations = 0);
|
||||
|
||||
void _clear();
|
||||
|
||||
public:
|
||||
void setup(RID p_shader, RD::RenderPrimitive p_primitive, const RD::PipelineRasterizationState &p_rasterization_state, RD::PipelineMultisampleState p_multisample, const RD::PipelineDepthStencilState &p_depth_stencil_state, const RD::PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags = 0);
|
||||
void setup(RID p_shader, RD::RenderPrimitive p_primitive, const RD::PipelineRasterizationState &p_rasterization_state, RD::PipelineMultisampleState p_multisample, const RD::PipelineDepthStencilState &p_depth_stencil_state, const RD::PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags = 0, const Vector<RD::PipelineSpecializationConstant> &p_base_specialization_constants = Vector<RD::PipelineSpecializationConstant>());
|
||||
void update_shader(RID p_shader);
|
||||
|
||||
_FORCE_INLINE_ RID get_render_pipeline(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id, bool p_wireframe = false, uint32_t p_render_pass = 0) {
|
||||
_FORCE_INLINE_ RID get_render_pipeline(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id, bool p_wireframe = false, uint32_t p_render_pass = 0, uint32_t p_bool_specializations = 0) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
ERR_FAIL_COND_V_MSG(shader.is_null(), RID(),
|
||||
"Attempted to use an unused shader variant (shader is null),");
|
||||
|
@ -75,13 +77,13 @@ public:
|
|||
spin_lock.lock();
|
||||
RID result;
|
||||
for (uint32_t i = 0; i < version_count; i++) {
|
||||
if (versions[i].vertex_id == p_vertex_format_id && versions[i].framebuffer_id == p_framebuffer_format_id && versions[i].wireframe == p_wireframe && versions[i].render_pass == p_render_pass) {
|
||||
if (versions[i].vertex_id == p_vertex_format_id && versions[i].framebuffer_id == p_framebuffer_format_id && versions[i].wireframe == p_wireframe && versions[i].render_pass == p_render_pass && versions[i].bool_specializations == p_bool_specializations) {
|
||||
result = versions[i].pipeline;
|
||||
spin_lock.unlock();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
result = _generate_version(p_vertex_format_id, p_framebuffer_format_id, p_wireframe, p_render_pass);
|
||||
result = _generate_version(p_vertex_format_id, p_framebuffer_format_id, p_wireframe, p_render_pass, p_bool_specializations);
|
||||
spin_lock.unlock();
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -2377,7 +2377,7 @@ void RendererSceneRenderRD::_setup_reflections(const PagedArray<RID> &p_reflecti
|
|||
}
|
||||
}
|
||||
|
||||
void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const Transform3D &p_camera_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count) {
|
||||
void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const Transform3D &p_camera_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count, bool &r_directional_light_soft_shadows) {
|
||||
Transform3D inverse_transform = p_camera_transform.affine_inverse();
|
||||
|
||||
r_directional_light_count = 0;
|
||||
|
@ -2389,6 +2389,8 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
|
|||
cluster.omni_light_count = 0;
|
||||
cluster.spot_light_count = 0;
|
||||
|
||||
r_directional_light_soft_shadows = false;
|
||||
|
||||
for (int i = 0; i < (int)p_lights.size(); i++) {
|
||||
LightInstance *li = light_instance_owner.getornull(p_lights[i]);
|
||||
if (!li) {
|
||||
|
@ -2427,6 +2429,9 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const
|
|||
// technically this will keep expanding until reaching the sun, but all we care
|
||||
// is expand until we reach the radius of the near plane (there can't be more occluders than that)
|
||||
angular_diameter = Math::tan(Math::deg2rad(angular_diameter));
|
||||
if (storage->light_has_shadow(base)) {
|
||||
r_directional_light_soft_shadows = true;
|
||||
}
|
||||
} else {
|
||||
angular_diameter = 0.0;
|
||||
}
|
||||
|
@ -3621,7 +3626,7 @@ void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool
|
|||
|
||||
uint32_t directional_light_count = 0;
|
||||
uint32_t positional_light_count = 0;
|
||||
_setup_lights(*p_render_data->lights, p_render_data->cam_transform, p_render_data->shadow_atlas, using_shadows, directional_light_count, positional_light_count);
|
||||
_setup_lights(*p_render_data->lights, p_render_data->cam_transform, p_render_data->shadow_atlas, using_shadows, directional_light_count, positional_light_count, p_render_data->directional_light_soft_shadows);
|
||||
_setup_decals(*p_render_data->decals, p_render_data->cam_transform.affine_inverse());
|
||||
|
||||
p_render_data->directional_light_count = directional_light_count;
|
||||
|
|
|
@ -80,6 +80,7 @@ struct RenderDataRD {
|
|||
uint32_t cluster_max_elements = 0;
|
||||
|
||||
uint32_t directional_light_count = 0;
|
||||
bool directional_light_soft_shadows = false;
|
||||
|
||||
RendererScene::RenderInfo *render_info = nullptr;
|
||||
};
|
||||
|
@ -99,7 +100,7 @@ protected:
|
|||
};
|
||||
virtual RenderBufferData *_create_render_buffer_data() = 0;
|
||||
|
||||
void _setup_lights(const PagedArray<RID> &p_lights, const Transform3D &p_camera_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count);
|
||||
void _setup_lights(const PagedArray<RID> &p_lights, const Transform3D &p_camera_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count, bool &r_directional_light_soft_shadows);
|
||||
void _setup_decals(const PagedArray<RID> &p_decals, const Transform3D &p_camera_inverse_xform);
|
||||
void _setup_reflections(const PagedArray<RID> &p_reflections, const Transform3D &p_camera_inverse_transform, RID p_environment);
|
||||
|
||||
|
|
|
@ -2531,6 +2531,8 @@ void RendererStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_su
|
|||
Mesh *mesh = mesh_owner.getornull(p_mesh);
|
||||
ERR_FAIL_COND(!mesh);
|
||||
|
||||
ERR_FAIL_COND(mesh->surface_count == RS::MAX_MESH_SURFACES);
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
//do a validation, to catch errors first
|
||||
{
|
||||
|
@ -5886,6 +5888,10 @@ void RendererStorageRD::light_set_param(RID p_light, RS::LightParam p_param, flo
|
|||
ERR_FAIL_COND(!light);
|
||||
ERR_FAIL_INDEX(p_param, RS::LIGHT_PARAM_MAX);
|
||||
|
||||
if (light->param[p_param] == p_value) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (p_param) {
|
||||
case RS::LIGHT_PARAM_RANGE:
|
||||
case RS::LIGHT_PARAM_SPOT_ANGLE:
|
||||
|
@ -5899,6 +5905,12 @@ void RendererStorageRD::light_set_param(RID p_light, RS::LightParam p_param, flo
|
|||
light->version++;
|
||||
light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT);
|
||||
} break;
|
||||
case RS::LIGHT_PARAM_SIZE: {
|
||||
if ((light->param[p_param] > CMP_EPSILON) != (p_value > CMP_EPSILON)) {
|
||||
//changing from no size to size and the opposite
|
||||
light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR);
|
||||
}
|
||||
} break;
|
||||
default: {
|
||||
}
|
||||
}
|
||||
|
@ -5935,9 +5947,12 @@ void RendererStorageRD::light_set_projector(RID p_light, RID p_texture) {
|
|||
|
||||
light->projector = p_texture;
|
||||
|
||||
if (light->type != RS::LIGHT_DIRECTIONAL && light->projector.is_valid()) {
|
||||
if (light->type != RS::LIGHT_DIRECTIONAL) {
|
||||
if (light->projector.is_valid()) {
|
||||
texture_add_to_decal_atlas(light->projector, light->type == RS::LIGHT_OMNI);
|
||||
}
|
||||
light->dependency.changed_notify(DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR);
|
||||
}
|
||||
}
|
||||
|
||||
void RendererStorageRD::light_set_negative(RID p_light, bool p_enable) {
|
||||
|
|
|
@ -1888,6 +1888,13 @@ public:
|
|||
return light->shadow;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ bool light_has_projector(RID p_light) const {
|
||||
const Light *light = light_owner.getornull(p_light);
|
||||
ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL);
|
||||
|
||||
return texture_owner.owns(light->projector);
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ bool light_is_negative(RID p_light) const {
|
||||
const Light *light = light_owner.getornull(p_light);
|
||||
ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL);
|
||||
|
|
|
@ -356,6 +356,13 @@ void main() {
|
|||
|
||||
#VERSION_DEFINES
|
||||
|
||||
/* Specialization Constants */
|
||||
|
||||
layout(constant_id = 0) const bool sc_use_forward_gi = false;
|
||||
layout(constant_id = 1) const bool sc_use_light_projector = false;
|
||||
layout(constant_id = 2) const bool sc_use_light_soft_shadows = false;
|
||||
layout(constant_id = 3) const bool sc_use_directional_soft_shadows = false;
|
||||
|
||||
#include "scene_forward_clustered_inc.glsl"
|
||||
|
||||
/* Varyings */
|
||||
|
@ -450,12 +457,8 @@ layout(location = 0) out vec4 frag_color;
|
|||
|
||||
#include "scene_forward_lights_inc.glsl"
|
||||
|
||||
#ifdef USE_FORWARD_GI
|
||||
|
||||
#include "scene_forward_gi_inc.glsl"
|
||||
|
||||
#endif //USE_FORWARD_GI
|
||||
|
||||
#endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
|
||||
|
||||
#ifndef MODE_RENDER_DEPTH
|
||||
|
@ -963,9 +966,9 @@ void main() {
|
|||
ambient_light += textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw, 0.0).rgb;
|
||||
}
|
||||
}
|
||||
#elif defined(USE_FORWARD_GI)
|
||||
#else
|
||||
|
||||
if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_SDFGI)) { //has lightmap capture
|
||||
if (sc_use_forward_gi && bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_SDFGI)) { //has lightmap capture
|
||||
|
||||
//make vertex orientation the world one, but still align to camera
|
||||
vec3 cam_pos = mat3(scene_data.camera_matrix) * vertex;
|
||||
|
@ -1037,7 +1040,7 @@ void main() {
|
|||
}
|
||||
}
|
||||
|
||||
if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_VOXEL_GI)) { // process voxel_gi_instances
|
||||
if (sc_use_forward_gi && bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_VOXEL_GI)) { // process voxel_gi_instances
|
||||
|
||||
uint index1 = instances.data[instance_index].gi_offset & 0xFFFF;
|
||||
vec3 ref_vec = normalize(reflect(normalize(vertex), normal));
|
||||
|
@ -1068,9 +1071,8 @@ void main() {
|
|||
specular_light = spec_accum.rgb;
|
||||
ambient_light = amb_accum.rgb;
|
||||
}
|
||||
#else
|
||||
|
||||
if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_GI_BUFFERS)) { //use GI buffers
|
||||
if (!sc_use_forward_gi && bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_GI_BUFFERS)) { //use GI buffers
|
||||
|
||||
vec2 coord;
|
||||
|
||||
|
@ -1101,7 +1103,7 @@ void main() {
|
|||
ambient_light = mix(ambient_light, buffer_ambient.rgb, buffer_ambient.a);
|
||||
specular_light = mix(specular_light, buffer_reflection.rgb, buffer_reflection.a);
|
||||
}
|
||||
#endif
|
||||
#endif // !USE_LIGHTMAP
|
||||
|
||||
if (scene_data.ssao_enabled) {
|
||||
float ssao = texture(sampler2D(ao_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), screen_uv).r;
|
||||
|
@ -1228,12 +1230,11 @@ void main() {
|
|||
|
||||
float shadow = 1.0;
|
||||
|
||||
#ifdef USE_SOFT_SHADOWS
|
||||
//version with soft shadows, more expensive
|
||||
if (directional_lights.data[i].shadow_enabled) {
|
||||
if (sc_use_directional_soft_shadows && directional_lights.data[i].softshadow_angle > 0) {
|
||||
float depth_z = -vertex.z;
|
||||
|
||||
vec4 pssm_coord;
|
||||
vec3 shadow_color = vec3(0.0);
|
||||
vec3 light_dir = directional_lights.data[i].direction;
|
||||
|
||||
|
@ -1243,163 +1244,100 @@ void main() {
|
|||
normal_bias -= light_dir * dot(light_dir, normal_bias); \
|
||||
m_var.xyz += normal_bias;
|
||||
|
||||
uint blend_index = 0;
|
||||
|
||||
if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
|
||||
vec4 v = vec4(vertex, 1.0);
|
||||
|
||||
BIAS_FUNC(v, 0)
|
||||
|
||||
pssm_coord = (directional_lights.data[i].shadow_matrix1 * v);
|
||||
vec4 pssm_coord = (directional_lights.data[i].shadow_matrix1 * v);
|
||||
pssm_coord /= pssm_coord.w;
|
||||
|
||||
if (directional_lights.data[i].softshadow_angle > 0) {
|
||||
float range_pos = dot(directional_lights.data[i].direction, v.xyz);
|
||||
float range_begin = directional_lights.data[i].shadow_range_begin.x;
|
||||
float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle;
|
||||
vec2 tex_scale = directional_lights.data[i].uv_scale1 * test_radius;
|
||||
shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
|
||||
} else {
|
||||
shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
|
||||
blend_index++;
|
||||
}
|
||||
|
||||
shadow_color = directional_lights.data[i].shadow_color1.rgb;
|
||||
|
||||
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
|
||||
if (blend_index < 2 && depth_z < directional_lights.data[i].shadow_split_offsets.y) {
|
||||
vec4 v = vec4(vertex, 1.0);
|
||||
|
||||
BIAS_FUNC(v, 1)
|
||||
|
||||
pssm_coord = (directional_lights.data[i].shadow_matrix2 * v);
|
||||
vec4 pssm_coord = (directional_lights.data[i].shadow_matrix2 * v);
|
||||
pssm_coord /= pssm_coord.w;
|
||||
|
||||
if (directional_lights.data[i].softshadow_angle > 0) {
|
||||
float range_pos = dot(directional_lights.data[i].direction, v.xyz);
|
||||
float range_begin = directional_lights.data[i].shadow_range_begin.y;
|
||||
float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle;
|
||||
vec2 tex_scale = directional_lights.data[i].uv_scale2 * test_radius;
|
||||
shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
|
||||
float s = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
|
||||
|
||||
if (blend_index == 0) {
|
||||
shadow = s;
|
||||
} else {
|
||||
shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
|
||||
//blend
|
||||
float blend = smoothstep(0.0, directional_lights.data[i].shadow_split_offsets.x, depth_z);
|
||||
shadow = mix(shadow, s, blend);
|
||||
}
|
||||
|
||||
shadow_color = directional_lights.data[i].shadow_color2.rgb;
|
||||
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
|
||||
blend_index++;
|
||||
}
|
||||
|
||||
if (blend_index < 2 && depth_z < directional_lights.data[i].shadow_split_offsets.z) {
|
||||
vec4 v = vec4(vertex, 1.0);
|
||||
|
||||
BIAS_FUNC(v, 2)
|
||||
|
||||
pssm_coord = (directional_lights.data[i].shadow_matrix3 * v);
|
||||
vec4 pssm_coord = (directional_lights.data[i].shadow_matrix3 * v);
|
||||
pssm_coord /= pssm_coord.w;
|
||||
|
||||
if (directional_lights.data[i].softshadow_angle > 0) {
|
||||
float range_pos = dot(directional_lights.data[i].direction, v.xyz);
|
||||
float range_begin = directional_lights.data[i].shadow_range_begin.z;
|
||||
float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle;
|
||||
vec2 tex_scale = directional_lights.data[i].uv_scale3 * test_radius;
|
||||
shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
|
||||
float s = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
|
||||
|
||||
if (blend_index == 0) {
|
||||
shadow = s;
|
||||
} else {
|
||||
shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
|
||||
//blend
|
||||
float blend = smoothstep(directional_lights.data[i].shadow_split_offsets.x, directional_lights.data[i].shadow_split_offsets.y, depth_z);
|
||||
shadow = mix(shadow, s, blend);
|
||||
}
|
||||
|
||||
shadow_color = directional_lights.data[i].shadow_color3.rgb;
|
||||
blend_index++;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (blend_index < 2) {
|
||||
vec4 v = vec4(vertex, 1.0);
|
||||
|
||||
BIAS_FUNC(v, 3)
|
||||
|
||||
pssm_coord = (directional_lights.data[i].shadow_matrix4 * v);
|
||||
vec4 pssm_coord = (directional_lights.data[i].shadow_matrix4 * v);
|
||||
pssm_coord /= pssm_coord.w;
|
||||
|
||||
if (directional_lights.data[i].softshadow_angle > 0) {
|
||||
float range_pos = dot(directional_lights.data[i].direction, v.xyz);
|
||||
float range_begin = directional_lights.data[i].shadow_range_begin.w;
|
||||
float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle;
|
||||
vec2 tex_scale = directional_lights.data[i].uv_scale4 * test_radius;
|
||||
shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
|
||||
float s = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
|
||||
|
||||
if (blend_index == 0) {
|
||||
shadow = s;
|
||||
} else {
|
||||
shadow = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
|
||||
//blend
|
||||
float blend = smoothstep(directional_lights.data[i].shadow_split_offsets.y, directional_lights.data[i].shadow_split_offsets.z, depth_z);
|
||||
shadow = mix(shadow, s, blend);
|
||||
}
|
||||
|
||||
shadow_color = directional_lights.data[i].shadow_color4.rgb;
|
||||
}
|
||||
|
||||
if (directional_lights.data[i].blend_splits) {
|
||||
vec3 shadow_color_blend = vec3(0.0);
|
||||
float pssm_blend;
|
||||
float shadow2;
|
||||
|
||||
if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
|
||||
vec4 v = vec4(vertex, 1.0);
|
||||
BIAS_FUNC(v, 1)
|
||||
pssm_coord = (directional_lights.data[i].shadow_matrix2 * v);
|
||||
pssm_coord /= pssm_coord.w;
|
||||
|
||||
if (directional_lights.data[i].softshadow_angle > 0) {
|
||||
float range_pos = dot(directional_lights.data[i].direction, v.xyz);
|
||||
float range_begin = directional_lights.data[i].shadow_range_begin.y;
|
||||
float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle;
|
||||
vec2 tex_scale = directional_lights.data[i].uv_scale2 * test_radius;
|
||||
shadow2 = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
|
||||
} else {
|
||||
shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
|
||||
}
|
||||
|
||||
pssm_blend = smoothstep(0.0, directional_lights.data[i].shadow_split_offsets.x, depth_z);
|
||||
shadow_color_blend = directional_lights.data[i].shadow_color2.rgb;
|
||||
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
|
||||
vec4 v = vec4(vertex, 1.0);
|
||||
BIAS_FUNC(v, 2)
|
||||
pssm_coord = (directional_lights.data[i].shadow_matrix3 * v);
|
||||
pssm_coord /= pssm_coord.w;
|
||||
|
||||
if (directional_lights.data[i].softshadow_angle > 0) {
|
||||
float range_pos = dot(directional_lights.data[i].direction, v.xyz);
|
||||
float range_begin = directional_lights.data[i].shadow_range_begin.z;
|
||||
float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle;
|
||||
vec2 tex_scale = directional_lights.data[i].uv_scale3 * test_radius;
|
||||
shadow2 = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
|
||||
} else {
|
||||
shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
|
||||
}
|
||||
|
||||
pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.x, directional_lights.data[i].shadow_split_offsets.y, depth_z);
|
||||
|
||||
shadow_color_blend = directional_lights.data[i].shadow_color3.rgb;
|
||||
} else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
|
||||
vec4 v = vec4(vertex, 1.0);
|
||||
BIAS_FUNC(v, 3)
|
||||
pssm_coord = (directional_lights.data[i].shadow_matrix4 * v);
|
||||
pssm_coord /= pssm_coord.w;
|
||||
if (directional_lights.data[i].softshadow_angle > 0) {
|
||||
float range_pos = dot(directional_lights.data[i].direction, v.xyz);
|
||||
float range_begin = directional_lights.data[i].shadow_range_begin.w;
|
||||
float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle;
|
||||
vec2 tex_scale = directional_lights.data[i].uv_scale4 * test_radius;
|
||||
shadow2 = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale);
|
||||
} else {
|
||||
shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord);
|
||||
}
|
||||
|
||||
pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.y, directional_lights.data[i].shadow_split_offsets.z, depth_z);
|
||||
shadow_color_blend = directional_lights.data[i].shadow_color4.rgb;
|
||||
} else {
|
||||
pssm_blend = 0.0; //if no blend, same coord will be used (divide by z will result in same value, and already cached)
|
||||
}
|
||||
|
||||
pssm_blend = sqrt(pssm_blend);
|
||||
|
||||
shadow = mix(shadow, shadow2, pssm_blend);
|
||||
shadow_color = mix(shadow_color, shadow_color_blend, pssm_blend);
|
||||
}
|
||||
|
||||
shadow = mix(shadow, 1.0, smoothstep(directional_lights.data[i].fade_from, directional_lights.data[i].fade_to, vertex.z)); //done with negative values for performance
|
||||
|
||||
#undef BIAS_FUNC
|
||||
}
|
||||
#else
|
||||
// Soft shadow disabled version
|
||||
} else { //no soft shadows
|
||||
|
||||
if (directional_lights.data[i].shadow_enabled) {
|
||||
float depth_z = -vertex.z;
|
||||
|
||||
vec4 pssm_coord;
|
||||
|
@ -1475,7 +1413,7 @@ void main() {
|
|||
|
||||
#undef BIAS_FUNC
|
||||
}
|
||||
#endif
|
||||
} // shadows
|
||||
|
||||
if (i < 4) {
|
||||
shadow0 |= uint(clamp(shadow * 255.0, 0.0, 255.0)) << (i * 8);
|
||||
|
@ -1554,7 +1492,9 @@ void main() {
|
|||
|
||||
blur_shadow(shadow);
|
||||
|
||||
light_compute(normal, directional_lights.data[i].direction, normalize(view), directional_lights.data[i].color * directional_lights.data[i].energy, shadow, f0, orms, 1.0,
|
||||
float size_A = sc_use_light_soft_shadows ? directional_lights.data[i].size : 0.0;
|
||||
|
||||
light_compute(normal, directional_lights.data[i].direction, normalize(view), size_A, directional_lights.data[i].color * directional_lights.data[i].energy, shadow, f0, orms, 1.0,
|
||||
#ifdef LIGHT_BACKLIGHT_USED
|
||||
backlight,
|
||||
#endif
|
||||
|
@ -1573,9 +1513,6 @@ void main() {
|
|||
#ifdef LIGHT_ANISOTROPY_USED
|
||||
binormal, tangent, anisotropy,
|
||||
#endif
|
||||
#ifdef USE_SOFT_SHADOW
|
||||
directional_lights.data[i].size,
|
||||
#endif
|
||||
#ifdef USE_SHADOW_TO_OPACITY
|
||||
alpha,
|
||||
#endif
|
||||
|
|
|
@ -73,7 +73,7 @@ vec3 F0(float metallic, float specular, vec3 albedo) {
|
|||
return mix(vec3(dielectric), albedo, vec3(metallic));
|
||||
}
|
||||
|
||||
void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, float attenuation, vec3 f0, uint orms, float specular_amount,
|
||||
void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float attenuation, vec3 f0, uint orms, float specular_amount,
|
||||
#ifdef LIGHT_BACKLIGHT_USED
|
||||
vec3 backlight,
|
||||
#endif
|
||||
|
@ -92,9 +92,6 @@ void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, float attenuation,
|
|||
#ifdef LIGHT_ANISOTROPY_USED
|
||||
vec3 B, vec3 T, float anisotropy,
|
||||
#endif
|
||||
#ifdef USE_SOFT_SHADOWS
|
||||
float A,
|
||||
#endif
|
||||
#ifdef USE_SHADOW_TO_OPACITY
|
||||
inout float alpha,
|
||||
#endif
|
||||
|
@ -111,11 +108,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, float attenuation,
|
|||
|
||||
#else
|
||||
|
||||
#ifdef USE_SOFT_SHADOWS
|
||||
float NdotL = min(A + dot(N, L), 1.0);
|
||||
#else
|
||||
float NdotL = dot(N, L);
|
||||
#endif
|
||||
float cNdotL = max(NdotL, 0.0); // clamped NdotL
|
||||
float NdotV = dot(N, V);
|
||||
float cNdotV = max(NdotV, 0.0);
|
||||
|
@ -125,19 +118,11 @@ void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, float attenuation,
|
|||
#endif
|
||||
|
||||
#if defined(SPECULAR_BLINN) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_CLEARCOAT_USED)
|
||||
#ifdef USE_SOFT_SHADOWS
|
||||
float cNdotH = clamp(A + dot(N, H), 0.0, 1.0);
|
||||
#else
|
||||
float cNdotH = clamp(dot(N, H), 0.0, 1.0);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(DIFFUSE_BURLEY) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_CLEARCOAT_USED)
|
||||
#ifdef USE_SOFT_SHADOWS
|
||||
float cLdotH = clamp(A + dot(L, H), 0.0, 1.0);
|
||||
#else
|
||||
float cLdotH = clamp(dot(L, H), 0.0, 1.0);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
float metallic = unpackUnorm4x8(orms).z;
|
||||
|
@ -232,11 +217,7 @@ void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, float attenuation,
|
|||
#elif defined(SPECULAR_PHONG)
|
||||
|
||||
vec3 R = normalize(-reflect(L, N));
|
||||
#ifdef USE_SOFT_SHADOWS
|
||||
float cRdotV = clamp(A + dot(R, V), 0.0, 1.0);
|
||||
#else
|
||||
float cRdotV = clamp(dot(R, V), 0.0, 1.0);
|
||||
#endif
|
||||
float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25;
|
||||
float phong = pow(cRdotV, shininess);
|
||||
phong *= (shininess + 8.0) * (1.0 / (8.0 * M_PI));
|
||||
|
@ -442,8 +423,7 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) {
|
|||
|
||||
float shadow;
|
||||
|
||||
#ifdef USE_SOFT_SHADOWS
|
||||
if (omni_lights.data[idx].soft_shadow_size > 0.0) {
|
||||
if (sc_use_light_soft_shadows && omni_lights.data[idx].soft_shadow_size > 0.0) {
|
||||
//soft shadow
|
||||
|
||||
//find blocker
|
||||
|
@ -533,7 +513,6 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) {
|
|||
shadow = 1.0;
|
||||
}
|
||||
} else {
|
||||
#endif
|
||||
splane.xyz = normalize(splane.xyz);
|
||||
vec4 clamp_rect = omni_lights.data[idx].atlas_rect;
|
||||
|
||||
|
@ -553,9 +532,7 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) {
|
|||
splane.xy = clamp_rect.xy + splane.xy * clamp_rect.zw;
|
||||
splane.w = 1.0; //needed? i think it should be 1 already
|
||||
shadow = sample_pcf_shadow(shadow_atlas, omni_lights.data[idx].soft_shadow_scale * scene_data.shadow_atlas_pixel_size, splane);
|
||||
#ifdef USE_SOFT_SHADOWS
|
||||
}
|
||||
#endif
|
||||
|
||||
return shadow;
|
||||
}
|
||||
|
@ -592,14 +569,12 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
|
|||
float light_attenuation = omni_attenuation;
|
||||
vec3 color = omni_lights.data[idx].color;
|
||||
|
||||
#ifdef USE_SOFT_SHADOWS
|
||||
float size_A = 0.0;
|
||||
|
||||
if (omni_lights.data[idx].size > 0.0) {
|
||||
if (sc_use_light_soft_shadows && omni_lights.data[idx].size > 0.0) {
|
||||
float t = omni_lights.data[idx].size / max(0.001, light_length);
|
||||
size_A = max(0.0, 1.0 - 1 / sqrt(1 + t * t));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef LIGHT_TRANSMITTANCE_USED
|
||||
float transmittance_z = transmittance_depth; //no transmittance by default
|
||||
|
@ -633,9 +608,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
|
|||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
|
||||
if (omni_lights.data[idx].projector_rect != vec4(0.0)) {
|
||||
if (sc_use_light_projector && omni_lights.data[idx].projector_rect != vec4(0.0)) {
|
||||
vec3 local_v = (omni_lights.data[idx].shadow_matrix * vec4(vertex, 1.0)).xyz;
|
||||
local_v = normalize(local_v);
|
||||
|
||||
|
@ -686,13 +659,12 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
|
|||
}
|
||||
|
||||
vec4 proj = textureGrad(sampler2D(decal_atlas_srgb, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), proj_uv + atlas_rect.xy, proj_uv_ddx, proj_uv_ddy);
|
||||
no_shadow = mix(no_shadow, proj.rgb, proj.a);
|
||||
color *= proj.rgb * proj.a;
|
||||
}
|
||||
#endif
|
||||
|
||||
light_attenuation *= shadow;
|
||||
|
||||
light_compute(normal, normalize(light_rel_vec), eye_vec, color, light_attenuation, f0, orms, omni_lights.data[idx].specular_amount,
|
||||
light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, light_attenuation, f0, orms, omni_lights.data[idx].specular_amount,
|
||||
#ifdef LIGHT_BACKLIGHT_USED
|
||||
backlight,
|
||||
#endif
|
||||
|
@ -711,9 +683,6 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
|
|||
#ifdef LIGHT_ANISOTROPY_USED
|
||||
binormal, tangent, anisotropy,
|
||||
#endif
|
||||
#ifdef USE_SOFT_SHADOWS
|
||||
size_A,
|
||||
#endif
|
||||
#ifdef USE_SHADOW_TO_OPACITY
|
||||
alpha,
|
||||
#endif
|
||||
|
@ -747,8 +716,7 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) {
|
|||
vec4 splane = (spot_lights.data[idx].shadow_matrix * v);
|
||||
splane /= splane.w;
|
||||
|
||||
#ifdef USE_SOFT_SHADOWS
|
||||
if (spot_lights.data[idx].soft_shadow_size > 0.0) {
|
||||
if (sc_use_light_soft_shadows && spot_lights.data[idx].soft_shadow_size > 0.0) {
|
||||
//soft shadow
|
||||
|
||||
//find blocker
|
||||
|
@ -772,7 +740,7 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) {
|
|||
vec2 suv = shadow_uv + (disk_rotation * scene_data.penumbra_shadow_kernel[i].xy) * uv_size;
|
||||
suv = clamp(suv, spot_lights.data[idx].atlas_rect.xy, clamp_max);
|
||||
float d = textureLod(sampler2D(shadow_atlas, material_samplers[SAMPLER_LINEAR_CLAMP]), suv, 0.0).r;
|
||||
if (d < z_norm) {
|
||||
if (d < splane.z) {
|
||||
blocker_average += d;
|
||||
blocker_count += 1.0;
|
||||
}
|
||||
|
@ -788,7 +756,7 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) {
|
|||
for (uint i = 0; i < scene_data.penumbra_shadow_samples; i++) {
|
||||
vec2 suv = shadow_uv + (disk_rotation * scene_data.penumbra_shadow_kernel[i].xy) * uv_size;
|
||||
suv = clamp(suv, spot_lights.data[idx].atlas_rect.xy, clamp_max);
|
||||
shadow += textureProj(sampler2DShadow(shadow_atlas, shadow_sampler), vec4(suv, z_norm, 1.0));
|
||||
shadow += textureProj(sampler2DShadow(shadow_atlas, shadow_sampler), vec4(suv, splane.z, 1.0));
|
||||
}
|
||||
|
||||
shadow /= float(scene_data.penumbra_shadow_samples);
|
||||
|
@ -799,14 +767,11 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) {
|
|||
}
|
||||
|
||||
} else {
|
||||
#endif
|
||||
//hard shadow
|
||||
vec4 shadow_uv = vec4(splane.xy * spot_lights.data[idx].atlas_rect.zw + spot_lights.data[idx].atlas_rect.xy, splane.z, 1.0);
|
||||
|
||||
shadow = sample_pcf_shadow(shadow_atlas, spot_lights.data[idx].soft_shadow_scale * scene_data.shadow_atlas_pixel_size, shadow_uv);
|
||||
#ifdef USE_SOFT_SHADOWS
|
||||
}
|
||||
#endif
|
||||
|
||||
return shadow;
|
||||
}
|
||||
|
@ -816,6 +781,18 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) {
|
|||
return 1.0;
|
||||
}
|
||||
|
||||
vec2 normal_to_panorama(vec3 n) {
|
||||
n = normalize(n);
|
||||
vec2 panorama_coords = vec2(atan(n.x, n.z), acos(-n.y));
|
||||
|
||||
if (panorama_coords.x < 0.0) {
|
||||
panorama_coords.x += M_PI * 2.0;
|
||||
}
|
||||
|
||||
panorama_coords /= vec2(M_PI * 2.0, M_PI);
|
||||
return panorama_coords;
|
||||
}
|
||||
|
||||
void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 vertex_ddx, vec3 vertex_ddy, vec3 f0, uint orms, float shadow,
|
||||
#ifdef LIGHT_BACKLIGHT_USED
|
||||
vec3 backlight,
|
||||
|
@ -850,20 +827,12 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
|
|||
vec3 color = spot_lights.data[idx].color;
|
||||
float specular_amount = spot_lights.data[idx].specular_amount;
|
||||
|
||||
#ifdef USE_SOFT_SHADOWS
|
||||
float size_A = 0.0;
|
||||
|
||||
if (spot_lights.data[idx].size > 0.0) {
|
||||
if (sc_use_light_soft_shadows && spot_lights.data[idx].size > 0.0) {
|
||||
float t = spot_lights.data[idx].size / max(0.001, light_length);
|
||||
size_A = max(0.0, 1.0 - 1 / sqrt(1 + t * t));
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
if (spot_lights.data[idx].atlas_rect!=vec4(0.0)) {
|
||||
//use projector texture
|
||||
}
|
||||
*/
|
||||
|
||||
#ifdef LIGHT_TRANSMITTANCE_USED
|
||||
float transmittance_z = transmittance_depth;
|
||||
|
@ -886,9 +855,27 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
|
|||
}
|
||||
#endif //LIGHT_TRANSMITTANCE_USED
|
||||
|
||||
if (sc_use_light_projector && spot_lights.data[idx].projector_rect != vec4(0.0)) {
|
||||
vec4 splane = (spot_lights.data[idx].shadow_matrix * vec4(vertex, 1.0));
|
||||
splane /= splane.w;
|
||||
|
||||
vec2 proj_uv = normal_to_panorama(splane.xyz) * spot_lights.data[idx].projector_rect.zw;
|
||||
|
||||
//ensure we have proper mipmaps
|
||||
vec4 splane_ddx = (spot_lights.data[idx].shadow_matrix * vec4(vertex + vertex_ddx, 1.0));
|
||||
splane_ddx /= splane_ddx.w;
|
||||
vec2 proj_uv_ddx = normal_to_panorama(splane_ddx.xyz) * spot_lights.data[idx].projector_rect.zw - proj_uv;
|
||||
|
||||
vec4 splane_ddy = (spot_lights.data[idx].shadow_matrix * vec4(vertex + vertex_ddy, 1.0));
|
||||
splane_ddy /= splane_ddy.w;
|
||||
vec2 proj_uv_ddy = normal_to_panorama(splane_ddy.xyz) * spot_lights.data[idx].projector_rect.zw - proj_uv;
|
||||
|
||||
vec4 proj = textureGrad(sampler2D(decal_atlas_srgb, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), proj_uv + spot_lights.data[idx].projector_rect.xy, proj_uv_ddx, proj_uv_ddy);
|
||||
color *= proj.rgb * proj.a;
|
||||
}
|
||||
light_attenuation *= shadow;
|
||||
|
||||
light_compute(normal, normalize(light_rel_vec), eye_vec, color, light_attenuation, f0, orms, spot_lights.data[idx].specular_amount,
|
||||
light_compute(normal, normalize(light_rel_vec), eye_vec, size_A, color, light_attenuation, f0, orms, spot_lights.data[idx].specular_amount,
|
||||
#ifdef LIGHT_BACKLIGHT_USED
|
||||
backlight,
|
||||
#endif
|
||||
|
@ -907,9 +894,6 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
|
|||
#ifdef LIGHT_ANISOTROPY_USED
|
||||
binormal, tangent, anisotropy,
|
||||
#endif
|
||||
#ifdef USE_SOFT_SHADOW
|
||||
size_A,
|
||||
#endif
|
||||
#ifdef USE_SHADOW_TO_OPACITY
|
||||
alpha,
|
||||
#endif
|
||||
|
|
|
@ -370,6 +370,13 @@ void main() {
|
|||
|
||||
#VERSION_DEFINES
|
||||
|
||||
/* Specialization Constants */
|
||||
|
||||
//unused but there for compatibility
|
||||
layout(constant_id = 0) const bool sc_use_forward_gi = false;
|
||||
layout(constant_id = 1) const bool sc_use_light_projector = false;
|
||||
layout(constant_id = 2) const bool sc_use_light_soft_shadows = false;
|
||||
|
||||
/* Include our forward mobile UBOs definitions etc. */
|
||||
#include "scene_forward_mobile_inc.glsl"
|
||||
|
||||
|
|
|
@ -151,6 +151,22 @@ void RendererSceneCull::_instance_pair(Instance *p_A, Instance *p_B) {
|
|||
idata.flags |= InstanceData::FLAG_GEOM_LIGHTING_DIRTY;
|
||||
}
|
||||
|
||||
if (light->uses_projector) {
|
||||
geom->projector_count++;
|
||||
if (geom->projector_count == 1) {
|
||||
InstanceData &idata = A->scenario->instance_data[A->array_index];
|
||||
idata.flags |= InstanceData::FLAG_GEOM_PROJECTOR_SOFTSHADOW_DIRTY;
|
||||
}
|
||||
}
|
||||
|
||||
if (light->uses_softshadow) {
|
||||
geom->softshadow_count++;
|
||||
if (geom->softshadow_count == 1) {
|
||||
InstanceData &idata = A->scenario->instance_data[A->array_index];
|
||||
idata.flags |= InstanceData::FLAG_GEOM_PROJECTOR_SOFTSHADOW_DIRTY;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (self->geometry_instance_pair_mask & (1 << RS::INSTANCE_REFLECTION_PROBE) && B->base_type == RS::INSTANCE_REFLECTION_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
|
||||
InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(B->base_data);
|
||||
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
|
||||
|
@ -242,6 +258,32 @@ void RendererSceneCull::_instance_unpair(Instance *p_A, Instance *p_B) {
|
|||
idata.flags |= InstanceData::FLAG_GEOM_LIGHTING_DIRTY;
|
||||
}
|
||||
|
||||
if (light->uses_projector) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (geom->projector_count == 0) {
|
||||
ERR_PRINT("geom->projector_count==0 - BUG!");
|
||||
}
|
||||
#endif
|
||||
geom->projector_count--;
|
||||
if (geom->projector_count == 0) {
|
||||
InstanceData &idata = A->scenario->instance_data[A->array_index];
|
||||
idata.flags |= InstanceData::FLAG_GEOM_PROJECTOR_SOFTSHADOW_DIRTY;
|
||||
}
|
||||
}
|
||||
|
||||
if (light->uses_softshadow) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (geom->softshadow_count == 0) {
|
||||
ERR_PRINT("geom->softshadow_count==0 - BUG!");
|
||||
}
|
||||
#endif
|
||||
geom->softshadow_count--;
|
||||
if (geom->softshadow_count == 0) {
|
||||
InstanceData &idata = A->scenario->instance_data[A->array_index];
|
||||
idata.flags |= InstanceData::FLAG_GEOM_PROJECTOR_SOFTSHADOW_DIRTY;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (self->geometry_instance_pair_mask & (1 << RS::INSTANCE_REFLECTION_PROBE) && B->base_type == RS::INSTANCE_REFLECTION_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) {
|
||||
InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(B->base_data);
|
||||
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(A->base_data);
|
||||
|
@ -1532,7 +1574,11 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
|
|||
}
|
||||
} break;
|
||||
case RS::INSTANCE_LIGHT: {
|
||||
idata.instance_data_rid = static_cast<InstanceLightData *>(p_instance->base_data)->instance.get_id();
|
||||
InstanceLightData *light_data = static_cast<InstanceLightData *>(p_instance->base_data);
|
||||
idata.instance_data_rid = light_data->instance.get_id();
|
||||
light_data->uses_projector = RSG::storage->light_has_projector(p_instance->base);
|
||||
light_data->uses_softshadow = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SIZE) > CMP_EPSILON;
|
||||
|
||||
} break;
|
||||
case RS::INSTANCE_REFLECTION_PROBE: {
|
||||
idata.instance_data_rid = static_cast<InstanceReflectionProbeData *>(p_instance->base_data)->instance.get_id();
|
||||
|
@ -2646,6 +2692,13 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
|
|||
idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_LIGHTING_DIRTY);
|
||||
}
|
||||
|
||||
if (idata.flags & InstanceData::FLAG_GEOM_PROJECTOR_SOFTSHADOW_DIRTY) {
|
||||
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
|
||||
|
||||
scene_render->geometry_instance_set_softshadow_projector_pairing(geom->geometry_instance, geom->softshadow_count > 0, geom->projector_count > 0);
|
||||
idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_PROJECTOR_SOFTSHADOW_DIRTY);
|
||||
}
|
||||
|
||||
if (geometry_instance_pair_mask & (1 << RS::INSTANCE_REFLECTION_PROBE) && (idata.flags & InstanceData::FLAG_GEOM_REFLECTION_DIRTY)) {
|
||||
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
|
||||
uint32_t idx = 0;
|
||||
|
|
|
@ -267,6 +267,7 @@ public:
|
|||
FLAG_VISIBILITY_DEPENDENCY_NEEDS_CHECK = (3 << 20), // 2 bits, overlaps with the other vis. dependency flags
|
||||
FLAG_VISIBILITY_DEPENDENCY_HIDDEN_CLOSE_RANGE = (1 << 20),
|
||||
FLAG_VISIBILITY_DEPENDENCY_HIDDEN = (1 << 21),
|
||||
FLAG_GEOM_PROJECTOR_SOFTSHADOW_DIRTY = (1 << 22),
|
||||
};
|
||||
|
||||
uint32_t flags = 0;
|
||||
|
@ -489,6 +490,14 @@ public:
|
|||
case RendererStorage::DEPENDENCY_CHANGED_SKELETON_BONES: {
|
||||
//ignored
|
||||
} break;
|
||||
case RendererStorage::DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR: {
|
||||
//requires repairing
|
||||
if (instance->indexer_id.is_valid()) {
|
||||
singleton->_unpair_instance(instance);
|
||||
singleton->_instance_queue_update(instance, true, true);
|
||||
}
|
||||
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -567,6 +576,8 @@ public:
|
|||
Set<Instance *> lights;
|
||||
bool can_cast_shadows;
|
||||
bool material_is_animated;
|
||||
uint32_t projector_count = 0;
|
||||
uint32_t softshadow_count = 0;
|
||||
|
||||
Set<Instance *> decals;
|
||||
Set<Instance *> reflection_probes;
|
||||
|
@ -631,6 +642,8 @@ public:
|
|||
List<Instance *>::Element *D; // directional light in scenario
|
||||
|
||||
bool shadow_dirty;
|
||||
bool uses_projector = false;
|
||||
bool uses_softshadow = false;
|
||||
|
||||
Set<Instance *> geometries;
|
||||
|
||||
|
|
|
@ -69,6 +69,8 @@ public:
|
|||
virtual void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) = 0;
|
||||
virtual void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) = 0;
|
||||
|
||||
virtual void geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) = 0;
|
||||
|
||||
virtual void geometry_instance_free(GeometryInstance *p_geometry_instance) = 0;
|
||||
|
||||
/* SHADOW ATLAS API */
|
||||
|
|
|
@ -48,6 +48,7 @@ public:
|
|||
DEPENDENCY_CHANGED_SKELETON_DATA,
|
||||
DEPENDENCY_CHANGED_SKELETON_BONES,
|
||||
DEPENDENCY_CHANGED_LIGHT,
|
||||
DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR,
|
||||
DEPENDENCY_CHANGED_REFLECTION_PROBE,
|
||||
};
|
||||
|
||||
|
@ -337,6 +338,8 @@ public:
|
|||
|
||||
virtual bool light_has_shadow(RID p_light) const = 0;
|
||||
|
||||
virtual bool light_has_projector(RID p_light) const = 0;
|
||||
|
||||
virtual RS::LightType light_get_type(RID p_light) const = 0;
|
||||
virtual AABB light_get_aabb(RID p_light) const = 0;
|
||||
virtual float light_get_param(RID p_light, RS::LightParam p_param) = 0;
|
||||
|
|
|
@ -78,7 +78,8 @@ public:
|
|||
CANVAS_ITEM_Z_MAX = 4096,
|
||||
MAX_GLOW_LEVELS = 7,
|
||||
MAX_CURSORS = 8,
|
||||
MAX_2D_DIRECTIONAL_LIGHTS = 8
|
||||
MAX_2D_DIRECTIONAL_LIGHTS = 8,
|
||||
MAX_MESH_SURFACES = 256
|
||||
};
|
||||
|
||||
/* TEXTURE API */
|
||||
|
|
Loading…
Reference in a new issue