#[set(everything)] const constants: { VP: float4x4; invVP: float4x4; mouse: float2; tex_step: float2; radius: float; camera_right: float3; opacity: float; angle: float2; scale_x: float; camera_up: float3; camera_align: float; }; #[set(everything)] const sampler_linear: sampler; #[set(everything)] const gbufferD: tex2d; #[set(everything)] const texdecal: tex2d; #[set(everything)] const gbuffer0: tex2d; struct vert_in { pos: float4; nor: float2; tex: float2; } struct vert_out { pos: float4; tex: float2; } fun get_pos(uv: float2): float3 { var depth: float = sample_lod(gbufferD, sampler_linear, float2(uv.x, 1.0 - uv.y), 0.0).r; var wpos: float4 = float4(uv * 2.0 - 1.0, depth, 1.0); wpos = constants.invVP * wpos; return wpos.xyz / wpos.w; } fun octahedron_wrap(v: float2): float2 { var a: float2; if (v.x >= 0.0) { a.x = 1.0; } else { a.x = -1.0; } if (v.y >= 0.0) { a.y = 1.0; } else { a.y = -1.0; } var r: float2; r.x = 1.0 - abs(v.y); r.y = 1.0 - abs(v.x); return r * a; } fun get_normal(uv: float2): float3 { var g0: float2 = sample_lod(gbuffer0, sampler_linear, float2(uv.x, 1.0 - uv.y), 0.0).rg; var n: float3; n.z = 1.0 - abs(g0.x) - abs(g0.y); if (n.z >= 0.0) { n.x = g0.x; n.y = g0.y; } else { var fw: float2 = octahedron_wrap(g0.xy); n.x = fw.x; n.y = fw.y; } return n; } fun cursor_decal_vert(input: vert_in): vert_out { var keep: float = input.pos.x + input.nor.x; // hlsl var output: vert_out; output.tex = input.tex; var wpos: float3 = get_pos(constants.mouse); var uv1: float2 = constants.mouse + constants.tex_step * float2(4.0, 4.0); var uv2: float2 = constants.mouse - constants.tex_step * float2(4.0, 4.0); var n: float3 = normalize(get_normal(constants.mouse) + get_normal(uv1) + get_normal(uv2)); var n_tan: float3; var n_bin: float3; if (constants.camera_align > 0.0) { n_tan = constants.camera_right; n_bin = -constants.camera_up; } else { var cam_right: float3 = constants.camera_right; if (abs(dot(n, cam_right)) > 0.999) { cam_right = float3(0.0, 0.0, 1.0); } n_tan = normalize(cam_right - n * dot(cam_right, n)); n_bin = cross(n_tan, n); } // Rotate tangent basis by brush angle var r_tan: float3 = constants.angle.x * n_tan + constants.angle.y * n_bin; var r_bin: float3 = -constants.angle.y * n_tan + constants.angle.x * n_bin; if (vertex_id() == 3) { wpos += (-constants.scale_x * r_tan - r_bin) * constants.radius; } /*else */if (vertex_id() == 2) { wpos += ( constants.scale_x * r_tan - r_bin) * constants.radius; } /*else */if (vertex_id() == 1) { wpos += ( constants.scale_x * r_tan + r_bin) * constants.radius; } /*else */if (vertex_id() == 0) { wpos += (-constants.scale_x * r_tan + r_bin) * constants.radius; } output.pos = constants.VP * float4(wpos, 1.0); return output; } fun cursor_decal_frag(input: vert_out): float4 { var col: float4 = sample_lod(texdecal, sampler_linear, input.tex, 0.0); return float4(col.rgb, col.a * constants.opacity); } #[pipe] struct pipe { vertex = cursor_decal_vert; fragment = cursor_decal_frag; }