Fix opaque pre pass, closes #10472

This commit is contained in:
Juan Linietsky 2017-09-04 20:27:02 -03:00
parent 44adf75cd5
commit e611ff5f01
3 changed files with 41 additions and 40 deletions

View File

@ -1939,6 +1939,7 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_
bool prev_use_instancing = false;
storage->info.render.draw_call_count += p_element_count;
bool prev_opaque_prepass = false;
for (int i = 0; i < p_element_count; i++) {
@ -2072,6 +2073,13 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_
}
}
bool use_opaque_prepass = e->sort_key & RenderList::SORT_KEY_OPAQUE_PRE_PASS;
if (use_opaque_prepass != prev_opaque_prepass) {
state.scene_shader.set_conditional(SceneShaderGLES3::USE_OPAQUE_PREPASS, use_opaque_prepass);
rebind = true;
}
bool use_instancing = e->instance->base_type == VS::INSTANCE_MULTIMESH || e->instance->base_type == VS::INSTANCE_PARTICLES;
if (use_instancing != prev_use_instancing) {
@ -2127,6 +2135,7 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_
prev_shading = shading;
prev_skeleton = skeleton;
prev_use_instancing = use_instancing;
prev_opaque_prepass = use_opaque_prepass;
first = false;
}
@ -2148,9 +2157,10 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_
state.scene_shader.set_conditional(SceneShaderGLES3::USE_GI_PROBES, false);
state.scene_shader.set_conditional(SceneShaderGLES3::USE_CONTACT_SHADOWS, false);
state.scene_shader.set_conditional(SceneShaderGLES3::USE_VERTEX_LIGHTING, false);
state.scene_shader.set_conditional(SceneShaderGLES3::USE_OPAQUE_PREPASS, false);
}
void RasterizerSceneGLES3::_add_geometry(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, int p_material, bool p_shadow) {
void RasterizerSceneGLES3::_add_geometry(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, int p_material, bool p_depth_pass) {
RasterizerStorageGLES3::Material *m = NULL;
RID m_src = p_instance->material_override.is_valid() ? p_instance->material_override : (p_material >= 0 ? p_instance->materials[p_material] : p_geometry->material);
@ -2182,22 +2192,21 @@ void RasterizerSceneGLES3::_add_geometry(RasterizerStorageGLES3::Geometry *p_geo
ERR_FAIL_COND(!m);
_add_geometry_with_material(p_geometry, p_instance, p_owner, m, p_shadow);
_add_geometry_with_material(p_geometry, p_instance, p_owner, m, p_depth_pass);
while (m->next_pass.is_valid()) {
m = storage->material_owner.getornull(m->next_pass);
if (!m || !m->shader || !m->shader->valid)
break;
_add_geometry_with_material(p_geometry, p_instance, p_owner, m, p_shadow);
_add_geometry_with_material(p_geometry, p_instance, p_owner, m, p_depth_pass);
}
}
void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, RasterizerStorageGLES3::Material *p_material, bool p_shadow) {
void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, RasterizerStorageGLES3::Material *p_material, bool p_depth_pass) {
bool has_base_alpha = (p_material->shader->spatial.uses_alpha && !p_material->shader->spatial.uses_alpha_scissor) || p_material->shader->spatial.uses_screen_texture;
bool has_blend_alpha = p_material->shader->spatial.blend_mode != RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_MIX;
bool has_alpha = has_base_alpha || has_blend_alpha;
bool shadow = false;
bool mirror = p_instance->mirror;
bool no_cull = false;
@ -2217,7 +2226,7 @@ void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::G
state.used_screen_texture = true;
}
if (p_shadow) {
if (p_depth_pass) {
if (has_blend_alpha || (has_base_alpha && p_material->shader->spatial.depth_draw_mode != RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS))
return; //bye
@ -2252,14 +2261,14 @@ void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::G
e->geometry->index = current_geometry_index++;
}
if (!p_shadow && directional_light && (directional_light->light_ptr->cull_mask & e->instance->layer_mask) == 0) {
if (!p_depth_pass && directional_light && (directional_light->light_ptr->cull_mask & e->instance->layer_mask) == 0) {
e->sort_key |= SORT_KEY_NO_DIRECTIONAL_FLAG;
}
e->sort_key |= uint64_t(e->geometry->index) << RenderList::SORT_KEY_GEOMETRY_INDEX_SHIFT;
e->sort_key |= uint64_t(e->instance->base_type) << RenderList::SORT_KEY_GEOMETRY_TYPE_SHIFT;
if (!p_shadow) {
if (!p_depth_pass) {
if (e->material->last_pass != render_pass) {
e->material->last_pass = render_pass;
@ -2269,17 +2278,6 @@ void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::G
e->sort_key |= uint64_t(e->material->index) << RenderList::SORT_KEY_MATERIAL_INDEX_SHIFT;
e->sort_key |= uint64_t(e->instance->depth_layer) << RenderList::SORT_KEY_OPAQUE_DEPTH_LAYER_SHIFT;
if (!has_blend_alpha && has_alpha && p_material->shader->spatial.depth_draw_mode == RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) {
//if nothing exists, add this element as opaque too
RenderList::Element *oe = render_list.add_element();
if (!oe)
return;
copymem(oe, e, sizeof(RenderList::Element));
}
if (e->instance->gi_probe_instances.size()) {
e->sort_key |= SORT_KEY_GI_PROBES_FLAG;
}
@ -2302,25 +2300,21 @@ void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::G
//e->light_type=0xFF; // no lights!
if (shadow || p_material->shader->spatial.unshaded || state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_UNSHADED) {
if (p_depth_pass) {
if (p_material->shader->spatial.unshaded || state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_UNSHADED) {
e->sort_key |= SORT_KEY_UNSHADED_FLAG;
e->sort_key |= SORT_KEY_UNSHADED_FLAG;
}
if (p_material->shader->spatial.depth_draw_mode == RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) {
e->sort_key |= RenderList::SORT_KEY_OPAQUE_PRE_PASS;
}
}
if (!shadow && (p_material->shader->spatial.uses_vertex_lighting || storage->config.force_vertex_shading)) {
if (!p_depth_pass && (p_material->shader->spatial.uses_vertex_lighting || storage->config.force_vertex_shading)) {
e->sort_key |= SORT_KEY_VERTEX_LIT_FLAG;
}
if (!shadow && has_alpha && p_material->shader->spatial.depth_draw_mode == RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) {
//depth prepass for alpha
RenderList::Element *eo = render_list.add_element();
eo->instance = e->instance;
eo->geometry = e->geometry;
eo->material = e->material;
eo->sort_key = e->sort_key;
}
}
void RasterizerSceneGLES3::_draw_sky(RasterizerStorageGLES3::Sky *p_sky, const CameraMatrix &p_projection, const Transform &p_transform, bool p_vflip, float p_scale, float p_energy) {
@ -3032,7 +3026,7 @@ void RasterizerSceneGLES3::_copy_texture_to_front_buffer(GLuint p_texture) {
storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, false);
}
void RasterizerSceneGLES3::_fill_render_list(InstanceBase **p_cull_result, int p_cull_count, bool p_shadow) {
void RasterizerSceneGLES3::_fill_render_list(InstanceBase **p_cull_result, int p_cull_count, bool p_depth_pass) {
current_geometry_index = 0;
current_material_index = 0;
@ -3057,7 +3051,7 @@ void RasterizerSceneGLES3::_fill_render_list(InstanceBase **p_cull_result, int p
int mat_idx = inst->materials[i].is_valid() ? i : -1;
RasterizerStorageGLES3::Surface *s = mesh->surfaces[i];
_add_geometry(s, inst, NULL, mat_idx, p_shadow);
_add_geometry(s, inst, NULL, mat_idx, p_depth_pass);
}
//mesh->last_pass=frame;
@ -3080,7 +3074,7 @@ void RasterizerSceneGLES3::_fill_render_list(InstanceBase **p_cull_result, int p
for (int i = 0; i < ssize; i++) {
RasterizerStorageGLES3::Surface *s = mesh->surfaces[i];
_add_geometry(s, inst, multi_mesh, -1, p_shadow);
_add_geometry(s, inst, multi_mesh, -1, p_depth_pass);
}
} break;
@ -3089,7 +3083,7 @@ void RasterizerSceneGLES3::_fill_render_list(InstanceBase **p_cull_result, int p
RasterizerStorageGLES3::Immediate *immediate = storage->immediate_owner.getptr(inst->base);
ERR_CONTINUE(!immediate);
_add_geometry(immediate, inst, NULL, -1, p_shadow);
_add_geometry(immediate, inst, NULL, -1, p_depth_pass);
} break;
case VS::INSTANCE_PARTICLES: {
@ -3111,7 +3105,7 @@ void RasterizerSceneGLES3::_fill_render_list(InstanceBase **p_cull_result, int p
for (int j = 0; j < ssize; j++) {
RasterizerStorageGLES3::Surface *s = mesh->surfaces[j];
_add_geometry(s, inst, particles, -1, p_shadow);
_add_geometry(s, inst, particles, -1, p_depth_pass);
}
}

View File

@ -664,6 +664,7 @@ public:
//bits 12-8 geometry type
SORT_KEY_GEOMETRY_TYPE_SHIFT = 8,
//bits 0-7 for flags
SORT_KEY_OPAQUE_PRE_PASS = 8,
SORT_KEY_CULL_DISABLED_FLAG = 4,
SORT_KEY_SKELETON_FLAG = 2,
SORT_KEY_MIRROR_FLAG = 1
@ -805,9 +806,9 @@ public:
void _render_list(RenderList::Element **p_elements, int p_element_count, const Transform &p_view_transform, const CameraMatrix &p_projection, GLuint p_base_env, bool p_reverse_cull, bool p_alpha_pass, bool p_shadow, bool p_directional_add, bool p_directional_shadows);
_FORCE_INLINE_ void _add_geometry(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, int p_material, bool p_shadow);
_FORCE_INLINE_ void _add_geometry(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, int p_material, bool p_depth_passs);
_FORCE_INLINE_ void _add_geometry_with_material(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, RasterizerStorageGLES3::Material *p_material, bool p_shadow);
_FORCE_INLINE_ void _add_geometry_with_material(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, RasterizerStorageGLES3::Material *p_material, bool p_depth_pass);
void _draw_sky(RasterizerStorageGLES3::Sky *p_sky, const CameraMatrix &p_projection, const Transform &p_transform, bool p_vflip, float p_scale, float p_energy);
@ -820,7 +821,7 @@ public:
void _copy_to_front_buffer(Environment *env);
void _copy_texture_to_front_buffer(GLuint p_texture); //used for debug
void _fill_render_list(InstanceBase **p_cull_result, int p_cull_count, bool p_shadow);
void _fill_render_list(InstanceBase **p_cull_result, int p_cull_count, bool p_depth_pass);
void _blur_effect_buffer();
void _render_mrts(Environment *env, const CameraMatrix &p_cam_projection);

View File

@ -1590,6 +1590,12 @@ FRAGMENT_SHADER_CODE
}
#endif
#ifdef USE_OPAQUE_PREPASS
if (alpha<0.99) {
discard;
}
#endif
#if defined(ENABLE_NORMALMAP)