ani
This commit is contained in:
@@ -36,8 +36,10 @@ render_mode unshaded, fog_disabled, depth_draw_never, depth_test_disabled, cull_
|
||||
// away from the viewer) inks faintly. That is what an animator does — the
|
||||
// outside line of a shape is heavy, the contact line inside it is light.
|
||||
|
||||
uniform sampler2D screen_tex : hint_screen_texture, filter_linear;
|
||||
uniform sampler2D depth_tex : hint_depth_texture, filter_nearest;
|
||||
uniform sampler2D screen_tex : hint_screen_texture, filter_linear, repeat_disable;
|
||||
uniform sampler2D depth_tex : hint_depth_texture, filter_nearest, repeat_disable;
|
||||
uniform sampler2D normal_roughness_tex : hint_normal_roughness_texture,
|
||||
filter_nearest, repeat_disable;
|
||||
|
||||
group_uniforms ink;
|
||||
uniform vec4 ink_color : source_color = vec4(0.224, 0.196, 0.310, 1.0);
|
||||
@@ -163,8 +165,7 @@ vec3 painted_sky(vec3 dir) {
|
||||
|
||||
// Linear view depth, with the sky pinned to a finite value so the second
|
||||
// difference across a silhouette is large but never infinite.
|
||||
float linear_depth(vec2 uv, mat4 inv_proj) {
|
||||
float d = texture(depth_tex, uv).r;
|
||||
float linear_depth(vec2 uv, float d, mat4 inv_proj) {
|
||||
// Godot 4.3+ is reverse-Z: the far plane and the sky read exactly 0.
|
||||
if (d <= 0.000001) {
|
||||
return ink_sky_depth;
|
||||
@@ -175,6 +176,18 @@ float linear_depth(vec2 uv, mat4 inv_proj) {
|
||||
}
|
||||
|
||||
|
||||
vec3 view_position(vec2 uv, float raw_depth, mat4 inv_proj) {
|
||||
vec4 ndc = vec4(uv * 2.0 - 1.0, raw_depth, 1.0);
|
||||
vec4 view = inv_proj * ndc;
|
||||
return view.xyz / view.w;
|
||||
}
|
||||
|
||||
|
||||
vec3 screen_normal(vec2 uv) {
|
||||
return normalize(texture(normal_roughness_tex, uv).xyz * 2.0 - 1.0);
|
||||
}
|
||||
|
||||
|
||||
vec3 apply_grade(vec3 c, vec2 uv) {
|
||||
if (!grade_enabled) {
|
||||
return c;
|
||||
@@ -226,11 +239,15 @@ void fragment() {
|
||||
}
|
||||
|
||||
vec2 t = px * ink_thickness;
|
||||
float dc = linear_depth(uv, INV_PROJECTION_MATRIX);
|
||||
float dl = linear_depth(uv - vec2(t.x, 0.0), INV_PROJECTION_MATRIX);
|
||||
float dr = linear_depth(uv + vec2(t.x, 0.0), INV_PROJECTION_MATRIX);
|
||||
float du = linear_depth(uv + vec2(0.0, t.y), INV_PROJECTION_MATRIX);
|
||||
float dd = linear_depth(uv - vec2(0.0, t.y), INV_PROJECTION_MATRIX);
|
||||
float raw_l = texture(depth_tex, uv - vec2(t.x, 0.0)).r;
|
||||
float raw_r = texture(depth_tex, uv + vec2(t.x, 0.0)).r;
|
||||
float raw_u = texture(depth_tex, uv + vec2(0.0, t.y)).r;
|
||||
float raw_d = texture(depth_tex, uv - vec2(0.0, t.y)).r;
|
||||
float dc = linear_depth(uv, raw_depth, INV_PROJECTION_MATRIX);
|
||||
float dl = linear_depth(uv - vec2(t.x, 0.0), raw_l, INV_PROJECTION_MATRIX);
|
||||
float dr = linear_depth(uv + vec2(t.x, 0.0), raw_r, INV_PROJECTION_MATRIX);
|
||||
float du = linear_depth(uv + vec2(0.0, t.y), raw_u, INV_PROJECTION_MATRIX);
|
||||
float dd = linear_depth(uv - vec2(0.0, t.y), raw_d, INV_PROJECTION_MATRIX);
|
||||
|
||||
// Second difference of linear depth, normalised by distance so that a given
|
||||
// real-world crease inks with the same weight near and far.
|
||||
@@ -245,6 +262,44 @@ void fragment() {
|
||||
edge = max(edge, smoothstep(
|
||||
ink_concave, ink_concave * 3.4, concave) * ink_concave_amount);
|
||||
|
||||
// Depth precision forms a staircase on a flat floor viewed almost edge-on.
|
||||
// Its second difference looks like curvature even though every tapped point
|
||||
// belongs to the same plane; beyond a camera-dependent distance the old test
|
||||
// therefore inked the entire road as one dark band. Confirm that curvature
|
||||
// with the normal/depth prepass before drawing it. A true edge either changes
|
||||
// normal, leaves the centre tangent plane, or crosses from geometry to sky.
|
||||
if (edge > 0.0001) {
|
||||
float sky_edge = step(raw_depth, 0.000001)
|
||||
!= step(raw_l, 0.000001) || step(raw_depth, 0.000001)
|
||||
!= step(raw_r, 0.000001) || step(raw_depth, 0.000001)
|
||||
!= step(raw_u, 0.000001) || step(raw_depth, 0.000001)
|
||||
!= step(raw_d, 0.000001) ? 1.0 : 0.0;
|
||||
float geometry_evidence = sky_edge;
|
||||
if (raw_depth > 0.000001 && sky_edge < 0.5) {
|
||||
vec3 nc = screen_normal(uv);
|
||||
vec3 nl = screen_normal(uv - vec2(t.x, 0.0));
|
||||
vec3 nr = screen_normal(uv + vec2(t.x, 0.0));
|
||||
vec3 nu = screen_normal(uv + vec2(0.0, t.y));
|
||||
vec3 nd = screen_normal(uv - vec2(0.0, t.y));
|
||||
float normal_turn = max(max(1.0 - dot(nc, nl), 1.0 - dot(nc, nr)),
|
||||
max(1.0 - dot(nc, nu), 1.0 - dot(nc, nd)));
|
||||
|
||||
vec3 pc = view_position(uv, raw_depth, INV_PROJECTION_MATRIX);
|
||||
vec3 pl = view_position(uv - vec2(t.x, 0.0), raw_l, INV_PROJECTION_MATRIX);
|
||||
vec3 pr = view_position(uv + vec2(t.x, 0.0), raw_r, INV_PROJECTION_MATRIX);
|
||||
vec3 pu = view_position(uv + vec2(0.0, t.y), raw_u, INV_PROJECTION_MATRIX);
|
||||
vec3 pd = view_position(uv - vec2(0.0, t.y), raw_d, INV_PROJECTION_MATRIX);
|
||||
float off_plane = max(max(abs(dot(nc, normalize(pl - pc))),
|
||||
abs(dot(nc, normalize(pr - pc)))),
|
||||
max(abs(dot(nc, normalize(pu - pc))),
|
||||
abs(dot(nc, normalize(pd - pc)))));
|
||||
float normal_evidence = smoothstep(0.006, 0.045, normal_turn);
|
||||
float plane_evidence = smoothstep(0.012, 0.080, off_plane);
|
||||
geometry_evidence = max(normal_evidence, plane_evidence);
|
||||
}
|
||||
edge *= geometry_evidence;
|
||||
}
|
||||
|
||||
// Fade on the nearest real surface involved in the edge, not on dc: a sky
|
||||
// pixel beside a nearby roof would otherwise be measured at 900 m and its
|
||||
// half of the silhouette would fade out while the roof's half did not.
|
||||
|
||||
Reference in New Issue
Block a user