Work on passes/pipeline, render targets
This commit is contained in:
225
renderer.odin
225
renderer.odin
@@ -1,5 +1,7 @@
|
||||
package renderer
|
||||
|
||||
import "core:slice"
|
||||
import "core:sort"
|
||||
import "core:math/linalg"
|
||||
import "core:fmt"
|
||||
import "core:log"
|
||||
@@ -75,9 +77,9 @@ set_viewport :: proc(renderer: ^Renderer, x, y, width, height: u16) {
|
||||
}
|
||||
}
|
||||
|
||||
@(private="file") clear_screen :: proc(renderer: ^Renderer, clear_depth: bool) {
|
||||
@(private="file") clear_screen :: proc(renderer: ^Renderer, clear_color: bool, clear_depth: bool) {
|
||||
when RENDER_BACKEND_OPENGL {
|
||||
opengl_clear_screen(renderer, clear_depth)
|
||||
opengl_clear_screen(renderer, clear_color, clear_depth)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,54 +89,103 @@ render_frame :: proc(renderer: ^Renderer) {
|
||||
return
|
||||
}
|
||||
|
||||
view_matrix, view_matrix_ok := get_camera_view_matrix(renderer.active_camera)
|
||||
assert(view_matrix_ok)
|
||||
projection_matrix, projection_matrix_ok := get_camera_projection_matrix(renderer, renderer.active_camera)
|
||||
assert(projection_matrix_ok)
|
||||
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_passes {
|
||||
pass := pipeline.passes[i]
|
||||
|
||||
set_clear_color(renderer, pass.clear_color)
|
||||
clear_screen(renderer, pass.should_clear_depth)
|
||||
enable_depth_testing(renderer, pass.should_test_depth)
|
||||
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..<pass.draw_command_count {
|
||||
command := &pass.draw_commands[i]
|
||||
for i in 0 ..< pipeline.amount_of_post_processing_passes {
|
||||
execute_post_processing_pass(renderer, pipeline.post_processing_passes[i], view_matrix, projection_matrix)
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
model_matrix := linalg.identity(linalg.Matrix4x4f32)
|
||||
if pipeline.fullscreen_mesh != nil {
|
||||
draw_mesh(pipeline.fullscreen_mesh)
|
||||
}
|
||||
else {
|
||||
log.warn("Renderer is missing a fullscreen-mesh.")
|
||||
}
|
||||
|
||||
// Translate.
|
||||
translation := linalg.matrix4_translate(command.position)
|
||||
|
||||
// Rotate.
|
||||
rot_x := linalg.matrix4_rotate(linalg.to_radians(command.rotation.x), [3]f32 { 1, 0, 0 })
|
||||
rot_y := linalg.matrix4_rotate(linalg.to_radians(command.rotation.y), [3]f32 { 0, 1, 0 })
|
||||
rot_z := linalg.matrix4_rotate(linalg.to_radians(command.rotation.z), [3]f32 { 0, 0, 1 })
|
||||
rotation := rot_z * rot_y * rot_x
|
||||
|
||||
// Scale.
|
||||
scale := linalg.matrix4_scale(command.scale)
|
||||
|
||||
model_matrix *= translation * rotation * scale
|
||||
|
||||
activate_material(&command.material, model_matrix, view_matrix, projection_matrix)
|
||||
|
||||
draw_mesh(&command.mesh)
|
||||
deactivate_fullscreen_material(renderer)
|
||||
}
|
||||
|
||||
// TODO: SS - "Deactivate" the pass.
|
||||
|
||||
// Clear the pass' draw-commands.
|
||||
pass.draw_command_count = 0
|
||||
else {
|
||||
log.warn("Fullscreen-material does not have a texture.")
|
||||
}
|
||||
}
|
||||
else {
|
||||
log.warn("Renderer is missing a fullscreen-material.")
|
||||
}
|
||||
|
||||
when RENDER_BACKEND_OPENGL {
|
||||
opengl_swap_buffers(renderer)
|
||||
}
|
||||
}
|
||||
|
||||
clear_screen(renderer, true)
|
||||
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'
|
||||
|
||||
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
|
||||
|
||||
clear_screen(renderer, should_clear_color, should_clear_depth)
|
||||
apply_depth(renderer, should_test_depth, should_write_depth)
|
||||
|
||||
apply_blend_mode(renderer, pass.blend_mode)
|
||||
|
||||
sort_draw_commands(renderer, pass)
|
||||
|
||||
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)
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
destroy :: proc(renderer: ^Renderer) {
|
||||
@@ -154,6 +205,21 @@ 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)
|
||||
|
||||
@@ -162,8 +228,89 @@ destroy :: proc(renderer: ^Renderer) {
|
||||
}
|
||||
}
|
||||
|
||||
@(private) enable_depth_testing :: proc(renderer: ^Renderer, enable: bool) {
|
||||
@(private) apply_depth :: proc(renderer: ^Renderer, test_depth, write_depth: bool) {
|
||||
when RENDER_BACKEND_OPENGL {
|
||||
opengl_enable_depth_testing(renderer, true)
|
||||
opengl_apply_depth(renderer, test_depth, write_depth)
|
||||
}
|
||||
}
|
||||
|
||||
@(private) apply_blend_mode :: proc(renderer: ^Renderer, blend_mode: Blend_Mode) {
|
||||
table := BLEND_FACTOR_TABLE
|
||||
|
||||
when RENDER_BACKEND_OPENGL {
|
||||
opengl_set_blending(renderer, blend_mode != .None, table[blend_mode])
|
||||
}
|
||||
}
|
||||
|
||||
@(private) sort_draw_commands :: proc(renderer: ^Renderer, pass: ^Scene_Pass) {
|
||||
switch pass.sort_mode {
|
||||
case .None: {}
|
||||
case .Back_To_Front: {
|
||||
slice.sort_by(
|
||||
pass.draw_commands[:],
|
||||
proc(i, j: Draw_Command) -> bool {
|
||||
assert(i.renderer != nil)
|
||||
assert(j.renderer != nil)
|
||||
assert(i.renderer == j.renderer)
|
||||
|
||||
active_camera := get_active_camera(i.renderer)
|
||||
if active_camera == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
i_dist := distance_to_camera(active_camera, i.position)
|
||||
j_dist := distance_to_camera(active_camera, j.position)
|
||||
|
||||
return i_dist > j_dist
|
||||
}
|
||||
)
|
||||
}
|
||||
case .Front_To_Back: {
|
||||
slice.sort_by(
|
||||
pass.draw_commands[:],
|
||||
proc(i, j: Draw_Command) -> bool {
|
||||
assert(i.renderer != nil)
|
||||
assert(j.renderer != nil)
|
||||
assert(i.renderer == j.renderer)
|
||||
|
||||
active_camera := get_active_camera(i.renderer)
|
||||
if active_camera == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
i_dist := distance_to_camera(active_camera, i.position)
|
||||
j_dist := distance_to_camera(active_camera, j.position)
|
||||
|
||||
return i_dist < j_dist
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
distance_to_camera :: proc(camera: ^Camera, position: [3]f32) -> f32 {
|
||||
assert(camera != nil)
|
||||
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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user