Pārlūkot izejas kodu

Changes to GLES2 renderer to not use cube shadows if not available, fixes #25132

Juan Linietsky 6 gadi atpakaļ
vecāks
revīzija
46af4b0a4b

+ 2 - 2
drivers/gles2/rasterizer_scene_gles2.cpp

@@ -2877,7 +2877,7 @@ void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_
 
 		if (light->type == VS::LIGHT_OMNI) {
 			// cubemap only
-			if (light->omni_shadow_mode == VS::LIGHT_OMNI_SHADOW_CUBE) {
+			if (light->omni_shadow_mode == VS::LIGHT_OMNI_SHADOW_CUBE && storage->config.support_write_depth) {
 				int cubemap_index = shadow_cubemaps.size() - 1;
 
 				// find an appropriate cubemap to render to
@@ -2973,7 +2973,7 @@ void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_
 	state.scene_shader.set_conditional(SceneShaderGLES2::RENDER_DEPTH_DUAL_PARABOLOID, false);
 
 	// convert cubemap to dual paraboloid if needed
-	if (light->type == VS::LIGHT_OMNI && light->omni_shadow_mode == VS::LIGHT_OMNI_SHADOW_CUBE && p_pass == 5) {
+	if (light->type == VS::LIGHT_OMNI && (light->omni_shadow_mode == VS::LIGHT_OMNI_SHADOW_CUBE && storage->config.support_write_depth) && p_pass == 5) {
 		ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas);
 
 		glBindFramebuffer(GL_FRAMEBUFFER, shadow_atlas->fbo);

+ 1 - 0
drivers/gles2/rasterizer_scene_gles2.h

@@ -473,6 +473,7 @@ public:
 	virtual void light_instance_set_transform(RID p_light_instance, const Transform &p_transform);
 	virtual void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_bias_scale = 1.0);
 	virtual void light_instance_mark_visible(RID p_light_instance);
+	virtual bool light_instances_can_render_shadow_cube() const { return storage->config.support_write_depth; }
 
 	LightInstance **render_light_instances;
 	int render_directional_lights;

+ 7 - 0
drivers/gles2/rasterizer_storage_gles2.cpp

@@ -4673,6 +4673,13 @@ void RasterizerStorageGLES2::initialize() {
 	config.support_32_bits_indices = config.extensions.has("GL_OES_element_index_uint");
 #endif
 
+#ifdef GLES_OVER_GL
+	config.support_write_depth = true;
+#else
+	config.support_write_depth = config.extensions.has("GL_EXT_frag_depth");
+#endif
+
+
 	frame.count = 0;
 	frame.delta = 0;
 	frame.current_rt = NULL;

+ 1 - 0
drivers/gles2/rasterizer_storage_gles2.h

@@ -80,6 +80,7 @@ public:
 		bool use_rgba_2d_shadows;
 
 		bool support_32_bits_indices;
+		bool support_write_depth;
 	} config;
 
 	struct Resources {

+ 1 - 0
drivers/gles3/rasterizer_scene_gles3.cpp

@@ -1832,6 +1832,7 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) {
 					storage->info.render.vertices_count += s->index_array_len * amount;
 				} else
 #endif
+
 						if (s->index_array_len > 0) {
 
 					glDrawElementsInstanced(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0, amount);

+ 1 - 0
servers/visual/rasterizer.h

@@ -141,6 +141,7 @@ public:
 	virtual void light_instance_set_transform(RID p_light_instance, const Transform &p_transform) = 0;
 	virtual void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_bias_scale = 1.0) = 0;
 	virtual void light_instance_mark_visible(RID p_light_instance) = 0;
+	virtual bool light_instances_can_render_shadow_cube() const { return true; }
 
 	virtual RID reflection_atlas_create() = 0;
 	virtual void reflection_atlas_set_size(RID p_ref_atlas, int p_size) = 0;

+ 80 - 84
servers/visual/visual_server_scene.cpp

@@ -1535,106 +1535,102 @@ bool VisualServerScene::_light_instance_update_shadow(Instance *p_instance, cons
 
 			VS::LightOmniShadowMode shadow_mode = VSG::storage->light_omni_get_shadow_mode(p_instance->base);
 
-			switch (shadow_mode) {
-				case VS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID: {
+			if (shadow_mode == VS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID || !VSG::scene_render->light_instances_can_render_shadow_cube()) {
 
-					for (int i = 0; i < 2; i++) {
+				for (int i = 0; i < 2; i++) {
 
-						//using this one ensures that raster deferred will have it
+					//using this one ensures that raster deferred will have it
 
-						float radius = VSG::storage->light_get_param(p_instance->base, VS::LIGHT_PARAM_RANGE);
-
-						float z = i == 0 ? -1 : 1;
-						Vector<Plane> planes;
-						planes.resize(5);
-						planes.write[0] = light_transform.xform(Plane(Vector3(0, 0, z), radius));
-						planes.write[1] = light_transform.xform(Plane(Vector3(1, 0, z).normalized(), radius));
-						planes.write[2] = light_transform.xform(Plane(Vector3(-1, 0, z).normalized(), radius));
-						planes.write[3] = light_transform.xform(Plane(Vector3(0, 1, z).normalized(), radius));
-						planes.write[4] = light_transform.xform(Plane(Vector3(0, -1, z).normalized(), radius));
-
-						int cull_count = p_scenario->octree.cull_convex(planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, VS::INSTANCE_GEOMETRY_MASK);
-						Plane near_plane(light_transform.origin, light_transform.basis.get_axis(2) * z);
-
-						for (int j = 0; j < cull_count; j++) {
-
-							Instance *instance = instance_shadow_cull_result[j];
-							if (!instance->visible || !((1 << instance->base_type) & VS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) {
-								cull_count--;
-								SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]);
-								j--;
-							} else {
-								if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
-									animated_material_found = true;
-								}
+					float radius = VSG::storage->light_get_param(p_instance->base, VS::LIGHT_PARAM_RANGE);
 
-								instance->depth = near_plane.distance_to(instance->transform.origin);
-								instance->depth_layer = 0;
+					float z = i == 0 ? -1 : 1;
+					Vector<Plane> planes;
+					planes.resize(5);
+					planes.write[0] = light_transform.xform(Plane(Vector3(0, 0, z), radius));
+					planes.write[1] = light_transform.xform(Plane(Vector3(1, 0, z).normalized(), radius));
+					planes.write[2] = light_transform.xform(Plane(Vector3(-1, 0, z).normalized(), radius));
+					planes.write[3] = light_transform.xform(Plane(Vector3(0, 1, z).normalized(), radius));
+					planes.write[4] = light_transform.xform(Plane(Vector3(0, -1, z).normalized(), radius));
+
+					int cull_count = p_scenario->octree.cull_convex(planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, VS::INSTANCE_GEOMETRY_MASK);
+					Plane near_plane(light_transform.origin, light_transform.basis.get_axis(2) * z);
+
+					for (int j = 0; j < cull_count; j++) {
+
+						Instance *instance = instance_shadow_cull_result[j];
+						if (!instance->visible || !((1 << instance->base_type) & VS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) {
+							cull_count--;
+							SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]);
+							j--;
+						} else {
+							if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
+								animated_material_found = true;
 							}
-						}
 
-						VSG::scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, i);
-						VSG::scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count);
+							instance->depth = near_plane.distance_to(instance->transform.origin);
+							instance->depth_layer = 0;
+						}
 					}
-				} break;
-				case VS::LIGHT_OMNI_SHADOW_CUBE: {
-
-					float radius = VSG::storage->light_get_param(p_instance->base, VS::LIGHT_PARAM_RANGE);
-					CameraMatrix cm;
-					cm.set_perspective(90, 1, 0.01, radius);
-
-					for (int i = 0; i < 6; i++) {
 
-						//using this one ensures that raster deferred will have it
-
-						static const Vector3 view_normals[6] = {
-							Vector3(-1, 0, 0),
-							Vector3(+1, 0, 0),
-							Vector3(0, -1, 0),
-							Vector3(0, +1, 0),
-							Vector3(0, 0, -1),
-							Vector3(0, 0, +1)
-						};
-						static const Vector3 view_up[6] = {
-							Vector3(0, -1, 0),
-							Vector3(0, -1, 0),
-							Vector3(0, 0, -1),
-							Vector3(0, 0, +1),
-							Vector3(0, -1, 0),
-							Vector3(0, -1, 0)
-						};
-
-						Transform xform = light_transform * Transform().looking_at(view_normals[i], view_up[i]);
-
-						Vector<Plane> planes = cm.get_projection_planes(xform);
+					VSG::scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, i);
+					VSG::scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count);
+				}
+			} else { //shadow cube
 
-						int cull_count = p_scenario->octree.cull_convex(planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, VS::INSTANCE_GEOMETRY_MASK);
+				float radius = VSG::storage->light_get_param(p_instance->base, VS::LIGHT_PARAM_RANGE);
+				CameraMatrix cm;
+				cm.set_perspective(90, 1, 0.01, radius);
 
-						Plane near_plane(xform.origin, -xform.basis.get_axis(2));
-						for (int j = 0; j < cull_count; j++) {
+				for (int i = 0; i < 6; i++) {
 
-							Instance *instance = instance_shadow_cull_result[j];
-							if (!instance->visible || !((1 << instance->base_type) & VS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) {
-								cull_count--;
-								SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]);
-								j--;
-							} else {
-								if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
-									animated_material_found = true;
-								}
-								instance->depth = near_plane.distance_to(instance->transform.origin);
-								instance->depth_layer = 0;
+					//using this one ensures that raster deferred will have it
+
+					static const Vector3 view_normals[6] = {
+						Vector3(-1, 0, 0),
+						Vector3(+1, 0, 0),
+						Vector3(0, -1, 0),
+						Vector3(0, +1, 0),
+						Vector3(0, 0, -1),
+						Vector3(0, 0, +1)
+					};
+					static const Vector3 view_up[6] = {
+						Vector3(0, -1, 0),
+						Vector3(0, -1, 0),
+						Vector3(0, 0, -1),
+						Vector3(0, 0, +1),
+						Vector3(0, -1, 0),
+						Vector3(0, -1, 0)
+					};
+
+					Transform xform = light_transform * Transform().looking_at(view_normals[i], view_up[i]);
+
+					Vector<Plane> planes = cm.get_projection_planes(xform);
+
+					int cull_count = p_scenario->octree.cull_convex(planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, VS::INSTANCE_GEOMETRY_MASK);
+
+					Plane near_plane(xform.origin, -xform.basis.get_axis(2));
+					for (int j = 0; j < cull_count; j++) {
+
+						Instance *instance = instance_shadow_cull_result[j];
+						if (!instance->visible || !((1 << instance->base_type) & VS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData *>(instance->base_data)->can_cast_shadows) {
+							cull_count--;
+							SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]);
+							j--;
+						} else {
+							if (static_cast<InstanceGeometryData *>(instance->base_data)->material_is_animated) {
+								animated_material_found = true;
 							}
+							instance->depth = near_plane.distance_to(instance->transform.origin);
+							instance->depth_layer = 0;
 						}
-
-						VSG::scene_render->light_instance_set_shadow_transform(light->instance, cm, xform, radius, 0, i);
-						VSG::scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count);
 					}
 
-					//restore the regular DP matrix
-					VSG::scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, 0);
+					VSG::scene_render->light_instance_set_shadow_transform(light->instance, cm, xform, radius, 0, i);
+					VSG::scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count);
+				}
 
-				} break;
+				//restore the regular DP matrix
+				VSG::scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, 0);
 			}
 
 		} break;