Fixed handling of depth texture so it's resolved and bound when needed
- Cleaned up and improved the code determining when we need to use a depth prepass (previously it wasn't executed in certain cases even if it was needed) - Added code to prepare and bind the depth texture even when no depth prepass or MRTs (more precisely effect buffers) are used Fixes #25870, #25535, and #25387.
This commit is contained in:
parent
81292665d5
commit
849596c40c
|
@ -2349,6 +2349,10 @@ void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::G
|
||||||
state.used_screen_texture = true;
|
state.used_screen_texture = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (p_material->shader->spatial.uses_depth_texture) {
|
||||||
|
state.used_depth_texture = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (p_depth_pass) {
|
if (p_depth_pass) {
|
||||||
|
|
||||||
if (has_blend_alpha || p_material->shader->spatial.uses_depth_texture || (has_base_alpha && p_material->shader->spatial.depth_draw_mode != RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) || p_material->shader->spatial.depth_draw_mode == RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_NEVER || p_material->shader->spatial.no_depth_test)
|
if (has_blend_alpha || p_material->shader->spatial.uses_depth_texture || (has_base_alpha && p_material->shader->spatial.depth_draw_mode != RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) || p_material->shader->spatial.depth_draw_mode == RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_NEVER || p_material->shader->spatial.no_depth_test)
|
||||||
|
@ -3165,6 +3169,7 @@ void RasterizerSceneGLES3::_fill_render_list(InstanceBase **p_cull_result, int p
|
||||||
current_material_index = 0;
|
current_material_index = 0;
|
||||||
state.used_sss = false;
|
state.used_sss = false;
|
||||||
state.used_screen_texture = false;
|
state.used_screen_texture = false;
|
||||||
|
state.used_depth_texture = false;
|
||||||
|
|
||||||
//fill list
|
//fill list
|
||||||
|
|
||||||
|
@ -3281,14 +3286,8 @@ void RasterizerSceneGLES3::_blur_effect_buffer() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerSceneGLES3::_render_mrts(Environment *env, const CameraMatrix &p_cam_projection) {
|
void RasterizerSceneGLES3::_prepare_depth_texture() {
|
||||||
|
if (!state.prepared_depth_texture) {
|
||||||
glDepthMask(GL_FALSE);
|
|
||||||
glDisable(GL_DEPTH_TEST);
|
|
||||||
glDisable(GL_CULL_FACE);
|
|
||||||
glDisable(GL_BLEND);
|
|
||||||
|
|
||||||
if (!state.used_depth_prepass_and_resolved) {
|
|
||||||
//resolve depth buffer
|
//resolve depth buffer
|
||||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo);
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo);
|
||||||
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
||||||
|
@ -3296,7 +3295,28 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env, const CameraMatrix &p_
|
||||||
glBlitFramebuffer(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, 0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
|
glBlitFramebuffer(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, 0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
|
||||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||||
|
state.prepared_depth_texture = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RasterizerSceneGLES3::_bind_depth_texture() {
|
||||||
|
if (!state.bound_depth_texture) {
|
||||||
|
ERR_FAIL_COND(!state.prepared_depth_texture)
|
||||||
|
//bind depth for read
|
||||||
|
glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 8);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth);
|
||||||
|
state.bound_depth_texture = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RasterizerSceneGLES3::_render_mrts(Environment *env, const CameraMatrix &p_cam_projection) {
|
||||||
|
|
||||||
|
glDepthMask(GL_FALSE);
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
glDisable(GL_CULL_FACE);
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
|
||||||
|
_prepare_depth_texture();
|
||||||
|
|
||||||
if (env->ssao_enabled || env->ssr_enabled) {
|
if (env->ssao_enabled || env->ssr_enabled) {
|
||||||
|
|
||||||
|
@ -4149,7 +4169,8 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
|
||||||
glDepthFunc(GL_LEQUAL);
|
glDepthFunc(GL_LEQUAL);
|
||||||
|
|
||||||
state.used_contact_shadows = false;
|
state.used_contact_shadows = false;
|
||||||
state.used_depth_prepass_and_resolved = false;
|
state.prepared_depth_texture = false;
|
||||||
|
state.bound_depth_texture = false;
|
||||||
|
|
||||||
for (int i = 0; i < p_light_cull_count; i++) {
|
for (int i = 0; i < p_light_cull_count; i++) {
|
||||||
|
|
||||||
|
@ -4161,7 +4182,17 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!storage->config.no_depth_prepass && storage->frame.current_rt && state.debug_draw != VS::VIEWPORT_DEBUG_DRAW_OVERDRAW && !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_NO_3D_EFFECTS]) { //detect with state.used_contact_shadows too
|
// Do depth prepass if it's explicitly enabled
|
||||||
|
bool use_depth_prepass = storage->config.use_depth_prepass;
|
||||||
|
|
||||||
|
// If contact shadows are used then we need to do depth prepass even if it's otherwise disabled
|
||||||
|
use_depth_prepass = use_depth_prepass || state.used_contact_shadows;
|
||||||
|
|
||||||
|
// Never do depth prepass if effects are disabled or if we render overdraws
|
||||||
|
use_depth_prepass = use_depth_prepass && storage->frame.current_rt && !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_NO_3D_EFFECTS];
|
||||||
|
use_depth_prepass = use_depth_prepass && state.debug_draw != VS::VIEWPORT_DEBUG_DRAW_OVERDRAW;
|
||||||
|
|
||||||
|
if (use_depth_prepass) {
|
||||||
//pre z pass
|
//pre z pass
|
||||||
|
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
|
@ -4188,16 +4219,8 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
|
||||||
|
|
||||||
if (state.used_contact_shadows) {
|
if (state.used_contact_shadows) {
|
||||||
|
|
||||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo);
|
_prepare_depth_texture();
|
||||||
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
_bind_depth_texture();
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->fbo);
|
|
||||||
glBlitFramebuffer(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, 0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
|
|
||||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
|
||||||
//bind depth for read
|
|
||||||
glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 8);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth);
|
|
||||||
state.used_depth_prepass_and_resolved = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fb_cleared = true;
|
fb_cleared = true;
|
||||||
|
@ -4455,7 +4478,12 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
|
||||||
|
|
||||||
_render_mrts(env, p_cam_projection);
|
_render_mrts(env, p_cam_projection);
|
||||||
} else {
|
} else {
|
||||||
//FIXME: check that this is possible to use
|
// Here we have to do the blits/resolves that otherwise are done in the MRT rendering, in particular
|
||||||
|
// - prepare screen texture for any geometry that uses a shader with screen texture
|
||||||
|
// - prepare depth texture for any geometry that uses a shader with depth texture
|
||||||
|
|
||||||
|
bool framebuffer_dirty = false;
|
||||||
|
|
||||||
if (storage->frame.current_rt && storage->frame.current_rt->buffers.active && state.used_screen_texture) {
|
if (storage->frame.current_rt && storage->frame.current_rt->buffers.active && state.used_screen_texture) {
|
||||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo);
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo);
|
||||||
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
||||||
|
@ -4464,12 +4492,25 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
|
||||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||||
_blur_effect_buffer();
|
_blur_effect_buffer();
|
||||||
//restored framebuffer
|
framebuffer_dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (storage->frame.current_rt && storage->frame.current_rt->buffers.active && state.used_depth_texture) {
|
||||||
|
_prepare_depth_texture();
|
||||||
|
framebuffer_dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (framebuffer_dirty) {
|
||||||
|
// Restore framebuffer
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo);
|
glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo);
|
||||||
glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height);
|
glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (storage->frame.current_rt && state.used_depth_texture && storage->frame.current_rt->buffers.active) {
|
||||||
|
_bind_depth_texture();
|
||||||
|
}
|
||||||
|
|
||||||
if (storage->frame.current_rt && state.used_screen_texture && storage->frame.current_rt->buffers.active) {
|
if (storage->frame.current_rt && state.used_screen_texture && storage->frame.current_rt->buffers.active) {
|
||||||
glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 7);
|
glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 7);
|
||||||
glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color);
|
glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color);
|
||||||
|
|
|
@ -206,7 +206,10 @@ public:
|
||||||
bool used_screen_texture;
|
bool used_screen_texture;
|
||||||
|
|
||||||
bool used_depth_prepass;
|
bool used_depth_prepass;
|
||||||
bool used_depth_prepass_and_resolved;
|
|
||||||
|
bool used_depth_texture;
|
||||||
|
bool prepared_depth_texture;
|
||||||
|
bool bound_depth_texture;
|
||||||
|
|
||||||
VS::ViewportDebugDraw debug_draw;
|
VS::ViewportDebugDraw debug_draw;
|
||||||
} state;
|
} state;
|
||||||
|
@ -848,6 +851,9 @@ public:
|
||||||
void _render_mrts(Environment *env, const CameraMatrix &p_cam_projection);
|
void _render_mrts(Environment *env, const CameraMatrix &p_cam_projection);
|
||||||
void _post_process(Environment *env, const CameraMatrix &p_cam_projection);
|
void _post_process(Environment *env, const CameraMatrix &p_cam_projection);
|
||||||
|
|
||||||
|
void _prepare_depth_texture();
|
||||||
|
void _bind_depth_texture();
|
||||||
|
|
||||||
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_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 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);
|
virtual bool free(RID p_rid);
|
||||||
|
|
|
@ -8042,8 +8042,8 @@ void RasterizerStorageGLES3::initialize() {
|
||||||
|
|
||||||
String renderer = (const char *)glGetString(GL_RENDERER);
|
String renderer = (const char *)glGetString(GL_RENDERER);
|
||||||
|
|
||||||
config.no_depth_prepass = !bool(GLOBAL_GET("rendering/quality/depth_prepass/enable"));
|
config.use_depth_prepass = bool(GLOBAL_GET("rendering/quality/depth_prepass/enable"));
|
||||||
if (!config.no_depth_prepass) {
|
if (config.use_depth_prepass) {
|
||||||
|
|
||||||
String vendors = GLOBAL_GET("rendering/quality/depth_prepass/disable_for_vendors");
|
String vendors = GLOBAL_GET("rendering/quality/depth_prepass/disable_for_vendors");
|
||||||
Vector<String> vendor_match = vendors.split(",");
|
Vector<String> vendor_match = vendors.split(",");
|
||||||
|
@ -8053,7 +8053,7 @@ void RasterizerStorageGLES3::initialize() {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (renderer.findn(v) != -1) {
|
if (renderer.findn(v) != -1) {
|
||||||
config.no_depth_prepass = true;
|
config.use_depth_prepass = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,7 +103,7 @@ public:
|
||||||
|
|
||||||
bool keep_original_textures;
|
bool keep_original_textures;
|
||||||
|
|
||||||
bool no_depth_prepass;
|
bool use_depth_prepass;
|
||||||
bool force_vertex_shading;
|
bool force_vertex_shading;
|
||||||
} config;
|
} config;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue