Spheres/primitive built-in meshes, cull-modes, vec4 uniforms

This commit is contained in:
2026-02-05 00:17:33 +01:00
parent efa2c274f3
commit 3b32097c56
6 changed files with 510 additions and 172 deletions

155
pass.odin
View File

@@ -2,6 +2,7 @@ package renderer
import "core:math/linalg"
import "core:fmt"
import "core:log"
MAX_DRAW_COMMANDS_CAPACITY :: 4096
MAX_POST_PROCESS_NODES_PER_PASS :: 8
@@ -19,6 +20,7 @@ Pass_Type :: union {
Scene_Pass :: struct {
blend_mode: Blend_Mode,
sort_mode: Sort_Mode,
cull_mode: Cull_Mode,
draw_commands: [dynamic]Draw_Command, // Capacity is 'MAX_DRAW_COMMANDS_CAPACITY'.
@@ -31,10 +33,21 @@ Post_Processing_Pass :: struct {
Uniform :: union {
Uniform_Texture,
Uniform_Float,
Uniform_Float_Pointer,
Uniform_Matrix4f32,
Uniform_Matrix4f32_Pointer,
Uniform_Vector3,
Uniform_Vector3_Pointer,
Uniform_Vector4,
Uniform_Vector4_Pointer,
Uniform_Color,
Uniform_Color_Pointer,
}
Uniform_Texture :: struct {
@@ -43,21 +56,46 @@ Uniform_Texture :: struct {
}
Uniform_Float :: struct {
name: string,
value: f32,
}
Uniform_Float_Pointer :: struct {
name: string,
value: ^f32,
}
Uniform_Matrix4f32 :: struct {
name: string,
value: linalg.Matrix4f32,
}
Uniform_Matrix4f32_Pointer :: struct {
name: string,
value: ^linalg.Matrix4f32,
}
Uniform_Vector3 :: struct {
name: string,
value: [3]f32,
}
Uniform_Vector3_Pointer :: struct {
name: string,
value: ^[3]f32,
}
Uniform_Vector4 :: struct {
name: string,
value: [4]f32,
}
Uniform_Vector4_Pointer :: struct {
name: string,
value: ^[4]f32,
}
Uniform_Color :: struct {
name: string,
value: Color,
}
Uniform_Color_Pointer :: struct {
name: string,
value: ^Color,
}
@@ -69,16 +107,46 @@ Post_Processing_Node :: struct {
program: ^Shader_Program,
}
// TODO: SS - Create a pool of 'Draw_Command's and reuse them.
MAX_UNIFORMS_PER_DRAW_COMMAND :: 8
Draw_Command :: struct {
renderer: ^Renderer, // Needed for sorting.
mesh: Mesh,
material: Material,
uniforms: [MAX_UNIFORMS_PER_DRAW_COMMAND]Uniform,
uniform_count: u8,
position: [3]f32,
rotation: [3]f32,
scale: [3]f32,
}
create_draw_command :: proc(renderer: ^Renderer, mesh: Mesh, material: Material, uniforms: []Uniform, position, rotation, scale: [3]f32, loc := #caller_location) -> Draw_Command {
dc: Draw_Command
dc.renderer = renderer
dc.mesh = mesh
dc.material = material
dc.position = position
dc.rotation = rotation
dc.scale = scale
for u in uniforms {
if dc.uniform_count >= MAX_UNIFORMS_PER_DRAW_COMMAND {
log.warnf("Hit max capacity (%v) of uniforms per draw command! %v", MAX_UNIFORMS_PER_DRAW_COMMAND, loc)
break
}
dc.uniforms[dc.uniform_count] = u
dc.uniform_count += 1
}
return dc
}
Blend_Mode :: enum {
None,
Alpha,
@@ -117,10 +185,18 @@ Sort_Mode :: enum {
Front_To_Back, // Sorts the commands in the 'draw_commmands' array (from front to back) before drawing them.
}
Cull_Mode :: enum {
None,
Back,
Front,
Front_Back,
}
create_scene_pass :: proc(
name: string,
blend_mode: Blend_Mode,
sort_mode: Sort_Mode,
cull_mode: Cull_Mode,
output_rt: ^Render_Target,
) -> Pass
{
@@ -131,6 +207,7 @@ create_scene_pass :: proc(
p.type = Scene_Pass {
blend_mode = blend_mode,
sort_mode = sort_mode,
cull_mode = cull_mode,
draw_commands = make([dynamic]Draw_Command, 0, MAX_DRAW_COMMANDS_CAPACITY),
@@ -194,7 +271,83 @@ add_command_to_pass :: proc(renderer: ^Renderer, pass: ^Pass, command: Draw_Comm
assert(err == .None)
}
}
return true
}
execute_pass :: proc(renderer: ^Renderer, pass: ^Pass, view_matrix, projection_matrix: linalg.Matrix4x4f32) { // TODO: SS - Move to 'pass.odin'.
// fmt.printfln("Executing pass '%v'.", pass.name)
assert(renderer != nil)
assert(pass != nil)
switch &t in &pass.type {
case Scene_Pass: {
apply_polygon_mode(renderer, renderer.polygon_mode)
assert(t.output_rt != nil)
bind_render_target(renderer, t.output_rt)
defer bind_render_target(renderer, nil)
should_write_depth := t.output_rt.depth_texture != nil
should_test_depth := should_write_depth
should_clear_depth := should_write_depth
should_clear_color := true
set_clear_color(renderer, RGBA_Color { 0, 0, 0, 0 })
clear_screen(renderer, should_clear_color, should_clear_depth)
apply_depth(renderer, should_test_depth, should_write_depth)
apply_blend_mode(renderer, t.blend_mode)
defer apply_blend_mode(renderer, .None)
apply_cull_mode(renderer, t.cull_mode)
defer apply_cull_mode(renderer, .None)
sort_draw_commands(renderer, &t)
for &dc in &t.draw_commands { // TODO: SS - Don't think we need the address of the draw-commands.
model_matrix := linalg.identity(linalg.Matrix4x4f32)
// Translate.
translation := linalg.matrix4_translate(dc.position)
// Rotate.
rot_x := linalg.matrix4_rotate(linalg.to_radians(dc.rotation.x), [3]f32 { 1, 0, 0 })
rot_y := linalg.matrix4_rotate(linalg.to_radians(dc.rotation.y), [3]f32 { 0, 1, 0 })
rot_z := linalg.matrix4_rotate(linalg.to_radians(dc.rotation.z), [3]f32 { 0, 0, 1 })
rotation := rot_z * rot_y * rot_x
// Scale.
scale := linalg.matrix4_scale(dc.scale)
model_matrix *= translation * rotation * scale
// Apply uniforms.
activate_material(&dc.material, model_matrix, view_matrix, projection_matrix)
if dc.uniform_count > 0 {
set_shader_uniforms(dc.material.shader_program, dc.uniforms[:dc.uniform_count])
}
// Draw the mesh.
draw_mesh(&dc.mesh)
}
// Clear the pass' draw-commands.
clear(&t.draw_commands)
// TODO: SS - "Deactivate" the pass?
apply_polygon_mode(renderer, .Fill)
}
case Post_Processing_Pass: {
// Execute the post-processing nodes.
for &pp in &t.post_processing_nodes {
execute_post_processing_node(renderer, &pp, view_matrix, projection_matrix)
}
// TODO: SS - "Deactivate" the pass?
}
}
}