Restructured passes
This commit is contained in:
290
renderer.odin
290
renderer.odin
@@ -18,7 +18,11 @@ Renderer :: struct {
|
||||
|
||||
pipeline: Pipeline,
|
||||
|
||||
active_camera: ^Camera,
|
||||
active_camera: ^Camera, // NOTE: SS - Hardcoded to 1 active camera. Split-screen is likely not possible due to this. Fix(?).
|
||||
|
||||
fullscreen_vertex_shader, fullscreen_fragment_shader: Shader,
|
||||
fullscreen_shader_program: Shader_Program,
|
||||
fullscreen_mesh: Mesh,
|
||||
}
|
||||
|
||||
Viewport :: struct {
|
||||
@@ -32,6 +36,11 @@ get_aspect_ratio :: proc(renderer: ^Renderer) -> f32 {
|
||||
return f32(viewport.width) / f32(viewport.height)
|
||||
}
|
||||
|
||||
Color :: union {
|
||||
RGB_Color,
|
||||
RGBA_Color,
|
||||
}
|
||||
|
||||
RGB_Color :: [3]u8
|
||||
RGBA_Color :: [4]u8
|
||||
|
||||
@@ -52,6 +61,40 @@ create :: proc(surface_ptr: rawptr) -> (^Renderer, bool) {
|
||||
fmt.printfln("Unhandled backend or no backend selected.")
|
||||
return nil, false
|
||||
}
|
||||
|
||||
{ // Create the fullscreen shaders, material and mesh.
|
||||
fs_vertex_shader, fs_vertex_shader_ok := create_shader(renderer, .Vertex, "fs_vertex.glsl")
|
||||
assert(fs_vertex_shader_ok)
|
||||
|
||||
fs_frag_shader, fs_frag_shader_ok := create_shader(renderer, .Fragment, "fs_frag.glsl")
|
||||
assert(fs_frag_shader_ok)
|
||||
|
||||
fs_program, fs_program_ok := create_shader_program(renderer, &fs_vertex_shader, &fs_frag_shader)
|
||||
assert(fs_program_ok)
|
||||
|
||||
fs_quad_mesh, fs_quad_mesh_created := create_mesh(
|
||||
renderer = renderer,
|
||||
layout = {
|
||||
{ "position", 2, size_of(f32), },
|
||||
},
|
||||
vertices = []f32 {
|
||||
-1, -1,
|
||||
1, -1,
|
||||
1, 1,
|
||||
-1, 1,
|
||||
},
|
||||
indices = []u32 {
|
||||
0, 1, 2,
|
||||
0, 2, 3,
|
||||
}
|
||||
)
|
||||
assert(fs_quad_mesh_created)
|
||||
|
||||
renderer.fullscreen_vertex_shader = fs_vertex_shader
|
||||
renderer.fullscreen_fragment_shader = fs_frag_shader
|
||||
renderer.fullscreen_shader_program = fs_program
|
||||
renderer.fullscreen_mesh = fs_quad_mesh
|
||||
}
|
||||
|
||||
return renderer, true
|
||||
}
|
||||
@@ -71,7 +114,7 @@ set_viewport :: proc(renderer: ^Renderer, x, y, width, height: u16) {
|
||||
}
|
||||
}
|
||||
|
||||
@(private="file") set_clear_color :: proc(renderer: ^Renderer, color: RGB_Color) {
|
||||
@(private="file") set_clear_color :: proc(renderer: ^Renderer, color: Color) {
|
||||
when RENDER_BACKEND_OPENGL {
|
||||
opengl_set_clear_color(renderer, color)
|
||||
}
|
||||
@@ -83,7 +126,7 @@ set_viewport :: proc(renderer: ^Renderer, x, y, width, height: u16) {
|
||||
}
|
||||
}
|
||||
|
||||
render_frame :: proc(renderer: ^Renderer) {
|
||||
render_frame :: proc(renderer: ^Renderer, texture_to_present: ^Texture, clear_color: Color) {
|
||||
if renderer.active_camera == nil {
|
||||
fmt.printfln("No active camera!")
|
||||
return
|
||||
@@ -92,100 +135,153 @@ render_frame :: proc(renderer: ^Renderer) {
|
||||
view_matrix, _ := get_camera_view_matrix(renderer.active_camera)
|
||||
projection_matrix, _ := get_camera_projection_matrix(renderer, renderer.active_camera)
|
||||
|
||||
pipeline := &renderer.pipeline
|
||||
|
||||
for i in 0 ..< pipeline.amount_of_scene_passes {
|
||||
execute_scene_pass(renderer, pipeline.scene_passes[i], view_matrix, projection_matrix)
|
||||
for i in 0 ..< renderer.pipeline.amount_of_passes {
|
||||
execute_pass(renderer, renderer.pipeline.passes[i], view_matrix, projection_matrix)
|
||||
}
|
||||
|
||||
if texture_to_present != nil { // Present.
|
||||
// Bind to the screen.
|
||||
bind_render_target(renderer, nil)
|
||||
|
||||
for i in 0 ..< pipeline.amount_of_post_processing_passes {
|
||||
execute_post_processing_pass(renderer, pipeline.post_processing_passes[i], view_matrix, projection_matrix)
|
||||
}
|
||||
// Disable depth
|
||||
apply_depth(renderer, false, false)
|
||||
|
||||
bind_render_target(renderer, nil) // Det görs ju här..
|
||||
|
||||
if pipeline.fullscreen_material != nil {
|
||||
if pipeline.fullscreen_material.texture != nil {
|
||||
activate_fullscreen_material(renderer)
|
||||
|
||||
if pipeline.fullscreen_mesh != nil {
|
||||
draw_mesh(pipeline.fullscreen_mesh)
|
||||
}
|
||||
else {
|
||||
log.warn("Renderer is missing a fullscreen-mesh.")
|
||||
}
|
||||
|
||||
deactivate_fullscreen_material(renderer)
|
||||
// Clear
|
||||
set_clear_color(renderer, clear_color)
|
||||
clear_screen(renderer, true, true)
|
||||
|
||||
// Create a temporary Material.
|
||||
mat := Material {
|
||||
shader_program = &renderer.fullscreen_shader_program,
|
||||
textures = {
|
||||
0 = texture_to_present,
|
||||
},
|
||||
texture_count = 1,
|
||||
}
|
||||
else {
|
||||
log.warn("Fullscreen-material does not have a texture.")
|
||||
}
|
||||
}
|
||||
else {
|
||||
log.warn("Renderer is missing a fullscreen-material.")
|
||||
}
|
||||
|
||||
// Activate.
|
||||
activate_fullscreen_material(renderer, &mat)
|
||||
defer deactivate_fullscreen_material(renderer)
|
||||
|
||||
// Draw.
|
||||
draw_mesh(&renderer.fullscreen_mesh)
|
||||
}
|
||||
|
||||
when RENDER_BACKEND_OPENGL {
|
||||
opengl_swap_buffers(renderer)
|
||||
}
|
||||
}
|
||||
|
||||
execute_scene_pass :: proc(renderer: ^Renderer, pass: ^Scene_Pass, view_matrix, projection_matrix: linalg.Matrix4x4f32) {
|
||||
// fmt.printfln("Rendering pass '%v' to output_rt %v.", pass.name, pass.output_rt)
|
||||
|
||||
// TODO: SS - Use 'pass.input_textures'
|
||||
execute_pass :: proc(renderer: ^Renderer, pass: ^Pass, view_matrix, projection_matrix: linalg.Matrix4x4f32) {
|
||||
// fmt.printfln("Executing pass '%v'.", pass.name)
|
||||
|
||||
assert(pass.output_rt != nil)
|
||||
bind_render_target(renderer, pass.output_rt)
|
||||
|
||||
should_write_depth := pass.output_rt.depth_texture != nil
|
||||
should_test_depth := should_write_depth
|
||||
should_clear_depth := should_write_depth
|
||||
|
||||
cc, has_clear_color := pass.clear_color.?
|
||||
if has_clear_color {
|
||||
set_clear_color(renderer, cc)
|
||||
}
|
||||
|
||||
should_clear_color := has_clear_color && pass.output_rt.color_texture != nil
|
||||
assert(renderer != nil)
|
||||
assert(pass != nil)
|
||||
|
||||
clear_screen(renderer, should_clear_color, should_clear_depth)
|
||||
apply_depth(renderer, should_test_depth, should_write_depth)
|
||||
switch &t in &pass.type {
|
||||
case Scene_Pass: {
|
||||
assert(t.output_rt != nil)
|
||||
bind_render_target(renderer, t.output_rt)
|
||||
|
||||
apply_blend_mode(renderer, pass.blend_mode)
|
||||
should_write_depth := t.output_rt.depth_texture != nil
|
||||
should_test_depth := should_write_depth
|
||||
should_clear_depth := should_write_depth
|
||||
|
||||
sort_draw_commands(renderer, pass)
|
||||
should_clear_color := true
|
||||
set_clear_color(renderer, RGBA_Color { 0, 0, 0, 0 })
|
||||
|
||||
for &dc in &pass.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)
|
||||
clear_screen(renderer, should_clear_color, should_clear_depth)
|
||||
apply_depth(renderer, should_test_depth, should_write_depth)
|
||||
|
||||
// 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
|
||||
apply_blend_mode(renderer, t.blend_mode)
|
||||
|
||||
// Scale.
|
||||
scale := linalg.matrix4_scale(dc.scale)
|
||||
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
|
||||
|
||||
activate_material(&dc.material, model_matrix, view_matrix, projection_matrix)
|
||||
|
||||
draw_mesh(&dc.mesh)
|
||||
}
|
||||
|
||||
model_matrix *= translation * rotation * scale
|
||||
// Clear the pass' draw-commands.
|
||||
clear(&t.draw_commands)
|
||||
|
||||
activate_material(&dc.material, model_matrix, view_matrix, projection_matrix)
|
||||
// TODO: SS - "Deactivate" the pass?
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
||||
draw_mesh(&dc.mesh)
|
||||
// TODO: SS - "Deactivate" the pass?
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: SS - "Deactivate" the pass.
|
||||
|
||||
// Clear the pass' draw-commands.
|
||||
clear(&pass.draw_commands)
|
||||
}
|
||||
|
||||
execute_post_processing_pass :: proc(renderer: ^Renderer, pass: ^Post_Processing_Pass, view_matrix, projection_matrix: linalg.Matrix4x4f32) {
|
||||
fmt.printfln("TODO: SS - Execute post-processing pass '%v'.", pass.name)
|
||||
execute_post_processing_node :: proc(renderer: ^Renderer, node: ^Post_Processing_Node, view_matrix, projection_matrix: linalg.Matrix4x4f32) {
|
||||
assert(renderer != nil)
|
||||
assert(node != nil)
|
||||
assert(node.program != nil)
|
||||
assert(node.output != nil)
|
||||
|
||||
assert(node.output != nil)
|
||||
bind_render_target(renderer, node.output)
|
||||
|
||||
apply_depth(renderer, false, false)
|
||||
clear_screen(renderer, true, false)
|
||||
|
||||
// fmt.printfln("TODO: SS - Execute post-processing node '%v' (VS: '%v', FS: '%v').", "NAME", node.program.vertex_shader.path, node.program.fragment_shader.path)
|
||||
|
||||
t: [MATERIAL_MAX_TEXTURES]^Texture
|
||||
t_count := u8(0)
|
||||
for input_texture, i in node.input {
|
||||
if i > MATERIAL_MAX_TEXTURES {
|
||||
break
|
||||
}
|
||||
|
||||
set_shader_value(node.program, input_texture, u8(i))
|
||||
t[i] = input_texture
|
||||
t_count += 1
|
||||
}
|
||||
|
||||
mat := Material {
|
||||
shader_program = node.program,
|
||||
textures = t,
|
||||
texture_count = t_count,
|
||||
}
|
||||
|
||||
activate_fullscreen_material(renderer, &mat)
|
||||
draw_mesh(&renderer.fullscreen_mesh)
|
||||
}
|
||||
|
||||
set_shader_value :: proc {
|
||||
set_shader_value_texture,
|
||||
}
|
||||
|
||||
set_shader_value_texture :: proc(program: ^Shader_Program, value: ^Texture, index: u8) {
|
||||
assert(program != nil)
|
||||
assert(value != nil)
|
||||
|
||||
when RENDER_BACKEND_OPENGL {
|
||||
opengl_set_shader_value_texture(program, value, index)
|
||||
}
|
||||
}
|
||||
|
||||
destroy :: proc(renderer: ^Renderer) {
|
||||
@@ -205,21 +301,6 @@ destroy :: proc(renderer: ^Renderer) {
|
||||
}
|
||||
}
|
||||
|
||||
@(private) activate_fullscreen_material :: proc(renderer: ^Renderer) {
|
||||
assert(renderer != nil)
|
||||
mat := renderer.pipeline.fullscreen_material
|
||||
when RENDER_BACKEND_OPENGL {
|
||||
opengl_activate_fullscreen_material(mat)
|
||||
}
|
||||
}
|
||||
|
||||
@(private) deactivate_fullscreen_material :: proc(renderer: ^Renderer) {
|
||||
assert(renderer != nil)
|
||||
when RENDER_BACKEND_OPENGL {
|
||||
opengl_deactivate_fullscreen_material()
|
||||
}
|
||||
}
|
||||
|
||||
@(private) draw_mesh :: proc(mesh: ^Mesh) {
|
||||
assert(mesh != nil)
|
||||
|
||||
@@ -293,24 +374,23 @@ distance_to_camera :: proc(camera: ^Camera, position: [3]f32) -> f32 {
|
||||
return linalg.distance(camera.position, position)
|
||||
}
|
||||
|
||||
@(private) bind_framebuffer :: proc(renderer: ^Renderer, rt: ^Render_Target) -> bool {
|
||||
// when RENDER_BACKEND_OPENGL {
|
||||
// return opengl_bind_framebuffer(renderer, rt)
|
||||
// }
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
@(private) bind_depth_texture :: proc(renderer: ^Renderer, rt: ^Render_Target) -> bool {
|
||||
// when RENDER_BACKEND_OPENGL {
|
||||
// return opengl_bind_depth_texture(renderer, rt)
|
||||
// }
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
@(private) bind_render_target :: proc(renderer: ^Renderer, rt: ^Render_Target) {
|
||||
when RENDER_BACKEND_OPENGL {
|
||||
opengl_bind_render_target(renderer, rt)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@(private) activate_fullscreen_material :: proc(renderer: ^Renderer, material: ^Material) { // TODO: SS - Maybe remove.
|
||||
assert(renderer != nil)
|
||||
when RENDER_BACKEND_OPENGL {
|
||||
opengl_activate_fullscreen_material(material)
|
||||
}
|
||||
}
|
||||
|
||||
@(private) deactivate_fullscreen_material :: proc(renderer: ^Renderer) { // TODO: SS - Maybe remove.
|
||||
assert(renderer != nil)
|
||||
when RENDER_BACKEND_OPENGL {
|
||||
opengl_deactivate_fullscreen_material()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user