package main import "core:fmt" import "core:math" import gpu "../.." import app "../../app" import particles "../../particles" MAX_TORCHES :: 4 MAX_COLUMNS :: 6 SHADOW_Y :: f32(0.006) torch_positions := [MAX_TORCHES]gpu.Vec3{ {-3, 5.0, -3}, { 3, 5.0, -3}, {-3, 5.0, 3}, { 3, 5.0, 3}, } column_positions := [MAX_COLUMNS]gpu.Vec3{ {-3, 0, -3}, { 3, 0, -3}, {-3, 0, 3}, { 3, 0, 3}, {-1, 0, 0}, { 1, 0, 0}, } frame_material :: proc(frame: ^gpu.Frame, color: gpu.Color, roughness: f32 = 0.7) -> gpu.Material_Handle { return gpu.add_mesh_material(frame, { color = color, roughness = roughness, reflectance = 0.35, }) } clamp01 :: proc(v: f32) -> f32 { return max(0, min(1, v)) } draw_column_shadow :: proc(frame: ^gpu.Frame, column: gpu.Vec3, flickers: [MAX_TORCHES]f32, sort_key: u64) { best_index := -1 best_power: f32 for light, i in torch_positions { dx := column.x - light.x dz := column.z - light.z dist := math.sqrt(dx * dx + dz * dz) if dist < 0.001 { continue } reach := clamp01(1 - dist / 8.0) power := reach * flickers[i] if power > best_power { best_power = power best_index = i } } if best_index < 0 { return } light := torch_positions[best_index] dx := column.x - light.x dz := column.z - light.z dist := math.sqrt(dx * dx + dz * dz) if dist < 0.001 { return } dir_x := dx / dist dir_z := dz / dist right_x := -dir_z right_z := dir_x strength := clamp01(best_power / 2.4) near_len: f32 = 0.18 far_len := 1.0 + 2.4 * strength near_width := 0.34 + 0.22 * strength far_width := 0.52 + 0.42 * strength alpha := 0.08 + 0.18 * strength start_x := column.x + dir_x * near_len start_z := column.z + dir_z * near_len end_x := column.x + dir_x * far_len end_z := column.z + dir_z * far_len _ = gpu.draw_quad_3d_frame(frame, { corners = { {start_x - right_x * near_width, SHADOW_Y, start_z - right_z * near_width}, {start_x + right_x * near_width, SHADOW_Y, start_z + right_z * near_width}, {end_x + right_x * far_width, SHADOW_Y, end_z + right_z * far_width}, {end_x - right_x * far_width, SHADOW_Y, end_z - right_z * far_width}, }, normal = {0, 1, 0}, color = {0, 0, 0, alpha}, sort_key = sort_key, order = .Sortable, }) } main :: proc() { state, ok := app.init_window(1024, 768, "GPU - Torches & Point Lights") if !ok { return } defer app.shutdown(&state) camera := gpu.default_camera_3d() camera.position = {6, 5, 8} camera.target = {0, 1, 0} fire_config := particles.default_config_3d() fire_config.max_particles = 200 fire_config.emission_rate = 60 fire_config.direction = {0, 1, 0} fire_config.gravity = {0, 2.0, 0} fire_config.speed = {0.8, 2.0} fire_config.spread = 25 fire_config.start_color = {1.0, 0.7, 0.1, 0.9} fire_config.end_color = {0.8, 0.1, 0.0, 0.0} fire_config.start_size = 0.35 fire_config.end_size = 0.05 fire_config.lifetime = {0.4, 1.0} fire_systems: [MAX_TORCHES]particles.System_3D for i in 0..