Compare commits
13 commits
hugom/rend
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| aa28465147 | |||
| fe42f2665c | |||
| 2ba1022f79 | |||
| b9aaeb62c9 | |||
| f658d040ed | |||
| db75a10f2b | |||
| e1e480daf2 | |||
| 2ee22c118c | |||
| 1852cf3a7f | |||
| 6d43f30c09 | |||
| 77c5c23cf5 | |||
| 705f498daa | |||
| 29e7b5e499 |
10
Makefile
|
|
@ -1,17 +1,25 @@
|
||||||
build-shaders:
|
build-shaders:
|
||||||
./sokol-shdc -i shaders/src/shader.glsl -o shaders/out/shader.odin -l metal_macos -f sokol_odin
|
./sokol-shdc -i shaders/src/cube.glsl -o shaders/out/cube.odin -l metal_macos -f sokol_odin
|
||||||
|
./sokol-shdc -i shaders/src/outline.glsl -o shaders/out/outline.odin -l metal_macos -f sokol_odin
|
||||||
|
|
||||||
build: build-shaders
|
build: build-shaders
|
||||||
odin build . -use-single-module
|
odin build . -use-single-module
|
||||||
|
|
||||||
build-debug: build-shaders
|
build-debug: build-shaders
|
||||||
odin build . -debug -use-single-module
|
odin build . -debug -use-single-module
|
||||||
|
|
||||||
|
build-release: build-shaders
|
||||||
|
odin build . -o:speed -use-single-module
|
||||||
|
|
||||||
run: build-shaders
|
run: build-shaders
|
||||||
odin run . -use-single-module
|
odin run . -use-single-module
|
||||||
|
|
||||||
run-debug: build-shaders
|
run-debug: build-shaders
|
||||||
odin run . -debug -use-single-module
|
odin run . -debug -use-single-module
|
||||||
|
|
||||||
|
run-release: build-shaders
|
||||||
|
odin run . -o:speed -use-single-module
|
||||||
|
|
||||||
check: build-shaders
|
check: build-shaders
|
||||||
odin strip-semicolon .
|
odin strip-semicolon .
|
||||||
odin check .
|
odin check .
|
||||||
|
|
|
||||||
5
README.md
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
# ECS Test
|
||||||
|
|
||||||
|
A project where I created a simple ECS in Odin to test performance/developer experience. The project uses Sokol to render the scene.
|
||||||
|
|
||||||
|

|
||||||
28
config/program_config.odin
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
package program_config
|
||||||
|
|
||||||
|
import sg "../sokol/gfx"
|
||||||
|
|
||||||
|
// Application
|
||||||
|
WINDOW_TITLE :: "ECS Test"
|
||||||
|
|
||||||
|
// Behaviour
|
||||||
|
SPAWN_INTERVAL :: 0.05 // in seconds
|
||||||
|
GRAVITY_CONSTANT :: -2.5
|
||||||
|
SPAWN_AREA :: 30 // one side
|
||||||
|
Y_DESPAWN_CUTOFF :: -15
|
||||||
|
|
||||||
|
// Colors
|
||||||
|
BACKGROUND_COLOR :: sg.Color{ 1.0000, 0.9725, 0.9059, 1 }
|
||||||
|
CUBE_COLORS := [][4]f32{
|
||||||
|
{ 0.6235, 0.7725, 0.9098, 1 },
|
||||||
|
{ 0.9216, 0.6392, 0.6392, 1 },
|
||||||
|
{ 0.7137, 0.8431, 0.6588, 1 },
|
||||||
|
{ 0.7059, 0.6549, 0.8392, 1 },
|
||||||
|
{ 1.0000, 0.8980, 0.6000, 1 },
|
||||||
|
}
|
||||||
|
BORDER_COLOR :: [4]f32{ 0, 0, 0, 1 }
|
||||||
|
|
||||||
|
// User
|
||||||
|
MOVEMENT_SPEED :: 3.0
|
||||||
|
LOOK_SENSITIVITY :: 0.15
|
||||||
|
START_POSITION :: [3]f32{ 15, 0, 60 }
|
||||||
47
ecs/camera_system.odin
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
package ecs
|
||||||
|
|
||||||
|
import "core:math"
|
||||||
|
import "core:math/linalg"
|
||||||
|
|
||||||
|
CameraSystem :: struct {
|
||||||
|
using _: SystemBase,
|
||||||
|
}
|
||||||
|
|
||||||
|
camera_system_update :: proc(camera_system: ^CameraSystem, coordinator: ^Coordinator, dt: f32) {
|
||||||
|
for entity_id in camera_system.entities {
|
||||||
|
camera := coordinator_get_component(coordinator, CameraComponent, entity_id)
|
||||||
|
input := coordinator_get_component(coordinator, InputComponent, entity_id)
|
||||||
|
|
||||||
|
move_input: Vec3
|
||||||
|
if input.key_down[.W] do move_input.y = 1
|
||||||
|
else if input.key_down[.S] do move_input.y = -1
|
||||||
|
|
||||||
|
if input.key_down[.D] do move_input.x = 1
|
||||||
|
else if input.key_down[.A] do move_input.x = -1
|
||||||
|
|
||||||
|
if input.key_down[.SPACE] do move_input.z = 1
|
||||||
|
else if input.key_down[.LEFT_SHIFT] do move_input.z = -1
|
||||||
|
|
||||||
|
look_input: Vec2 = -input.mouse_movement * camera.look_sensitivity
|
||||||
|
camera.look += look_input
|
||||||
|
camera.look.x = math.wrap(camera.look.x, 360)
|
||||||
|
camera.look.y = math.clamp(camera.look.y, -89.5, 89.5)
|
||||||
|
|
||||||
|
look_mat := linalg.matrix4_from_yaw_pitch_roll_f32(
|
||||||
|
linalg.to_radians(camera.look.x),
|
||||||
|
linalg.to_radians(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) * camera.movement_speed * dt
|
||||||
|
camera.position += motion
|
||||||
|
|
||||||
|
camera.target = camera.position + forward
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,66 +1,88 @@
|
||||||
|
#+private
|
||||||
package ecs
|
package ecs
|
||||||
|
|
||||||
import "core:log"
|
import "core:log"
|
||||||
|
|
||||||
ComponentManager :: struct {
|
ComponentManager :: struct {
|
||||||
component_types: map[typeid]ComponentType,
|
component_ids: map[typeid]ComponentID,
|
||||||
component_pools: map[typeid]^ComponentPool(any),
|
component_pools: map[typeid]^ComponentPool(any),
|
||||||
next_component_type: ComponentType,
|
next_component_id: ComponentID,
|
||||||
|
|
||||||
|
component_pool_destroy_entity_cbs: map[typeid]proc(pool: ^ComponentPool(any), entity_id: EntityID),
|
||||||
|
component_pool_delete_cbs: map[typeid]proc(pool: ^ComponentPool(any)),
|
||||||
}
|
}
|
||||||
|
|
||||||
component_manager_create :: proc() -> ComponentManager {
|
component_manager_init :: proc(component_manager: ^ComponentManager) {
|
||||||
component_manager := ComponentManager {
|
component_manager.component_ids = make(map[typeid]ComponentID, context.allocator)
|
||||||
component_types = make(map[typeid]ComponentType, context.allocator),
|
component_manager.component_pools = make(map[typeid]^ComponentPool(any), context.allocator)
|
||||||
component_pools = make(map[typeid]^ComponentPool(any), context.allocator),
|
|
||||||
next_component_type = 0
|
component_manager.component_pool_destroy_entity_cbs = make(map[typeid]proc(pool: ^ComponentPool(any), entity_id: EntityID), context.allocator)
|
||||||
|
component_manager.component_pool_delete_cbs = make(map[typeid]proc(pool: ^ComponentPool(any)), context.allocator)
|
||||||
|
|
||||||
|
component_manager.next_component_id = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
return component_manager
|
component_manager_register_component :: proc($Component: typeid, component_manager: ^ComponentManager) {
|
||||||
|
log.assertf(Component not_in component_manager.component_ids, "Registering component more than once")
|
||||||
|
|
||||||
|
component_manager.component_ids[Component] = component_manager.next_component_id
|
||||||
|
|
||||||
|
component_pool := new(ComponentPool(Component), context.allocator)
|
||||||
|
component_pool_init(component_pool)
|
||||||
|
|
||||||
|
component_manager.component_pools[Component] = cast(^ComponentPool(any))component_pool
|
||||||
|
|
||||||
|
component_manager.component_pool_destroy_entity_cbs[Component] = proc(any_component_pool: ^ComponentPool(any), entity_id: EntityID) {
|
||||||
|
typed_component_pool := cast(^ComponentPool(Component))any_component_pool
|
||||||
|
if entity_id in typed_component_pool.entity_to_index {
|
||||||
|
component_pool_remove_data(typed_component_pool, entity_id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
component_manager_register_component :: proc($T: typeid, component_manager: ^ComponentManager) {
|
component_manager.component_pool_delete_cbs[Component] = proc(any_component_pool: ^ComponentPool(any)) {
|
||||||
log.assertf(T not_in component_manager.component_types, "Registering component more than once")
|
typed_component_pool := cast(^ComponentPool(Component))any_component_pool
|
||||||
|
component_pool_delete(typed_component_pool)
|
||||||
component_manager.component_types[T] = component_manager.next_component_type
|
free(typed_component_pool)
|
||||||
component_pool := new(ComponentPool(T), context.allocator)
|
|
||||||
component_pool^ = component_pool_create(T)
|
|
||||||
component_manager.component_pools[T] = cast(^ComponentPool(any))component_pool
|
|
||||||
component_manager.next_component_type += 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
component_manager_get_component_type :: proc($T: typeid, component_manager: ^ComponentManager) -> ComponentType {
|
component_manager.next_component_id += 1
|
||||||
log.assertf(T in component_manager.component_types, "Component not registered before use")
|
|
||||||
return component_manager.component_types[T]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
component_manager_add_component :: proc($T: typeid, component_manager: ^ComponentManager, entity_id: EntityID, component: T) {
|
component_manager_get_component_id :: proc(component_manager: ^ComponentManager, $Component: typeid) -> ComponentID {
|
||||||
component_pool := cast(^ComponentPool(T))component_manager.component_pools[T]
|
log.assertf(Component in component_manager.component_ids, "Component not registered before use")
|
||||||
component_pool_insert_data(T, component_pool, entity_id, component)
|
return component_manager.component_ids[Component]
|
||||||
}
|
}
|
||||||
|
|
||||||
component_manager_remove_component :: proc($T: typeid, component_manager: ^ComponentManager, entity_id: EntityID) {
|
component_manager_add_component :: proc(component_manager: ^ComponentManager, component: $Component, entity_id: EntityID) {
|
||||||
component_pool := cast(^ComponentPool(T))component_manager.component_pools[T]
|
component_pool := cast(^ComponentPool(Component))component_manager.component_pools[Component]
|
||||||
component_pool_remove_data(T, component_pool, entity_id)
|
component_pool_insert_data(component_pool, entity_id, component)
|
||||||
}
|
}
|
||||||
|
|
||||||
component_manager_get_component :: proc($T: typeid, component_manager: ^ComponentManager, entity_id: EntityID) -> ^T {
|
component_manager_remove_component :: proc(component_manager: ^ComponentManager, $Component: typeid, entity_id: EntityID) {
|
||||||
component_pool := cast(^ComponentPool(T))component_manager.component_pools[T]
|
component_pool := cast(^ComponentPool(Component))component_manager.component_pools[Component]
|
||||||
return component_pool_get(T, component_pool, entity_id)
|
component_pool_remove_data(component_pool, entity_id)
|
||||||
|
}
|
||||||
|
|
||||||
|
component_manager_get_component :: proc(component_manager: ^ComponentManager, $Component: typeid, entity_id: EntityID) -> ^Component {
|
||||||
|
component_pool := cast(^ComponentPool(Component)) component_manager.component_pools[Component]
|
||||||
|
return component_pool_get(component_pool, entity_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
component_manager_destroy_entity :: proc(component_manager: ^ComponentManager, entity_id: EntityID) {
|
component_manager_destroy_entity :: proc(component_manager: ^ComponentManager, entity_id: EntityID) {
|
||||||
for _, component_pool in component_manager.component_pools {
|
for Component, component_pool in component_manager.component_pools {
|
||||||
component_pool_destroy_entity(component_pool, entity_id)
|
component_manager.component_pool_destroy_entity_cbs[Component](component_pool, entity_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
component_manager_destroy :: proc(component_manager: ^ComponentManager) {
|
component_manager_delete :: proc(component_manager: ^ComponentManager) {
|
||||||
for _, &component_pool in component_manager.component_pools {
|
for Component, &component_pool in component_manager.component_pools {
|
||||||
component_pool_destroy(component_pool)
|
component_manager.component_pool_delete_cbs[Component](component_pool)
|
||||||
free(component_pool)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
delete(component_manager.component_pools)
|
delete(component_manager.component_pools)
|
||||||
delete(component_manager.component_types)
|
delete(component_manager.component_ids)
|
||||||
|
|
||||||
|
delete(component_manager.component_pool_destroy_entity_cbs)
|
||||||
|
delete(component_manager.component_pool_delete_cbs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,23 @@
|
||||||
|
#+private
|
||||||
package ecs
|
package ecs
|
||||||
|
|
||||||
import "core:log"
|
import "core:log"
|
||||||
|
|
||||||
ComponentPool :: struct($T: typeid) {
|
ComponentPool :: struct(Component: typeid) {
|
||||||
data: []T,
|
data: []Component,
|
||||||
entity_to_index: map[EntityID]uintptr,
|
entity_to_index: map[EntityID]uintptr,
|
||||||
index_to_entity: map[uintptr]EntityID,
|
index_to_entity: map[uintptr]EntityID,
|
||||||
size: uintptr,
|
size: uintptr,
|
||||||
}
|
}
|
||||||
|
|
||||||
component_pool_create :: proc($T: typeid) -> ComponentPool(T) {
|
component_pool_init :: proc(component_pool: ^ComponentPool($Component)) {
|
||||||
component_pool := ComponentPool(T) {
|
component_pool.data = make([]Component, ENTITY_MAX, context.allocator)
|
||||||
data = make([]T, ENTITY_MAX),
|
component_pool.entity_to_index = make(map[EntityID]uintptr, context.allocator)
|
||||||
entity_to_index = make(map[EntityID]uintptr, context.allocator),
|
component_pool.index_to_entity = make(map[uintptr]EntityID, context.allocator)
|
||||||
index_to_entity = make(map[uintptr]EntityID, context.allocator),
|
component_pool.size = 0
|
||||||
size = 0,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return component_pool
|
component_pool_insert_data :: proc(component_pool: ^ComponentPool($Component), entity_id: EntityID, component: Component) {
|
||||||
}
|
|
||||||
|
|
||||||
component_pool_insert_data :: proc($T: typeid, component_pool: ^ComponentPool(T), entity_id: EntityID, component: T) {
|
|
||||||
log.assertf(entity_id not_in component_pool.entity_to_index, "Component already added to entity")
|
log.assertf(entity_id not_in component_pool.entity_to_index, "Component already added to entity")
|
||||||
|
|
||||||
new_idx := component_pool.size
|
new_idx := component_pool.size
|
||||||
|
|
@ -31,7 +28,7 @@ component_pool_insert_data :: proc($T: typeid, component_pool: ^ComponentPool(T)
|
||||||
component_pool.size += 1
|
component_pool.size += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
component_pool_remove_data :: proc(component_pool: ^ComponentPool(any), entity_id: EntityID) {
|
component_pool_remove_data :: proc(component_pool: ^ComponentPool($Component), entity_id: EntityID) {
|
||||||
log.assertf(entity_id in component_pool.entity_to_index, "Entity doesn't have component")
|
log.assertf(entity_id in component_pool.entity_to_index, "Entity doesn't have component")
|
||||||
|
|
||||||
removed_entity_idx := component_pool.entity_to_index[entity_id]
|
removed_entity_idx := component_pool.entity_to_index[entity_id]
|
||||||
|
|
@ -48,21 +45,21 @@ component_pool_remove_data :: proc(component_pool: ^ComponentPool(any), entity_i
|
||||||
component_pool.size -= 1
|
component_pool.size -= 1
|
||||||
}
|
}
|
||||||
|
|
||||||
component_pool_get :: proc($T: typeid, component_pool: ^ComponentPool(T), entity_id: EntityID) -> ^T {
|
component_pool_get :: proc(component_pool: ^ComponentPool($Component), entity_id: EntityID) -> ^Component {
|
||||||
log.assertf(entity_id in component_pool.entity_to_index, "Entity doesn't have component")
|
log.assertf(entity_id in component_pool.entity_to_index, "Entity doesn't have component")
|
||||||
|
|
||||||
idx := component_pool.entity_to_index[entity_id]
|
idx := component_pool.entity_to_index[entity_id]
|
||||||
return &component_pool.data[idx]
|
return &component_pool.data[idx]
|
||||||
}
|
}
|
||||||
|
|
||||||
component_pool_destroy_entity :: proc(component_pool: ^ComponentPool(any), entity_id: EntityID) {
|
component_pool_destroy_entity :: proc(component_pool: ^ComponentPool($Component), entity_id: EntityID) {
|
||||||
if entity_id in component_pool.entity_to_index {
|
if entity_id in component_pool.entity_to_index {
|
||||||
component_pool_remove_data(component_pool, entity_id)
|
component_pool_remove_data(component_pool, entity_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
component_pool_destroy :: proc(component_pool: ^ComponentPool(any)) {
|
component_pool_delete :: proc(component_pool: ^ComponentPool($Component)) {
|
||||||
|
delete(component_pool.data)
|
||||||
delete(component_pool.entity_to_index)
|
delete(component_pool.entity_to_index)
|
||||||
delete(component_pool.index_to_entity)
|
delete(component_pool.index_to_entity)
|
||||||
delete(component_pool.data)
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package ecs
|
package ecs
|
||||||
|
|
||||||
|
import sa "../sokol/app"
|
||||||
import sg "../sokol/gfx"
|
import sg "../sokol/gfx"
|
||||||
|
|
||||||
Mat4 :: matrix[4, 4]f32
|
Mat4 :: matrix[4, 4]f32
|
||||||
|
|
@ -8,38 +9,52 @@ Vec2 :: [2]f32
|
||||||
Vec3 :: [3]f32
|
Vec3 :: [3]f32
|
||||||
Vec4 :: [4]f32
|
Vec4 :: [4]f32
|
||||||
|
|
||||||
Gravity :: struct {
|
GravityComponent :: struct {
|
||||||
force: Vec3
|
force: Vec3
|
||||||
}
|
}
|
||||||
|
|
||||||
RigidBody :: struct {
|
RigidBodyComponent :: struct {
|
||||||
velocity: Vec3,
|
velocity: Vec3,
|
||||||
acceleration: Vec3,
|
acceleration: Vec3,
|
||||||
}
|
}
|
||||||
|
|
||||||
Transform :: struct {
|
TransformComponent :: struct {
|
||||||
position: Vec3,
|
position: Vec3,
|
||||||
rotation: Vec3,
|
rotation: Vec3,
|
||||||
scale: Vec3,
|
scale: Vec3,
|
||||||
}
|
}
|
||||||
|
|
||||||
Color :: struct {
|
ColorComponent :: struct {
|
||||||
color: Vec4,
|
color: Vec4,
|
||||||
}
|
}
|
||||||
|
|
||||||
Mesh :: struct {
|
MeshID :: enum {
|
||||||
vertex_buffer: sg.Buffer,
|
Cube,
|
||||||
index_buffer: sg.Buffer,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Material :: struct {
|
MeshComponent :: struct {
|
||||||
shader: sg.Shader,
|
mesh_id: MeshID
|
||||||
image: sg.Image,
|
|
||||||
sampler: sg.Sampler,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Camera :: struct {
|
MaterialID :: enum {
|
||||||
|
Cube,
|
||||||
|
Outline,
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialComponent :: struct {
|
||||||
|
material_id: MaterialID
|
||||||
|
}
|
||||||
|
|
||||||
|
CameraComponent :: struct {
|
||||||
position: Vec3,
|
position: Vec3,
|
||||||
target: Vec3,
|
target: Vec3,
|
||||||
look: Vec2
|
look: Vec2,
|
||||||
|
|
||||||
|
look_sensitivity: f32,
|
||||||
|
movement_speed: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
InputComponent :: struct {
|
||||||
|
mouse_movement: Vec2,
|
||||||
|
key_down: #sparse[sa.Keycode]bool,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,4 +6,4 @@ COMPONENT_MAX :: 32
|
||||||
ID :: u32
|
ID :: u32
|
||||||
|
|
||||||
EntityID :: ID
|
EntityID :: ID
|
||||||
ComponentType :: u8
|
ComponentID :: u16
|
||||||
|
|
|
||||||
|
|
@ -1,82 +1,70 @@
|
||||||
package ecs
|
package ecs
|
||||||
|
|
||||||
Coordinator :: struct {
|
Coordinator :: struct {
|
||||||
component_manager: ^ComponentManager,
|
component_manager: ComponentManager,
|
||||||
entity_manager: ^EntityManager,
|
entity_manager: EntityManager,
|
||||||
system_manager: ^SystemManager,
|
system_manager: SystemManager,
|
||||||
}
|
}
|
||||||
|
|
||||||
coordinator_create :: proc() -> Coordinator {
|
coordinator_init:: proc(coordinator: ^Coordinator) {
|
||||||
coordinator := Coordinator{}
|
component_manager_init(&coordinator.component_manager)
|
||||||
coordinator.component_manager = new(ComponentManager, context.allocator)
|
entity_manager_init(&coordinator.entity_manager)
|
||||||
coordinator.component_manager^ = component_manager_create()
|
system_manager_init(&coordinator.system_manager)
|
||||||
|
|
||||||
coordinator.entity_manager = new(EntityManager, context.allocator)
|
|
||||||
coordinator.entity_manager^ = entity_manager_create()
|
|
||||||
|
|
||||||
coordinator.system_manager = new(SystemManager, context.allocator)
|
|
||||||
coordinator.system_manager^ = system_manager_create()
|
|
||||||
|
|
||||||
return coordinator
|
|
||||||
}
|
}
|
||||||
|
|
||||||
coordinator_create_entity :: proc(coordinator: ^Coordinator) -> EntityID {
|
coordinator_create_entity :: proc(coordinator: ^Coordinator) -> EntityID {
|
||||||
return entity_manager_create_entity(coordinator.entity_manager)
|
return entity_manager_create_entity(&coordinator.entity_manager)
|
||||||
}
|
}
|
||||||
|
|
||||||
coordinator_destroy_entity :: proc(coordinator: ^Coordinator, entity_id: EntityID) {
|
coordinator_destroy_entity :: proc(coordinator: ^Coordinator, entity_id: EntityID) {
|
||||||
component_manager_destroy_entity(coordinator.component_manager, entity_id)
|
component_manager_destroy_entity(&coordinator.component_manager, entity_id)
|
||||||
entity_manager_destroy_entity(coordinator.entity_manager, entity_id)
|
entity_manager_destroy_entity(&coordinator.entity_manager, entity_id)
|
||||||
system_manager_destroy_entity(coordinator.system_manager, entity_id)
|
system_manager_destroy_entity(&coordinator.system_manager, entity_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
coordinator_register_component :: proc($T: typeid, coordinator: ^Coordinator) {
|
coordinator_register_component :: proc(coordinator: ^Coordinator, $Component: typeid) {
|
||||||
component_manager_register_component(T, coordinator.component_manager)
|
component_manager_register_component(Component, &coordinator.component_manager)
|
||||||
}
|
}
|
||||||
|
|
||||||
coordinator_add_component :: proc($T: typeid, coordinator: ^Coordinator, entity_id: EntityID, component: T) {
|
coordinator_add_component :: proc(coordinator: ^Coordinator, component: $Component, entity_id: EntityID) {
|
||||||
component_manager_add_component(T, coordinator.component_manager, entity_id, component)
|
component_manager_add_component(&coordinator.component_manager, component, entity_id)
|
||||||
|
|
||||||
signature := entity_manager_get_signature(coordinator.entity_manager, entity_id)
|
signature := entity_manager_get_signature(&coordinator.entity_manager, entity_id)
|
||||||
signature_set(&signature, component_manager_get_component_type(T, coordinator.component_manager))
|
signature_set(&signature, component_manager_get_component_id(&coordinator.component_manager, Component))
|
||||||
entity_manager_set_signature(coordinator.entity_manager, entity_id, signature)
|
entity_manager_set_signature(&coordinator.entity_manager, entity_id, signature)
|
||||||
|
|
||||||
system_manager_change_entity_signature(coordinator.system_manager, entity_id, signature)
|
system_manager_change_entity_signature(&coordinator.system_manager, entity_id, signature)
|
||||||
}
|
}
|
||||||
|
|
||||||
coordinator_remove_component :: proc($T: typeid, coordinator: ^Coordinator, entity_id: EntityID) {
|
coordinator_remove_component :: proc(coordinator: ^Coordinator, $Component: typeid, entity_id: EntityID) {
|
||||||
component_manager_remove_component(T, coordinator.component_manager, entity_id)
|
component_manager_remove_component(&coordinator.component_manager, Component, entity_id)
|
||||||
|
|
||||||
signature := entity_manager_get_signature(coordinator.entity_manager, entity_id)
|
signature := entity_manager_get_signature(&coordinator.entity_manager, entity_id)
|
||||||
signature_unset(&signature, component_manager_get_component_type(T, coordinator.component_manager))
|
signature_unset(&signature, component_manager_get_component_id(&coordinator.component_manager, Component))
|
||||||
entity_manager_set_signature(coordinator.entity_manager, entity_id, signature)
|
entity_manager_set_signature(&coordinator.entity_manager, entity_id, signature)
|
||||||
|
|
||||||
system_manager_change_entity_signature(coordinator.system_manager, entity_id, signature)
|
system_manager_change_entity_signature(&coordinator.system_manager, entity_id, signature)
|
||||||
}
|
}
|
||||||
|
|
||||||
coordinator_get_component :: proc($T: typeid, coordinator: ^Coordinator, entity_id: EntityID) -> ^T {
|
coordinator_get_component :: proc(coordinator: ^Coordinator, $Component: typeid, entity_id: EntityID) -> ^Component {
|
||||||
return component_manager_get_component(T, coordinator.component_manager, entity_id)
|
return component_manager_get_component(&coordinator.component_manager, Component, entity_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
coordinator_get_component_type :: proc($T: typeid, coordinator: ^Coordinator) -> ComponentType {
|
coordinator_get_component_id :: proc(coordinator: ^Coordinator, $Component: typeid) -> ComponentID {
|
||||||
return component_manager_get_component_type(T, coordinator.component_manager)
|
return component_manager_get_component_id(&coordinator.component_manager, Component)
|
||||||
}
|
}
|
||||||
|
|
||||||
coordinator_register_system :: proc($T: typeid, coordinator: ^Coordinator) -> ^T {
|
coordinator_register_system :: proc(coordinator: ^Coordinator, $System: typeid) -> ^System {
|
||||||
return system_manager_register_system(T, coordinator.system_manager)
|
return system_manager_register_system(&coordinator.system_manager, System)
|
||||||
}
|
}
|
||||||
|
|
||||||
coordinator_set_system_signature :: proc($T: typeid, coordinator: ^Coordinator, signature: Signature) {
|
coordinator_set_system_signature :: proc(coordinator: ^Coordinator, $System: typeid, signature: Signature) {
|
||||||
system_manager_set_signature(T, coordinator.system_manager, signature)
|
system_manager_set_signature(&coordinator.system_manager, System, signature)
|
||||||
}
|
}
|
||||||
|
|
||||||
coordinator_destroy :: proc(coordinator: ^Coordinator) {
|
coordinator_delete :: proc(coordinator: ^Coordinator) {
|
||||||
component_manager_destroy(coordinator.component_manager)
|
component_manager_delete(&coordinator.component_manager)
|
||||||
entity_manager_destroy(coordinator.entity_manager)
|
entity_manager_delete(&coordinator.entity_manager)
|
||||||
system_manager_destroy(coordinator.system_manager)
|
system_manager_delete(&coordinator.system_manager)
|
||||||
|
|
||||||
free(coordinator.component_manager)
|
|
||||||
free(coordinator.entity_manager)
|
|
||||||
free(coordinator.system_manager)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
#+private
|
||||||
package ecs
|
package ecs
|
||||||
|
|
||||||
import "core:log"
|
import "core:log"
|
||||||
|
|
@ -9,15 +10,12 @@ EntityManager :: struct {
|
||||||
living_entity_count: u32,
|
living_entity_count: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
entity_manager_create :: proc() -> EntityManager {
|
entity_manager_init :: proc(entity_manager: ^EntityManager) {
|
||||||
entity_manager := EntityManager{living_entity_count = 0}
|
|
||||||
queue.init(&entity_manager.available_entities)
|
queue.init(&entity_manager.available_entities)
|
||||||
|
|
||||||
for entity_id in 0..<ENTITY_MAX {
|
for entity_id in 0..<ENTITY_MAX {
|
||||||
queue.push_back(&entity_manager.available_entities, cast(EntityID) entity_id)
|
queue.push_back(&entity_manager.available_entities, cast(EntityID) entity_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
return entity_manager
|
|
||||||
}
|
}
|
||||||
|
|
||||||
entity_manager_create_entity :: proc(entity_manager: ^EntityManager) -> EntityID {
|
entity_manager_create_entity :: proc(entity_manager: ^EntityManager) -> EntityID {
|
||||||
|
|
@ -49,6 +47,6 @@ entity_manager_get_signature :: proc(entity_manager: ^EntityManager, entity_id:
|
||||||
return entity_manager.signatures[entity_id]
|
return entity_manager.signatures[entity_id]
|
||||||
}
|
}
|
||||||
|
|
||||||
entity_manager_destroy :: proc(entity_manager: ^EntityManager) {
|
entity_manager_delete :: proc(entity_manager: ^EntityManager) {
|
||||||
queue.destroy(&entity_manager.available_entities)
|
queue.destroy(&entity_manager.available_entities)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
32
ecs/input_system.odin
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
package ecs
|
||||||
|
|
||||||
|
import sa "../sokol/app"
|
||||||
|
|
||||||
|
InputSystem :: struct {
|
||||||
|
using _: SystemBase,
|
||||||
|
}
|
||||||
|
|
||||||
|
input_system_update :: proc(input_system: ^InputSystem, coordinator: ^Coordinator, event: ^sa.Event) {
|
||||||
|
for entity_id in input_system.entities {
|
||||||
|
input := coordinator_get_component(coordinator, InputComponent, entity_id)
|
||||||
|
|
||||||
|
#partial switch event.type {
|
||||||
|
case .MOUSE_MOVE:
|
||||||
|
input.mouse_movement += {event.mouse_dx, event.mouse_dy}
|
||||||
|
case .KEY_DOWN:
|
||||||
|
input.key_down[event.key_code] = true
|
||||||
|
case .KEY_UP:
|
||||||
|
input.key_down[event.key_code] = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.key_down[.ESCAPE] do sa.quit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input_system_mouse_reset :: proc(input_system: ^InputSystem, coordinator: ^Coordinator) {
|
||||||
|
for entity_id in input_system.entities {
|
||||||
|
input_id := coordinator_get_component(coordinator, InputComponent, entity_id)
|
||||||
|
|
||||||
|
input_id.mouse_movement = { 0, 0 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,16 +1,31 @@
|
||||||
package ecs
|
package ecs
|
||||||
|
|
||||||
|
import "core:log"
|
||||||
|
|
||||||
|
import program_config "../config"
|
||||||
|
|
||||||
PhysicsSystem :: struct {
|
PhysicsSystem :: struct {
|
||||||
using base: SystemBase,
|
using _: SystemBase,
|
||||||
}
|
}
|
||||||
|
|
||||||
physics_system_update :: proc(physics_system: ^PhysicsSystem, coordinator: ^Coordinator, dt: f32) {
|
physics_system_update :: proc(physics_system: ^PhysicsSystem, coordinator: ^Coordinator, dt: f32) {
|
||||||
for entity in physics_system.entities {
|
entities_to_delete := make([dynamic]EntityID)
|
||||||
rigid_body := coordinator_get_component(RigidBody, coordinator, entity)
|
defer delete(entities_to_delete)
|
||||||
transform := coordinator_get_component(Transform, coordinator, entity)
|
|
||||||
gravity := coordinator_get_component(Gravity, coordinator, entity)
|
for entity_id in physics_system.entities {
|
||||||
|
rigid_body := coordinator_get_component(coordinator, RigidBodyComponent, entity_id)
|
||||||
|
transform := coordinator_get_component(coordinator, TransformComponent, entity_id)
|
||||||
|
gravity := coordinator_get_component(coordinator, GravityComponent, entity_id)
|
||||||
|
|
||||||
transform.position += rigid_body.velocity * dt
|
transform.position += rigid_body.velocity * dt
|
||||||
rigid_body.velocity += gravity.force * dt
|
rigid_body.velocity += gravity.force * dt
|
||||||
|
|
||||||
|
if transform.position.y < program_config.Y_DESPAWN_CUTOFF {
|
||||||
|
append(&entities_to_delete, entity_id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for entity in entities_to_delete {
|
||||||
|
coordinator_destroy_entity(coordinator, entity)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,49 +17,44 @@ import "core:os"
|
||||||
import stbi "vendor:stb/image"
|
import stbi "vendor:stb/image"
|
||||||
|
|
||||||
import sa "../sokol/app"
|
import sa "../sokol/app"
|
||||||
|
import sl "../sokol/log"
|
||||||
import sh "../sokol/helpers"
|
import sh "../sokol/helpers"
|
||||||
import sg "../sokol/gfx"
|
import sg "../sokol/gfx"
|
||||||
|
|
||||||
|
import program_config "../config"
|
||||||
|
|
||||||
import shaders "../shaders/out"
|
import shaders "../shaders/out"
|
||||||
|
|
||||||
VertexData :: struct {
|
VertexData :: struct {
|
||||||
pos: Vec3,
|
pos: Vec3,
|
||||||
uv: Vec2,
|
}
|
||||||
|
|
||||||
|
Mesh :: struct {
|
||||||
|
vertex_buffer: sg.Buffer,
|
||||||
|
index_buffer: sg.Buffer,
|
||||||
|
}
|
||||||
|
|
||||||
|
Material :: struct {
|
||||||
|
pipeline: sg.Pipeline,
|
||||||
|
shader: sg.Shader,
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderSystem :: struct {
|
RenderSystem :: struct {
|
||||||
using base: SystemBase,
|
using _: SystemBase,
|
||||||
|
user_entity: EntityID,
|
||||||
|
|
||||||
shader: sg.Shader,
|
materials: map[MaterialID]Material,
|
||||||
pipeline: sg.Pipeline,
|
meshes : map[MeshID]Mesh,
|
||||||
vertex_buffer: sg.Buffer,
|
|
||||||
index_buffer: sg.Buffer,
|
|
||||||
image: sg.Image,
|
|
||||||
sampler: sg.Sampler,
|
|
||||||
|
|
||||||
camera: struct {
|
|
||||||
pos: Vec3,
|
|
||||||
target: Vec3,
|
|
||||||
look: Vec2,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
init_render_system :: proc(render_system: ^RenderSystem) {
|
@(private="file")
|
||||||
default_context := runtime.default_context()
|
init_outline_material :: proc(render_system: ^RenderSystem) {
|
||||||
|
shader := sg.make_shader(shaders.outline_shader_desc(sg.query_backend()))
|
||||||
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({
|
pipeline := sg.make_pipeline({
|
||||||
shader = shader,
|
shader = shader,
|
||||||
layout = {
|
layout = {
|
||||||
attrs = {
|
attrs = {
|
||||||
shaders.ATTR_main_pos = { format = .FLOAT3 },
|
shaders.ATTR_outline_pos = { format = .FLOAT3 },
|
||||||
shaders.ATTR_main_uv = { format = .FLOAT2 },
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
index_type = .UINT16,
|
index_type = .UINT16,
|
||||||
|
|
@ -72,187 +67,247 @@ init_render_system :: proc(render_system: ^RenderSystem) {
|
||||||
bias_slope_scale = 1.0,
|
bias_slope_scale = 1.0,
|
||||||
compare = .LESS_EQUAL,
|
compare = .LESS_EQUAL,
|
||||||
},
|
},
|
||||||
|
sample_count = 4,
|
||||||
})
|
})
|
||||||
|
|
||||||
vertices := []VertexData {
|
render_system.materials[.Outline] = Material{
|
||||||
{ pos = { -0.5, -0.5, 0.5 }, uv = { 0, 0 } },
|
shader = shader,
|
||||||
{ pos = { 0.5, -0.5, 0.5 }, uv = { 1, 0 } },
|
pipeline = pipeline,
|
||||||
{ 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 } },
|
@(private="file")
|
||||||
{ pos = { 0.5, -0.5, -0.5 }, uv = { 0, 0 } },
|
init_cube_material :: proc(render_system: ^RenderSystem) {
|
||||||
{ pos = { 0.5, 0.5, -0.5 }, uv = { 0, 1 } },
|
shader := sg.make_shader(shaders.cube_shader_desc(sg.query_backend()))
|
||||||
{ pos = { -0.5, 0.5, -0.5 }, uv = { 1, 1 } },
|
pipeline := sg.make_pipeline({
|
||||||
|
shader = shader,
|
||||||
|
layout = {
|
||||||
|
attrs = {
|
||||||
|
shaders.ATTR_cube_pos = { format = .FLOAT3 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
index_type = .UINT16,
|
||||||
|
cull_mode = .FRONT,
|
||||||
|
depth = {
|
||||||
|
pixel_format = .DEFAULT,
|
||||||
|
write_enabled = true,
|
||||||
|
bias = 0.001,
|
||||||
|
bias_clamp = 0.0,
|
||||||
|
bias_slope_scale = 1.0,
|
||||||
|
compare = .LESS_EQUAL,
|
||||||
|
},
|
||||||
|
sample_count = 4,
|
||||||
|
})
|
||||||
|
|
||||||
{ pos = { -0.5, 0.5, 0.5 }, uv = { 0, 0 } },
|
render_system.materials[.Cube] = Material{
|
||||||
{ pos = { 0.5, 0.5, 0.5 }, uv = { 1, 0 } },
|
shader = shader,
|
||||||
{ pos = { 0.5, 0.5, -0.5 }, uv = { 1, 1 } },
|
pipeline = pipeline,
|
||||||
{ pos = { -0.5, 0.5, -0.5 }, uv = { 0, 1 } },
|
}
|
||||||
|
}
|
||||||
|
|
||||||
{ pos = { -0.5, -0.5, 0.5 }, uv = { 0, 0 } },
|
@(private="file")
|
||||||
{ pos = { 0.5, -0.5, 0.5 }, uv = { 1, 0 } },
|
init_cube_mesh :: proc (render_system: ^RenderSystem) {
|
||||||
{ pos = { 0.5, -0.5, -0.5 }, uv = { 1, 1 } },
|
cube_vertices := []VertexData {
|
||||||
{ pos = { -0.5, -0.5, -0.5 }, uv = { 0, 1 } },
|
{ pos = { -0.5, -0.5, 0.5 }, },
|
||||||
|
{ pos = { 0.5, -0.5, 0.5 }, },
|
||||||
|
{ pos = { 0.5, 0.5, 0.5 }, },
|
||||||
|
{ pos = { -0.5, 0.5, 0.5 }, },
|
||||||
|
|
||||||
{ pos = { 0.5, -0.5, 0.5 }, uv = { 0, 0 } },
|
{ pos = { -0.5, -0.5, -0.5 }, },
|
||||||
{ pos = { 0.5, -0.5, -0.5 }, uv = { 1, 0 } },
|
{ pos = { 0.5, -0.5, -0.5 }, },
|
||||||
{ pos = { 0.5, 0.5, -0.5 }, uv = { 1, 1 } },
|
{ pos = { 0.5, 0.5, -0.5 }, },
|
||||||
{ pos = { 0.5, 0.5, 0.5 }, uv = { 0, 1 } },
|
{ pos = { -0.5, 0.5, -0.5 }, },
|
||||||
|
|
||||||
{ pos = { -0.5, -0.5, 0.5 }, uv = { 1, 0 } },
|
{ pos = { -0.5, 0.5, 0.5 }, },
|
||||||
{ pos = { -0.5, -0.5, -0.5 }, uv = { 0, 0 } },
|
{ pos = { 0.5, 0.5, 0.5 }, },
|
||||||
{ pos = { -0.5, 0.5, -0.5 }, uv = { 0, 1 } },
|
{ pos = { 0.5, 0.5, -0.5 }, },
|
||||||
{ pos = { -0.5, 0.5, 0.5 }, uv = { 1, 1 } },
|
{ pos = { -0.5, 0.5, -0.5 }, },
|
||||||
|
|
||||||
|
{ pos = { -0.5, -0.5, 0.5 }, },
|
||||||
|
{ pos = { 0.5, -0.5, 0.5 }, },
|
||||||
|
{ pos = { 0.5, -0.5, -0.5 }, },
|
||||||
|
{ pos = { -0.5, -0.5, -0.5 }, },
|
||||||
|
|
||||||
|
{ pos = { 0.5, -0.5, 0.5 }, },
|
||||||
|
{ pos = { 0.5, -0.5, -0.5 }, },
|
||||||
|
{ pos = { 0.5, 0.5, -0.5 }, },
|
||||||
|
{ pos = { 0.5, 0.5, 0.5 }, },
|
||||||
|
|
||||||
|
{ pos = { -0.5, -0.5, 0.5 }, },
|
||||||
|
{ pos = { -0.5, -0.5, -0.5 }, },
|
||||||
|
{ pos = { -0.5, 0.5, -0.5 }, },
|
||||||
|
{ pos = { -0.5, 0.5, 0.5 }, },
|
||||||
}
|
}
|
||||||
vertex_buffer := sg.make_buffer({
|
vertex_buffer := sg.make_buffer({
|
||||||
data = sg_range(vertices)
|
data = sg_range(cube_vertices)
|
||||||
})
|
})
|
||||||
|
|
||||||
indices := []u16 {
|
cube_indices := []u16 {
|
||||||
1, 0, 2,
|
0, 1, 2, 0, 2, 3,
|
||||||
3, 2, 0,
|
6, 5, 4, 7, 6, 4,
|
||||||
7, 4, 6,
|
8, 9, 10, 8, 10, 11,
|
||||||
5, 6, 4,
|
14, 13, 12, 15, 14, 12,
|
||||||
9, 8, 10,
|
16, 17, 18, 16, 18, 19,
|
||||||
11, 10, 8,
|
22, 21, 20, 23, 22, 20,
|
||||||
15, 12, 14,
|
|
||||||
13, 14, 12,
|
|
||||||
17, 16, 18,
|
|
||||||
19, 18, 16,
|
|
||||||
23, 20, 22,
|
|
||||||
21, 22, 20,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
index_buffer := sg.make_buffer({
|
index_buffer := sg.make_buffer({
|
||||||
usage = { index_buffer = true },
|
usage = { index_buffer = true },
|
||||||
data = sg_range(indices),
|
data = sg_range(cube_indices),
|
||||||
})
|
})
|
||||||
|
|
||||||
w, h: i32
|
render_system.meshes[.Cube] = Mesh{
|
||||||
pixels := stbi.load("res/white.png", &w, &h, nil, 4)
|
vertex_buffer = vertex_buffer,
|
||||||
assert(pixels != nil)
|
index_buffer = index_buffer,
|
||||||
defer(stbi.image_free(pixels))
|
}
|
||||||
|
}
|
||||||
|
|
||||||
image := sg.make_image({
|
render_system_init :: proc(render_system: ^RenderSystem, user_entity: EntityID) {
|
||||||
width = w,
|
default_context := runtime.default_context()
|
||||||
height = h,
|
|
||||||
pixel_format = .RGBA8,
|
sg.setup({
|
||||||
data = {
|
environment = sh.glue_environment(),
|
||||||
subimage = {
|
allocator = sg.Allocator(sh.allocator(&default_context)),
|
||||||
0 = {
|
logger = sg.Logger( { func = sl.func } ),
|
||||||
0 = {
|
|
||||||
ptr = pixels,
|
|
||||||
size = uint(w * h * 4)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
sampler := sg.make_sampler({})
|
render_system.materials = make(map[MaterialID]Material)
|
||||||
|
render_system.meshes = make(map[MeshID]Mesh)
|
||||||
|
render_system.user_entity = user_entity
|
||||||
|
|
||||||
render_system.sampler = sampler
|
init_cube_mesh(render_system)
|
||||||
render_system.shader = shader
|
init_cube_material(render_system)
|
||||||
render_system.image = image
|
|
||||||
render_system.pipeline = pipeline
|
init_outline_material(render_system)
|
||||||
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) {
|
render_system_delete :: proc(render_system: ^RenderSystem, coordinator: ^Coordinator) {
|
||||||
sg.destroy_buffer(render_system.index_buffer)
|
cube_mesh := render_system.meshes[.Cube]
|
||||||
sg.destroy_buffer(render_system.vertex_buffer)
|
sg.destroy_buffer(cube_mesh.index_buffer)
|
||||||
sg.destroy_image(render_system.image)
|
sg.destroy_buffer(cube_mesh.vertex_buffer)
|
||||||
sg.destroy_sampler(render_system.sampler)
|
|
||||||
sg.destroy_pipeline(render_system.pipeline)
|
cube_material := render_system.materials[.Cube]
|
||||||
sg.destroy_shader(render_system.shader)
|
sg.destroy_pipeline(cube_material.pipeline)
|
||||||
|
sg.destroy_shader(cube_material.shader)
|
||||||
|
|
||||||
|
outline_material := render_system.materials[.Outline]
|
||||||
|
sg.destroy_pipeline(outline_material.pipeline)
|
||||||
|
sg.destroy_shader(outline_material.shader)
|
||||||
|
|
||||||
|
delete(render_system.materials)
|
||||||
|
delete(render_system.meshes)
|
||||||
|
|
||||||
sg.shutdown()
|
sg.shutdown()
|
||||||
}
|
}
|
||||||
|
|
||||||
render_system_update :: proc(render_system: ^RenderSystem, coordinator: ^Coordinator, dt: f32, key_down: #sparse[sa.Keycode]bool, mouse_move: Vec2) {
|
@(private="file")
|
||||||
update_camera(render_system, dt, key_down, mouse_move)
|
CLEAR_SCREEN_ACTION :: sg.Pass_Action{
|
||||||
|
colors = {
|
||||||
|
0 = {
|
||||||
|
load_action = .CLEAR,
|
||||||
|
clear_value = program_config.BACKGROUND_COLOR,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
proj := linalg.matrix4_perspective_f32(70, sa.widthf() / sa.heightf(), 0.001, 1000)
|
@(private="file")
|
||||||
view := linalg.matrix4_look_at_f32(render_system.camera.pos, render_system.camera.target, { 0, 1, 0 } )
|
outline_pass :: proc(render_system: ^RenderSystem, coordinator: ^Coordinator, proj: Mat4, view: Mat4) {
|
||||||
|
for entity_id in render_system.entities {
|
||||||
|
transform := coordinator_get_component(coordinator, TransformComponent, entity_id)
|
||||||
|
mesh_id := coordinator_get_component(coordinator, MeshComponent, entity_id).mesh_id
|
||||||
|
mesh := render_system.meshes[mesh_id]
|
||||||
|
|
||||||
sg.begin_pass({ swapchain = sh.glue_swapchain() })
|
scale_mat := linalg.matrix4_scale_f32(transform.scale * 1.2)
|
||||||
|
rot_mat := linalg.matrix4_from_yaw_pitch_roll_f32(
|
||||||
|
transform.rotation.y,
|
||||||
|
transform.rotation.x,
|
||||||
|
transform.rotation.z
|
||||||
|
)
|
||||||
|
pos_mat := linalg.matrix4_translate_f32(transform.position)
|
||||||
|
model := pos_mat * rot_mat * scale_mat
|
||||||
|
mvp := proj * view * model
|
||||||
|
|
||||||
|
outline_material := render_system.materials[.Outline]
|
||||||
|
sg.apply_pipeline(outline_material.pipeline)
|
||||||
|
|
||||||
sg.apply_pipeline(render_system.pipeline)
|
|
||||||
sg.apply_bindings({
|
sg.apply_bindings({
|
||||||
vertex_buffers = { 0 = render_system.vertex_buffer },
|
vertex_buffers = { 0 = mesh.vertex_buffer },
|
||||||
index_buffer = render_system.index_buffer,
|
index_buffer = mesh.index_buffer,
|
||||||
images = { shaders.IMG_tex = render_system.image },
|
|
||||||
samplers = { shaders.SMP_smp = render_system.sampler },
|
|
||||||
})
|
})
|
||||||
|
|
||||||
for entity in render_system.entities {
|
sg.apply_uniforms(shaders.UB_VsParamsOutline, sg_range(&shaders.Vsparamsoutline{
|
||||||
transform := coordinator_get_component(Transform, coordinator, entity)
|
mvp = mvp,
|
||||||
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{
|
sg.apply_uniforms(shaders.UB_FsParamsOutline, sg_range(&shaders.Fsparamsoutline{
|
||||||
mvp = proj * view * model,
|
col = program_config.BORDER_COLOR,
|
||||||
col = color.color
|
}))
|
||||||
|
|
||||||
|
|
||||||
|
sg.draw(0, 36, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@(private="file")
|
||||||
|
cube_pass :: proc(render_system: ^RenderSystem, coordinator: ^Coordinator, proj: Mat4, view: Mat4) {
|
||||||
|
for entity_id in render_system.entities {
|
||||||
|
transform := coordinator_get_component(coordinator, TransformComponent, entity_id)
|
||||||
|
|
||||||
|
mesh_id := coordinator_get_component(coordinator, MeshComponent, entity_id).mesh_id
|
||||||
|
mesh := render_system.meshes[mesh_id]
|
||||||
|
|
||||||
|
material_id := coordinator_get_component(coordinator, MaterialComponent, entity_id).material_id
|
||||||
|
material := render_system.materials[material_id]
|
||||||
|
|
||||||
|
color := coordinator_get_component(coordinator, ColorComponent, entity_id)
|
||||||
|
|
||||||
|
scale_mat := linalg.matrix4_scale_f32(transform.scale)
|
||||||
|
rot_mat := linalg.matrix4_from_yaw_pitch_roll_f32(
|
||||||
|
transform.rotation.y,
|
||||||
|
transform.rotation.x,
|
||||||
|
transform.rotation.z
|
||||||
|
)
|
||||||
|
pos_mat := linalg.matrix4_translate_f32(transform.position)
|
||||||
|
model := pos_mat * rot_mat * scale_mat
|
||||||
|
mvp := proj * view * model
|
||||||
|
|
||||||
|
sg.apply_pipeline(material.pipeline)
|
||||||
|
sg.apply_bindings({
|
||||||
|
vertex_buffers = { 0 = mesh.vertex_buffer },
|
||||||
|
index_buffer = mesh.index_buffer,
|
||||||
|
})
|
||||||
|
|
||||||
|
sg.apply_uniforms(shaders.UB_VsParamsCube, sg_range(&shaders.Vsparamscube{
|
||||||
|
mvp = mvp,
|
||||||
|
col = color.color,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
sg.draw(0, 36, 1)
|
sg.draw(0, 36, 1)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render_system_update :: proc(render_system: ^RenderSystem, coordinator: ^Coordinator) {
|
||||||
|
camera := coordinator_get_component(coordinator, CameraComponent, render_system.user_entity)
|
||||||
|
|
||||||
|
proj := linalg.matrix4_perspective_f32(70, sa.widthf() / sa.heightf(), 0.001, 1000)
|
||||||
|
view := linalg.matrix4_look_at_f32(camera.position, camera.target, { 0, 1, 0 } )
|
||||||
|
|
||||||
|
sg.begin_pass({ swapchain = sh.glue_swapchain(), action = CLEAR_SCREEN_ACTION })
|
||||||
|
cube_pass(render_system, coordinator, proj, view)
|
||||||
|
outline_pass(render_system, coordinator, proj, view)
|
||||||
sg.end_pass()
|
sg.end_pass()
|
||||||
|
|
||||||
sg.commit()
|
sg.commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
@(private)
|
@(private="file")
|
||||||
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 :: proc {
|
||||||
sg_range_from_slice,
|
sg_range_from_slice,
|
||||||
sg_range_from_struct,
|
sg_range_from_struct,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@(private="file")
|
||||||
sg_range_from_slice :: proc(s: []$T) -> sg.Range {
|
sg_range_from_slice :: proc(s: []$T) -> sg.Range {
|
||||||
return {
|
return {
|
||||||
ptr = raw_data(s),
|
ptr = raw_data(s),
|
||||||
|
|
@ -260,6 +315,7 @@ sg_range_from_slice :: proc(s: []$T) -> sg.Range {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@(private="file")
|
||||||
sg_range_from_struct :: proc(s: ^$T) -> sg.Range where intrinsics.type_is_struct(T) {
|
sg_range_from_struct :: proc(s: ^$T) -> sg.Range where intrinsics.type_is_struct(T) {
|
||||||
return {
|
return {
|
||||||
ptr = s,
|
ptr = s,
|
||||||
|
|
|
||||||
|
|
@ -2,15 +2,15 @@ package ecs
|
||||||
|
|
||||||
Signature :: bit_set[0..<COMPONENT_MAX]
|
Signature :: bit_set[0..<COMPONENT_MAX]
|
||||||
|
|
||||||
signature_create :: proc() -> Signature {
|
signature_make :: proc() -> Signature {
|
||||||
return Signature{}
|
return Signature{}
|
||||||
}
|
}
|
||||||
|
|
||||||
signature_set :: proc(signature: ^Signature, type: ComponentType) {
|
signature_set :: proc(signature: ^Signature, type: ComponentID) {
|
||||||
signature^ += {cast(int)type}
|
signature^ += {cast(int)type}
|
||||||
}
|
}
|
||||||
|
|
||||||
signature_unset :: proc(signature: ^Signature, type: ComponentType) {
|
signature_unset :: proc(signature: ^Signature, type: ComponentID) {
|
||||||
signature^ -= {cast(int)type}
|
signature^ -= {cast(int)type}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,14 @@
|
||||||
|
#+private
|
||||||
package ecs
|
package ecs
|
||||||
|
|
||||||
import "base:intrinsics"
|
import "base:intrinsics"
|
||||||
import "core:log"
|
import "core:log"
|
||||||
|
|
||||||
|
@(private = "file")
|
||||||
|
EntitySet :: map[EntityID]struct{}
|
||||||
|
|
||||||
SystemBase :: struct {
|
SystemBase :: struct {
|
||||||
entities: map[EntityID]struct{}, // Treat as set
|
entities: EntitySet
|
||||||
}
|
}
|
||||||
|
|
||||||
SystemManager :: struct {
|
SystemManager :: struct {
|
||||||
|
|
@ -12,29 +16,30 @@ SystemManager :: struct {
|
||||||
systems: map[typeid]^SystemBase
|
systems: map[typeid]^SystemBase
|
||||||
}
|
}
|
||||||
|
|
||||||
system_manager_create :: proc() -> SystemManager {
|
system_base_init :: proc(system_base: ^SystemBase) {
|
||||||
system_manager := SystemManager{
|
system_base.entities = make(EntitySet, context.allocator)
|
||||||
signatures = make(map[typeid]Signature, context.allocator),
|
|
||||||
systems = make(map[typeid]^SystemBase, context.allocator),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return system_manager
|
system_manager_init :: proc(system_manager: ^SystemManager) {
|
||||||
|
system_manager.signatures = make(map[typeid]Signature, context.allocator)
|
||||||
|
system_manager.systems = make(map[typeid]^SystemBase, context.allocator)
|
||||||
}
|
}
|
||||||
|
|
||||||
system_manager_register_system :: proc($T: typeid, system_manager: ^SystemManager) -> ^T {
|
system_manager_register_system :: proc(system_manager: ^SystemManager, $System: typeid) -> ^System {
|
||||||
log.assertf(T not_in system_manager.systems, "Registering system more than once")
|
log.assertf(System not_in system_manager.systems, "Registering system more than once")
|
||||||
log.assertf(intrinsics.type_has_field(T, "entities"), "Registering non system type")
|
log.assertf(intrinsics.type_has_field(System, "entities"), "Registering non system type")
|
||||||
|
|
||||||
system := new(T, context.allocator)
|
system := new(System, context.allocator)
|
||||||
system.entities = make(map[EntityID]struct{})
|
system_base_init(system)
|
||||||
system_manager.systems[T] = system
|
|
||||||
|
system_manager.systems[System] = system
|
||||||
|
|
||||||
return system
|
return system
|
||||||
}
|
}
|
||||||
|
|
||||||
system_manager_set_signature :: proc($T: typeid, system_manager: ^SystemManager, signature: Signature) {
|
system_manager_set_signature :: proc(system_manager: ^SystemManager, $System: typeid, signature: Signature) {
|
||||||
log.assertf(T in system_manager.systems, "System used before registered")
|
log.assertf(System in system_manager.systems, "System used before registered")
|
||||||
system_manager.signatures[T] = signature
|
system_manager.signatures[System] = signature
|
||||||
}
|
}
|
||||||
|
|
||||||
system_manager_destroy_entity :: proc(system_manager: ^SystemManager, entity_id: EntityID) {
|
system_manager_destroy_entity :: proc(system_manager: ^SystemManager, entity_id: EntityID) {
|
||||||
|
|
@ -54,7 +59,7 @@ system_manager_change_entity_signature :: proc(system_manager: ^SystemManager, e
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
system_manager_destroy :: proc(system_manager: ^SystemManager) {
|
system_manager_delete :: proc(system_manager: ^SystemManager) {
|
||||||
for _, system in system_manager.systems {
|
for _, system in system_manager.systems {
|
||||||
delete(system.entities)
|
delete(system.entities)
|
||||||
free(system)
|
free(system)
|
||||||
|
|
|
||||||
BIN
examples/example.gif
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
226
main.odin
|
|
@ -18,42 +18,47 @@ import "core:math/rand"
|
||||||
import stbi "vendor:stb/image"
|
import stbi "vendor:stb/image"
|
||||||
|
|
||||||
import sa "sokol/app"
|
import sa "sokol/app"
|
||||||
|
import sg "sokol/app"
|
||||||
|
import sl "sokol/log"
|
||||||
import sh "sokol/helpers"
|
import sh "sokol/helpers"
|
||||||
|
|
||||||
import "ecs"
|
import "ecs"
|
||||||
|
import program_config "config"
|
||||||
|
|
||||||
Vec2 :: [2]f32
|
Vec2 :: ecs.Vec2
|
||||||
Vec3 :: [3]f32
|
Vec3 :: ecs.Vec3
|
||||||
Vec4 :: [4]f32
|
Vec4 :: ecs.Vec4
|
||||||
|
|
||||||
Globals :: struct {
|
Globals :: struct {
|
||||||
coordinator: ecs.Coordinator,
|
coordinator: ecs.Coordinator,
|
||||||
|
input_system: ^ecs.InputSystem,
|
||||||
physics_system: ^ecs.PhysicsSystem,
|
physics_system: ^ecs.PhysicsSystem,
|
||||||
|
camera_system: ^ecs.CameraSystem,
|
||||||
render_system: ^ecs.RenderSystem,
|
render_system: ^ecs.RenderSystem,
|
||||||
entities: []ecs.EntityID,
|
|
||||||
|
time_since_cube: f32,
|
||||||
|
current_color: i32,
|
||||||
}
|
}
|
||||||
g: ^Globals
|
g: ^Globals
|
||||||
|
|
||||||
mouse_move: Vec2
|
|
||||||
key_down: #sparse[sa.Keycode]bool
|
|
||||||
|
|
||||||
default_context: runtime.Context
|
default_context: runtime.Context
|
||||||
|
tracking_allocator: mem.Tracking_Allocator
|
||||||
|
|
||||||
main :: proc() {
|
main :: proc() {
|
||||||
context.logger = log.create_console_logger()
|
context.logger = log.create_console_logger()
|
||||||
|
|
||||||
tracking_allocator: mem.Tracking_Allocator
|
|
||||||
mem.tracking_allocator_init(&tracking_allocator, context.allocator)
|
mem.tracking_allocator_init(&tracking_allocator, context.allocator)
|
||||||
context.allocator = mem.tracking_allocator(&tracking_allocator)
|
context.allocator = mem.tracking_allocator(&tracking_allocator)
|
||||||
defer reset_tracking_allocator(&tracking_allocator)
|
|
||||||
|
|
||||||
default_context = context
|
default_context = context
|
||||||
|
|
||||||
sa.run({
|
sa.run({
|
||||||
window_title = "Ecs Test",
|
window_title = program_config.WINDOW_TITLE,
|
||||||
|
|
||||||
allocator = sa.Allocator(sh.allocator(&default_context)),
|
allocator = sa.Allocator(sh.allocator(&default_context)),
|
||||||
logger = sa.Logger(sh.logger(&default_context)),
|
logger = sg.Logger( { func = sl.func } ),
|
||||||
|
|
||||||
|
sample_count = 4,
|
||||||
|
|
||||||
init_cb = init_cb,
|
init_cb = init_cb,
|
||||||
frame_cb = frame_cb,
|
frame_cb = frame_cb,
|
||||||
|
|
@ -69,7 +74,7 @@ init_cb :: proc "c" () {
|
||||||
sa.lock_mouse(true)
|
sa.lock_mouse(true)
|
||||||
|
|
||||||
g = new(Globals)
|
g = new(Globals)
|
||||||
g.coordinator = ecs.coordinator_create()
|
ecs.coordinator_init(&g.coordinator)
|
||||||
|
|
||||||
create_scene()
|
create_scene()
|
||||||
}
|
}
|
||||||
|
|
@ -77,122 +82,175 @@ init_cb :: proc "c" () {
|
||||||
frame_cb:: proc "c" () {
|
frame_cb:: proc "c" () {
|
||||||
context = default_context
|
context = default_context
|
||||||
|
|
||||||
if key_down[.ESCAPE] {
|
|
||||||
sa.quit()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
dt := f32(sa.frame_duration())
|
dt := f32(sa.frame_duration())
|
||||||
|
|
||||||
ecs.physics_system_update(g.physics_system, &g.coordinator, dt)
|
g.time_since_cube += dt
|
||||||
ecs.render_system_update(g.render_system, &g.coordinator, dt, key_down, mouse_move)
|
if g.time_since_cube >= program_config.SPAWN_INTERVAL {
|
||||||
|
g.time_since_cube = 0
|
||||||
|
create_cube()
|
||||||
|
}
|
||||||
|
|
||||||
mouse_move = {}
|
ecs.physics_system_update(g.physics_system, &g.coordinator, dt)
|
||||||
|
ecs.camera_system_update(g.camera_system, &g.coordinator, dt)
|
||||||
|
ecs.render_system_update(g.render_system, &g.coordinator)
|
||||||
|
|
||||||
|
ecs.input_system_mouse_reset(g.input_system, &g.coordinator)
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup_cb :: proc "c" () {
|
cleanup_cb :: proc "c" () {
|
||||||
context = default_context
|
context = default_context
|
||||||
|
|
||||||
ecs.delete_render_system(g.render_system)
|
ecs.render_system_delete(g.render_system, &g.coordinator)
|
||||||
|
|
||||||
delete(g.entities)
|
ecs.coordinator_delete(&g.coordinator)
|
||||||
ecs.coordinator_destroy(&g.coordinator)
|
|
||||||
free(g)
|
free(g)
|
||||||
|
|
||||||
|
reset_tracking_allocator(&tracking_allocator)
|
||||||
}
|
}
|
||||||
|
|
||||||
event_cb :: proc "c" (event: ^sa.Event) {
|
event_cb :: proc "c" (event: ^sa.Event) {
|
||||||
context = default_context
|
context = default_context
|
||||||
|
|
||||||
#partial switch event.type {
|
ecs.input_system_update(g.input_system, &g.coordinator, event)
|
||||||
case .MOUSE_MOVE:
|
|
||||||
mouse_move += {event.mouse_dx, event.mouse_dy}
|
|
||||||
case .KEY_DOWN:
|
|
||||||
key_down[event.key_code] = true
|
|
||||||
case .KEY_UP:
|
|
||||||
key_down[event.key_code] = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
create_scene :: proc() {
|
create_cube :: proc() {
|
||||||
ecs.coordinator_register_component(ecs.Gravity, &g.coordinator)
|
entity := ecs.coordinator_create_entity(&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)
|
|
||||||
|
|
||||||
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, &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)
|
|
||||||
|
|
||||||
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.coordinator_add_component(
|
||||||
ecs.Gravity,
|
|
||||||
&g.coordinator,
|
&g.coordinator,
|
||||||
entity,
|
ecs.GravityComponent{
|
||||||
ecs.Gravity{
|
ecs.Vec3{ 0.0, program_config.GRAVITY_CONSTANT, 0.0 }
|
||||||
ecs.Vec3{0.0, -2.82, 0.0}
|
},
|
||||||
})
|
entity
|
||||||
|
)
|
||||||
ecs.coordinator_add_component(
|
ecs.coordinator_add_component(
|
||||||
ecs.RigidBody,
|
|
||||||
&g.coordinator,
|
&g.coordinator,
|
||||||
entity,
|
ecs.RigidBodyComponent{
|
||||||
ecs.RigidBody{
|
|
||||||
velocity = ecs.Vec3{ 0.0, 0.0, 0.0 },
|
velocity = ecs.Vec3{ 0.0, 0.0, 0.0 },
|
||||||
acceleration = ecs.Vec3{ 0.0, 0.0, 0.0 },
|
acceleration = ecs.Vec3{ 0.0, 0.0, 0.0 },
|
||||||
})
|
},
|
||||||
|
entity
|
||||||
|
)
|
||||||
ecs.coordinator_add_component(
|
ecs.coordinator_add_component(
|
||||||
ecs.Transform,
|
|
||||||
&g.coordinator,
|
&g.coordinator,
|
||||||
entity,
|
ecs.TransformComponent{
|
||||||
ecs.Transform{
|
|
||||||
position = Vec3{
|
position = Vec3{
|
||||||
f32(rand.int_max(50)),
|
f32(rand.int_max(program_config.SPAWN_AREA)),
|
||||||
f32(rand.int_max(10)),
|
10,
|
||||||
f32(rand.int_max(50)),
|
f32(rand.int_max(program_config.SPAWN_AREA)),
|
||||||
},
|
},
|
||||||
rotation = ecs.Vec3{ 0.0, 0.0, 0.0 },
|
rotation = ecs.Vec3{ 0.0, 0.0, 0.0 },
|
||||||
scale = ecs.Vec3{ 1.0, 1.0, 1.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),
|
|
||||||
},
|
},
|
||||||
})
|
entity
|
||||||
|
)
|
||||||
|
ecs.coordinator_add_component(
|
||||||
|
&g.coordinator,
|
||||||
|
ecs.ColorComponent{
|
||||||
|
color = program_config.CUBE_COLORS[g.current_color]
|
||||||
|
},
|
||||||
|
entity
|
||||||
|
)
|
||||||
|
g.current_color += 1
|
||||||
|
g.current_color %= i32(len(program_config.CUBE_COLORS))
|
||||||
|
|
||||||
|
ecs.coordinator_add_component(
|
||||||
|
&g.coordinator,
|
||||||
|
ecs.MeshComponent{
|
||||||
|
mesh_id = .Cube
|
||||||
|
},
|
||||||
|
entity
|
||||||
|
)
|
||||||
|
ecs.coordinator_add_component(
|
||||||
|
&g.coordinator,
|
||||||
|
ecs.MaterialComponent{
|
||||||
|
material_id = .Cube
|
||||||
|
},
|
||||||
|
entity
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
create_scene :: proc() {
|
||||||
|
coordinator := &g.coordinator
|
||||||
|
|
||||||
|
ecs.coordinator_register_component(coordinator, ecs.GravityComponent)
|
||||||
|
ecs.coordinator_register_component(coordinator, ecs.RigidBodyComponent)
|
||||||
|
ecs.coordinator_register_component(coordinator, ecs.TransformComponent)
|
||||||
|
ecs.coordinator_register_component(coordinator, ecs.ColorComponent)
|
||||||
|
ecs.coordinator_register_component(coordinator, ecs.CameraComponent)
|
||||||
|
ecs.coordinator_register_component(coordinator, ecs.MaterialComponent)
|
||||||
|
ecs.coordinator_register_component(coordinator, ecs.MeshComponent)
|
||||||
|
ecs.coordinator_register_component(coordinator, ecs.InputComponent)
|
||||||
|
|
||||||
|
g.physics_system = ecs.coordinator_register_system(coordinator, ecs.PhysicsSystem)
|
||||||
|
signature := ecs.signature_make()
|
||||||
|
ecs.signature_set(&signature, ecs.coordinator_get_component_id(coordinator, ecs.GravityComponent))
|
||||||
|
ecs.signature_set(&signature, ecs.coordinator_get_component_id(coordinator, ecs.RigidBodyComponent))
|
||||||
|
ecs.signature_set(&signature, ecs.coordinator_get_component_id(coordinator, ecs.TransformComponent))
|
||||||
|
ecs.coordinator_set_system_signature(coordinator, ecs.PhysicsSystem, signature)
|
||||||
|
|
||||||
|
g.render_system = ecs.coordinator_register_system(coordinator, ecs.RenderSystem)
|
||||||
|
ecs.signature_clear(&signature)
|
||||||
|
ecs.signature_set(&signature, ecs.coordinator_get_component_id(coordinator, ecs.TransformComponent))
|
||||||
|
ecs.signature_set(&signature, ecs.coordinator_get_component_id(coordinator, ecs.ColorComponent))
|
||||||
|
ecs.signature_set(&signature, ecs.coordinator_get_component_id(coordinator, ecs.MeshComponent))
|
||||||
|
ecs.signature_set(&signature, ecs.coordinator_get_component_id(coordinator, ecs.MaterialComponent))
|
||||||
|
ecs.coordinator_set_system_signature(coordinator, ecs.RenderSystem, signature)
|
||||||
|
|
||||||
|
g.camera_system = ecs.coordinator_register_system(coordinator, ecs.CameraSystem)
|
||||||
|
ecs.signature_clear(&signature)
|
||||||
|
ecs.signature_set(&signature, ecs.coordinator_get_component_id(coordinator, ecs.CameraComponent))
|
||||||
|
ecs.signature_set(&signature, ecs.coordinator_get_component_id(coordinator, ecs.InputComponent))
|
||||||
|
ecs.coordinator_set_system_signature(coordinator, ecs.CameraSystem, signature)
|
||||||
|
|
||||||
|
g.input_system = ecs.coordinator_register_system(coordinator, ecs.InputSystem)
|
||||||
|
ecs.signature_clear(&signature)
|
||||||
|
ecs.signature_set(&signature, ecs.coordinator_get_component_id(coordinator, ecs.InputComponent))
|
||||||
|
ecs.coordinator_set_system_signature(coordinator, ecs.InputSystem, signature)
|
||||||
|
|
||||||
|
user_entity := ecs.coordinator_create_entity(coordinator)
|
||||||
|
ecs.coordinator_add_component(
|
||||||
|
coordinator,
|
||||||
|
ecs.CameraComponent{
|
||||||
|
position = program_config.START_POSITION,
|
||||||
|
target = { 0, 0, 1 },
|
||||||
|
look = { 0, 0 },
|
||||||
|
movement_speed = program_config.MOVEMENT_SPEED,
|
||||||
|
look_sensitivity = program_config.LOOK_SENSITIVITY,
|
||||||
|
},
|
||||||
|
user_entity
|
||||||
|
)
|
||||||
|
|
||||||
|
ecs.coordinator_add_component(
|
||||||
|
coordinator,
|
||||||
|
ecs.InputComponent{
|
||||||
|
key_down = {},
|
||||||
|
mouse_movement = Vec2{ 0, 0 }
|
||||||
|
},
|
||||||
|
user_entity
|
||||||
|
)
|
||||||
|
|
||||||
|
ecs.render_system_init(g.render_system, user_entity)
|
||||||
}
|
}
|
||||||
|
|
||||||
reset_tracking_allocator :: proc(track: ^mem.Tracking_Allocator) {
|
reset_tracking_allocator :: proc(track: ^mem.Tracking_Allocator) {
|
||||||
|
clean := true
|
||||||
if len(track.allocation_map) > 0 {
|
if len(track.allocation_map) > 0 {
|
||||||
fmt.eprintf("=== %v allocations not freed: ===\n", len(track.allocation_map))
|
fmt.eprintfln("=== %v allocations not freed: ===", len(track.allocation_map))
|
||||||
for _, entry in track.allocation_map {
|
for _, entry in track.allocation_map {
|
||||||
fmt.eprintf("- %v bytes @ %v\n", entry.size, entry.location)
|
fmt.eprintf("- %v bytes @ %v\n", entry.size, entry.location)
|
||||||
}
|
}
|
||||||
|
clean = false
|
||||||
}
|
}
|
||||||
if len(track.bad_free_array) > 0 {
|
if len(track.bad_free_array) > 0 {
|
||||||
fmt.eprintf("=== %v incorrect frees: ===\n", len(track.bad_free_array))
|
fmt.eprintfln("=== %v incorrect frees: ===", len(track.bad_free_array))
|
||||||
for entry in track.bad_free_array {
|
for entry in track.bad_free_array {
|
||||||
fmt.eprintf("- %p @ %v\n", entry.memory, entry.location)
|
fmt.eprintf("- %p @ %v\n", entry.memory, entry.location)
|
||||||
}
|
}
|
||||||
|
clean = false
|
||||||
}
|
}
|
||||||
|
if clean do fmt.printfln("=== No memory leaked ===")
|
||||||
|
|
||||||
mem.tracking_allocator_destroy(track)
|
mem.tracking_allocator_destroy(track)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 165 B |
|
Before Width: | Height: | Size: 165 B |
|
Before Width: | Height: | Size: 165 B |
|
Before Width: | Height: | Size: 165 B |
|
Before Width: | Height: | Size: 165 B |
|
Before Width: | Height: | Size: 162 B |
|
Before Width: | Height: | Size: 165 B |
BIN
res/white.png
|
Before Width: | Height: | Size: 105 B |
162
shaders/out/cube.odin
Normal file
|
|
@ -0,0 +1,162 @@
|
||||||
|
package shaders
|
||||||
|
import sg "../../sokol/gfx"
|
||||||
|
/*
|
||||||
|
#version:1# (machine generated, don't edit!)
|
||||||
|
|
||||||
|
Generated by sokol-shdc (https://github.com/floooh/sokol-tools)
|
||||||
|
|
||||||
|
Cmdline:
|
||||||
|
sokol-shdc -i shaders/src/cube.glsl -o shaders/out/cube.odin -l metal_macos -f sokol_odin
|
||||||
|
|
||||||
|
Overview:
|
||||||
|
=========
|
||||||
|
Shader program: 'cube':
|
||||||
|
Get shader desc: cube_shader_desc(sg.query_backend())
|
||||||
|
Vertex Shader: vs_cube
|
||||||
|
Fragment Shader: fs_cube
|
||||||
|
Attributes:
|
||||||
|
ATTR_cube_pos => 0
|
||||||
|
Bindings:
|
||||||
|
Uniform block 'VsParamsCube':
|
||||||
|
Odin struct: Vsparamscube
|
||||||
|
Bind slot: UB_VsParamsCube => 0
|
||||||
|
*/
|
||||||
|
ATTR_cube_pos :: 0
|
||||||
|
UB_VsParamsCube :: 0
|
||||||
|
Vsparamscube :: struct #align(16) {
|
||||||
|
using _: struct #packed {
|
||||||
|
mvp: Mat4,
|
||||||
|
col: [4]f32,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
#include <metal_stdlib>
|
||||||
|
#include <simd/simd.h>
|
||||||
|
|
||||||
|
using namespace metal;
|
||||||
|
|
||||||
|
struct VsParamsCube
|
||||||
|
{
|
||||||
|
float4x4 mvp;
|
||||||
|
float4 col;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct main0_out
|
||||||
|
{
|
||||||
|
float4 color [[user(locn0)]];
|
||||||
|
float4 gl_Position [[position]];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct main0_in
|
||||||
|
{
|
||||||
|
float3 pos [[attribute(0)]];
|
||||||
|
};
|
||||||
|
|
||||||
|
vertex main0_out main0(main0_in in [[stage_in]], constant VsParamsCube& _19 [[buffer(0)]])
|
||||||
|
{
|
||||||
|
main0_out out = {};
|
||||||
|
out.gl_Position = _19.mvp * float4(in.pos, 1.0);
|
||||||
|
out.color = _19.col;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
@(private="file")
|
||||||
|
vs_cube_source_metal_macos := [496]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,0x43,0x75,0x62,0x65,0x0a,0x7b,0x0a,0x20,0x20,
|
||||||
|
0x20,0x20,0x66,0x6c,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,0x29,0x5d,0x5d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,
|
||||||
|
0x61,0x74,0x34,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,
|
||||||
|
0x5b,0x5b,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x5d,0x5d,0x3b,0x0a,0x7d,0x3b,
|
||||||
|
0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,0x61,0x69,0x6e,0x30,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,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,0x43,0x75,0x62,0x65,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,
|
||||||
|
0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6f,0x75,0x74,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
|
||||||
|
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
#include <metal_stdlib>
|
||||||
|
#include <simd/simd.h>
|
||||||
|
|
||||||
|
using namespace metal;
|
||||||
|
|
||||||
|
struct main0_out
|
||||||
|
{
|
||||||
|
float4 frag_color [[color(0)]];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct main0_in
|
||||||
|
{
|
||||||
|
float4 color [[user(locn0)]];
|
||||||
|
};
|
||||||
|
|
||||||
|
fragment main0_out main0(main0_in in [[stage_in]])
|
||||||
|
{
|
||||||
|
main0_out out = {};
|
||||||
|
out.frag_color = in.color;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
@(private="file")
|
||||||
|
fs_cube_source_metal_macos := [315]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,0x6d,
|
||||||
|
0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,
|
||||||
|
0x6c,0x6f,0x61,0x74,0x34,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,
|
||||||
|
0x20,0x5b,0x5b,0x63,0x6f,0x6c,0x6f,0x72,0x28,0x30,0x29,0x5d,0x5d,0x3b,0x0a,0x7d,
|
||||||
|
0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,
|
||||||
|
0x69,0x6e,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,0x29,0x5d,0x5d,0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,0x66,0x72,0x61,0x67,0x6d,
|
||||||
|
0x65,0x6e,0x74,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,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,
|
||||||
|
0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x69,0x6e,0x2e,
|
||||||
|
0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,
|
||||||
|
0x6e,0x20,0x6f,0x75,0x74,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
|
||||||
|
}
|
||||||
|
cube_shader_desc :: proc (backend: sg.Backend) -> sg.Shader_Desc {
|
||||||
|
desc: sg.Shader_Desc
|
||||||
|
desc.label = "cube_shader"
|
||||||
|
#partial switch backend {
|
||||||
|
case .METAL_MACOS:
|
||||||
|
desc.vertex_func.source = transmute(cstring)&vs_cube_source_metal_macos
|
||||||
|
desc.vertex_func.entry = "main0"
|
||||||
|
desc.fragment_func.source = transmute(cstring)&fs_cube_source_metal_macos
|
||||||
|
desc.fragment_func.entry = "main0"
|
||||||
|
desc.attrs[0].base_type = .FLOAT
|
||||||
|
desc.uniform_blocks[0].stage = .VERTEX
|
||||||
|
desc.uniform_blocks[0].layout = .STD140
|
||||||
|
desc.uniform_blocks[0].size = 80
|
||||||
|
desc.uniform_blocks[0].msl_buffer_n = 0
|
||||||
|
}
|
||||||
|
return desc
|
||||||
|
}
|
||||||
167
shaders/out/outline.odin
Normal file
|
|
@ -0,0 +1,167 @@
|
||||||
|
package shaders
|
||||||
|
import sg "../../sokol/gfx"
|
||||||
|
/*
|
||||||
|
#version:1# (machine generated, don't edit!)
|
||||||
|
|
||||||
|
Generated by sokol-shdc (https://github.com/floooh/sokol-tools)
|
||||||
|
|
||||||
|
Cmdline:
|
||||||
|
sokol-shdc -i shaders/src/outline.glsl -o shaders/out/outline.odin -l metal_macos -f sokol_odin
|
||||||
|
|
||||||
|
Overview:
|
||||||
|
=========
|
||||||
|
Shader program: 'outline':
|
||||||
|
Get shader desc: outline_shader_desc(sg.query_backend())
|
||||||
|
Vertex Shader: vs_outline
|
||||||
|
Fragment Shader: fs_outline
|
||||||
|
Attributes:
|
||||||
|
ATTR_outline_pos => 0
|
||||||
|
Bindings:
|
||||||
|
Uniform block 'VsParamsOutline':
|
||||||
|
Odin struct: Vsparamsoutline
|
||||||
|
Bind slot: UB_VsParamsOutline => 0
|
||||||
|
Uniform block 'FsParamsOutline':
|
||||||
|
Odin struct: Fsparamsoutline
|
||||||
|
Bind slot: UB_FsParamsOutline => 1
|
||||||
|
*/
|
||||||
|
ATTR_outline_pos :: 0
|
||||||
|
UB_VsParamsOutline :: 0
|
||||||
|
UB_FsParamsOutline :: 1
|
||||||
|
Vsparamsoutline :: struct #align(16) {
|
||||||
|
using _: struct #packed {
|
||||||
|
mvp: Mat4,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
Fsparamsoutline :: struct #align(16) {
|
||||||
|
using _: struct #packed {
|
||||||
|
col: [4]f32,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
#include <metal_stdlib>
|
||||||
|
#include <simd/simd.h>
|
||||||
|
|
||||||
|
using namespace metal;
|
||||||
|
|
||||||
|
struct VsParamsOutline
|
||||||
|
{
|
||||||
|
float4x4 mvp;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct main0_out
|
||||||
|
{
|
||||||
|
float4 gl_Position [[position]];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct main0_in
|
||||||
|
{
|
||||||
|
float3 pos [[attribute(0)]];
|
||||||
|
};
|
||||||
|
|
||||||
|
vertex main0_out main0(main0_in in [[stage_in]], constant VsParamsOutline& _19 [[buffer(0)]])
|
||||||
|
{
|
||||||
|
main0_out out = {};
|
||||||
|
out.gl_Position = _19.mvp * float4(in.pos, 1.0);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
@(private="file")
|
||||||
|
vs_outline_source_metal_macos := [427]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,0x4f,0x75,0x74,0x6c,0x69,0x6e,0x65,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,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,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,
|
||||||
|
0x20,0x5b,0x5b,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x5d,0x5d,0x3b,0x0a,0x7d,
|
||||||
|
0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,0x61,0x69,0x6e,0x30,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,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,0x4f,0x75,0x74,0x6c,
|
||||||
|
0x69,0x6e,0x65,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,0x72,0x65,0x74,0x75,0x72,
|
||||||
|
0x6e,0x20,0x6f,0x75,0x74,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
#include <metal_stdlib>
|
||||||
|
#include <simd/simd.h>
|
||||||
|
|
||||||
|
using namespace metal;
|
||||||
|
|
||||||
|
struct FsParamsOutline
|
||||||
|
{
|
||||||
|
float4 col;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct main0_out
|
||||||
|
{
|
||||||
|
float4 frag_color [[color(0)]];
|
||||||
|
};
|
||||||
|
|
||||||
|
fragment main0_out main0(constant FsParamsOutline& _12 [[buffer(0)]])
|
||||||
|
{
|
||||||
|
main0_out out = {};
|
||||||
|
out.frag_color = _12.col;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
@(private="file")
|
||||||
|
fs_outline_source_metal_macos := [322]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,0x46,
|
||||||
|
0x73,0x50,0x61,0x72,0x61,0x6d,0x73,0x4f,0x75,0x74,0x6c,0x69,0x6e,0x65,0x0a,0x7b,
|
||||||
|
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,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x5b,0x5b,
|
||||||
|
0x63,0x6f,0x6c,0x6f,0x72,0x28,0x30,0x29,0x5d,0x5d,0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,
|
||||||
|
0x66,0x72,0x61,0x67,0x6d,0x65,0x6e,0x74,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x6f,
|
||||||
|
0x75,0x74,0x20,0x6d,0x61,0x69,0x6e,0x30,0x28,0x63,0x6f,0x6e,0x73,0x74,0x61,0x6e,
|
||||||
|
0x74,0x20,0x46,0x73,0x50,0x61,0x72,0x61,0x6d,0x73,0x4f,0x75,0x74,0x6c,0x69,0x6e,
|
||||||
|
0x65,0x26,0x20,0x5f,0x31,0x32,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,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,
|
||||||
|
0x6f,0x72,0x20,0x3d,0x20,0x5f,0x31,0x32,0x2e,0x63,0x6f,0x6c,0x3b,0x0a,0x20,0x20,
|
||||||
|
0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6f,0x75,0x74,0x3b,0x0a,0x7d,0x0a,
|
||||||
|
0x0a,0x00,
|
||||||
|
}
|
||||||
|
outline_shader_desc :: proc (backend: sg.Backend) -> sg.Shader_Desc {
|
||||||
|
desc: sg.Shader_Desc
|
||||||
|
desc.label = "outline_shader"
|
||||||
|
#partial switch backend {
|
||||||
|
case .METAL_MACOS:
|
||||||
|
desc.vertex_func.source = transmute(cstring)&vs_outline_source_metal_macos
|
||||||
|
desc.vertex_func.entry = "main0"
|
||||||
|
desc.fragment_func.source = transmute(cstring)&fs_outline_source_metal_macos
|
||||||
|
desc.fragment_func.entry = "main0"
|
||||||
|
desc.attrs[0].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].msl_buffer_n = 0
|
||||||
|
desc.uniform_blocks[1].stage = .FRAGMENT
|
||||||
|
desc.uniform_blocks[1].layout = .STD140
|
||||||
|
desc.uniform_blocks[1].size = 16
|
||||||
|
desc.uniform_blocks[1].msl_buffer_n = 0
|
||||||
|
}
|
||||||
|
return desc
|
||||||
|
}
|
||||||
|
|
@ -1,205 +0,0 @@
|
||||||
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 shaders/src/shader.glsl -o shaders/out/shader.odin -l metal_macos -f sokol_odin
|
|
||||||
|
|
||||||
Overview:
|
|
||||||
=========
|
|
||||||
Shader program: 'main':
|
|
||||||
Get shader desc: main_shader_desc(sg.query_backend())
|
|
||||||
Vertex Shader: vs
|
|
||||||
Fragment Shader: fs
|
|
||||||
Attributes:
|
|
||||||
ATTR_main_pos => 0
|
|
||||||
ATTR_main_uv => 1
|
|
||||||
Bindings:
|
|
||||||
Uniform block 'VsParams':
|
|
||||||
Odin struct: Vsparams
|
|
||||||
Bind slot: UB_VsParams => 0
|
|
||||||
Image 'tex':
|
|
||||||
Image type: ._2D
|
|
||||||
Sample type: .FLOAT
|
|
||||||
Multisampled: false
|
|
||||||
Bind slot: IMG_tex => 0
|
|
||||||
Sampler 'smp':
|
|
||||||
Type: .FILTERING
|
|
||||||
Bind slot: SMP_smp => 0
|
|
||||||
*/
|
|
||||||
ATTR_main_pos :: 0
|
|
||||||
ATTR_main_uv :: 1
|
|
||||||
UB_VsParams :: 0
|
|
||||||
IMG_tex :: 0
|
|
||||||
SMP_smp :: 0
|
|
||||||
Vsparams :: struct #align(16) {
|
|
||||||
using _: struct #packed {
|
|
||||||
mvp: ecs.Mat4,
|
|
||||||
col: [4]f32,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
#include <metal_stdlib>
|
|
||||||
#include <simd/simd.h>
|
|
||||||
|
|
||||||
using namespace metal;
|
|
||||||
|
|
||||||
struct VsParams
|
|
||||||
{
|
|
||||||
float4x4 mvp;
|
|
||||||
float4 col;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct main0_out
|
|
||||||
{
|
|
||||||
float4 color [[user(locn0)]];
|
|
||||||
float2 tex_coord [[user(locn1)]];
|
|
||||||
float4 gl_Position [[position]];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct main0_in
|
|
||||||
{
|
|
||||||
float3 pos [[attribute(0)]];
|
|
||||||
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 = _19.col;
|
|
||||||
out.tex_coord = in.uv;
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
|
||||||
@(private="file")
|
|
||||||
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,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,
|
|
||||||
0x29,0x5d,0x5d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x32,0x20,
|
|
||||||
0x74,0x65,0x78,0x5f,0x63,0x6f,0x6f,0x72,0x64,0x20,0x5b,0x5b,0x75,0x73,0x65,0x72,
|
|
||||||
0x28,0x6c,0x6f,0x63,0x6e,0x31,0x29,0x5d,0x5d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,
|
|
||||||
0x6c,0x6f,0x61,0x74,0x34,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,
|
|
||||||
0x6e,0x20,0x5b,0x5b,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x5d,0x5d,0x3b,0x0a,
|
|
||||||
0x7d,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,0x61,0x69,0x6e,0x30,
|
|
||||||
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,
|
|
||||||
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,
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
#include <metal_stdlib>
|
|
||||||
#include <simd/simd.h>
|
|
||||||
|
|
||||||
using namespace metal;
|
|
||||||
|
|
||||||
struct main0_out
|
|
||||||
{
|
|
||||||
float4 frag_color [[color(0)]];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct main0_in
|
|
||||||
{
|
|
||||||
float4 color [[user(locn0)]];
|
|
||||||
float2 tex_coord [[user(locn1)]];
|
|
||||||
};
|
|
||||||
|
|
||||||
fragment main0_out main0(main0_in in [[stage_in]], texture2d<float> tex [[texture(0)]], sampler smp [[sampler(0)]])
|
|
||||||
{
|
|
||||||
main0_out out = {};
|
|
||||||
out.frag_color = tex.sample(smp, in.tex_coord) * in.color;
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
|
||||||
@(private="file")
|
|
||||||
fs_source_metal_macos := [450]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,0x6d,
|
|
||||||
0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,
|
|
||||||
0x6c,0x6f,0x61,0x74,0x34,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,
|
|
||||||
0x20,0x5b,0x5b,0x63,0x6f,0x6c,0x6f,0x72,0x28,0x30,0x29,0x5d,0x5d,0x3b,0x0a,0x7d,
|
|
||||||
0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,
|
|
||||||
0x69,0x6e,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,0x29,0x5d,0x5d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,
|
|
||||||
0x32,0x20,0x74,0x65,0x78,0x5f,0x63,0x6f,0x6f,0x72,0x64,0x20,0x5b,0x5b,0x75,0x73,
|
|
||||||
0x65,0x72,0x28,0x6c,0x6f,0x63,0x6e,0x31,0x29,0x5d,0x5d,0x3b,0x0a,0x7d,0x3b,0x0a,
|
|
||||||
0x0a,0x66,0x72,0x61,0x67,0x6d,0x65,0x6e,0x74,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,0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x32,0x64,0x3c,0x66,0x6c,
|
|
||||||
0x6f,0x61,0x74,0x3e,0x20,0x74,0x65,0x78,0x20,0x5b,0x5b,0x74,0x65,0x78,0x74,0x75,
|
|
||||||
0x72,0x65,0x28,0x30,0x29,0x5d,0x5d,0x2c,0x20,0x73,0x61,0x6d,0x70,0x6c,0x65,0x72,
|
|
||||||
0x20,0x73,0x6d,0x70,0x20,0x5b,0x5b,0x73,0x61,0x6d,0x70,0x6c,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,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,
|
|
||||||
0x72,0x20,0x3d,0x20,0x74,0x65,0x78,0x2e,0x73,0x61,0x6d,0x70,0x6c,0x65,0x28,0x73,
|
|
||||||
0x6d,0x70,0x2c,0x20,0x69,0x6e,0x2e,0x74,0x65,0x78,0x5f,0x63,0x6f,0x6f,0x72,0x64,
|
|
||||||
0x29,0x20,0x2a,0x20,0x69,0x6e,0x2e,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x20,0x20,
|
|
||||||
0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6f,0x75,0x74,0x3b,0x0a,0x7d,0x0a,
|
|
||||||
0x0a,0x00,
|
|
||||||
}
|
|
||||||
main_shader_desc :: proc (backend: sg.Backend) -> sg.Shader_Desc {
|
|
||||||
desc: sg.Shader_Desc
|
|
||||||
desc.label = "main_shader"
|
|
||||||
#partial switch backend {
|
|
||||||
case .METAL_MACOS:
|
|
||||||
desc.vertex_func.source = transmute(cstring)&vs_source_metal_macos
|
|
||||||
desc.vertex_func.entry = "main0"
|
|
||||||
desc.fragment_func.source = transmute(cstring)&fs_source_metal_macos
|
|
||||||
desc.fragment_func.entry = "main0"
|
|
||||||
desc.attrs[0].base_type = .FLOAT
|
|
||||||
desc.attrs[1].base_type = .FLOAT
|
|
||||||
desc.uniform_blocks[0].stage = .VERTEX
|
|
||||||
desc.uniform_blocks[0].layout = .STD140
|
|
||||||
desc.uniform_blocks[0].size = 80
|
|
||||||
desc.uniform_blocks[0].msl_buffer_n = 0
|
|
||||||
desc.images[0].stage = .FRAGMENT
|
|
||||||
desc.images[0].multisampled = false
|
|
||||||
desc.images[0].image_type = ._2D
|
|
||||||
desc.images[0].sample_type = .FLOAT
|
|
||||||
desc.images[0].msl_texture_n = 0
|
|
||||||
desc.samplers[0].stage = .FRAGMENT
|
|
||||||
desc.samplers[0].sampler_type = .FILTERING
|
|
||||||
desc.samplers[0].msl_sampler_n = 0
|
|
||||||
desc.image_sampler_pairs[0].stage = .FRAGMENT
|
|
||||||
desc.image_sampler_pairs[0].image_slot = 0
|
|
||||||
desc.image_sampler_pairs[0].sampler_slot = 0
|
|
||||||
}
|
|
||||||
return desc
|
|
||||||
}
|
|
||||||
7
shaders/out/types.odin
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
package shaders
|
||||||
|
|
||||||
|
Mat4 :: matrix[4, 4]f32
|
||||||
|
|
||||||
|
Vec2 :: [2]f32
|
||||||
|
Vec3 :: [3]f32
|
||||||
|
Vec4 :: [4]f32
|
||||||
34
shaders/src/cube.glsl
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
@header package shaders
|
||||||
|
@header import sg "../../sokol/gfx"
|
||||||
|
|
||||||
|
@ctype mat4 Mat4
|
||||||
|
|
||||||
|
@vs vs_cube
|
||||||
|
in vec3 pos;
|
||||||
|
|
||||||
|
layout(binding = 0) uniform VsParamsCube {
|
||||||
|
mat4 mvp;
|
||||||
|
vec4 col;
|
||||||
|
};
|
||||||
|
|
||||||
|
out vec4 color;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
gl_Position = mvp * vec4(pos, 1);
|
||||||
|
color = col;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@fs fs_cube
|
||||||
|
in vec4 color;
|
||||||
|
|
||||||
|
out vec4 frag_color;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
frag_color = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@program cube vs_cube fs_cube
|
||||||
30
shaders/src/outline.glsl
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
@header package shaders
|
||||||
|
@header import sg "../../sokol/gfx"
|
||||||
|
|
||||||
|
@ctype mat4 Mat4
|
||||||
|
|
||||||
|
@vs vs_outline
|
||||||
|
in vec3 pos;
|
||||||
|
|
||||||
|
layout(binding = 0) uniform VsParamsOutline {
|
||||||
|
mat4 mvp;
|
||||||
|
};
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
gl_Position = mvp * vec4(pos, 1);
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
@fs fs_outline
|
||||||
|
layout(binding = 1) uniform FsParamsOutline {
|
||||||
|
vec4 col;
|
||||||
|
};
|
||||||
|
|
||||||
|
out vec4 frag_color;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
frag_color = col;
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
@program outline vs_outline fs_outline
|
||||||
|
|
@ -1,42 +0,0 @@
|
||||||
@header package shader
|
|
||||||
@header import sg "../../sokol/gfx"
|
|
||||||
@header import ecs "../../types"
|
|
||||||
|
|
||||||
@ctype mat4 ecs.Mat4
|
|
||||||
|
|
||||||
@vs vs
|
|
||||||
in vec3 pos;
|
|
||||||
in vec2 uv;
|
|
||||||
|
|
||||||
layout(binding = 0) uniform VsParams {
|
|
||||||
mat4 mvp;
|
|
||||||
vec4 col;
|
|
||||||
};
|
|
||||||
|
|
||||||
out vec4 color;
|
|
||||||
out vec2 tex_coord;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
gl_Position = mvp * vec4(pos, 1);
|
|
||||||
color = col;
|
|
||||||
tex_coord = uv;
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
@fs fs
|
|
||||||
in vec4 color;
|
|
||||||
in vec2 tex_coord;
|
|
||||||
|
|
||||||
layout(binding=0) uniform texture2D tex;
|
|
||||||
layout(binding=0) uniform sampler smp;
|
|
||||||
|
|
||||||
out vec4 frag_color;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
frag_color = texture(sampler2D(tex, smp), tex_coord) * color;
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
@program main vs fs
|
|
||||||