From f04359e70f87a6ffa0522f2b62319d605cd65792 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Sun, 7 Jul 2019 01:49:40 -0300 Subject: [PATCH] 2D lighting seems more or less complete. --- scene/2d/light_2d.cpp | 6 +- scene/2d/light_2d.h | 4 +- .../rasterizer/rasterizer_canvas_rd.cpp | 86 ++++++------------- .../visual/rasterizer/rasterizer_canvas_rd.h | 29 ++++--- servers/visual/rasterizer/shaders/canvas.glsl | 65 ++++++++++++++ .../rasterizer/shaders/canvas_occlusion.glsl | 8 +- .../shaders/canvas_occlusion_fix.glsl | 53 ++++++++++-- .../shaders/canvas_uniforms_inc.glsl | 9 +- servers/visual_server.cpp | 3 - servers/visual_server.h | 4 +- 10 files changed, 173 insertions(+), 94 deletions(-) diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp index c24ad9c1c47..f163e588ec4 100644 --- a/scene/2d/light_2d.cpp +++ b/scene/2d/light_2d.cpp @@ -308,6 +308,7 @@ float Light2D::get_shadow_gradient_length() const { } void Light2D::set_shadow_filter(ShadowFilter p_filter) { + ERR_FAIL_INDEX(p_filter, SHADOW_FILTER_MAX); shadow_filter = 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::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::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::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(SHADOW_FILTER_NONE); - BIND_ENUM_CONSTANT(SHADOW_FILTER_PCF3); BIND_ENUM_CONSTANT(SHADOW_FILTER_PCF5); - BIND_ENUM_CONSTANT(SHADOW_FILTER_PCF7); - BIND_ENUM_CONSTANT(SHADOW_FILTER_PCF9); BIND_ENUM_CONSTANT(SHADOW_FILTER_PCF13); } diff --git a/scene/2d/light_2d.h b/scene/2d/light_2d.h index 7c4e8834544..03335c26fe8 100644 --- a/scene/2d/light_2d.h +++ b/scene/2d/light_2d.h @@ -47,11 +47,9 @@ public: enum ShadowFilter { SHADOW_FILTER_NONE, - SHADOW_FILTER_PCF3, SHADOW_FILTER_PCF5, - SHADOW_FILTER_PCF7, - SHADOW_FILTER_PCF9, SHADOW_FILTER_PCF13, + SHADOW_FILTER_MAX }; private: diff --git a/servers/visual/rasterizer/rasterizer_canvas_rd.cpp b/servers/visual/rasterizer/rasterizer_canvas_rd.cpp index 838e26ac737..b72196d4b93 100644 --- a/servers/visual/rasterizer/rasterizer_canvas_rd.cpp +++ b/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; _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 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 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 { state.light_uniforms[index].shadow_pixel_size = 1.0; } 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->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; @@ -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()) { - 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); - - cl->shadow.fix_fb = RID(); + cl->shadow.fb = RID(); cl->shadow.texture = RID(); + cl->shadow.depth = RID(); } if (p_enable) { + Vector fb_textures; + { //texture RD::TextureFormat tf; 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; cl->shadow.texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); - - Vector fb_textures; fb_textures.push_back(cl->shadow.texture); - cl->shadow.fix_fb = RD::get_singleton()->framebuffer_create(fb_textures); } { RD::TextureFormat tf; tf.type = RD::TEXTURE_TYPE_2D; - tf.width = p_resolution / 2; + tf.width = p_resolution; tf.height = 1; 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; //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 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 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 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); @@ -1538,7 +1518,7 @@ void RasterizerCanvasRD::light_update_shadow(RID p_rid, const Transform2D &p_lig Vector 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.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; { @@ -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); } - 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()); 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]; } } + 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) *p_xform_cache = projection;*/ @@ -1572,7 +1557,7 @@ void RasterizerCanvasRD::light_update_shadow(RID p_rid, const Transform2D &p_lig 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)) { @@ -1580,7 +1565,7 @@ void RasterizerCanvasRD::light_update_shadow(RID p_rid, const Transform2D &p_lig 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_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(); } - - Vector 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() { @@ -1920,8 +1896,6 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) { attachments.push_back(af_color); - shadow_render.framebuffer_fix_format = RD::get_singleton()->framebuffer_format_create(attachments); - RD::AttachmentFormat af_depth; 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; @@ -1953,10 +1927,6 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) { 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.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 diff --git a/servers/visual/rasterizer/rasterizer_canvas_rd.h b/servers/visual/rasterizer/rasterizer_canvas_rd.h index 59193f2a682..5a0d05d6f37 100644 --- a/servers/visual/rasterizer/rasterizer_canvas_rd.h +++ b/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_SUB = (1 << 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 { @@ -216,13 +219,8 @@ class RasterizerCanvasRD : public RasterizerCanvas { struct { int size; RID texture; - - RID render_depth; - RID render_fb[4]; - RID render_textures[4]; - RID fix_fb; - RID uniform_set; - + RID depth; + RID fb; } shadow; }; @@ -230,7 +228,14 @@ class RasterizerCanvasRD : public RasterizerCanvas { struct ShadowRenderPushConstant { 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 { @@ -245,6 +250,7 @@ class RasterizerCanvasRD : public RasterizerCanvas { struct LightUniform { float matrix[8]; //light to texture coordinate matrix + float shadow_matrix[8]; //light to shadow coordinate matrix float color[4]; float shadow_color[4]; float position[2]; @@ -263,11 +269,6 @@ class RasterizerCanvasRD : public RasterizerCanvas { RID render_pipelines[3]; RD::VertexFormatID vertex_format; RD::FramebufferFormatID framebuffer_format; - - CanvasOcclusionFixShaderRD shader_fix; - RD::FramebufferFormatID framebuffer_fix_format; - RID shader_fix_version; - RID shader_fix_pipeline; } shadow_render; /***************/ diff --git a/servers/visual/rasterizer/shaders/canvas.glsl b/servers/visual/rasterizer/shaders/canvas.glsl index 6b1485c86b7..eb5bdbe46e8 100644 --- a/servers/visual/rasterizer/shaders/canvas.glsl +++ b/servers/visual/rasterizer/shaders/canvas.glsl @@ -491,6 +491,71 @@ FRAGMENT_SHADER_CODE 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; switch(blend_mode) { diff --git a/servers/visual/rasterizer/shaders/canvas_occlusion.glsl b/servers/visual/rasterizer/shaders/canvas_occlusion.glsl index fb35f169713..01e87411d3d 100644 --- a/servers/visual/rasterizer/shaders/canvas_occlusion.glsl +++ b/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 { - mat4 modelview; mat4 projection; + mat2x4 modelview; + vec2 direction; + vec2 pad; } constants; layout(location = 0) out highp float depth; 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; diff --git a/servers/visual/rasterizer/shaders/canvas_occlusion_fix.glsl b/servers/visual/rasterizer/shaders/canvas_occlusion_fix.glsl index 48757bb68a0..7c9651201e3 100644 --- a/servers/visual/rasterizer/shaders/canvas_occlusion_fix.glsl +++ b/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) out highp float distance; +layout(push_constant, binding = 0, std430) uniform Constants { + mat4 projection; + float far; + float pad[3]; +} constants; + void main() { //0-1 in the texture we are writing to represents a circle, 0-2PI) //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; - 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; - } 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; - } 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; } 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; } +#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; } diff --git a/servers/visual/rasterizer/shaders/canvas_uniforms_inc.glsl b/servers/visual/rasterizer/shaders/canvas_uniforms_inc.glsl index cf8a17ce1e6..7f55be051c6 100644 --- a/servers/visual/rasterizer/shaders/canvas_uniforms_inc.glsl +++ b/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_MIX (2<<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 { - 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 shadow_color; vec2 position; diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp index 9733db86aa1..02f7e2869d5 100644 --- a/servers/visual_server.cpp +++ b/servers/visual_server.cpp @@ -2189,10 +2189,7 @@ void VisualServer::_bind_methods() { BIND_ENUM_CONSTANT(CANVAS_LIGHT_MODE_MASK); 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_PCF7); - BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_PCF9); BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_PCF13); BIND_ENUM_CONSTANT(CANVAS_OCCLUDER_POLYGON_CULL_DISABLED); diff --git a/servers/visual_server.h b/servers/visual_server.h index faf2597292e..f92caf9ccf2 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -958,11 +958,9 @@ public: enum CanvasLightShadowFilter { CANVAS_LIGHT_FILTER_NONE, - CANVAS_LIGHT_FILTER_PCF3, CANVAS_LIGHT_FILTER_PCF5, - CANVAS_LIGHT_FILTER_PCF7, - CANVAS_LIGHT_FILTER_PCF9, CANVAS_LIGHT_FILTER_PCF13, + CANVAS_LIGHT_FILTER_MAX }; virtual void canvas_light_set_shadow_enabled(RID p_light, bool p_enabled) = 0;