Co-authored-by: m.sonaglioni <m.sonaglioni@jmpgames.it> Co-committed-by: m.sonaglioni <m.sonaglioni@jmpgames.it>
149 lines
5.3 KiB
GLSL
149 lines
5.3 KiB
GLSL
#[compute]
|
|
#version 450
|
|
// FOR THIS PROJECT THE INNER LINES MADE WITH THE SCREEN NORMAL IS NOT BEING USED, BUT THE CODE IS STILL AVAILABLE IN THE FILE
|
|
|
|
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
|
|
|
|
// --- MODIFICATO: Inserito line_thickness e mantenuto il padding (reserved) ---
|
|
layout(set = 0, binding = 0, std430) readonly buffer Params {
|
|
vec2 raster_size;
|
|
float line_thickness;
|
|
float reserved;
|
|
mat4 inv_proj_mat;
|
|
} params;
|
|
|
|
layout(rgba16f, set = 0, binding = 1) uniform image2D color_image;
|
|
layout(set = 0, binding = 2) uniform sampler2D depth_texture;
|
|
layout(set = 0, binding = 3) uniform sampler2D normal_texture;
|
|
|
|
|
|
const vec2 offset = vec2(0.0001);
|
|
const float line_highlight = 0.1;
|
|
const float line_shadow = 0.55;
|
|
|
|
|
|
float GetLinearDepth(vec2 uv, float mask) {
|
|
float raw_depth = texture(depth_texture, uv).r * mask;
|
|
vec3 ndc = vec3(uv * 2.0 - 1.0, raw_depth);
|
|
vec4 view = params.inv_proj_mat * vec4(ndc, 1.0);
|
|
view.xyz /= view.w;
|
|
return -view.z;
|
|
}
|
|
|
|
|
|
vec4 GetNormal(vec2 uv, float mask){
|
|
vec4 normal = texture(normal_texture, uv + offset) * mask;
|
|
return normal;
|
|
}
|
|
|
|
|
|
vec4 NormalRoughnessCompatibility(vec4 p_normal_roughness) {
|
|
float roughness = p_normal_roughness.w;
|
|
if (roughness > 0.5) {
|
|
roughness = 1.0 - roughness;
|
|
}
|
|
roughness /= (127.0 / 255.0);
|
|
vec4 normal_comp = vec4(normalize(p_normal_roughness.xyz * 2.0 - 1.0) * 0.5 + 0.5, roughness);
|
|
normal_comp = normal_comp * 2.0 - 1.0;
|
|
return normal_comp;
|
|
}
|
|
|
|
|
|
float NormalEdgeIndicator(vec3 normal_edge_bias, vec3 normal, vec3 neighbor_normal, float depth_difference){
|
|
float normal_difference = dot(normal - neighbor_normal, normal_edge_bias);
|
|
float normal_indicator = clamp(smoothstep(-.01, .01, normal_difference), 0.0, 1.0);
|
|
float depth_indicator = clamp(sign(depth_difference * .25 + .0025), 0.0, 1.0);
|
|
return (1.0 - dot(normal, neighbor_normal)) * depth_indicator * normal_indicator;
|
|
}
|
|
|
|
|
|
void main() {
|
|
vec2 size = params.raster_size;
|
|
ivec2 uv = ivec2(gl_GlobalInvocationID.xy);
|
|
|
|
if (uv.x >= size.x || uv.y >= size.y) {
|
|
return;
|
|
}
|
|
|
|
vec2 uv_normalized = uv / size;
|
|
vec2 texel_size = 1.0 / size.xy;
|
|
|
|
// 1. Leggiamo subito il canale Alpha (che in Godot contiene la Roughness codificata)
|
|
float raw_roughness = texture(normal_texture, uv_normalized + offset).a;
|
|
|
|
// --- INIZIO TRUCCO ESCLUSIONE ERBA ---
|
|
// Decodifichiamo la roughness esattamente come fa Godot (preso dalla tua funzione in alto)
|
|
float actual_roughness = raw_roughness;
|
|
if (actual_roughness > 0.5) {
|
|
actual_roughness = 1.0 - actual_roughness;
|
|
}
|
|
actual_roughness /= (127.0 / 255.0);
|
|
|
|
// Controlliamo se la roughness è quella "magica" dell'erba (0.02)
|
|
// Usiamo 0.005 come margine d'errore perché i float non sono mai precisi al 100%
|
|
if (abs(actual_roughness - 0.02) < 0.005) {
|
|
// Chiudiamo l'esecuzione per questo specifico pixel!
|
|
// Siccome non facciamo "imageStore", l'immagine mantiene i suoi colori
|
|
// originali senza che venga disegnata alcuna linea nera.
|
|
return;
|
|
}
|
|
// --- FINE TRUCCO ---
|
|
|
|
// Da qui in poi, il codice prosegue normalmente solo per gli altri oggetti
|
|
|
|
// --- MODIFICATO: Aggiunto multiplier "thickness" agli UV offsets ---
|
|
float thickness = params.line_thickness;
|
|
vec2 uv_offsets[4];
|
|
uv_offsets[0] = uv_normalized + vec2(0.0, -1.0) * texel_size * thickness + offset;
|
|
uv_offsets[1] = uv_normalized + vec2(0.0, 1.0) * texel_size * thickness + offset;
|
|
uv_offsets[2] = uv_normalized + vec2(1.0, 0.0) * texel_size * thickness + offset;
|
|
uv_offsets[3] = uv_normalized + vec2(-1.0, 0.0) * texel_size * thickness + offset;
|
|
|
|
float mask = ceil(raw_roughness);
|
|
|
|
// Depth based Outlines
|
|
float depth_difference = 0.0;
|
|
float inv_depth_difference = 0.5;
|
|
float depth = GetLinearDepth(uv_normalized + offset, mask);
|
|
|
|
for (int i = 0; i < uv_offsets.length(); i++){
|
|
float dOff = GetLinearDepth(uv_offsets[i], mask);
|
|
depth_difference += clamp(dOff - depth, 0.0, 1.0);
|
|
inv_depth_difference += depth - dOff;
|
|
}
|
|
|
|
inv_depth_difference = clamp(inv_depth_difference, 0.0, 1.0);
|
|
inv_depth_difference = clamp(smoothstep(0.9, 0.9, inv_depth_difference) * 10.0 , 0.0, 1.0);
|
|
depth_difference = smoothstep(0.45, 0.5, depth_difference);
|
|
|
|
|
|
// Normal based Innerlines
|
|
//float normal_difference = 0.0;
|
|
//vec3 normal_edge_bias = vec3(1.0, 1.0, 1.0);
|
|
//vec3 normal = NormalRoughnessCompatibility(GetNormal(uv_normalized, mask)).rgb;
|
|
|
|
//for (int i = 0; i < uv_offsets.length(); i++){
|
|
//vec3 n_offset = NormalRoughnessCompatibility(GetNormal(uv_offsets[i], mask)).rgb;
|
|
//normal_difference += NormalEdgeIndicator(normal_edge_bias, normal, n_offset, depth_difference);
|
|
//}
|
|
//normal_difference = smoothstep(0.2, 0.2, normal_difference);
|
|
//normal_difference = clamp(normal_difference - inv_depth_difference, 0.0, 1.0);
|
|
|
|
|
|
// Combine with screen render
|
|
|
|
vec4 color = imageLoad(color_image, uv);
|
|
|
|
vec3 outline = vec3(depth_difference);
|
|
//vec3 innerline = vec3(normal_difference) - outline;
|
|
//innerline = clamp(innerline, vec3(0.0), vec3(1.0));
|
|
//float line_mask = depth_difference + normal_difference;
|
|
float line_mask = depth_difference;
|
|
|
|
// Combine colors with lines
|
|
//vec4 color_with_lines = vec4(color.rgb + (innerline * line_highlight) - (color.rgb * outline * line_shadow), line_mask);
|
|
//vec4 color_with_lines = vec4(color.rgb - (color.rgb * outline * line_shadow), line_mask);
|
|
vec4 color_with_lines = mix(color, color * vec4(vec3(outline), 1.0) * vec4(vec3(line_shadow), 1.0), line_mask);
|
|
|
|
imageStore(color_image, uv, color_with_lines);
|
|
} |