diff options
author | Juan Linietsky <reduzio@gmail.com> | 2019-07-07 01:49:40 -0300 |
---|---|---|
committer | Juan Linietsky <reduzio@gmail.com> | 2020-02-11 11:53:28 +0100 |
commit | f04359e70f87a6ffa0522f2b62319d605cd65792 (patch) | |
tree | 9e3168f03d68dc2d934b92ea7e56bcb59aaeffdc /servers/visual/rasterizer/shaders | |
parent | a7b2ac7bb1b5f9155866382f14138e86e52efded (diff) |
2D lighting seems more or less complete.
Diffstat (limited to 'servers/visual/rasterizer/shaders')
4 files changed, 126 insertions, 9 deletions
diff --git a/servers/visual/rasterizer/shaders/canvas.glsl b/servers/visual/rasterizer/shaders/canvas.glsl index 6b1485c86b..eb5bdbe46e 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 fb35f16971..01e87411d3 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 48757bb68a..7c9651201e 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 cf8a17ce1e..7f55be051c 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; |