shader_type spatial; render_mode diffuse_burley, specular_schlick_ggx, cull_disabled; // Luneraria CLOTH: team banners and pennants. The mesh is a plain rectangle (UV v = 0 at the // pole, 1 at the hem); silhouette and emblem come from the team: shape 0 is the cool team's // swallowtail with a crescent, shape 1 the warm team's flame-tongue hem with a sun disc. // Wind waves grow towards the hem; `tatter` tears holes for damaged buildings. uniform float wind_strength = .12; uniform float wind_speed = 1.6; instance uniform vec4 cloth_color : source_color, instance_index(12) = vec4(.2, .4, .8, 1.0); instance uniform vec4 emblem_color : source_color, instance_index(13) = vec4(.92, .9, .8, 1.0); instance uniform float shape : instance_index(14) = 0.0; instance uniform float tatter : instance_index(15) = 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 world_pos; #include "res://scripts/luneraria/view/materials/lune_common.gdshaderinc" void vertex() { float hang = UV.y; float t = TIME * wind_speed + seed * 3.0; float wave = sin(t + UV.y * 4.0 + UV.x * 1.5) * .6 + sin(t * 1.7 + UV.y * 7.0) * .4; VERTEX += NORMAL * wave * wind_strength * hang * hang; VERTEX.y += cos(t * .8 + UV.x * 2.0) * .02 * hang; 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; vec2 uv = UV; // Team silhouette. if (shape < .5) { // Swallowtail: a V cut from the hem. float cut = .72 + .28 * abs(uv.x - .5) * 2.0; if (uv.y > cut) discard; } else { // Three flame tongues. float tongues = .8 + .2 * pow(max(0.0, cos((uv.x - .5) * 3.0 * 6.28318)), 2.0) - .05 * abs(uv.x - .5); if (uv.y > tongues) discard; } if (tatter > .01 && noise3(vec3(uv * vec2(9.0, 14.0), seed)) < tatter * .45 * smoothstep(.3, 1.0, uv.y)) discard; vec2 e = (uv - vec2(.5, .38)) * vec2(1.0, 1.35); float emblem; if (shape < .5) { // Crescent moon: a disc minus an offset disc, and a small star. float outer = length(e) - .2; float inner = length(e - vec2(.09, .04)) - .17; emblem = step(max(outer, -inner), 0.0); emblem = max(emblem, step(length(e - vec2(.12, -.12)), .03)); } else { // Sun: disc and rays. float a = atan(e.y, e.x); float r = length(e); emblem = step(r, .11); emblem = max(emblem, step(r, .2 + .05 * step(0.0, cos(a * 8.0))) * step(.14, r)); } float trim = step(uv.y, .06) + step(abs(uv.x - .5), .5) * (step(.46, abs(uv.x - .5))); vec3 color = mix(cloth_color.rgb, emblem_color.rgb, clamp(emblem + trim * .8, 0.0, 1.0)); float weave = noise3(vec3(uv * vec2(80.0, 120.0), seed)) * .08; ALBEDO = color * (.92 + weave) * (1.0 - tatter * .25); ROUGHNESS = .88; BACKLIGHT = color * .35; }