diff --git a/scripts/cube_logic.lua b/scripts/cube_logic.lua index ad3826e..c448235 100644 --- a/scripts/cube_logic.lua +++ b/scripts/cube_logic.lua @@ -204,6 +204,10 @@ local shader_variants = { vertex = "shaders/cube.vert.spv", fragment = "shaders/cube.frag.spv", }, + solid = { + vertex = "shaders/solid.vert.spv", + fragment = "shaders/solid.frag.spv", + }, } local camera = { @@ -232,10 +236,10 @@ local last_frame_time = nil local movement_log_cooldown = 0.0 local world_up = {0.0, 1.0, 0.0} local room = { - half_size = 6.0, - wall_thickness = 0.3, - wall_height = 2.5, - floor_half_thickness = 0.2, + half_size = 15.0, + wall_thickness = 0.5, + wall_height = 4.0, + floor_half_thickness = 0.3, floor_top = 0.0, } local player_state = { @@ -250,7 +254,7 @@ local player_state = { camera.position[1] = 0.0 camera.position[2] = room.floor_top + player_state.eye_height -camera.position[3] = 4.0 +camera.position[3] = 10.0 local function clamp(value, minValue, maxValue) if value < minValue then @@ -491,15 +495,16 @@ local rotation_speed = 0.9 local function create_spinning_cube() local function compute_model_matrix(time) local rotation = math3d.rotation_y(time * rotation_speed) - local position = math3d.translation(0.0, 3.4, 0.0) - return math3d.multiply(position, rotation) + local scale = scale_matrix(1.5, 1.5, 1.5) -- Make cube 3x3x3 units + local position = math3d.translation(0.0, 3.0, 0.0) + return math3d.multiply(position, math3d.multiply(rotation, scale)) end return { vertices = cube_vertices, indices = cube_indices, compute_model_matrix = compute_model_matrix, - shader_key = "default", + shader_key = "default", -- Rainbow shader for spinning cube } end @@ -533,7 +538,7 @@ local function create_static_cube(position, scale, color) vertices = vertices, indices = cube_indices, compute_model_matrix = compute_model_matrix, - shader_key = "default", + shader_key = "solid", -- Use solid color shader for room objects } end diff --git a/scripts/dev_commands.py b/scripts/dev_commands.py index 6aa27f3..f6a876f 100644 --- a/scripts/dev_commands.py +++ b/scripts/dev_commands.py @@ -254,6 +254,61 @@ def msvc_quick(args: argparse.Namespace) -> None: run_argvs([cmd], args.dry_run) +def _compile_shaders(dry_run: bool) -> None: + """ + Compile GLSL shaders to SPIR-V format using glslangValidator. + Compiles all .vert and .frag files in the shaders directory. + """ + shaders_dir = Path("shaders") + if not shaders_dir.exists(): + return + + # Find shader compiler + compiler = None + for cmd in ["glslangValidator", "glslc"]: + try: + result = subprocess.run([cmd, "--version"], + capture_output=True, + timeout=5) + if result.returncode == 0: + compiler = cmd + break + except (FileNotFoundError, subprocess.TimeoutExpired): + continue + + if not compiler: + print("⚠️ No shader compiler found (glslangValidator or glslc)") + print(" Skipping shader compilation") + return + + print("\n=== Compiling Shaders ===") + shader_files = list(shaders_dir.glob("*.vert")) + list(shaders_dir.glob("*.frag")) + + for shader_file in shader_files: + output_file = shader_file.with_suffix(shader_file.suffix + ".spv") + + # Check if compilation is needed + if output_file.exists(): + if output_file.stat().st_mtime >= shader_file.stat().st_mtime: + continue # Skip if .spv is newer than source + + print(f" Compiling {shader_file.name} -> {output_file.name}") + + if not dry_run: + if compiler == "glslangValidator": + cmd = [compiler, "-V", str(shader_file), "-o", str(output_file)] + else: # glslc + cmd = [compiler, str(shader_file), "-o", str(output_file)] + + result = subprocess.run(cmd, capture_output=True, text=True) + if result.returncode != 0: + print(f" ❌ Failed: {result.stderr}") + else: + print(f" ✓ Success") + + print("=== Shaders Compiled ===\n") + + def _sync_assets(build_dir: str, dry_run: bool) -> None: """ Sync asset files (scripts, shaders, models) from the project root to the @@ -302,13 +357,14 @@ def run_demo(args: argparse.Namespace) -> None: executable is `sdl3_app` (or `sdl3_app.exe` on Windows). Additional arguments can be passed to the executable after `--`. - By default, syncs asset files (scripts, shaders, models) before running. - Use --no-sync to skip asset synchronization. + By default, compiles shaders and syncs asset files before running. + Use --no-sync to skip shader compilation and asset synchronization. """ build_dir = _as_build_dir(args.build_dir, DEFAULT_BUILD_DIR) - # Sync assets unless --no-sync is specified + # Compile shaders and sync assets unless --no-sync is specified if not args.no_sync: + _compile_shaders(args.dry_run) _sync_assets(build_dir, args.dry_run) exe_name = args.target or ("sdl3_app.exe" if IS_WINDOWS else "sdl3_app") @@ -430,7 +486,7 @@ def main() -> int: runp.add_argument( "--no-sync", action="store_true", - help="skip syncing assets (scripts, shaders, models) before running", + help="skip shader compilation and asset syncing before running", ) runp.add_argument( "args", diff --git a/shaders/solid.frag b/shaders/solid.frag new file mode 100644 index 0000000..9791877 --- /dev/null +++ b/shaders/solid.frag @@ -0,0 +1,10 @@ +#version 450 + +layout(location = 0) in vec3 fragColor; +layout(location = 1) in vec3 fragWorldPos; +layout(location = 0) out vec4 outColor; + +void main() { + // Use vertex color directly for solid colors + outColor = vec4(fragColor, 1.0); +} diff --git a/shaders/solid.frag.spv b/shaders/solid.frag.spv new file mode 100644 index 0000000..45f555f Binary files /dev/null and b/shaders/solid.frag.spv differ diff --git a/shaders/solid.vert b/shaders/solid.vert new file mode 100644 index 0000000..39930c3 --- /dev/null +++ b/shaders/solid.vert @@ -0,0 +1,19 @@ +#version 450 + +layout(location = 0) in vec3 inPos; +layout(location = 1) in vec3 inColor; + +layout(location = 0) out vec3 fragColor; +layout(location = 1) out vec3 fragWorldPos; + +layout(push_constant) uniform PushConstants { + mat4 model; + mat4 viewProj; +} pushConstants; + +void main() { + fragColor = inColor; + vec4 worldPos = pushConstants.model * vec4(inPos, 1.0); + fragWorldPos = worldPos.xyz; + gl_Position = pushConstants.viewProj * worldPos; +} diff --git a/shaders/solid.vert.spv b/shaders/solid.vert.spv new file mode 100644 index 0000000..986dc4b Binary files /dev/null and b/shaders/solid.vert.spv differ