Add render system
This commit is contained in:
parent
af76df6a81
commit
05ba2a60d6
8 changed files with 395 additions and 330 deletions
|
|
@ -1,10 +1,268 @@
|
|||
package ecs
|
||||
|
||||
import "base:runtime"
|
||||
import "base:intrinsics"
|
||||
|
||||
import "core:log"
|
||||
import "core:mem"
|
||||
import "core:time"
|
||||
import "core:fmt"
|
||||
import "core:testing"
|
||||
import "core:strings"
|
||||
import "core:path/filepath"
|
||||
import "core:math"
|
||||
import "core:math/linalg"
|
||||
import "core:os"
|
||||
|
||||
import stbi "vendor:stb/image"
|
||||
|
||||
import sa "../sokol/app"
|
||||
import sh "../sokol/helpers"
|
||||
import sg "../sokol/gfx"
|
||||
|
||||
import shaders "../shaders/out"
|
||||
|
||||
VertexData :: struct {
|
||||
pos: Vec3,
|
||||
uv: Vec2,
|
||||
}
|
||||
|
||||
RenderSystem :: struct {
|
||||
using base: SystemBase,
|
||||
|
||||
shader: sg.Shader,
|
||||
pipeline: sg.Pipeline,
|
||||
vertex_buffer: sg.Buffer,
|
||||
index_buffer: sg.Buffer,
|
||||
image: sg.Image,
|
||||
sampler: sg.Sampler,
|
||||
|
||||
camera: struct {
|
||||
pos: Vec3,
|
||||
target: Vec3,
|
||||
look: Vec2,
|
||||
},
|
||||
}
|
||||
|
||||
render_system_update :: proc(render_system: ^RenderSystem, coordinator: ^Coordinator) {
|
||||
for entity in render_system.entities {
|
||||
init_render_system :: proc(render_system: ^RenderSystem) {
|
||||
default_context := runtime.default_context()
|
||||
|
||||
sg.setup({
|
||||
environment = sh.glue_environment(),
|
||||
allocator = sg.Allocator(sh.allocator(&default_context)),
|
||||
logger = sg.Logger(sh.logger(&default_context)),
|
||||
})
|
||||
|
||||
shader := sg.make_shader(shaders.main_shader_desc(sg.query_backend()))
|
||||
pipeline := sg.make_pipeline({
|
||||
shader = shader,
|
||||
layout = {
|
||||
attrs = {
|
||||
shaders.ATTR_main_pos = { format = .FLOAT3 },
|
||||
shaders.ATTR_main_uv = { format = .FLOAT2 },
|
||||
},
|
||||
},
|
||||
index_type = .UINT16,
|
||||
cull_mode = .BACK,
|
||||
depth = {
|
||||
pixel_format = .DEFAULT,
|
||||
write_enabled = true,
|
||||
bias = 0.001,
|
||||
bias_clamp = 0.0,
|
||||
bias_slope_scale = 1.0,
|
||||
compare = .LESS_EQUAL,
|
||||
},
|
||||
})
|
||||
|
||||
vertices := []VertexData {
|
||||
{ pos = { -0.5, -0.5, 0.5 }, uv = { 0, 0 } },
|
||||
{ pos = { 0.5, -0.5, 0.5 }, uv = { 1, 0 } },
|
||||
{ pos = { 0.5, 0.5, 0.5 }, uv = { 1, 1 } },
|
||||
{ pos = { -0.5, 0.5, 0.5 }, uv = { 0, 1 } },
|
||||
|
||||
{ pos = { -0.5, -0.5, -0.5 }, uv = { 1, 0 } },
|
||||
{ pos = { 0.5, -0.5, -0.5 }, uv = { 0, 0 } },
|
||||
{ pos = { 0.5, 0.5, -0.5 }, uv = { 0, 1 } },
|
||||
{ pos = { -0.5, 0.5, -0.5 }, uv = { 1, 1 } },
|
||||
|
||||
{ pos = { -0.5, 0.5, 0.5 }, uv = { 0, 0 } },
|
||||
{ pos = { 0.5, 0.5, 0.5 }, uv = { 1, 0 } },
|
||||
{ pos = { 0.5, 0.5, -0.5 }, uv = { 1, 1 } },
|
||||
{ pos = { -0.5, 0.5, -0.5 }, uv = { 0, 1 } },
|
||||
|
||||
{ pos = { -0.5, -0.5, 0.5 }, uv = { 0, 0 } },
|
||||
{ pos = { 0.5, -0.5, 0.5 }, uv = { 1, 0 } },
|
||||
{ pos = { 0.5, -0.5, -0.5 }, uv = { 1, 1 } },
|
||||
{ pos = { -0.5, -0.5, -0.5 }, uv = { 0, 1 } },
|
||||
|
||||
{ pos = { 0.5, -0.5, 0.5 }, uv = { 0, 0 } },
|
||||
{ pos = { 0.5, -0.5, -0.5 }, uv = { 1, 0 } },
|
||||
{ pos = { 0.5, 0.5, -0.5 }, uv = { 1, 1 } },
|
||||
{ pos = { 0.5, 0.5, 0.5 }, uv = { 0, 1 } },
|
||||
|
||||
{ pos = { -0.5, -0.5, 0.5 }, uv = { 1, 0 } },
|
||||
{ pos = { -0.5, -0.5, -0.5 }, uv = { 0, 0 } },
|
||||
{ pos = { -0.5, 0.5, -0.5 }, uv = { 0, 1 } },
|
||||
{ pos = { -0.5, 0.5, 0.5 }, uv = { 1, 1 } },
|
||||
}
|
||||
vertex_buffer := sg.make_buffer({
|
||||
data = sg_range(vertices)
|
||||
})
|
||||
|
||||
indices := []u16 {
|
||||
1, 0, 2,
|
||||
3, 2, 0,
|
||||
7, 4, 6,
|
||||
5, 6, 4,
|
||||
9, 8, 10,
|
||||
11, 10, 8,
|
||||
15, 12, 14,
|
||||
13, 14, 12,
|
||||
17, 16, 18,
|
||||
19, 18, 16,
|
||||
23, 20, 22,
|
||||
21, 22, 20,
|
||||
}
|
||||
|
||||
index_buffer := sg.make_buffer({
|
||||
usage = { index_buffer = true },
|
||||
data = sg_range(indices),
|
||||
})
|
||||
|
||||
w, h: i32
|
||||
pixels := stbi.load("res/white.png", &w, &h, nil, 4)
|
||||
assert(pixels != nil)
|
||||
defer(stbi.image_free(pixels))
|
||||
|
||||
image := sg.make_image({
|
||||
width = w,
|
||||
height = h,
|
||||
pixel_format = .RGBA8,
|
||||
data = {
|
||||
subimage = {
|
||||
0 = {
|
||||
0 = {
|
||||
ptr = pixels,
|
||||
size = uint(w * h * 4)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
sampler := sg.make_sampler({})
|
||||
|
||||
render_system.sampler = sampler
|
||||
render_system.shader = shader
|
||||
render_system.image = image
|
||||
render_system.pipeline = pipeline
|
||||
render_system.vertex_buffer = vertex_buffer
|
||||
render_system.index_buffer = index_buffer
|
||||
render_system.camera = {
|
||||
pos = { 30, 0, 60 },
|
||||
target = { 0, 0, 1 },
|
||||
}
|
||||
}
|
||||
|
||||
delete_render_system :: proc(render_system: ^RenderSystem) {
|
||||
sg.destroy_buffer(render_system.index_buffer)
|
||||
sg.destroy_buffer(render_system.vertex_buffer)
|
||||
sg.destroy_image(render_system.image)
|
||||
sg.destroy_sampler(render_system.sampler)
|
||||
sg.destroy_pipeline(render_system.pipeline)
|
||||
sg.destroy_shader(render_system.shader)
|
||||
|
||||
sg.shutdown()
|
||||
}
|
||||
|
||||
render_system_update :: proc(render_system: ^RenderSystem, coordinator: ^Coordinator, dt: f32, key_down: #sparse[sa.Keycode]bool, mouse_move: Vec2) {
|
||||
update_camera(render_system, dt, key_down, mouse_move)
|
||||
|
||||
proj := linalg.matrix4_perspective_f32(70, sa.widthf() / sa.heightf(), 0.001, 1000)
|
||||
view := linalg.matrix4_look_at_f32(render_system.camera.pos, render_system.camera.target, { 0, 1, 0 } )
|
||||
|
||||
sg.begin_pass({ swapchain = sh.glue_swapchain() })
|
||||
|
||||
sg.apply_pipeline(render_system.pipeline)
|
||||
sg.apply_bindings({
|
||||
vertex_buffers = { 0 = render_system.vertex_buffer },
|
||||
index_buffer = render_system.index_buffer,
|
||||
images = { shaders.IMG_tex = render_system.image },
|
||||
samplers = { shaders.SMP_smp = render_system.sampler },
|
||||
})
|
||||
|
||||
for entity in render_system.entities {
|
||||
transform := coordinator_get_component(Transform, coordinator, entity)
|
||||
color := coordinator_get_component(Color, coordinator, entity)
|
||||
pos_mat := linalg.matrix4_translate_f32(transform.position)
|
||||
rot_mat := linalg.matrix4_from_yaw_pitch_roll_f32(transform.rotation.y, transform.rotation.x, transform.rotation.z)
|
||||
model := pos_mat * rot_mat
|
||||
|
||||
sg.apply_uniforms(shaders.UB_VsParams, sg_range(&shaders.Vsparams{
|
||||
mvp = proj * view * model,
|
||||
col = color.color
|
||||
}))
|
||||
|
||||
sg.draw(0, 36, 1)
|
||||
}
|
||||
|
||||
sg.end_pass()
|
||||
sg.commit()
|
||||
}
|
||||
|
||||
@(private)
|
||||
update_camera :: proc(render_system: ^RenderSystem, dt: f32, key_down: #sparse[sa.Keycode]bool, mouse_move: Vec2) {
|
||||
MOVE_SPEED :: 3
|
||||
LOOK_SENSITIVITY :: 0.15
|
||||
|
||||
move_input: Vec3
|
||||
if key_down[.W] do move_input.y = 1
|
||||
else if key_down[.S] do move_input.y = -1
|
||||
|
||||
if key_down[.D] do move_input.x = 1
|
||||
else if key_down[.A] do move_input.x = -1
|
||||
|
||||
if key_down[.SPACE] do move_input.z = 1
|
||||
else if key_down[.LEFT_SHIFT] do move_input.z = -1
|
||||
|
||||
look_input: Vec2 = -mouse_move * LOOK_SENSITIVITY
|
||||
render_system.camera.look += look_input
|
||||
render_system.camera.look.x = math.wrap(render_system.camera.look.x, 360)
|
||||
render_system.camera.look.y = math.clamp(render_system.camera.look.y, -89.5, 89.5)
|
||||
|
||||
look_mat := linalg.matrix4_from_yaw_pitch_roll_f32(
|
||||
linalg.to_radians(render_system.camera.look.x),
|
||||
linalg.to_radians(render_system.camera.look.y),
|
||||
0,
|
||||
)
|
||||
|
||||
forward := (look_mat * Vec4{0, 0, -1, 1}).xyz
|
||||
right := (look_mat * Vec4{1, 0, 0, 1}).xyz
|
||||
up := (look_mat * Vec4{0, 1, 0, 1}).xyz
|
||||
|
||||
move_dir := forward * move_input.y + right * move_input.x + up * move_input.z
|
||||
motion := linalg.normalize0(move_dir) * MOVE_SPEED * dt
|
||||
render_system.camera.pos += motion
|
||||
|
||||
render_system.camera.target = render_system.camera.pos + forward
|
||||
}
|
||||
|
||||
|
||||
sg_range :: proc {
|
||||
sg_range_from_slice,
|
||||
sg_range_from_struct,
|
||||
}
|
||||
|
||||
sg_range_from_slice :: proc(s: []$T) -> sg.Range {
|
||||
return {
|
||||
ptr = raw_data(s),
|
||||
size = len(s) * size_of(T),
|
||||
}
|
||||
}
|
||||
|
||||
sg_range_from_struct :: proc(s: ^$T) -> sg.Range where intrinsics.type_is_struct(T) {
|
||||
return {
|
||||
ptr = s,
|
||||
size = size_of(T),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue