feat: Add solid shader support and update room dimensions in cube logic

This commit is contained in:
2026-01-05 09:01:39 +00:00
parent acb4a8338e
commit a5cfcee03d
6 changed files with 103 additions and 13 deletions

View File

@@ -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

View File

@@ -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",

10
shaders/solid.frag Normal file
View File

@@ -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);
}

BIN
shaders/solid.frag.spv Normal file

Binary file not shown.

19
shaders/solid.vert Normal file
View File

@@ -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;
}

BIN
shaders/solid.vert.spv Normal file

Binary file not shown.