138 lines
3.0 KiB
Plaintext
138 lines
3.0 KiB
Plaintext
|
|
#[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;
|
|
}
|