Browse Source

2D lighting seems more or less complete.

Juan Linietsky 6 years ago
parent
commit
f04359e70f

+ 2 - 4
scene/2d/light_2d.cpp

@@ -308,6 +308,7 @@ float Light2D::get_shadow_gradient_length() const {
 }
 }
 
 
 void Light2D::set_shadow_filter(ShadowFilter p_filter) {
 void Light2D::set_shadow_filter(ShadowFilter p_filter) {
+	ERR_FAIL_INDEX(p_filter, SHADOW_FILTER_MAX);
 	shadow_filter = p_filter;
 	shadow_filter = p_filter;
 	VS::get_singleton()->canvas_light_set_shadow_filter(canvas_light, VS::CanvasLightShadowFilter(p_filter));
 	VS::get_singleton()->canvas_light_set_shadow_filter(canvas_light, VS::CanvasLightShadowFilter(p_filter));
 }
 }
@@ -456,7 +457,7 @@ void Light2D::_bind_methods() {
 	ADD_PROPERTY(PropertyInfo(Variant::COLOR, "shadow_color"), "set_shadow_color", "get_shadow_color");
 	ADD_PROPERTY(PropertyInfo(Variant::COLOR, "shadow_color"), "set_shadow_color", "get_shadow_color");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_buffer_size", PROPERTY_HINT_RANGE, "32,16384,1"), "set_shadow_buffer_size", "get_shadow_buffer_size");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_buffer_size", PROPERTY_HINT_RANGE, "32,16384,1"), "set_shadow_buffer_size", "get_shadow_buffer_size");
 	ADD_PROPERTY(PropertyInfo(Variant::REAL, "shadow_gradient_length", PROPERTY_HINT_RANGE, "0,4096,0.1"), "set_shadow_gradient_length", "get_shadow_gradient_length");
 	ADD_PROPERTY(PropertyInfo(Variant::REAL, "shadow_gradient_length", PROPERTY_HINT_RANGE, "0,4096,0.1"), "set_shadow_gradient_length", "get_shadow_gradient_length");
-	ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_filter", PROPERTY_HINT_ENUM, "None,PCF3,PCF5,PCF7,PCF9,PCF13"), "set_shadow_filter", "get_shadow_filter");
+	ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_filter", PROPERTY_HINT_ENUM, "None,PCF5,PCF13"), "set_shadow_filter", "get_shadow_filter");
 	ADD_PROPERTY(PropertyInfo(Variant::REAL, "shadow_filter_smooth", PROPERTY_HINT_RANGE, "0,64,0.1"), "set_shadow_smooth", "get_shadow_smooth");
 	ADD_PROPERTY(PropertyInfo(Variant::REAL, "shadow_filter_smooth", PROPERTY_HINT_RANGE, "0,64,0.1"), "set_shadow_smooth", "get_shadow_smooth");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_item_cull_mask", PROPERTY_HINT_LAYERS_2D_RENDER), "set_item_shadow_cull_mask", "get_item_shadow_cull_mask");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_item_cull_mask", PROPERTY_HINT_LAYERS_2D_RENDER), "set_item_shadow_cull_mask", "get_item_shadow_cull_mask");
 
 
@@ -466,10 +467,7 @@ void Light2D::_bind_methods() {
 	BIND_ENUM_CONSTANT(MODE_MASK);
 	BIND_ENUM_CONSTANT(MODE_MASK);
 
 
 	BIND_ENUM_CONSTANT(SHADOW_FILTER_NONE);
 	BIND_ENUM_CONSTANT(SHADOW_FILTER_NONE);
-	BIND_ENUM_CONSTANT(SHADOW_FILTER_PCF3);
 	BIND_ENUM_CONSTANT(SHADOW_FILTER_PCF5);
 	BIND_ENUM_CONSTANT(SHADOW_FILTER_PCF5);
-	BIND_ENUM_CONSTANT(SHADOW_FILTER_PCF7);
-	BIND_ENUM_CONSTANT(SHADOW_FILTER_PCF9);
 	BIND_ENUM_CONSTANT(SHADOW_FILTER_PCF13);
 	BIND_ENUM_CONSTANT(SHADOW_FILTER_PCF13);
 }
 }
 
 

+ 1 - 3
scene/2d/light_2d.h

@@ -47,11 +47,9 @@ public:
 
 
 	enum ShadowFilter {
 	enum ShadowFilter {
 		SHADOW_FILTER_NONE,
 		SHADOW_FILTER_NONE,
-		SHADOW_FILTER_PCF3,
 		SHADOW_FILTER_PCF5,
 		SHADOW_FILTER_PCF5,
-		SHADOW_FILTER_PCF7,
-		SHADOW_FILTER_PCF9,
 		SHADOW_FILTER_PCF13,
 		SHADOW_FILTER_PCF13,
+		SHADOW_FILTER_MAX
 	};
 	};
 
 
 private:
 private:

+ 28 - 58
servers/visual/rasterizer/rasterizer_canvas_rd.cpp

@@ -1367,6 +1367,7 @@ void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_ite
 			state.light_uniforms[index].position[1] = canvas_light_pos.y;
 			state.light_uniforms[index].position[1] = canvas_light_pos.y;
 
 
 			_update_transform_2d_to_mat2x4(to_light_xform, state.light_uniforms[index].matrix);
 			_update_transform_2d_to_mat2x4(to_light_xform, state.light_uniforms[index].matrix);
+			_update_transform_2d_to_mat2x4(l->xform_cache.affine_inverse(), state.light_uniforms[index].shadow_matrix);
 
 
 			state.light_uniforms[index].height = l->height * (p_canvas_transform.elements[0].length() + p_canvas_transform.elements[1].length()) * 0.5; //approximate height conversion to the canvas size, since all calculations are done in canvas coords to avoid precision loss
 			state.light_uniforms[index].height = l->height * (p_canvas_transform.elements[0].length() + p_canvas_transform.elements[1].length()) * 0.5; //approximate height conversion to the canvas size, since all calculations are done in canvas coords to avoid precision loss
 			for (int i = 0; i < 4; i++) {
 			for (int i = 0; i < 4; i++) {
@@ -1377,12 +1378,16 @@ void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_ite
 			state.light_uniforms[index].color[3] = l->energy; //use alpha for energy, so base color can go separate
 			state.light_uniforms[index].color[3] = l->energy; //use alpha for energy, so base color can go separate
 
 
 			if (clight->shadow.texture.is_valid()) {
 			if (clight->shadow.texture.is_valid()) {
-				state.light_uniforms[index].shadow_pixel_size = 1.0 / clight->shadow.size;
+				state.light_uniforms[index].shadow_pixel_size = (1.0 / clight->shadow.size) * (1.0 + l->shadow_smooth);
 			} else {
 			} else {
 				state.light_uniforms[index].shadow_pixel_size = 1.0;
 				state.light_uniforms[index].shadow_pixel_size = 1.0;
 			}
 			}
 			state.light_uniforms[index].flags = clight->texture_index;
 			state.light_uniforms[index].flags = clight->texture_index;
 			state.light_uniforms[index].flags |= l->mode << LIGHT_FLAGS_BLEND_SHIFT;
 			state.light_uniforms[index].flags |= l->mode << LIGHT_FLAGS_BLEND_SHIFT;
+			state.light_uniforms[index].flags |= l->shadow_filter << LIGHT_FLAGS_FILTER_SHIFT;
+			if (clight->shadow.texture.is_valid()) {
+				state.light_uniforms[index].flags |= LIGHT_FLAGS_HAS_SHADOW;
+			}
 
 
 			l->render_index_cache = index;
 			l->render_index_cache = index;
 
 
@@ -1454,24 +1459,18 @@ void RasterizerCanvasRD::light_set_use_shadow(RID p_rid, bool p_enable, int p_re
 
 
 	if (cl->shadow.texture.is_valid()) {
 	if (cl->shadow.texture.is_valid()) {
 
 
-		RD::get_singleton()->free(cl->shadow.uniform_set);
-		cl->shadow.uniform_set = RID();
-
-		for (int i = 0; i < 4; i++) {
-			RD::get_singleton()->free(cl->shadow.render_fb[i]);
-			RD::get_singleton()->free(cl->shadow.render_textures[i]);
-			cl->shadow.render_fb[i] = RID();
-			cl->shadow.render_textures[i] = RID();
-		}
-		RD::get_singleton()->free(cl->shadow.fix_fb);
+		RD::get_singleton()->free(cl->shadow.fb);
+		RD::get_singleton()->free(cl->shadow.depth);
 		RD::get_singleton()->free(cl->shadow.texture);
 		RD::get_singleton()->free(cl->shadow.texture);
-
-		cl->shadow.fix_fb = RID();
+		cl->shadow.fb = RID();
 		cl->shadow.texture = RID();
 		cl->shadow.texture = RID();
+		cl->shadow.depth = RID();
 	}
 	}
 
 
 	if (p_enable) {
 	if (p_enable) {
 
 
+		Vector<RID> fb_textures;
+
 		{ //texture
 		{ //texture
 			RD::TextureFormat tf;
 			RD::TextureFormat tf;
 			tf.type = RD::TEXTURE_TYPE_2D;
 			tf.type = RD::TEXTURE_TYPE_2D;
@@ -1481,44 +1480,25 @@ void RasterizerCanvasRD::light_set_use_shadow(RID p_rid, bool p_enable, int p_re
 			tf.format = RD::DATA_FORMAT_R32_SFLOAT;
 			tf.format = RD::DATA_FORMAT_R32_SFLOAT;
 
 
 			cl->shadow.texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
 			cl->shadow.texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
-
-			Vector<RID> fb_textures;
 			fb_textures.push_back(cl->shadow.texture);
 			fb_textures.push_back(cl->shadow.texture);
-			cl->shadow.fix_fb = RD::get_singleton()->framebuffer_create(fb_textures);
 		}
 		}
 		{
 		{
 			RD::TextureFormat tf;
 			RD::TextureFormat tf;
 			tf.type = RD::TEXTURE_TYPE_2D;
 			tf.type = RD::TEXTURE_TYPE_2D;
-			tf.width = p_resolution / 2;
+			tf.width = p_resolution;
 			tf.height = 1;
 			tf.height = 1;
 			tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
 			tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
 			tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_X8_D24_UNORM_PACK32, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_X8_D24_UNORM_PACK32 : RD::DATA_FORMAT_D32_SFLOAT;
 			tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_X8_D24_UNORM_PACK32, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_X8_D24_UNORM_PACK32 : RD::DATA_FORMAT_D32_SFLOAT;
 			//chunks to write
 			//chunks to write
-			cl->shadow.render_depth = RD::get_singleton()->texture_create(tf, RD::TextureView());
-
-			RD::Uniform tex_uniforms;
-			tex_uniforms.type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
-			tex_uniforms.binding = 0;
-
-			for (int i = 0; i < 4; i++) {
-				tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
-				tf.format = RD::DATA_FORMAT_R32_SFLOAT;
-				cl->shadow.render_textures[i] = RD::get_singleton()->texture_create(tf, RD::TextureView());
-				Vector<RID> textures;
-				textures.push_back(cl->shadow.render_textures[i]);
-				textures.push_back(cl->shadow.render_depth);
-				cl->shadow.render_fb[i] = RD::get_singleton()->framebuffer_create(textures);
-
-				tex_uniforms.ids.push_back(default_samplers.samplers[VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST][VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED]);
-				tex_uniforms.ids.push_back(cl->shadow.render_textures[i]);
-			}
-
-			Vector<RD::Uniform> tex_uniforms_set;
-			tex_uniforms_set.push_back(tex_uniforms);
-			cl->shadow.uniform_set = RD::get_singleton()->uniform_set_create(tex_uniforms_set, shadow_render.shader_fix.version_get_shader(shadow_render.shader_fix_version, 0), 0);
+			cl->shadow.depth = RD::get_singleton()->texture_create(tf, RD::TextureView());
+			fb_textures.push_back(cl->shadow.depth);
 		}
 		}
+
+		cl->shadow.fb = RD::get_singleton()->framebuffer_create(fb_textures);
 	}
 	}
 
 
+	cl->shadow.size = p_resolution;
+
 	//canvas state uniform set needs updating
 	//canvas state uniform set needs updating
 	if (state.canvas_state_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(state.canvas_state_uniform_set)) {
 	if (state.canvas_state_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(state.canvas_state_uniform_set)) {
 		RD::get_singleton()->free(state.canvas_state_uniform_set);
 		RD::get_singleton()->free(state.canvas_state_uniform_set);
@@ -1538,7 +1518,7 @@ void RasterizerCanvasRD::light_update_shadow(RID p_rid, const Transform2D &p_lig
 
 
 		Vector<Color> cc;
 		Vector<Color> cc;
 		cc.push_back(Color(p_far, p_far, p_far, 1.0));
 		cc.push_back(Color(p_far, p_far, p_far, 1.0));
-		RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(cl->shadow.render_fb[i], RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ_COLOR_DISCARD_DEPTH, cc);
+		RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(cl->shadow.fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ_COLOR_DISCARD_DEPTH, cc, Rect2i((cl->shadow.size / 4) * i, 0, (cl->shadow.size / 4), 1));
 
 
 		CameraMatrix projection;
 		CameraMatrix projection;
 		{
 		{
@@ -1555,7 +1535,7 @@ void RasterizerCanvasRD::light_update_shadow(RID p_rid, const Transform2D &p_lig
 			projection.set_frustum(xmin, xmax, ymin, ymax, nearp, farp);
 			projection.set_frustum(xmin, xmax, ymin, ymax, nearp, farp);
 		}
 		}
 
 
-		Vector3 cam_target = Basis(Vector3(0, 0, Math_PI * 2 * (i / 4.0))).xform(Vector3(0, 1, 0));
+		Vector3 cam_target = Basis(Vector3(0, 0, Math_PI * 2 * ((i + 3) / 4.0))).xform(Vector3(0, 1, 0));
 		projection = projection * CameraMatrix(Transform().looking_at(cam_target, Vector3(0, 0, -1)).affine_inverse());
 		projection = projection * CameraMatrix(Transform().looking_at(cam_target, Vector3(0, 0, -1)).affine_inverse());
 
 
 		ShadowRenderPushConstant push_constant;
 		ShadowRenderPushConstant push_constant;
@@ -1564,6 +1544,11 @@ void RasterizerCanvasRD::light_update_shadow(RID p_rid, const Transform2D &p_lig
 				push_constant.projection[y * 4 + x] = projection.matrix[y][x];
 				push_constant.projection[y * 4 + x] = projection.matrix[y][x];
 			}
 			}
 		}
 		}
+		static const Vector2 directions[4] = { Vector2(1, 0), Vector2(0, 1), Vector2(-1, 0), Vector2(0, -1) };
+		push_constant.direction[0] = directions[i].x;
+		push_constant.direction[1] = directions[i].y;
+		push_constant.pad[0] = 0;
+		push_constant.pad[1] = 0;
 
 
 		/*if (i == 0)
 		/*if (i == 0)
 			*p_xform_cache = projection;*/
 			*p_xform_cache = projection;*/
@@ -1572,7 +1557,7 @@ void RasterizerCanvasRD::light_update_shadow(RID p_rid, const Transform2D &p_lig
 
 
 		while (instance) {
 		while (instance) {
 
 
-			OccluderPolygon *co = occluder_polygon_owner.getornull(instance->polygon);
+			OccluderPolygon *co = occluder_polygon_owner.getornull(instance->occluder);
 
 
 			if (!co || co->index_array.is_null() || !(p_light_mask & instance->light_mask)) {
 			if (!co || co->index_array.is_null() || !(p_light_mask & instance->light_mask)) {
 
 
@@ -1580,7 +1565,7 @@ void RasterizerCanvasRD::light_update_shadow(RID p_rid, const Transform2D &p_lig
 				continue;
 				continue;
 			}
 			}
 
 
-			_update_transform_2d_to_mat4(p_light_xform * instance->xform_cache, push_constant.modelview);
+			_update_transform_2d_to_mat2x4(p_light_xform * instance->xform_cache, push_constant.modelview);
 
 
 			RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, shadow_render.render_pipelines[co->cull_mode]);
 			RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, shadow_render.render_pipelines[co->cull_mode]);
 			RD::get_singleton()->draw_list_bind_vertex_array(draw_list, co->vertex_array);
 			RD::get_singleton()->draw_list_bind_vertex_array(draw_list, co->vertex_array);
@@ -1594,15 +1579,6 @@ void RasterizerCanvasRD::light_update_shadow(RID p_rid, const Transform2D &p_lig
 
 
 		RD::get_singleton()->draw_list_end();
 		RD::get_singleton()->draw_list_end();
 	}
 	}
-
-	Vector<Color> cc;
-	cc.push_back(Color(p_far, p_far, p_far, 1.0));
-	RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(cl->shadow.fix_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ_COLOR_DISCARD_DEPTH, cc);
-	RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, shadow_render.shader_fix_pipeline);
-	RD::get_singleton()->draw_list_bind_index_array(draw_list, primitive_arrays.index_array[3]);
-	RD::get_singleton()->draw_list_bind_uniform_set(draw_list, cl->shadow.uniform_set, 0);
-	RD::get_singleton()->draw_list_draw(draw_list, true);
-	RD::get_singleton()->draw_list_end();
 }
 }
 
 
 RID RasterizerCanvasRD::occluder_polygon_create() {
 RID RasterizerCanvasRD::occluder_polygon_create() {
@@ -1920,8 +1896,6 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) {
 
 
 			attachments.push_back(af_color);
 			attachments.push_back(af_color);
 
 
-			shadow_render.framebuffer_fix_format = RD::get_singleton()->framebuffer_format_create(attachments);
-
 			RD::AttachmentFormat af_depth;
 			RD::AttachmentFormat af_depth;
 			af_depth.format = RD::DATA_FORMAT_D24_UNORM_S8_UINT;
 			af_depth.format = RD::DATA_FORMAT_D24_UNORM_S8_UINT;
 			af_depth.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_X8_D24_UNORM_PACK32, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_X8_D24_UNORM_PACK32 : RD::DATA_FORMAT_D32_SFLOAT;
 			af_depth.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_X8_D24_UNORM_PACK32, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_X8_D24_UNORM_PACK32 : RD::DATA_FORMAT_D32_SFLOAT;
@@ -1953,10 +1927,6 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) {
 			ds.depth_compare_operator = RD::COMPARE_OP_LESS;
 			ds.depth_compare_operator = RD::COMPARE_OP_LESS;
 			shadow_render.render_pipelines[i] = RD::get_singleton()->render_pipeline_create(shadow_render.shader.version_get_shader(shadow_render.shader_version, 0), shadow_render.framebuffer_format, shadow_render.vertex_format, RD::RENDER_PRIMITIVE_TRIANGLES, rs, RD::PipelineMultisampleState(), ds, RD::PipelineColorBlendState::create_disabled(), 0);
 			shadow_render.render_pipelines[i] = RD::get_singleton()->render_pipeline_create(shadow_render.shader.version_get_shader(shadow_render.shader_version, 0), shadow_render.framebuffer_format, shadow_render.vertex_format, RD::RENDER_PRIMITIVE_TRIANGLES, rs, RD::PipelineMultisampleState(), ds, RD::PipelineColorBlendState::create_disabled(), 0);
 		}
 		}
-
-		shadow_render.shader_fix.initialize(versions);
-		shadow_render.shader_fix_version = shadow_render.shader_fix.version_create();
-		shadow_render.shader_fix_pipeline = RD::get_singleton()->render_pipeline_create(shadow_render.shader_fix.version_get_shader(shadow_render.shader_fix_version, 0), shadow_render.framebuffer_fix_format, RD::INVALID_ID, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
 	}
 	}
 
 
 	{ //bindings
 	{ //bindings

+ 15 - 14
servers/visual/rasterizer/rasterizer_canvas_rd.h

@@ -62,7 +62,10 @@ class RasterizerCanvasRD : public RasterizerCanvas {
 		LIGHT_FLAGS_BLEND_MODE_ADD = (0 << 16),
 		LIGHT_FLAGS_BLEND_MODE_ADD = (0 << 16),
 		LIGHT_FLAGS_BLEND_MODE_SUB = (1 << 16),
 		LIGHT_FLAGS_BLEND_MODE_SUB = (1 << 16),
 		LIGHT_FLAGS_BLEND_MODE_MIX = (2 << 16),
 		LIGHT_FLAGS_BLEND_MODE_MIX = (2 << 16),
-		LIGHT_FLAGS_BLEND_MODE_MASK = (3 << 16)
+		LIGHT_FLAGS_BLEND_MODE_MASK = (3 << 16),
+		LIGHT_FLAGS_HAS_SHADOW = (1 << 20),
+		LIGHT_FLAGS_FILTER_SHIFT = 22
+
 	};
 	};
 
 
 	enum {
 	enum {
@@ -216,13 +219,8 @@ class RasterizerCanvasRD : public RasterizerCanvas {
 		struct {
 		struct {
 			int size;
 			int size;
 			RID texture;
 			RID texture;
-
-			RID render_depth;
-			RID render_fb[4];
-			RID render_textures[4];
-			RID fix_fb;
-			RID uniform_set;
-
+			RID depth;
+			RID fb;
 		} shadow;
 		} shadow;
 	};
 	};
 
 
@@ -230,7 +228,14 @@ class RasterizerCanvasRD : public RasterizerCanvas {
 
 
 	struct ShadowRenderPushConstant {
 	struct ShadowRenderPushConstant {
 		float projection[16];
 		float projection[16];
-		float modelview[16];
+		float modelview[8];
+		float direction[2];
+		float pad[2];
+	};
+	struct ShadowFixPushConstant {
+		float projection[16];
+		float far;
+		float pad[3];
 	};
 	};
 
 
 	struct OccluderPolygon {
 	struct OccluderPolygon {
@@ -245,6 +250,7 @@ class RasterizerCanvasRD : public RasterizerCanvas {
 
 
 	struct LightUniform {
 	struct LightUniform {
 		float matrix[8]; //light to texture coordinate matrix
 		float matrix[8]; //light to texture coordinate matrix
+		float shadow_matrix[8]; //light to shadow coordinate matrix
 		float color[4];
 		float color[4];
 		float shadow_color[4];
 		float shadow_color[4];
 		float position[2];
 		float position[2];
@@ -263,11 +269,6 @@ class RasterizerCanvasRD : public RasterizerCanvas {
 		RID render_pipelines[3];
 		RID render_pipelines[3];
 		RD::VertexFormatID vertex_format;
 		RD::VertexFormatID vertex_format;
 		RD::FramebufferFormatID framebuffer_format;
 		RD::FramebufferFormatID framebuffer_format;
-
-		CanvasOcclusionFixShaderRD shader_fix;
-		RD::FramebufferFormatID framebuffer_fix_format;
-		RID shader_fix_version;
-		RID shader_fix_pipeline;
 	} shadow_render;
 	} shadow_render;
 
 
 	/***************/
 	/***************/

+ 65 - 0
servers/visual/rasterizer/shaders/canvas.glsl

@@ -491,6 +491,71 @@ FRAGMENT_SHADER_CODE
 			light_color.a = 0.0;
 			light_color.a = 0.0;
 		}
 		}
 
 
+		if (bool(light_array.data[light_base].flags&LIGHT_FLAGS_HAS_SHADOW)) {
+
+			vec2 shadow_pos = (vec4(vertex,0.0,1.0) * mat4(light_array.data[light_base].shadow_matrix[0],light_array.data[light_base].shadow_matrix[1],vec4(0.0,0.0,1.0,0.0),vec4(0.0,0.0,0.0,1.0))).xy; //multiply inverse given its transposed. Optimizer removes useless operations.
+
+			vec2 pos_norm = normalize(shadow_pos);
+			vec2 pos_abs = abs(pos_norm);
+			vec2 pos_box = pos_norm / max(pos_abs.x,pos_abs.y);
+			vec2 pos_rot = pos_norm * mat2(vec2(0.7071067811865476,-0.7071067811865476),vec2(0.7071067811865476,0.7071067811865476)); //is there a faster way to 45 degrees rot?
+			float tex_ofs;
+			float distance;
+			if (pos_rot.y>0) {
+				if (pos_rot.x>0) {
+					tex_ofs=pos_box.y*0.125+0.125;
+					distance=shadow_pos.x;
+				} else {
+					tex_ofs=pos_box.x*-0.125+(0.25+0.125);
+					distance=shadow_pos.y;
+				}
+			} else {
+				if (pos_rot.x<0) {
+					tex_ofs=pos_box.y*-0.125+(0.5+0.125);
+					distance=-shadow_pos.x;
+				} else {
+					tex_ofs=pos_box.x*0.125+(0.75+0.125);
+					distance=-shadow_pos.y;
+				}
+			}
+
+			//float distance = length(shadow_pos);
+			float shadow;
+			uint shadow_mode = light_array.data[light_base].flags&LIGHT_FLAGS_FILTER_MASK;
+			if (shadow_mode==LIGHT_FLAGS_SHADOW_NEAREST) {
+				shadow = step(texture(sampler2D(shadow_textures[texture_idx],texture_sampler),vec2(tex_ofs,0.0)).x,distance);
+			} else if (shadow_mode==LIGHT_FLAGS_SHADOW_PCF5) {
+				float shadow_pixel_size = light_array.data[light_base].shadow_pixel_size;
+				shadow = 0.0;
+				shadow += step(texture(sampler2D(shadow_textures[texture_idx],texture_sampler),vec2(tex_ofs-shadow_pixel_size*2.0,0.0)).x,distance);
+				shadow += step(texture(sampler2D(shadow_textures[texture_idx],texture_sampler),vec2(tex_ofs-shadow_pixel_size,0.0)).x,distance);
+				shadow += step(texture(sampler2D(shadow_textures[texture_idx],texture_sampler),vec2(tex_ofs,0.0)).x,distance);
+				shadow += step(texture(sampler2D(shadow_textures[texture_idx],texture_sampler),vec2(tex_ofs+shadow_pixel_size,0.0)).x,distance);
+				shadow += step(texture(sampler2D(shadow_textures[texture_idx],texture_sampler),vec2(tex_ofs+shadow_pixel_size*2.0,0.0)).x,distance);
+				shadow/=5.0;
+			} else if (shadow_mode==LIGHT_FLAGS_SHADOW_PCF13) {
+				float shadow_pixel_size = light_array.data[light_base].shadow_pixel_size;
+				shadow = 0.0;
+				shadow += step(texture(sampler2D(shadow_textures[texture_idx],texture_sampler),vec2(tex_ofs-shadow_pixel_size*6.0,0.0)).x,distance);
+				shadow += step(texture(sampler2D(shadow_textures[texture_idx],texture_sampler),vec2(tex_ofs-shadow_pixel_size*5.0,0.0)).x,distance);
+				shadow += step(texture(sampler2D(shadow_textures[texture_idx],texture_sampler),vec2(tex_ofs-shadow_pixel_size*4.0,0.0)).x,distance);
+				shadow += step(texture(sampler2D(shadow_textures[texture_idx],texture_sampler),vec2(tex_ofs-shadow_pixel_size*3.0,0.0)).x,distance);
+				shadow += step(texture(sampler2D(shadow_textures[texture_idx],texture_sampler),vec2(tex_ofs-shadow_pixel_size*2.0,0.0)).x,distance);
+				shadow += step(texture(sampler2D(shadow_textures[texture_idx],texture_sampler),vec2(tex_ofs-shadow_pixel_size,0.0)).x,distance);
+				shadow += step(texture(sampler2D(shadow_textures[texture_idx],texture_sampler),vec2(tex_ofs,0.0)).x,distance);
+				shadow += step(texture(sampler2D(shadow_textures[texture_idx],texture_sampler),vec2(tex_ofs+shadow_pixel_size,0.0)).x,distance);
+				shadow += step(texture(sampler2D(shadow_textures[texture_idx],texture_sampler),vec2(tex_ofs+shadow_pixel_size*2.0,0.0)).x,distance);
+				shadow += step(texture(sampler2D(shadow_textures[texture_idx],texture_sampler),vec2(tex_ofs+shadow_pixel_size*3.0,0.0)).x,distance);
+				shadow += step(texture(sampler2D(shadow_textures[texture_idx],texture_sampler),vec2(tex_ofs+shadow_pixel_size*4.0,0.0)).x,distance);
+				shadow += step(texture(sampler2D(shadow_textures[texture_idx],texture_sampler),vec2(tex_ofs+shadow_pixel_size*5.0,0.0)).x,distance);
+				shadow += step(texture(sampler2D(shadow_textures[texture_idx],texture_sampler),vec2(tex_ofs+shadow_pixel_size*6.0,0.0)).x,distance);
+				shadow/=13.0;
+			}
+
+			light_color = mix(light_color,light_array.data[light_base].shadow_color,shadow);
+
+		}
+
 		uint blend_mode = light_array.data[light_base].flags&LIGHT_FLAGS_BLEND_MASK;
 		uint blend_mode = light_array.data[light_base].flags&LIGHT_FLAGS_BLEND_MASK;
 
 
 		switch(blend_mode) {
 		switch(blend_mode) {

+ 5 - 3
servers/visual/rasterizer/shaders/canvas_occlusion.glsl

@@ -8,16 +8,18 @@ layout(location = 0) in highp vec3 vertex;
 
 
 layout(push_constant, binding = 0, std430) uniform Constants {
 layout(push_constant, binding = 0, std430) uniform Constants {
 
 
-	mat4 modelview;
 	mat4 projection;
 	mat4 projection;
+	mat2x4 modelview;
+	vec2 direction;
+	vec2 pad;
 } constants;
 } constants;
 
 
 layout(location = 0) out highp float depth;
 layout(location = 0) out highp float depth;
 
 
 void main() {
 void main() {
 
 
-	highp vec4 vtx = (constants.modelview * vec4(vertex, 1.0));
-	depth = length(vtx.xy);
+	highp vec4 vtx = vec4(vertex, 1.0) * mat4(constants.modelview[0],constants.modelview[1],vec4(0.0,0.0,1.0,0.0),vec4(0.0,0.0,0.0,1.0));
+	depth = dot(constants.direction,vtx.xy);
 
 
 	gl_Position = constants.projection * vtx;
 	gl_Position = constants.projection * vtx;
 
 

+ 48 - 5
servers/visual/rasterizer/shaders/canvas_occlusion_fix.glsl

@@ -35,22 +35,65 @@ layout(set=0, binding=0) uniform sampler2D textures[4];
 layout(location = 0) in highp float u;
 layout(location = 0) in highp float u;
 layout(location = 0) out highp float distance;
 layout(location = 0) out highp float distance;
 
 
+layout(push_constant, binding = 0, std430) uniform Constants {
+	mat4 projection;
+	float far;
+	float pad[3];
+} constants;
+
 void main() {
 void main() {
 
 
 	//0-1 in the texture we are writing to represents a circle, 0-2PI)
 	//0-1 in the texture we are writing to represents a circle, 0-2PI)
 	//obtain the quarter circle from the source textures
 	//obtain the quarter circle from the source textures
-	highp float sub_angle = ((mod(u,0.25)/0.25)*2.0-1.0)*(PI/4.0);
-	highp float x=tan(sub_angle)*0.5+0.5;
+	float angle=fract(u+1.0-0.125);
 
 
 	float depth;
 	float depth;
-	if (u<0.25) {
+#if 0
+	if (angle<0.25) {
+		highp float sub_angle = ((angle/0.25)*2.0-1.0)*(PI/4.0);
+		highp float x=tan(sub_angle)*0.5+0.5;
 		depth=texture(textures[0],vec2(x,0.0)).x;
 		depth=texture(textures[0],vec2(x,0.0)).x;
-	} else if (u<0.50) {
+	} else if (angle<0.50) {
+		highp float sub_angle = (((angle-0.25)/0.25)*2.0-1.0)*(PI/4.0);
+		highp float x=tan(sub_angle)*0.5+0.5;
 		depth=texture(textures[1],vec2(x,0.0)).x;
 		depth=texture(textures[1],vec2(x,0.0)).x;
-	} else if (u<0.75) {
+	} else if (angle<0.75) {
+		highp float sub_angle = (((angle-0.5)/0.25)*2.0-1.0)*(PI/4.0);
+		highp float x=tan(sub_angle)*0.5+0.5;
 		depth=texture(textures[2],vec2(x,0.0)).x;
 		depth=texture(textures[2],vec2(x,0.0)).x;
 	} else {
 	} else {
+		highp float sub_angle = (((angle-0.75)/0.25)*2.0-1.0)*(PI/4.0);
+		highp float x=tan(sub_angle)*0.5+0.5;
 		depth=texture(textures[3],vec2(x,0.0)).x;
 		depth=texture(textures[3],vec2(x,0.0)).x;
 	}
 	}
+#else
+	if (angle<0.25) {
+		highp float sub_angle = ((angle/0.25)*2.0-1.0)*(PI/4.0);
+		vec2 pos = vec2(cos(sub_angle),sin(sub_angle))*constants.far;
+		vec4 proj = constants.projection * vec4(pos,0.0,1.0);
+		float coord = (proj.x/proj.w)*0.5+0.5;
+		depth=texture(textures[0],vec2(coord,0.0)).x;
+	} else if (angle<0.50) {
+		highp float sub_angle = (((angle-0.25)/0.25)*2.0-1.0)*(PI/4.0);
+		vec2 pos = vec2(cos(sub_angle),sin(sub_angle))*constants.far;
+		vec4 proj = constants.projection * vec4(pos,0.0,1.0);
+		float coord = (proj.x/proj.w)*0.5+0.5;
+		depth=texture(textures[1],vec2(coord,0.0)).x;
+	} else if (angle<0.75) {
+		highp float sub_angle = (((angle-0.5)/0.25)*2.0-1.0)*(PI/4.0);
+		vec2 pos = vec2(cos(sub_angle),sin(sub_angle))*constants.far;
+		vec4 proj = constants.projection * vec4(pos,0.0,1.0);
+		float coord = (proj.x/proj.w)*0.5+0.5;
+		depth=texture(textures[2],vec2(coord,0.0)).x;
+	} else {
+		highp float sub_angle = (((angle-0.75)/0.25)*2.0-1.0)*(PI/4.0);
+		vec2 pos = vec2(cos(sub_angle),sin(sub_angle))*constants.far;
+		vec4 proj = constants.projection * vec4(pos,0.0,1.0);
+		float coord = (proj.x/proj.w)*0.5+0.5;
+		depth=texture(textures[3],vec2(coord,0.0)).x;
+	}
+
+
+#endif
 	distance=depth;
 	distance=depth;
 }
 }

+ 8 - 1
servers/visual/rasterizer/shaders/canvas_uniforms_inc.glsl

@@ -93,10 +93,17 @@ layout(set = 3, binding = 0, std140) uniform CanvasData {
 #define LIGHT_FLAGS_BLEND_MODE_SUB (1<<16)
 #define LIGHT_FLAGS_BLEND_MODE_SUB (1<<16)
 #define LIGHT_FLAGS_BLEND_MODE_MIX (2<<16)
 #define LIGHT_FLAGS_BLEND_MODE_MIX (2<<16)
 #define LIGHT_FLAGS_BLEND_MODE_MASK (3<<16)
 #define LIGHT_FLAGS_BLEND_MODE_MASK (3<<16)
+#define LIGHT_FLAGS_HAS_SHADOW (1<<20)
+#define LIGHT_FLAGS_FILTER_SHIFT 22
+#define LIGHT_FLAGS_FILTER_MASK (3<<22)
+#define LIGHT_FLAGS_SHADOW_NEAREST (0<<22)
+#define LIGHT_FLAGS_SHADOW_PCF5 (1<<22)
+#define LIGHT_FLAGS_SHADOW_PCF13 (2<<22)
 
 
 
 
 struct Light {
 struct Light {
-	mat2x4 matrix; //light to texture coordinate matrix
+	mat2x4 matrix; //light to texture coordinate matrix (transposed)
+	mat2x4 shadow_matrix; //light to shadow coordinate matrix (transposed)
 	vec4 color;
 	vec4 color;
 	vec4 shadow_color;
 	vec4 shadow_color;
 	vec2 position;
 	vec2 position;

+ 0 - 3
servers/visual_server.cpp

@@ -2189,10 +2189,7 @@ void VisualServer::_bind_methods() {
 	BIND_ENUM_CONSTANT(CANVAS_LIGHT_MODE_MASK);
 	BIND_ENUM_CONSTANT(CANVAS_LIGHT_MODE_MASK);
 
 
 	BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_NONE);
 	BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_NONE);
-	BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_PCF3);
 	BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_PCF5);
 	BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_PCF5);
-	BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_PCF7);
-	BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_PCF9);
 	BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_PCF13);
 	BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_PCF13);
 
 
 	BIND_ENUM_CONSTANT(CANVAS_OCCLUDER_POLYGON_CULL_DISABLED);
 	BIND_ENUM_CONSTANT(CANVAS_OCCLUDER_POLYGON_CULL_DISABLED);

+ 1 - 3
servers/visual_server.h

@@ -958,11 +958,9 @@ public:
 
 
 	enum CanvasLightShadowFilter {
 	enum CanvasLightShadowFilter {
 		CANVAS_LIGHT_FILTER_NONE,
 		CANVAS_LIGHT_FILTER_NONE,
-		CANVAS_LIGHT_FILTER_PCF3,
 		CANVAS_LIGHT_FILTER_PCF5,
 		CANVAS_LIGHT_FILTER_PCF5,
-		CANVAS_LIGHT_FILTER_PCF7,
-		CANVAS_LIGHT_FILTER_PCF9,
 		CANVAS_LIGHT_FILTER_PCF13,
 		CANVAS_LIGHT_FILTER_PCF13,
+		CANVAS_LIGHT_FILTER_MAX
 	};
 	};
 
 
 	virtual void canvas_light_set_shadow_enabled(RID p_light, bool p_enabled) = 0;
 	virtual void canvas_light_set_shadow_enabled(RID p_light, bool p_enabled) = 0;