From 05ba2a60d6db577314e2e5761ff9f5a4b8c99e42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20M=C3=A5rdbrink?= Date: Sun, 24 Aug 2025 22:51:30 +0200 Subject: [PATCH] Add render system --- Makefile | 2 +- ecs/components.odin | 45 ++++ ecs/physics_system.odin | 18 -- ecs/render_system.odin | 262 +++++++++++++++++++- main.odin | 329 +++++-------------------- res/white.png | Bin 0 -> 105 bytes shader.odin => shaders/out/shader.odin | 60 +++-- shader.glsl => shaders/src/shader.glsl | 9 +- 8 files changed, 395 insertions(+), 330 deletions(-) create mode 100644 ecs/components.odin create mode 100644 res/white.png rename shader.odin => shaders/out/shader.odin (80%) rename shader.glsl => shaders/src/shader.glsl (79%) diff --git a/Makefile b/Makefile index bcc58bf..aec88c4 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ build-shaders: - ./sokol-shdc -i shader.glsl -o shader.odin -l metal_macos -f sokol_odin + ./sokol-shdc -i shaders/src/shader.glsl -o shaders/out/shader.odin -l metal_macos -f sokol_odin build: build-shaders odin build . -use-single-module diff --git a/ecs/components.odin b/ecs/components.odin new file mode 100644 index 0000000..b462c51 --- /dev/null +++ b/ecs/components.odin @@ -0,0 +1,45 @@ +package ecs + +import sg "../sokol/gfx" + +Mat4 :: matrix[4, 4]f32 + +Vec2 :: [2]f32 +Vec3 :: [3]f32 +Vec4 :: [4]f32 + +Gravity :: struct { + force: Vec3 +} + +RigidBody :: struct { + velocity: Vec3, + acceleration: Vec3, +} + +Transform :: struct { + position: Vec3, + rotation: Vec3, + scale: Vec3, +} + +Color :: struct { + color: Vec4, +} + +Mesh :: struct { + vertex_buffer: sg.Buffer, + index_buffer: sg.Buffer, +} + +Material :: struct { + shader: sg.Shader, + image: sg.Image, + sampler: sg.Sampler, +} + +Camera :: struct { + position: Vec3, + target: Vec3, + look: Vec2 +} diff --git a/ecs/physics_system.odin b/ecs/physics_system.odin index 39e2b4f..7074dfe 100644 --- a/ecs/physics_system.odin +++ b/ecs/physics_system.odin @@ -1,27 +1,9 @@ package ecs -Vec3 :: distinct [3]f32 - -Gravity :: struct { - force: Vec3 -} - -RigidBody :: struct { - velocity: Vec3, - acceleration: Vec3, -} - -Transform :: struct { - position: Vec3, - rotation: Vec3, - scale: Vec3, -} - PhysicsSystem :: struct { using base: SystemBase, } - physics_system_update :: proc(physics_system: ^PhysicsSystem, coordinator: ^Coordinator, dt: f32) { for entity in physics_system.entities { rigid_body := coordinator_get_component(RigidBody, coordinator, entity) diff --git a/ecs/render_system.odin b/ecs/render_system.odin index ff041e9..4a2a4ea 100644 --- a/ecs/render_system.odin +++ b/ecs/render_system.odin @@ -1,10 +1,268 @@ package ecs +import "base:runtime" +import "base:intrinsics" + +import "core:log" +import "core:mem" +import "core:time" +import "core:fmt" +import "core:testing" +import "core:strings" +import "core:path/filepath" +import "core:math" +import "core:math/linalg" +import "core:os" + +import stbi "vendor:stb/image" + +import sa "../sokol/app" +import sh "../sokol/helpers" +import sg "../sokol/gfx" + +import shaders "../shaders/out" + +VertexData :: struct { + pos: Vec3, + uv: Vec2, +} + RenderSystem :: struct { using base: SystemBase, + + shader: sg.Shader, + pipeline: sg.Pipeline, + vertex_buffer: sg.Buffer, + index_buffer: sg.Buffer, + image: sg.Image, + sampler: sg.Sampler, + + camera: struct { + pos: Vec3, + target: Vec3, + look: Vec2, + }, } -render_system_update :: proc(render_system: ^RenderSystem, coordinator: ^Coordinator) { - for entity in render_system.entities { +init_render_system :: proc(render_system: ^RenderSystem) { + default_context := runtime.default_context() + + sg.setup({ + environment = sh.glue_environment(), + allocator = sg.Allocator(sh.allocator(&default_context)), + logger = sg.Logger(sh.logger(&default_context)), + }) + + shader := sg.make_shader(shaders.main_shader_desc(sg.query_backend())) + pipeline := sg.make_pipeline({ + shader = shader, + layout = { + attrs = { + shaders.ATTR_main_pos = { format = .FLOAT3 }, + shaders.ATTR_main_uv = { format = .FLOAT2 }, + }, + }, + index_type = .UINT16, + cull_mode = .BACK, + depth = { + pixel_format = .DEFAULT, + write_enabled = true, + bias = 0.001, + bias_clamp = 0.0, + bias_slope_scale = 1.0, + compare = .LESS_EQUAL, + }, + }) + + vertices := []VertexData { + { pos = { -0.5, -0.5, 0.5 }, uv = { 0, 0 } }, + { pos = { 0.5, -0.5, 0.5 }, uv = { 1, 0 } }, + { pos = { 0.5, 0.5, 0.5 }, uv = { 1, 1 } }, + { pos = { -0.5, 0.5, 0.5 }, uv = { 0, 1 } }, + + { pos = { -0.5, -0.5, -0.5 }, uv = { 1, 0 } }, + { pos = { 0.5, -0.5, -0.5 }, uv = { 0, 0 } }, + { pos = { 0.5, 0.5, -0.5 }, uv = { 0, 1 } }, + { pos = { -0.5, 0.5, -0.5 }, uv = { 1, 1 } }, + + { pos = { -0.5, 0.5, 0.5 }, uv = { 0, 0 } }, + { pos = { 0.5, 0.5, 0.5 }, uv = { 1, 0 } }, + { pos = { 0.5, 0.5, -0.5 }, uv = { 1, 1 } }, + { pos = { -0.5, 0.5, -0.5 }, uv = { 0, 1 } }, + + { pos = { -0.5, -0.5, 0.5 }, uv = { 0, 0 } }, + { pos = { 0.5, -0.5, 0.5 }, uv = { 1, 0 } }, + { pos = { 0.5, -0.5, -0.5 }, uv = { 1, 1 } }, + { pos = { -0.5, -0.5, -0.5 }, uv = { 0, 1 } }, + + { pos = { 0.5, -0.5, 0.5 }, uv = { 0, 0 } }, + { pos = { 0.5, -0.5, -0.5 }, uv = { 1, 0 } }, + { pos = { 0.5, 0.5, -0.5 }, uv = { 1, 1 } }, + { pos = { 0.5, 0.5, 0.5 }, uv = { 0, 1 } }, + + { pos = { -0.5, -0.5, 0.5 }, uv = { 1, 0 } }, + { pos = { -0.5, -0.5, -0.5 }, uv = { 0, 0 } }, + { pos = { -0.5, 0.5, -0.5 }, uv = { 0, 1 } }, + { pos = { -0.5, 0.5, 0.5 }, uv = { 1, 1 } }, + } + vertex_buffer := sg.make_buffer({ + data = sg_range(vertices) + }) + + indices := []u16 { + 1, 0, 2, + 3, 2, 0, + 7, 4, 6, + 5, 6, 4, + 9, 8, 10, + 11, 10, 8, + 15, 12, 14, + 13, 14, 12, + 17, 16, 18, + 19, 18, 16, + 23, 20, 22, + 21, 22, 20, + } + + index_buffer := sg.make_buffer({ + usage = { index_buffer = true }, + data = sg_range(indices), + }) + + w, h: i32 + pixels := stbi.load("res/white.png", &w, &h, nil, 4) + assert(pixels != nil) + defer(stbi.image_free(pixels)) + + image := sg.make_image({ + width = w, + height = h, + pixel_format = .RGBA8, + data = { + subimage = { + 0 = { + 0 = { + ptr = pixels, + size = uint(w * h * 4) + } + } + } + } + }) + + sampler := sg.make_sampler({}) + + render_system.sampler = sampler + render_system.shader = shader + render_system.image = image + render_system.pipeline = pipeline + render_system.vertex_buffer = vertex_buffer + render_system.index_buffer = index_buffer + render_system.camera = { + pos = { 30, 0, 60 }, + target = { 0, 0, 1 }, + } +} + +delete_render_system :: proc(render_system: ^RenderSystem) { + sg.destroy_buffer(render_system.index_buffer) + sg.destroy_buffer(render_system.vertex_buffer) + sg.destroy_image(render_system.image) + sg.destroy_sampler(render_system.sampler) + sg.destroy_pipeline(render_system.pipeline) + sg.destroy_shader(render_system.shader) + + sg.shutdown() +} + +render_system_update :: proc(render_system: ^RenderSystem, coordinator: ^Coordinator, dt: f32, key_down: #sparse[sa.Keycode]bool, mouse_move: Vec2) { + update_camera(render_system, dt, key_down, mouse_move) + + proj := linalg.matrix4_perspective_f32(70, sa.widthf() / sa.heightf(), 0.001, 1000) + view := linalg.matrix4_look_at_f32(render_system.camera.pos, render_system.camera.target, { 0, 1, 0 } ) + + sg.begin_pass({ swapchain = sh.glue_swapchain() }) + + sg.apply_pipeline(render_system.pipeline) + sg.apply_bindings({ + vertex_buffers = { 0 = render_system.vertex_buffer }, + index_buffer = render_system.index_buffer, + images = { shaders.IMG_tex = render_system.image }, + samplers = { shaders.SMP_smp = render_system.sampler }, + }) + + for entity in render_system.entities { + transform := coordinator_get_component(Transform, coordinator, entity) + color := coordinator_get_component(Color, coordinator, entity) + pos_mat := linalg.matrix4_translate_f32(transform.position) + rot_mat := linalg.matrix4_from_yaw_pitch_roll_f32(transform.rotation.y, transform.rotation.x, transform.rotation.z) + model := pos_mat * rot_mat + + sg.apply_uniforms(shaders.UB_VsParams, sg_range(&shaders.Vsparams{ + mvp = proj * view * model, + col = color.color + })) + + sg.draw(0, 36, 1) + } + + sg.end_pass() + sg.commit() +} + +@(private) +update_camera :: proc(render_system: ^RenderSystem, dt: f32, key_down: #sparse[sa.Keycode]bool, mouse_move: Vec2) { + MOVE_SPEED :: 3 + LOOK_SENSITIVITY :: 0.15 + + move_input: Vec3 + if key_down[.W] do move_input.y = 1 + else if key_down[.S] do move_input.y = -1 + + if key_down[.D] do move_input.x = 1 + else if key_down[.A] do move_input.x = -1 + + if key_down[.SPACE] do move_input.z = 1 + else if key_down[.LEFT_SHIFT] do move_input.z = -1 + + look_input: Vec2 = -mouse_move * LOOK_SENSITIVITY + render_system.camera.look += look_input + render_system.camera.look.x = math.wrap(render_system.camera.look.x, 360) + render_system.camera.look.y = math.clamp(render_system.camera.look.y, -89.5, 89.5) + + look_mat := linalg.matrix4_from_yaw_pitch_roll_f32( + linalg.to_radians(render_system.camera.look.x), + linalg.to_radians(render_system.camera.look.y), + 0, + ) + + forward := (look_mat * Vec4{0, 0, -1, 1}).xyz + right := (look_mat * Vec4{1, 0, 0, 1}).xyz + up := (look_mat * Vec4{0, 1, 0, 1}).xyz + + move_dir := forward * move_input.y + right * move_input.x + up * move_input.z + motion := linalg.normalize0(move_dir) * MOVE_SPEED * dt + render_system.camera.pos += motion + + render_system.camera.target = render_system.camera.pos + forward +} + + +sg_range :: proc { + sg_range_from_slice, + sg_range_from_struct, +} + +sg_range_from_slice :: proc(s: []$T) -> sg.Range { + return { + ptr = raw_data(s), + size = len(s) * size_of(T), + } +} + +sg_range_from_struct :: proc(s: ^$T) -> sg.Range where intrinsics.type_is_struct(T) { + return { + ptr = s, + size = size_of(T), } } diff --git a/main.odin b/main.odin index f8d091e..7f107a5 100644 --- a/main.odin +++ b/main.odin @@ -13,12 +13,12 @@ import "core:path/filepath" import "core:math" import "core:math/linalg" import "core:os" +import "core:math/rand" import stbi "vendor:stb/image" import sa "sokol/app" import sh "sokol/helpers" -import sg "sokol/gfx" import "ecs" @@ -26,37 +26,11 @@ Vec2 :: [2]f32 Vec3 :: [3]f32 Vec4 :: [4]f32 -Mat4 :: matrix[4, 4]f32 - -VertexData :: struct { - pos: Vec3, - col: sg.Color, - uv: Vec2, -} - -Scene :: struct { - physics_system: ^ecs.PhysicsSystem, - entities: []ecs.EntityID, -} - Globals :: struct { - shader: sg.Shader, - pipeline: sg.Pipeline, - vertex_buffer: sg.Buffer, - index_buffer: sg.Buffer, - image: sg.Image, - sampler: sg.Sampler, - rotation: f32, - - camera: struct { - pos: Vec3, - target: Vec3, - look: Vec2, - }, - coordinator: ecs.Coordinator, - scene: Scene, - dt: f32, + physics_system: ^ecs.PhysicsSystem, + render_system: ^ecs.RenderSystem, + entities: []ecs.EntityID, } g: ^Globals @@ -86,131 +60,18 @@ main :: proc() { cleanup_cb = cleanup_cb, event_cb = event_cb, }) - - g.coordinator = ecs.coordinator_create() - defer ecs.coordinator_destroy(&g.coordinator) - - g.scene = create_scene(&g.coordinator) - defer delete(g.scene.entities) } init_cb :: proc "c" () { context = default_context - - sg.setup({ - environment = sh.glue_environment(), - allocator = sg.Allocator(sh.allocator(&default_context)), - logger = sg.Logger(sh.logger(&default_context)), - }) + sa.show_mouse(false) sa.lock_mouse(true) g = new(Globals) + g.coordinator = ecs.coordinator_create() - g.camera = { - pos = { 0, 0, 2 }, - target = { 0, 0, 1 }, - } - - g.shader = sg.make_shader(main_shader_desc(sg.query_backend())) - g.pipeline = sg.make_pipeline({ - shader = g.shader, - layout = { - attrs = { - ATTR_main_pos = { format = .FLOAT3 }, - ATTR_main_col = { format = .FLOAT4 }, - ATTR_main_uv = { format = .FLOAT2 }, - }, - }, - index_type = .UINT16, - cull_mode = .BACK, - depth = { - pixel_format = .DEFAULT, - write_enabled = true, - bias = 0.001, - bias_clamp = 0.0, - bias_slope_scale = 1.0, - compare = .LESS_EQUAL, - }, - }) - - vertices := []VertexData { - { pos = { -0.5, -0.5, 0.5 }, col = { 1, 1, 1, 1 }, uv = { 0, 0 } }, - { pos = { 0.5, -0.5, 0.5 }, col = { 1, 1, 1, 1 }, uv = { 1, 0 } }, - { pos = { 0.5, 0.5, 0.5 }, col = { 1, 1, 1, 1 }, uv = { 1, 1 } }, - { pos = { -0.5, 0.5, 0.5 }, col = { 1, 1, 1, 1 }, uv = { 0, 1 } }, - - { pos = { -0.5, -0.5, -0.5 }, col = { 1, 1, 1, 1 }, uv = { 1, 0 } }, - { pos = { 0.5, -0.5, -0.5 }, col = { 1, 1, 1, 1 }, uv = { 0, 0 } }, - { pos = { 0.5, 0.5, -0.5 }, col = { 1, 1, 1, 1 }, uv = { 0, 1 } }, - { pos = { -0.5, 0.5, -0.5 }, col = { 1, 1, 1, 1 }, uv = { 1, 1 } }, - - { pos = { -0.5, 0.5, 0.5 }, col = { 1, 1, 1, 1 }, uv = { 0, 0 } }, - { pos = { 0.5, 0.5, 0.5 }, col = { 1, 1, 1, 1 }, uv = { 1, 0 } }, - { pos = { 0.5, 0.5, -0.5 }, col = { 1, 1, 1, 1 }, uv = { 1, 1 } }, - { pos = { -0.5, 0.5, -0.5 }, col = { 1, 1, 1, 1 }, uv = { 0, 1 } }, - - { pos = { -0.5, -0.5, 0.5 }, col = { 1, 1, 1, 1 }, uv = { 0, 0 } }, - { pos = { 0.5, -0.5, 0.5 }, col = { 1, 1, 1, 1 }, uv = { 1, 0 } }, - { pos = { 0.5, -0.5, -0.5 }, col = { 1, 1, 1, 1 }, uv = { 1, 1 } }, - { pos = { -0.5, -0.5, -0.5 }, col = { 1, 1, 1, 1 }, uv = { 0, 1 } }, - - { pos = { 0.5, -0.5, 0.5 }, col = { 1, 1, 1, 1 }, uv = { 0, 0 } }, - { pos = { 0.5, -0.5, -0.5 }, col = { 1, 1, 1, 1 }, uv = { 1, 0 } }, - { pos = { 0.5, 0.5, -0.5 }, col = { 1, 1, 1, 1 }, uv = { 1, 1 } }, - { pos = { 0.5, 0.5, 0.5 }, col = { 1, 1, 1, 1 }, uv = { 0, 1 } }, - - { pos = { -0.5, -0.5, 0.5 }, col = { 1, 1, 1, 1 }, uv = { 1, 0 } }, - { pos = { -0.5, -0.5, -0.5 }, col = { 1, 1, 1, 1 }, uv = { 0, 0 } }, - { pos = { -0.5, 0.5, -0.5 }, col = { 1, 1, 1, 1 }, uv = { 0, 1 } }, - { pos = { -0.5, 0.5, 0.5 }, col = { 1, 1, 1, 1 }, uv = { 1, 1 } }, - } - g.vertex_buffer = sg.make_buffer({ - data = sg_range(vertices) - }) - - indices := []u16 { - 1, 0, 2, - 3, 2, 0, - 7, 4, 6, - 5, 6, 4, - 9, 8, 10, - 11, 10, 8, - 15, 12, 14, - 13, 14, 12, - 17, 16, 18, - 19, 18, 16, - 23, 20, 22, - 21, 22, 20, - } - - g.index_buffer = sg.make_buffer({ - usage = { index_buffer = true }, - data = sg_range(indices), - }) - - w, h: i32 - pixels := stbi.load("res/texture_blue.png", &w, &h, nil, 4) - assert(pixels != nil) - defer(stbi.image_free(pixels)) - - g.image = sg.make_image({ - width = w, - height = h, - pixel_format = .RGBA8, - data = { - subimage = { - 0 = { - 0 = { - ptr = pixels, - size = uint(w * h * 4) - } - } - } - } - }) - - g.sampler = sg.make_sampler({}) + create_scene() } frame_cb:: proc "c" () { @@ -221,103 +82,22 @@ frame_cb:: proc "c" () { return } - start_time := time.now() - //ecs.physics_system_update(g.scene.physics_system, &g.coordinator, g.dt) // seg fault - - g.dt = f32(sa.frame_duration()) - - update_camera(g.dt) - - g.rotation += linalg.to_radians(50 * g.dt) - - proj := linalg.matrix4_perspective_f32(70, sa.widthf() / sa.heightf(), 0.001, 1000) - view := linalg.matrix4_look_at_f32(g.camera.pos, g.camera.target, { 0, 1, 0 } ) + dt := f32(sa.frame_duration()) - Object :: struct { - pos: Vec3, - rot: Vec3, - } - objects := []Object { - { { -2, 0, 0 }, { 0, 0, 0 } }, - { { 0, 0, 0 }, { 0, 0, 0 } }, - { { 2, 0, 0 }, { 0, 0, 0 } }, - } - - sg.begin_pass({ swapchain = sh.glue_swapchain() }) - - sg.apply_pipeline(g.pipeline) - sg.apply_bindings({ - vertex_buffers = { 0 = g.vertex_buffer }, - index_buffer = g.index_buffer, - images = { IMG_tex = g.image }, - samplers = { SMP_smp = g.sampler }, - }) - - for obj in objects { - model := linalg.matrix4_translate_f32(obj.pos) * linalg.matrix4_from_yaw_pitch_roll_f32(obj.rot.y, obj.rot.x, obj.rot.z) - - sg.apply_uniforms(UB_VsParams, sg_range(&Vsparams { - mvp = proj * view * model - })) - - sg.draw(0, 36, 1) - } - - - sg.end_pass() - sg.commit() + ecs.physics_system_update(g.physics_system, &g.coordinator, dt) + ecs.render_system_update(g.render_system, &g.coordinator, dt, key_down, mouse_move) mouse_move = {} } -update_camera :: proc(dt: f32) { - MOVE_SPEED :: 3 - LOOK_SENSITIVITY :: 0.15 - - move_input: Vec3 - if key_down[.W] do move_input.y = 1 - else if key_down[.S] do move_input.y = -1 - - if key_down[.D] do move_input.x = 1 - else if key_down[.A] do move_input.x = -1 - - if key_down[.SPACE] do move_input.z = 1 - else if key_down[.LEFT_SHIFT] do move_input.z = -1 - - look_input: Vec2 = -mouse_move * LOOK_SENSITIVITY - g.camera.look += look_input - g.camera.look.x = math.wrap(g.camera.look.x, 360) - g.camera.look.y = math.clamp(g.camera.look.y, -89.5, 89.5) - - look_mat := linalg.matrix4_from_yaw_pitch_roll_f32( - linalg.to_radians(g.camera.look.x), - linalg.to_radians(g.camera.look.y), - 0, - ) - - forward := (look_mat * Vec4{0, 0, -1, 1}).xyz - right := (look_mat * Vec4{1, 0, 0, 1}).xyz - up := (look_mat * Vec4{0, 1, 0, 1}).xyz - - move_dir := forward * move_input.y + right * move_input.x + up * move_input.z - motion := linalg.normalize0(move_dir) * MOVE_SPEED * dt - g.camera.pos += motion - - g.camera.target = g.camera.pos + forward -} - cleanup_cb :: proc "c" () { context = default_context - sg.destroy_buffer(g.index_buffer) - sg.destroy_buffer(g.vertex_buffer) - sg.destroy_image(g.image) - sg.destroy_sampler(g.sampler) - sg.destroy_pipeline(g.pipeline) - sg.destroy_shader(g.shader) - + ecs.delete_render_system(g.render_system) + + delete(g.entities) + ecs.coordinator_destroy(&g.coordinator) free(g) - sg.shutdown() } event_cb :: proc "c" (event: ^sa.Event) { @@ -333,35 +113,41 @@ event_cb :: proc "c" (event: ^sa.Event) { } } -create_scene :: proc(coordinator: ^ecs.Coordinator) -> Scene { - scene := Scene{} - - ecs.coordinator_register_component(ecs.Gravity, coordinator) - ecs.coordinator_register_component(ecs.RigidBody, coordinator) - ecs.coordinator_register_component(ecs.Transform, coordinator) +create_scene :: proc() { + ecs.coordinator_register_component(ecs.Gravity, &g.coordinator) + ecs.coordinator_register_component(ecs.RigidBody, &g.coordinator) + ecs.coordinator_register_component(ecs.Transform, &g.coordinator) + ecs.coordinator_register_component(ecs.Color, &g.coordinator) - scene.physics_system = ecs.coordinator_register_system(ecs.PhysicsSystem, coordinator) + g.physics_system = ecs.coordinator_register_system(ecs.PhysicsSystem, &g.coordinator) + g.render_system = ecs.coordinator_register_system(ecs.RenderSystem, &g.coordinator) + ecs.init_render_system(g.render_system) signature := ecs.signature_create() - ecs.signature_set(&signature, ecs.coordinator_get_component_type(ecs.Gravity, coordinator)) - ecs.signature_set(&signature, ecs.coordinator_get_component_type(ecs.RigidBody, coordinator)) - ecs.signature_set(&signature, ecs.coordinator_get_component_type(ecs.Transform, coordinator)) - ecs.coordinator_set_system_signature(ecs.PhysicsSystem, coordinator, signature) + ecs.signature_set(&signature, ecs.coordinator_get_component_type(ecs.Gravity, &g.coordinator)) + ecs.signature_set(&signature, ecs.coordinator_get_component_type(ecs.RigidBody, &g.coordinator)) + ecs.signature_set(&signature, ecs.coordinator_get_component_type(ecs.Transform, &g.coordinator)) + ecs.coordinator_set_system_signature(ecs.PhysicsSystem, &g.coordinator, signature) - scene.entities = make([]ecs.EntityID, ecs.ENTITY_MAX) - for &entity in scene.entities { - entity = ecs.coordinator_create_entity(coordinator) + signature = ecs.signature_create() + ecs.signature_set(&signature, ecs.coordinator_get_component_type(ecs.Transform, &g.coordinator)) + ecs.signature_set(&signature, ecs.coordinator_get_component_type(ecs.Color, &g.coordinator)) + ecs.coordinator_set_system_signature(ecs.RenderSystem, &g.coordinator, signature) + + g.entities = make([]ecs.EntityID, ecs.ENTITY_MAX) + for &entity in g.entities { + entity = ecs.coordinator_create_entity(&g.coordinator) ecs.coordinator_add_component( ecs.Gravity, - coordinator, + &g.coordinator, entity, ecs.Gravity{ - ecs.Vec3{0.0, -9.82, 0.0} + ecs.Vec3{0.0, -2.82, 0.0} }) ecs.coordinator_add_component( ecs.RigidBody, - coordinator, + &g.coordinator, entity, ecs.RigidBody{ velocity = ecs.Vec3{0.0, 0.0, 0.0}, @@ -369,35 +155,30 @@ create_scene :: proc(coordinator: ^ecs.Coordinator) -> Scene { }) ecs.coordinator_add_component( ecs.Transform, - coordinator, + &g.coordinator, entity, ecs.Transform{ - position = ecs.Vec3{0.0, 0.0, 0.0}, + position = Vec3{ + f32(rand.int_max(50)), + f32(rand.int_max(10)), + f32(rand.int_max(50)), + }, rotation = ecs.Vec3{0.0, 0.0, 0.0}, scale = ecs.Vec3{1.0, 1.0, 1.0}, }) + ecs.coordinator_add_component( + ecs.Color, + &g.coordinator, + entity, + ecs.Color{ + color = Vec4{ + rand.float32_uniform(0,1), + rand.float32_uniform(0,1), + rand.float32_uniform(0,1), + rand.float32_uniform(0,1), + }, + }) } - - return scene -} - -sg_range :: proc { - sg_range_from_slice, - sg_range_from_struct, -} - -sg_range_from_slice :: proc(s: []$T) -> sg.Range { - return { - ptr = raw_data(s), - size = len(s) * size_of(T), - } -} - -sg_range_from_struct :: proc(s: ^$T) -> sg.Range where intrinsics.type_is_struct(T) { - return { - ptr = s, - size = size_of(T), - } } reset_tracking_allocator :: proc(track: ^mem.Tracking_Allocator) { diff --git a/res/white.png b/res/white.png new file mode 100644 index 0000000000000000000000000000000000000000..f05e9d6fd6a549a756eecd8a93dfc9e7b7f8854f GIT binary patch literal 105 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4mJh`hT^KKFANL}`kpS1ArbCxFE|P^FmN0; zcouK+AZdPxqyEkOuA>Z$Oe`D%3JwiW#sx78L!bJE5vx~oGB7YOc)I$ztaD0eVgLZz C;u+Wg literal 0 HcmV?d00001 diff --git a/shader.odin b/shaders/out/shader.odin similarity index 80% rename from shader.odin rename to shaders/out/shader.odin index 531fc43..ac97eaf 100644 --- a/shader.odin +++ b/shaders/out/shader.odin @@ -1,12 +1,13 @@ -package main -import sg "sokol/gfx" +package shader +import sg "../../sokol/gfx" +import ecs "../../types" /* #version:1# (machine generated, don't edit!) Generated by sokol-shdc (https://github.com/floooh/sokol-tools) Cmdline: - sokol-shdc -i shader.glsl -o shader.odin -l metal_macos -f sokol_odin + sokol-shdc -i shaders/src/shader.glsl -o shaders/out/shader.odin -l metal_macos -f sokol_odin Overview: ========= @@ -16,8 +17,7 @@ import sg "sokol/gfx" Fragment Shader: fs Attributes: ATTR_main_pos => 0 - ATTR_main_col => 1 - ATTR_main_uv => 2 + ATTR_main_uv => 1 Bindings: Uniform block 'VsParams': Odin struct: Vsparams @@ -32,14 +32,14 @@ import sg "sokol/gfx" Bind slot: SMP_smp => 0 */ ATTR_main_pos :: 0 -ATTR_main_col :: 1 -ATTR_main_uv :: 2 +ATTR_main_uv :: 1 UB_VsParams :: 0 IMG_tex :: 0 SMP_smp :: 0 Vsparams :: struct #align(16) { using _: struct #packed { - mvp: Mat4, + mvp: ecs.Mat4, + col: [4]f32, }, } /* @@ -51,6 +51,7 @@ Vsparams :: struct #align(16) { struct VsParams { float4x4 mvp; + float4 col; }; struct main0_out @@ -63,29 +64,29 @@ Vsparams :: struct #align(16) { struct main0_in { float3 pos [[attribute(0)]]; - float4 col [[attribute(1)]]; - float2 uv [[attribute(2)]]; + float2 uv [[attribute(1)]]; }; vertex main0_out main0(main0_in in [[stage_in]], constant VsParams& _19 [[buffer(0)]]) { main0_out out = {}; out.gl_Position = _19.mvp * float4(in.pos, 1.0); - out.color = in.col; + out.color = _19.col; out.tex_coord = in.uv; return out; } */ @(private="file") -vs_source_metal_macos := [601]u8 { +vs_source_metal_macos := [585]u8 { 0x23,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,0x20,0x3c,0x6d,0x65,0x74,0x61,0x6c,0x5f, 0x73,0x74,0x64,0x6c,0x69,0x62,0x3e,0x0a,0x23,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65, 0x20,0x3c,0x73,0x69,0x6d,0x64,0x2f,0x73,0x69,0x6d,0x64,0x2e,0x68,0x3e,0x0a,0x0a, 0x75,0x73,0x69,0x6e,0x67,0x20,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x20, 0x6d,0x65,0x74,0x61,0x6c,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x56, 0x73,0x50,0x61,0x72,0x61,0x6d,0x73,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c, - 0x6f,0x61,0x74,0x34,0x78,0x34,0x20,0x6d,0x76,0x70,0x3b,0x0a,0x7d,0x3b,0x0a,0x0a, + 0x6f,0x61,0x74,0x34,0x78,0x34,0x20,0x6d,0x76,0x70,0x3b,0x0a,0x20,0x20,0x20,0x20, + 0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x63,0x6f,0x6c,0x3b,0x0a,0x7d,0x3b,0x0a,0x0a, 0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74, 0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x63,0x6f, 0x6c,0x6f,0x72,0x20,0x5b,0x5b,0x75,0x73,0x65,0x72,0x28,0x6c,0x6f,0x63,0x6e,0x30, @@ -98,22 +99,20 @@ vs_source_metal_macos := [601]u8 { 0x5f,0x69,0x6e,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x33, 0x20,0x70,0x6f,0x73,0x20,0x5b,0x5b,0x61,0x74,0x74,0x72,0x69,0x62,0x75,0x74,0x65, 0x28,0x30,0x29,0x5d,0x5d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74, - 0x34,0x20,0x63,0x6f,0x6c,0x20,0x5b,0x5b,0x61,0x74,0x74,0x72,0x69,0x62,0x75,0x74, - 0x65,0x28,0x31,0x29,0x5d,0x5d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61, - 0x74,0x32,0x20,0x75,0x76,0x20,0x5b,0x5b,0x61,0x74,0x74,0x72,0x69,0x62,0x75,0x74, - 0x65,0x28,0x32,0x29,0x5d,0x5d,0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,0x76,0x65,0x72,0x74, - 0x65,0x78,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,0x20,0x6d,0x61,0x69, - 0x6e,0x30,0x28,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x69,0x6e,0x20,0x69,0x6e,0x20,0x5b, - 0x5b,0x73,0x74,0x61,0x67,0x65,0x5f,0x69,0x6e,0x5d,0x5d,0x2c,0x20,0x63,0x6f,0x6e, - 0x73,0x74,0x61,0x6e,0x74,0x20,0x56,0x73,0x50,0x61,0x72,0x61,0x6d,0x73,0x26,0x20, - 0x5f,0x31,0x39,0x20,0x5b,0x5b,0x62,0x75,0x66,0x66,0x65,0x72,0x28,0x30,0x29,0x5d, - 0x5d,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x6f, - 0x75,0x74,0x20,0x6f,0x75,0x74,0x20,0x3d,0x20,0x7b,0x7d,0x3b,0x0a,0x20,0x20,0x20, - 0x20,0x6f,0x75,0x74,0x2e,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e, - 0x20,0x3d,0x20,0x5f,0x31,0x39,0x2e,0x6d,0x76,0x70,0x20,0x2a,0x20,0x66,0x6c,0x6f, - 0x61,0x74,0x34,0x28,0x69,0x6e,0x2e,0x70,0x6f,0x73,0x2c,0x20,0x31,0x2e,0x30,0x29, - 0x3b,0x0a,0x20,0x20,0x20,0x20,0x6f,0x75,0x74,0x2e,0x63,0x6f,0x6c,0x6f,0x72,0x20, - 0x3d,0x20,0x69,0x6e,0x2e,0x63,0x6f,0x6c,0x3b,0x0a,0x20,0x20,0x20,0x20,0x6f,0x75, + 0x32,0x20,0x75,0x76,0x20,0x5b,0x5b,0x61,0x74,0x74,0x72,0x69,0x62,0x75,0x74,0x65, + 0x28,0x31,0x29,0x5d,0x5d,0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,0x76,0x65,0x72,0x74,0x65, + 0x78,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,0x20,0x6d,0x61,0x69,0x6e, + 0x30,0x28,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x69,0x6e,0x20,0x69,0x6e,0x20,0x5b,0x5b, + 0x73,0x74,0x61,0x67,0x65,0x5f,0x69,0x6e,0x5d,0x5d,0x2c,0x20,0x63,0x6f,0x6e,0x73, + 0x74,0x61,0x6e,0x74,0x20,0x56,0x73,0x50,0x61,0x72,0x61,0x6d,0x73,0x26,0x20,0x5f, + 0x31,0x39,0x20,0x5b,0x5b,0x62,0x75,0x66,0x66,0x65,0x72,0x28,0x30,0x29,0x5d,0x5d, + 0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75, + 0x74,0x20,0x6f,0x75,0x74,0x20,0x3d,0x20,0x7b,0x7d,0x3b,0x0a,0x20,0x20,0x20,0x20, + 0x6f,0x75,0x74,0x2e,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20, + 0x3d,0x20,0x5f,0x31,0x39,0x2e,0x6d,0x76,0x70,0x20,0x2a,0x20,0x66,0x6c,0x6f,0x61, + 0x74,0x34,0x28,0x69,0x6e,0x2e,0x70,0x6f,0x73,0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b, + 0x0a,0x20,0x20,0x20,0x20,0x6f,0x75,0x74,0x2e,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d, + 0x20,0x5f,0x31,0x39,0x2e,0x63,0x6f,0x6c,0x3b,0x0a,0x20,0x20,0x20,0x20,0x6f,0x75, 0x74,0x2e,0x74,0x65,0x78,0x5f,0x63,0x6f,0x6f,0x72,0x64,0x20,0x3d,0x20,0x69,0x6e, 0x2e,0x75,0x76,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20, 0x6f,0x75,0x74,0x3b,0x0a,0x7d,0x0a,0x0a,0x00, @@ -186,10 +185,9 @@ main_shader_desc :: proc (backend: sg.Backend) -> sg.Shader_Desc { desc.fragment_func.entry = "main0" desc.attrs[0].base_type = .FLOAT desc.attrs[1].base_type = .FLOAT - desc.attrs[2].base_type = .FLOAT desc.uniform_blocks[0].stage = .VERTEX desc.uniform_blocks[0].layout = .STD140 - desc.uniform_blocks[0].size = 64 + desc.uniform_blocks[0].size = 80 desc.uniform_blocks[0].msl_buffer_n = 0 desc.images[0].stage = .FRAGMENT desc.images[0].multisampled = false diff --git a/shader.glsl b/shaders/src/shader.glsl similarity index 79% rename from shader.glsl rename to shaders/src/shader.glsl index 6529946..ac6fb5a 100644 --- a/shader.glsl +++ b/shaders/src/shader.glsl @@ -1,15 +1,16 @@ -@header package main -@header import sg "sokol/gfx" +@header package shader +@header import sg "../../sokol/gfx" +@header import ecs "../../types" -@ctype mat4 Mat4 +@ctype mat4 ecs.Mat4 @vs vs in vec3 pos; -in vec4 col; in vec2 uv; layout(binding = 0) uniform VsParams { mat4 mvp; + vec4 col; }; out vec4 color;