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:
Daniel Rakos 2019-03-22 11:09:23 +01:00
parent 81292665d5
commit 849596c40c
4 changed files with 74 additions and 27 deletions

View file

@ -2349,6 +2349,10 @@ void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::G
state.used_screen_texture = true;
}
if (p_material->shader->spatial.uses_depth_texture) {
state.used_depth_texture = true;
}
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)
@ -3165,6 +3169,7 @@ void RasterizerSceneGLES3::_fill_render_list(InstanceBase **p_cull_result, int p
current_material_index = 0;
state.used_sss = false;
state.used_screen_texture = false;
state.used_depth_texture = false;
//fill list
@ -3281,14 +3286,8 @@ void RasterizerSceneGLES3::_blur_effect_buffer() {
}
}
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);
if (!state.used_depth_prepass_and_resolved) {
void RasterizerSceneGLES3::_prepare_depth_texture() {
if (!state.prepared_depth_texture) {
//resolve depth buffer
glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo);
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);
glBindFramebuffer(GL_READ_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) {
@ -4149,7 +4169,8 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
glDepthFunc(GL_LEQUAL);
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++) {
@ -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
glDisable(GL_BLEND);
@ -4188,16 +4219,8 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
if (state.used_contact_shadows) {
glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo);
glReadBuffer(GL_COLOR_ATTACHMENT0);
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;
_prepare_depth_texture();
_bind_depth_texture();
}
fb_cleared = true;
@ -4455,7 +4478,12 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
_render_mrts(env, p_cam_projection);
} 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) {
glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo);
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_DRAW_FRAMEBUFFER, 0);
_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);
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) {
glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 7);
glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color);

View file

@ -206,7 +206,10 @@ public:
bool used_screen_texture;
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;
} state;
@ -848,6 +851,9 @@ public:
void _render_mrts(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_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);

View file

@ -8042,8 +8042,8 @@ void RasterizerStorageGLES3::initialize() {
String renderer = (const char *)glGetString(GL_RENDERER);
config.no_depth_prepass = !bool(GLOBAL_GET("rendering/quality/depth_prepass/enable"));
if (!config.no_depth_prepass) {
config.use_depth_prepass = bool(GLOBAL_GET("rendering/quality/depth_prepass/enable"));
if (config.use_depth_prepass) {
String vendors = GLOBAL_GET("rendering/quality/depth_prepass/disable_for_vendors");
Vector<String> vendor_match = vendors.split(",");
@ -8053,7 +8053,7 @@ void RasterizerStorageGLES3::initialize() {
continue;
if (renderer.findn(v) != -1) {
config.no_depth_prepass = true;
config.use_depth_prepass = false;
}
}
}

View file

@ -103,7 +103,7 @@ public:
bool keep_original_textures;
bool no_depth_prepass;
bool use_depth_prepass;
bool force_vertex_shading;
} config;