#[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; layout(set = 0, binding = 0, std430) readonly buffer Params { vec2 raster_size; vec2 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 // UV ofssets vec2 uv_offsets[4]; uv_offsets[0] = uv_normalized + vec2(0.0, -1.0) * texel_size + offset; uv_offsets[1] = uv_normalized + vec2(0.0, 1.0) * texel_size + offset; uv_offsets[2] = uv_normalized + vec2(1.0, 0.0) * texel_size + offset; uv_offsets[3] = uv_normalized + vec2(-1.0, 0.0) * texel_size + 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); }