shader_type spatial; render_mode diffuse_burley, specular_schlick_ggx; // Luneraria METAL: team metal (silver-steel for the cool team, bronze-gold for the warm team), // iron and old bronze. Clearly metallic but never a mirror: roughness varies with hammered // noise and wear, occlusion from COLOR darkens and roughens cavities, bronze grows a // verdigris patina there, raised edges stay polished. Same occlusion fade as stone. uniform vec4 base_color : source_color = vec4(.74, .76, .80, 1.0); uniform float metallic_value = .92; uniform float roughness_base = .34; uniform float wear = .5; uniform float patina = 0.0; uniform vec4 patina_color : source_color = vec4(.30, .46, .40, 1.0); // Per building: team metal colour (alpha unused), damage soot, occlusion fade. instance uniform vec4 metal_tint : source_color, instance_index(7) = vec4(1.0); instance uniform float damage : instance_index(0) = 0.0; instance uniform float fade : instance_index(1) = 0.0; instance uniform float fade_floor : instance_index(2) = 2.2; instance uniform float seed : instance_index(3) = 0.0; varying vec3 local_pos; varying vec3 world_pos; #include "res://scripts/luneraria/view/materials/lune_common.gdshaderinc" void vertex() { local_pos = VERTEX; world_pos = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz; } void fragment() { if (PROJECTION_MATRIX[3][3] < .5 && faded(fade, fade_floor, world_pos.y, FRAGCOORD.xy)) discard; float occlusion = COLOR.r; float hammer = fbm3(local_pos * 9.0 + seed); float streak = noise3(vec3(local_pos.x * 2.0, local_pos.y * 14.0, local_pos.z * 2.0) + seed); float cavity = 1.0 - smoothstep(.45, .95, occlusion); vec3 color = base_color.rgb * metal_tint.rgb; color *= mix(.86, 1.08, hammer) * mix(.95, 1.03, streak); // Patina in cavities (bronze), soot where damaged. color = mix(color, patina_color.rgb, patina * cavity * smoothstep(.35, .7, noise3(local_pos * 4.0 + seed))); color *= 1.0 - damage * .35 * smoothstep(.4, .8, noise3(local_pos * 2.5 + seed * 2.0)); ALBEDO = color * mix(.6, 1.0, occlusion); METALLIC = metallic_value * (1.0 - patina * cavity * .7); ROUGHNESS = clamp(roughness_base + (hammer - .5) * .18 + cavity * wear * .3 + damage * .2, .12, .9); AO = occlusion; AO_LIGHT_AFFECT = .25; float height = hammer * .5 + streak * .2; vec3 dpdx = dFdx(VERTEX), dpdy = dFdy(VERTEX); vec3 rx = cross(dpdy, NORMAL), ry = cross(NORMAL, dpdx); float det = dot(dpdx, rx); vec3 grad = dFdx(height) * rx + dFdy(height) * ry; NORMAL = normalize(abs(det) * NORMAL - sign(det) * grad * .01); }