#[set(everything)] const constants: { dilate_radius: float; tex_size: float2; }; #[set(everything)] const sampler_linear: sampler; #[set(everything)] const tex: tex2d; #[set(everything)] const texdilate: tex2d; // const offsets: float2[8] = { // float2(-1.0, 0.0), float2( 1.0, 0.0), float2( 0.0, 1.0), float2( 0.0, -1.0), // float2(-1.0, 1.0), float2( 1.0, 1.0), float2( 1.0, -1.0), float2(-1.0, -1.0) // }; struct vert_in { pos: float2; } struct vert_out { pos: float4; tex: float2; } fun get_offset(i: int): float2 { if (i == 0) { return float2(-1.0, 0.0); } if (i == 1) { return float2( 1.0, 0.0); } if (i == 2) { return float2( 0.0, 1.0); } if (i == 3) { return float2( 0.0, -1.0); } if (i == 4) { return float2(-1.0, 1.0); } if (i == 5) { return float2( 1.0, 1.0); } if (i == 6) { return float2( 1.0, -1.0); } return float2(-1.0, -1.0); } fun dilate_pass_vert(input: vert_in): vert_out { var output: vert_out; output.tex = input.pos.xy * 0.5 + 0.5; output.tex.y = 1.0 - output.tex.y; output.pos = float4(input.pos.xy, 0.0, 1.0); return output; } fun dilate_pass_frag(input: vert_out): float4 { // Based on https://shaderbits.com/blog/uv-dilation by Ryan Brucks var texel_size: float2 = float2(1.0, 1.0) / constants.tex_size; var min_dist: float = 10000000.0; //var coord: uint2 = uint2(input.tex * constants.tex_size); var coordf: float2 = float2(input.tex.x * constants.tex_size.x, input.tex.y * constants.tex_size.y); var coord: uint2 = uint2(uint(coordf.x), uint(coordf.y)); //var mask: float = texdilate[coord].r; var mask4: float4 = texdilate[coord]; var mask: float = mask4.r; if (mask > 0.0) { discard; } var color: float4 = tex[coord]; var i: int = 0; while (i < int(constants.dilate_radius)) { i += 1; var j: int = 0; while (j < 8) { var cur_uv: float2 = input.tex + get_offset(j) * texel_size * float2(float(i), float(i)); coordf = cur_uv * constants.tex_size; coord = uint2(uint(coordf.x), uint(coordf.y)); var offset_mask4: float4 = texdilate[coord]; var offset_mask: float = offset_mask4.r; var offset_col: float4 = tex[coord]; if (offset_mask != 0.0) { var cur_dist: float = length(input.tex - cur_uv); if (cur_dist < min_dist) { var project_uv: float2 = cur_uv + get_offset(j) * texel_size * float2(float(i), float(i)) * float2(0.25, 0.25); var direction: float4 = sample_lod(tex, sampler_linear, project_uv, 0.0); min_dist = cur_dist; if (direction.x != 0.0 || direction.y != 0.0 || direction.z != 0.0) { var delta: float4 = offset_col - direction; color = offset_col + delta * float4(4.0, 4.0, 4.0, 4.0); } else { color = offset_col; } } } j += 1; } } return color; } #[pipe] struct pipe { vertex = dilate_pass_vert; fragment = dilate_pass_frag; }