Merge pull request #47129 from mortarroad/3.x-fix-directional-light-order

Fix draw order of transparent materials with multiple directional lights
This commit is contained in:
Rémi Verschelde 2021-04-28 19:03:37 +02:00 committed by GitHub
commit 25b170599b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 63 additions and 6 deletions

View file

@ -4130,6 +4130,26 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p
state.tonemap_shader.set_conditional(TonemapShaderGLES3::V_FLIP, false);
}
bool RasterizerSceneGLES3::_element_needs_directional_add(RenderList::Element *e) {
// return whether this element should take part in directional add
if (e->sort_key & SORT_KEY_UNSHADED_FLAG) {
return false;
}
for (int i = 0; i < state.directional_light_count; i++) {
LightInstance *l = directional_lights[i];
// any unbaked and unculled light?
if (e->instance->baked_light && l->light_ptr->bake_mode == VS::LightBakeMode::LIGHT_BAKE_ALL) {
continue;
}
if ((e->instance->layer_mask & l->light_ptr->cull_mask) == 0) {
continue;
}
return true;
}
return false; // no visible unbaked light
}
void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) {
//first of all, make a new render pass
@ -4609,14 +4629,50 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
render_list.sort_by_reverse_depth_and_priority(true);
if (state.directional_light_count == 0) {
directional_light = NULL;
if (state.directional_light_count <= 1) {
if (state.directional_light_count == 1) {
directional_light = directional_lights[0];
_setup_directional_light(0, p_cam_transform.affine_inverse(), use_shadows);
} else {
directional_light = NULL;
}
_render_list(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, p_cam_transform, p_cam_projection, sky, false, true, false, false, use_shadows);
} else {
for (int i = 0; i < state.directional_light_count; i++) {
directional_light = directional_lights[i];
_setup_directional_light(i, p_cam_transform.affine_inverse(), use_shadows);
_render_list(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, p_cam_transform, p_cam_projection, sky, false, true, false, i > 0, use_shadows);
// special handling for multiple directional lights
// first chunk_start
int chunk_split = render_list.max_elements - render_list.alpha_element_count;
while (chunk_split < render_list.max_elements) {
int chunk_start = chunk_split;
bool first = true;
bool chunk_directional_add = false;
uint32_t chunk_priority = 0;
// determine chunk end
for (; chunk_split < render_list.max_elements; chunk_split++) {
bool directional_add = _element_needs_directional_add(render_list.elements[chunk_split]);
uint32_t priority = uint32_t(render_list.elements[chunk_split]->sort_key >> RenderList::SORT_KEY_PRIORITY_SHIFT);
if (first) {
chunk_directional_add = directional_add;
chunk_priority = priority;
first = false;
}
if ((directional_add != chunk_directional_add) || (priority != chunk_priority)) {
break;
}
}
if (chunk_directional_add) {
for (int i = 0; i < state.directional_light_count; i++) {
directional_light = directional_lights[i];
_setup_directional_light(i, p_cam_transform.affine_inverse(), use_shadows);
_render_list(&render_list.elements[chunk_start], chunk_split - chunk_start, p_cam_transform, p_cam_projection, sky, false, true, false, i > 0, use_shadows);
}
} else {
directional_light = NULL;
_render_list(&render_list.elements[chunk_start], chunk_split - chunk_start, p_cam_transform, p_cam_projection, sky, false, true, false, false, use_shadows);
}
}
}

View file

@ -867,6 +867,7 @@ public:
void _prepare_depth_texture();
void _bind_depth_texture();
bool _element_needs_directional_add(RenderList::Element *e);
virtual void render_scene(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
virtual void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count);
virtual bool free(RID p_rid);