Browse Source

Fix opaque pre pass, closes #10472

Juan Linietsky 8 years ago
parent
commit
e611ff5f01

+ 31 - 37
drivers/gles3/rasterizer_scene_gles3.cpp

@@ -1939,6 +1939,7 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_
 	bool prev_use_instancing = false;
 	bool prev_use_instancing = false;
 
 
 	storage->info.render.draw_call_count += p_element_count;
 	storage->info.render.draw_call_count += p_element_count;
+	bool prev_opaque_prepass = false;
 
 
 	for (int i = 0; i < p_element_count; i++) {
 	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;
 		bool use_instancing = e->instance->base_type == VS::INSTANCE_MULTIMESH || e->instance->base_type == VS::INSTANCE_PARTICLES;
 
 
 		if (use_instancing != prev_use_instancing) {
 		if (use_instancing != prev_use_instancing) {
@@ -2127,6 +2135,7 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_
 		prev_shading = shading;
 		prev_shading = shading;
 		prev_skeleton = skeleton;
 		prev_skeleton = skeleton;
 		prev_use_instancing = use_instancing;
 		prev_use_instancing = use_instancing;
+		prev_opaque_prepass = use_opaque_prepass;
 		first = false;
 		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_GI_PROBES, false);
 	state.scene_shader.set_conditional(SceneShaderGLES3::USE_CONTACT_SHADOWS, 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_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;
 	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);
 	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);
 	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()) {
 	while (m->next_pass.is_valid()) {
 		m = storage->material_owner.getornull(m->next_pass);
 		m = storage->material_owner.getornull(m->next_pass);
 		if (!m || !m->shader || !m->shader->valid)
 		if (!m || !m->shader || !m->shader->valid)
 			break;
 			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_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_blend_alpha = p_material->shader->spatial.blend_mode != RasterizerStorageGLES3::Shader::Spatial::BLEND_MODE_MIX;
 	bool has_alpha = has_base_alpha || has_blend_alpha;
 	bool has_alpha = has_base_alpha || has_blend_alpha;
-	bool shadow = false;
 
 
 	bool mirror = p_instance->mirror;
 	bool mirror = p_instance->mirror;
 	bool no_cull = false;
 	bool no_cull = false;
@@ -2217,7 +2226,7 @@ void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::G
 		state.used_screen_texture = true;
 		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))
 		if (has_blend_alpha || (has_base_alpha && p_material->shader->spatial.depth_draw_mode != RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS))
 			return; //bye
 			return; //bye
@@ -2252,14 +2261,14 @@ void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::G
 		e->geometry->index = current_geometry_index++;
 		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 |= 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->geometry->index) << RenderList::SORT_KEY_GEOMETRY_INDEX_SHIFT;
 	e->sort_key |= uint64_t(e->instance->base_type) << RenderList::SORT_KEY_GEOMETRY_TYPE_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) {
 		if (e->material->last_pass != render_pass) {
 			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->material->index) << RenderList::SORT_KEY_MATERIAL_INDEX_SHIFT;
 		e->sort_key |= uint64_t(e->instance->depth_layer) << RenderList::SORT_KEY_OPAQUE_DEPTH_LAYER_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()) {
 		if (e->instance->gi_probe_instances.size()) {
 			e->sort_key |= SORT_KEY_GI_PROBES_FLAG;
 			e->sort_key |= SORT_KEY_GI_PROBES_FLAG;
 		}
 		}
@@ -2302,24 +2300,20 @@ void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::G
 
 
 	//e->light_type=0xFF; // no lights!
 	//e->light_type=0xFF; // no lights!
 
 
-	if (shadow || p_material->shader->spatial.unshaded || state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_UNSHADED) {
-
-		e->sort_key |= SORT_KEY_UNSHADED_FLAG;
-	}
+	if (p_depth_pass) {
+		if (p_material->shader->spatial.unshaded || state.debug_draw == VS::VIEWPORT_DEBUG_DRAW_UNSHADED) {
 
 
-	if (!shadow && (p_material->shader->spatial.uses_vertex_lighting || storage->config.force_vertex_shading)) {
+			e->sort_key |= SORT_KEY_UNSHADED_FLAG;
+		}
 
 
-		e->sort_key |= SORT_KEY_VERTEX_LIT_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 && 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();
+	if (!p_depth_pass && (p_material->shader->spatial.uses_vertex_lighting || storage->config.force_vertex_shading)) {
 
 
-		eo->instance = e->instance;
-		eo->geometry = e->geometry;
-		eo->material = e->material;
-		eo->sort_key = e->sort_key;
+		e->sort_key |= SORT_KEY_VERTEX_LIT_FLAG;
 	}
 	}
 }
 }
 
 
@@ -3032,7 +3026,7 @@ void RasterizerSceneGLES3::_copy_texture_to_front_buffer(GLuint p_texture) {
 	storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA, false);
 	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_geometry_index = 0;
 	current_material_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;
 					int mat_idx = inst->materials[i].is_valid() ? i : -1;
 					RasterizerStorageGLES3::Surface *s = mesh->surfaces[i];
 					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;
 				//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++) {
 				for (int i = 0; i < ssize; i++) {
 
 
 					RasterizerStorageGLES3::Surface *s = mesh->surfaces[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;
 			} 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);
 				RasterizerStorageGLES3::Immediate *immediate = storage->immediate_owner.getptr(inst->base);
 				ERR_CONTINUE(!immediate);
 				ERR_CONTINUE(!immediate);
 
 
-				_add_geometry(immediate, inst, NULL, -1, p_shadow);
+				_add_geometry(immediate, inst, NULL, -1, p_depth_pass);
 
 
 			} break;
 			} break;
 			case VS::INSTANCE_PARTICLES: {
 			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++) {
 					for (int j = 0; j < ssize; j++) {
 
 
 						RasterizerStorageGLES3::Surface *s = mesh->surfaces[j];
 						RasterizerStorageGLES3::Surface *s = mesh->surfaces[j];
-						_add_geometry(s, inst, particles, -1, p_shadow);
+						_add_geometry(s, inst, particles, -1, p_depth_pass);
 					}
 					}
 				}
 				}
 
 

+ 4 - 3
drivers/gles3/rasterizer_scene_gles3.h

@@ -664,6 +664,7 @@ public:
 			//bits 12-8 geometry type
 			//bits 12-8 geometry type
 			SORT_KEY_GEOMETRY_TYPE_SHIFT = 8,
 			SORT_KEY_GEOMETRY_TYPE_SHIFT = 8,
 			//bits 0-7 for flags
 			//bits 0-7 for flags
+			SORT_KEY_OPAQUE_PRE_PASS = 8,
 			SORT_KEY_CULL_DISABLED_FLAG = 4,
 			SORT_KEY_CULL_DISABLED_FLAG = 4,
 			SORT_KEY_SKELETON_FLAG = 2,
 			SORT_KEY_SKELETON_FLAG = 2,
 			SORT_KEY_MIRROR_FLAG = 1
 			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);
 	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);
 	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_to_front_buffer(Environment *env);
 	void _copy_texture_to_front_buffer(GLuint p_texture); //used for debug
 	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 _blur_effect_buffer();
 	void _render_mrts(Environment *env, const CameraMatrix &p_cam_projection);
 	void _render_mrts(Environment *env, const CameraMatrix &p_cam_projection);

+ 6 - 0
drivers/gles3/shaders/scene.glsl

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