Add outline pass to cubes

This commit is contained in:
Hugo Mårdbrink 2025-08-27 00:16:42 +02:00
parent 1852cf3a7f
commit 2ee22c118c
10 changed files with 425 additions and 108 deletions

View file

@ -20,6 +20,8 @@ import sa "../sokol/app"
import sh "../sokol/helpers"
import sg "../sokol/gfx"
import program_config "../config"
import shaders "../shaders/out"
VertexData :: struct {
@ -48,14 +50,46 @@ RenderSystem :: struct {
}
@(private)
init_grid_material :: proc(render_system: ^RenderSystem) {
shader := sg.make_shader(shaders.main_shader_desc(sg.query_backend()))
init_outline_material :: proc(render_system: ^RenderSystem) {
shader := sg.make_shader(shaders.outline_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 },
shaders.ATTR_outline_pos = { format = .FLOAT3 },
shaders.ATTR_outline_uv = { format = .FLOAT2 },
},
},
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,
},
})
sampler := sg.make_sampler({})
render_system.materials[.Outline] = Material{
shader = shader,
pipeline = pipeline,
sampler = sampler,
}
}
@(private)
init_cube_material :: proc(render_system: ^RenderSystem) {
shader := sg.make_shader(shaders.cube_shader_desc(sg.query_backend()))
pipeline := sg.make_pipeline({
shader = shader,
layout = {
attrs = {
shaders.ATTR_cube_pos = { format = .FLOAT3 },
shaders.ATTR_cube_uv = { format = .FLOAT2 },
},
},
index_type = .UINT16,
@ -93,7 +127,7 @@ init_grid_material :: proc(render_system: ^RenderSystem) {
sampler := sg.make_sampler({})
render_system.materials[.Grid] = Material{
render_system.materials[.Cube] = Material{
shader = shader,
pipeline = pipeline,
image = image,
@ -178,7 +212,9 @@ render_system_init :: proc(render_system: ^RenderSystem, camera_entity: EntityID
render_system.camera_entity = camera_entity
init_cube_mesh(render_system)
init_grid_material(render_system)
init_cube_material(render_system)
init_outline_material(render_system)
}
render_system_delete :: proc(render_system: ^RenderSystem, coordinator: ^Coordinator) {
@ -186,11 +222,16 @@ render_system_delete :: proc(render_system: ^RenderSystem, coordinator: ^Coordin
sg.destroy_buffer(cube_mesh.index_buffer)
sg.destroy_buffer(cube_mesh.vertex_buffer)
grid_material := render_system.materials[.Grid]
sg.destroy_image(grid_material.image)
sg.destroy_sampler(grid_material.sampler)
sg.destroy_pipeline(grid_material.pipeline)
sg.destroy_shader(grid_material.shader)
cube_material := render_system.materials[.Cube]
sg.destroy_image(cube_material.image)
sg.destroy_sampler(cube_material.sampler)
sg.destroy_pipeline(cube_material.pipeline)
sg.destroy_shader(cube_material.shader)
outline_material := render_system.materials[.Outline]
sg.destroy_sampler(outline_material.sampler)
sg.destroy_pipeline(outline_material.pipeline)
sg.destroy_shader(outline_material.shader)
delete(render_system.materials)
delete(render_system.meshes)
@ -198,24 +239,55 @@ render_system_delete :: proc(render_system: ^RenderSystem, coordinator: ^Coordin
sg.shutdown()
}
render_system_update :: proc(render_system: ^RenderSystem, coordinator: ^Coordinator, dt: f32) {
camera := coordinator_get_component(CameraComponent, coordinator, render_system.camera_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 } )
BACKGROUND_COLOR :: sg.Color{ 0, 0, 0, 1 }
CLEAR_SCREEN_ACTION :: sg.Pass_Action{
colors = {
0 = {
load_action = .CLEAR,
clear_value = BACKGROUND_COLOR,
}
@(private)
CLEAR_SCREEN_ACTION :: sg.Pass_Action{
colors = {
0 = {
load_action = .CLEAR,
clear_value = program_config.BACKGROUND_COLOR,
}
}
}
sg.begin_pass({ swapchain = sh.glue_swapchain(), action = CLEAR_SCREEN_ACTION })
outline_pass :: proc(render_system: ^RenderSystem, coordinator: ^Coordinator, proj: Mat4, view: Mat4) {
for entity in render_system.entities {
transform := coordinator_get_component(TransformComponent, coordinator, entity)
mesh_id := coordinator_get_component(MeshComponent, coordinator, entity).mesh_id
mesh := render_system.meshes[mesh_id]
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_bindings({
vertex_buffers = { 0 = mesh.vertex_buffer },
index_buffer = mesh.index_buffer,
})
sg.apply_uniforms(shaders.UB_VsParamsOutline, sg_range(&shaders.Vsparamsoutline{
mvp = mvp,
}))
sg.apply_uniforms(shaders.UB_FsParamsOutline, sg_range(&shaders.Fsparamsoutline{
col = program_config.BORDER_COLOR,
}))
sg.draw(0, 36, 1)
}
}
cube_pass :: proc(render_system: ^RenderSystem, coordinator: ^Coordinator, proj: Mat4, view: Mat4) {
for entity in render_system.entities {
transform := coordinator_get_component(TransformComponent, coordinator, entity)
@ -246,15 +318,26 @@ render_system_update :: proc(render_system: ^RenderSystem, coordinator: ^Coordin
index_buffer = mesh.index_buffer,
})
sg.apply_uniforms(shaders.UB_VsParams, sg_range(&shaders.Vsparams{
sg.apply_uniforms(shaders.UB_VsParamsCube, sg_range(&shaders.Vsparamscube{
mvp = mvp,
col = color.color,
}))
sg.draw(0, 36, 1)
}
}
render_system_update :: proc(render_system: ^RenderSystem, coordinator: ^Coordinator) {
camera := coordinator_get_component(CameraComponent, coordinator, render_system.camera_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 })
outline_pass(render_system, coordinator, proj, view)
cube_pass(render_system, coordinator, proj, view)
sg.end_pass()
sg.commit()
}