Fix draw order of transparent materials with multiple directional lights
This commit is contained in:
parent
acbd1e8b02
commit
63b7b7773c
2 changed files with 63 additions and 6 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue