shader_type spatial; render_mode diffuse_lambert, specular_disabled; // T-1088 greybox wall + camera-side cutaway (design §8) — technique // proto-production. // // COLOR-multiplied albedo (same four-state tint contract as the floor shader) // plus a smoothstep height cut along the CAMERA->CHARACTER SIGHTLINE CORRIDOR: // walls inside the corridor drop to a CUT_HEIGHT stub — the Xenonauts read, // aligned to what actually occludes the character (the earlier proximity dome // bit side walls while leaving the occluding wall standing). The cutaway cuts // RENDER HEIGHT; the tint gates KNOWLEDGE — independent factors, so remembered // walls can be cut too. Open box tops are acceptable greybox fidelity; ghost // band / dither / capping are named polish on this same shader. // // Corridor geometry (world space — the camera has yaw 0 and looks world -Z; // the diamond view is WorldRoot's 45 deg rotation, never the camera's, D-148): // the ground projection of the camera->character sightline is the +Z half-line // at the character's x. A wall occludes the character only within // |to_wall.x| < corridor half-width AND 0 < to_wall.y < reach, where reach is // pitch-derived (a WALL_H wall can occlude someone at most WALL_H / tan(pitch) // away in ortho): ~4.3 m at the -30 deg gameplay preset, long at -5 frontal, // near-zero at -80 overhead. u_char_pos_xz + u_cut_reach are pushed per frame // (GreyboxWorld.set_cutaway_char_pos) so the corridor glides with the character // and breathes with the tilt. Parked far away by default: no cut until pushed. // // Static uniforms default to the SandboxConstants values; GreyboxWorld pushes // them at material build so SandboxConstants stays the single source (§12). uniform vec2 u_char_pos_xz = vec2(1000000.0, 1000000.0); uniform float u_wall_h = 2.5; // SandboxConstants.WALL_H uniform float u_cut_height = 0.75; // SandboxConstants.CUT_HEIGHT — the stub uniform float u_corridor_half_w = 1.4; // SandboxConstants.CUT_CORRIDOR_HALF_W uniform float u_cut_band = 0.75; // SandboxConstants.CUT_BAND — falloff band uniform float u_cut_reach = 4.4; // per-frame: WALL_H / tan(camera pitch) // 0 = sightline corridor, 1 = bottom walls low, 2 = both (live-toggled, C key). uniform int u_cutaway_mode = 0; uniform vec3 u_base_albedo : source_color = vec3(0.66, 0.64, 0.60); varying vec3 v_world_pos; // Whole-box cut decision, computed per-INSTANCE in vertex() from the box's tile // center — every wall box is either full height or the stub, no per-fragment // falloff curves carving organic notches (the "sphere" read). X2-crisp tile // cuts; the smoothstep bands only shape where the 0.5 threshold falls. varying flat float v_cut; void vertex() { // MODEL_MATRIX folds in the per-instance MultiMesh transform; its origin // is the box center — .xz is the wall tile's center in world space. vec2 inst_xz = (MODEL_MATRIX * vec4(0.0, 0.0, 0.0, 1.0)).xz; vec2 to_wall = inst_xz - u_char_pos_xz; // Lateral gate: full cut inside (half_w - band), fading to none at half_w. float lateral = 1.0 - smoothstep(u_corridor_half_w - u_cut_band, u_corridor_half_w, abs(to_wall.x)); // Near gate: soft start just behind the character (no hard seam at their feet). float near_f = smoothstep(-0.25, 0.75, to_wall.y); // Far gate: corridor ends where a WALL_H wall can no longer occlude. float far_f = 1.0 - smoothstep(u_cut_reach, u_cut_reach + u_cut_band, to_wall.y); float corridor_f = lateral * near_f * far_f; // Bottom-wall flag (INSTANCE_CUSTOM.r, GreyboxWorld): KNOWN non-wall tile // behind this wall run — it would occlude interior the player should see. float cut_f = corridor_f; if (u_cutaway_mode == 1) { cut_f = INSTANCE_CUSTOM.r; } else if (u_cutaway_mode == 2) { cut_f = max(corridor_f, INSTANCE_CUSTOM.r); } v_cut = cut_f > 0.5 ? 1.0 : 0.0; v_world_pos = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz; } void fragment() { float allowed = mix(u_wall_h, u_cut_height, v_cut); if (v_world_pos.y > allowed) { discard; } ALBEDO = u_base_albedo * COLOR.rgb; ROUGHNESS = 1.0; }