shader_type spatial; render_mode diffuse_burley, specular_schlick_ggx; // Luneraria HIDE: the stone body of the Schlundkrone (G2) - dark basalt plates, pale moonstone // horns and claws, old bronze shackles. The mesh is skinned, so every pattern is taken from // the rest position that the generator stores in UV (x, z) and UV2 (y); nothing swims when // the limbs move. Thin lunar veins run through the basalt and glow in the colour of the team // the boss fights for (violet in the grotto); `energy` dims them (sleep, death), `damage` is // a short hit flash, `flicker` makes them stutter. uniform vec4 base_color : source_color = vec4(.21, .22, .26, 1.0); uniform vec4 plate_color : source_color = vec4(.31, .32, .37, 1.0); uniform float roughness_base = .84; uniform float metallic_value = 0.0; uniform float vein_amount = 1.0; uniform float vein_scale = 3.1; uniform float patina = 0.0; uniform vec4 patina_color : source_color = vec4(.30, .46, .40, 1.0); instance uniform vec4 tint : source_color, instance_index(4) = vec4(.72, .52, 1.0, 1.0); instance uniform float energy : instance_index(5) = 1.0; instance uniform float flicker : instance_index(6) = 0.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 rest; varying vec3 world_pos; #include "res://scripts/luneraria/view/materials/lune_common.gdshaderinc" void vertex() { rest = vec3(UV.x, UV2.x, UV.y); 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 large = fbm3(rest * 1.4 + seed); float fine = fbm3(rest * 7.5 + seed * 2.0); vec3 color = mix(base_color.rgb, plate_color.rgb, smoothstep(.35, .75, large)); color *= mix(.84, 1.1, fine); float cavity = 1.0 - smoothstep(.45, .95, occlusion); color = mix(color, patina_color.rgb, patina * cavity * smoothstep(.35, .7, noise3(rest * 5.0 + seed))); // Lunar veins: a ridged noise network, strongest in the crevices of the basalt. float ridge = 1.0 - abs(noise3(rest * vein_scale + seed * 3.0) * 2.0 - 1.0); // Only the deepest ridges glow, and only where the broad noise lets them: sparse veins. float vein = smoothstep(.962, .99, ridge) * smoothstep(.38, .62, large) * vein_amount; float t = TIME * 1.4 + seed * 5.0; float live = energy * (.8 + .2 * sin(t + rest.y * 3.0)); if (flicker > 0.0) live *= mix(1.0, .3 + .7 * step(.45, noise3(vec3(t * 1.9, seed, 3.0))), flicker); ALBEDO = mix(color, tint.rgb * .25, vein * .5) * mix(.5, 1.0, occlusion); ROUGHNESS = clamp(roughness_base + (fine - .5) * .12 + cavity * .08, .2, .98); METALLIC = metallic_value * (1.0 - patina * cavity * .6); SPECULAR = .4; AO = occlusion; AO_LIGHT_AFFECT = .3; EMISSION = tint.rgb * vein * live * 2.2 + tint.rgb * damage * (.06 + vein * 1.6); float height = fine * .5 + large * .3 - vein * .6; 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 * .02); }