diff options
author | omniscient <17525998+omnisci3nce@users.noreply.github.com> | 2024-07-14 23:55:18 +1000 |
---|---|---|
committer | omniscient <17525998+omnisci3nce@users.noreply.github.com> | 2024-07-14 23:55:18 +1000 |
commit | b9315f9cb625db09c3c41d8adf5230a67510bef7 (patch) | |
tree | 8e02010d4e29c82ec9310b02b7924f4c8456ef6f /src/new_render | |
parent | 529a603128d5e9dc4701322f44961f165e2183e1 (diff) |
wip shadows
Diffstat (limited to 'src/new_render')
-rw-r--r-- | src/new_render/render.c | 117 | ||||
-rw-r--r-- | src/new_render/render_scene.h | 2 | ||||
-rw-r--r-- | src/new_render/render_types.h | 5 | ||||
-rw-r--r-- | src/new_render/shader_layouts.h | 3 | ||||
-rw-r--r-- | src/new_render/shadows.c | 125 | ||||
-rw-r--r-- | src/new_render/shadows.h | 13 |
6 files changed, 209 insertions, 56 deletions
diff --git a/src/new_render/render.c b/src/new_render/render.c index cfd0b11..21046ea 100644 --- a/src/new_render/render.c +++ b/src/new_render/render.c @@ -2,17 +2,18 @@ * @brief */ -#include <glfw3.h> #include "render.h" -#include "core.h" +#include <glfw3.h> #include "camera.h" #include "colours.h" +#include "core.h" #include "log.h" #include "maths.h" #include "maths_types.h" #include "pbr.h" #include "ral_common.h" #include "ral_impl.h" +#include "ral_types.h" #include "render_scene.h" #include "render_types.h" #include "shadows.h" @@ -35,30 +36,30 @@ struct Renderer { }; bool Renderer_Init(RendererConfig config, Renderer* ren) { - INFO("Renderer init"); + INFO("Renderer init"); - // init resource pools - DEBUG("Initialise GPU resource pools"); - arena pool_arena = arena_create(malloc(1024 * 1024), 1024 * 1024); - ren->resource_pools = arena_alloc(&pool_arena, sizeof(struct ResourcePools)); - ResourcePools_Init(&pool_arena, ren->resource_pools); + // init resource pools + DEBUG("Initialise GPU resource pools"); + arena pool_arena = arena_create(malloc(1024 * 1024), 1024 * 1024); + ren->resource_pools = arena_alloc(&pool_arena, sizeof(struct ResourcePools)); + ResourcePools_Init(&pool_arena, ren->resource_pools); // GLFW window creation // NOTE: all platforms use GLFW at the moment but thats subject to change glfwInit(); - #if defined(CEL_REND_BACKEND_OPENGL) - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); - #elif defined(CEL_REND_BACKEND_VULKAN) - glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); - #endif - - GLFWwindow* window = glfwCreateWindow(config.scr_width, config.scr_height, - config.window_name, NULL, NULL); +#if defined(CEL_REND_BACKEND_OPENGL) + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); +#elif defined(CEL_REND_BACKEND_VULKAN) + glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); +#endif + + GLFWwindow* window = + glfwCreateWindow(config.scr_width, config.scr_height, config.window_name, NULL, NULL); if (window == NULL) { ERROR("Failed to create GLFW window\n"); glfwTerminate(); @@ -76,7 +77,6 @@ bool Renderer_Init(RendererConfig config, Renderer* ren) { GPU_Device_Create(&ren->device); GPU_Swapchain_Create(&ren->swapchain); - // set up default scene Camera default_cam = Camera_Create(vec3(0.0, 2.0, 4.0), vec3_normalise(vec3(0.0, -2.0, -4.0)), VEC3_Y, 45.0); @@ -90,46 +90,57 @@ bool Renderer_Init(RendererConfig config, Renderer* ren) { return true; } -void Renderer_Shutdown(Renderer* renderer) { } +void Renderer_Shutdown(Renderer* ren) {} size_t Renderer_GetMemReqs() { return sizeof(Renderer); } -void Render_FrameBegin(Renderer *renderer) { - renderer->frame_aborted = false; - if (GPU_Backend) - +void Render_FrameBegin(Renderer* ren) { + ren->frame_aborted = false; + if (!GPU_Backend_BeginFrame()) { + ren->frame_aborted = true; + WARN("Frame aborted"); + return; + } } -void Render_FrameEnd(Renderer* renderer) { +void Render_FrameEnd(Renderer* ren) { + if (ren->frame_aborted) { + return; + } + GPU_CmdEncoder* enc = GPU_GetDefaultEncoder(); } void Render_RenderEntities(RenderEnt* entities, size_t entity_count) { - Renderer* ren = Core_GetRenderer(&g_core); - - GPU_CmdEncoder* enc = GPU_GetDefaultEncoder(); - // bind shadow - GPU_EncodeBindPipeline(enc, ren->shadows) - + Renderer* ren = Core_GetRenderer(&g_core); + RenderScene scene = ren->scene; + + // -- Shadows + f32 near_plane = 1.0, far_plane = 10.0; + Mat4 light_projection = mat4_orthographic(-10.0, 10.0, -10.0, 10.0, near_plane, far_plane); + Vec3 pos = vec3_negate(scene.sun.direction); + Mat4 light_view = mat4_look_at(pos, VEC3_ZERO, VEC3_Y); + Mat4 light_space_matrix = mat4_mult(light_view, light_projection); + Shadow_ShadowmapExecute(ren->shadows, light_space_matrix, entities, entity_count); } Mesh Mesh_Create(Geometry* geometry, bool free_on_upload) { - Mesh m = { 0 }; - - // Create and upload vertex buffer - size_t vert_bytes = geometry->vertices->len * sizeof(Vertex); - INFO("Creating vertex buffer with size %d (%d x %d)", vert_bytes, geometry->vertices->len, - sizeof(Vertex)); - m.vertex_buffer = GPU_BufferCreate(vert_bytes, BUFFER_VERTEX, BUFFER_FLAG_GPU, - geometry->vertices->data); - - // Create and upload index buffer - size_t index_bytes = geometry->indices->len * sizeof(u32); - INFO("Creating index buffer with size %d (len: %d)", index_bytes, geometry->indices->len); - m.index_buffer = GPU_BufferCreate(index_bytes, BUFFER_INDEX, BUFFER_FLAG_GPU, - geometry->indices->data); - - m.is_uploaded = true; - m.geometry = geometry; - if (free_on_upload) { - Geometry_Destroy(geometry); - } - return m; + Mesh m = { 0 }; + + // Create and upload vertex buffer + size_t vert_bytes = geometry->vertices->len * sizeof(Vertex); + INFO("Creating vertex buffer with size %d (%d x %d)", vert_bytes, geometry->vertices->len, + sizeof(Vertex)); + m.vertex_buffer = + GPU_BufferCreate(vert_bytes, BUFFER_VERTEX, BUFFER_FLAG_GPU, geometry->vertices->data); + + // Create and upload index buffer + size_t index_bytes = geometry->indices->len * sizeof(u32); + INFO("Creating index buffer with size %d (len: %d)", index_bytes, geometry->indices->len); + m.index_buffer = + GPU_BufferCreate(index_bytes, BUFFER_INDEX, BUFFER_FLAG_GPU, geometry->indices->data); + + m.is_uploaded = true; + m.geometry = geometry; + if (free_on_upload) { + Geometry_Destroy(geometry); + } + return m; } diff --git a/src/new_render/render_scene.h b/src/new_render/render_scene.h index 7591d8f..791e862 100644 --- a/src/new_render/render_scene.h +++ b/src/new_render/render_scene.h @@ -11,7 +11,7 @@ * Whenever you call draw functions you can think of this as an implicit parameter. */ typedef struct RenderScene { Camera camera; - PointLight light; + DirectionalLight sun; } RenderScene; // --- Public APIs diff --git a/src/new_render/render_types.h b/src/new_render/render_types.h index 1cf6c7e..81cf1c3 100644 --- a/src/new_render/render_types.h +++ b/src/new_render/render_types.h @@ -32,6 +32,10 @@ typedef struct Mesh { Geometry* geometry; // NULL means it has been freed CPU-side bool is_uploaded; // has the data been uploaded to the GPU } Mesh; +#ifndef TYPED_MESH_ARRAY +KITC_DECL_TYPED_ARRAY(Mesh) +#define TYPED_MESH_ARRAY +#endif typedef struct TextureData { TextureDesc description; @@ -54,6 +58,7 @@ typedef struct Material { typedef struct Model { // meshes + Mesh_darray* meshes; // materials } Model; diff --git a/src/new_render/shader_layouts.h b/src/new_render/shader_layouts.h new file mode 100644 index 0000000..d1ed1cc --- /dev/null +++ b/src/new_render/shader_layouts.h @@ -0,0 +1,3 @@ +#pragma once +#include "maths_types.h" +#include "ral_types.h" diff --git a/src/new_render/shadows.c b/src/new_render/shadows.c new file mode 100644 index 0000000..df836b4 --- /dev/null +++ b/src/new_render/shadows.c @@ -0,0 +1,125 @@ +#include <string.h> +#include "shadows.h" +#include "core.h" +#include "log.h" +#include "maths.h" +#include "ral_common.h" +#include "ral_impl.h" +#include "ral_types.h" +#include "render.h" +#include "render_scene.h" +#include "render_types.h" + +typedef struct ShadowUniforms { + Mat4 light_space; + Mat4 model; +} ShadowUniforms; + +ShaderDataLayout ShadowUniforms_GetLayout(void* data) { + ShadowUniforms* d = (ShadowUniforms*)data; + bool has_data = data != NULL; + + ShaderBinding b1 = { + .label = "ShadowUniforms", + .kind = BINDING_BYTES, + .vis = VISIBILITY_VERTEX, + .data = { .bytes = { .size = sizeof(ShadowUniforms) } } + // TODO: split this into two bindings so we can update model matrix independently + }; + + if (has_data) { + b1.data.bytes.data = data; + } + + return (ShaderDataLayout){ .binding_count = 1, .bindings = { b1 } }; +} + +void Shadow_Init(Shadow_Storage* storage, u32x2 shadowmap_extents) { + memset(storage, 0, sizeof(Shadow_Storage)); + arena scratch = arena_create(malloc(1024 * 1024), 1024 * 1024); + + TextureDesc depthmap_desc = { .extents = shadowmap_extents, + .format = TEXTURE_FORMAT_DEPTH_DEFAULT, + .tex_type = TEXTURE_TYPE_2D }; + TextureHandle depthmap = GPU_TextureCreate(depthmap_desc, false, NULL); + storage->depth_texture = depthmap; + + GPU_RenderpassDesc rpass_desc = { .default_framebuffer = false, + .has_color_target = false, + .has_depth_stencil = true, + .depth_stencil = depthmap }; + + storage->shadowmap_pass = GPU_Renderpass_Create(rpass_desc); + + Str8 vert_path = str8("assets/shaders/shadows.vert"); + Str8 frag_path = str8("assets/shaders/shadows.frag"); + str8_opt vertex_shader = str8_from_file(&scratch, vert_path); + str8_opt fragment_shader = str8_from_file(&scratch, frag_path); + if (!vertex_shader.has_value || !fragment_shader.has_value) { + ERROR_EXIT("Failed to load shaders from disk"); + } + + ShaderData uniforms = { .data = NULL, .get_layout = &ShadowUniforms_GetLayout }; + + GraphicsPipelineDesc pipeline_desc = { + .debug_name = "Shadows Pipeline", + .vertex_desc = static_3d_vertex_description(), + .data_layouts = { uniforms }, + .data_layouts_count = 1, + .vs = { .debug_name = "Shadows Vert shader", + .filepath = vert_path, + .code = vertex_shader.contents, + .is_spirv = false }, + .fs = { .debug_name = "Shadows Frag shader", + .filepath = frag_path, + .code = fragment_shader.contents, + .is_spirv = false }, + }; + storage->pipeline = GPU_GraphicsPipeline_Create(pipeline_desc, storage->shadowmap_pass); + + arena_free_storage(&scratch); +} + +void Shadow_ShadowmapExecute(Shadow_Storage* storage, Mat4 light_space_transform, + RenderEnt* entities, size_t entity_count) { + GPU_CmdEncoder shadow_encoder = GPU_CmdEncoder_Create(); + + GPU_CmdEncoder_BeginRender(&shadow_encoder, storage->shadowmap_pass); + DEBUG("Begin shadowmap renderpass"); + + GPU_EncodeBindPipeline(&shadow_encoder, storage->pipeline); + + ShadowUniforms uniforms = { + .light_space = light_space_transform, + .model = mat4_ident() // this will be overwritten for each Model + }; + ShaderData shader_data = { + .data = &uniforms, + .get_layout = &ShadowUniforms_GetLayout, + }; + + for (size_t ent_i = 0; ent_i < entity_count; ent_i++) { + RenderEnt renderable = entities[ent_i]; + if (renderable.casts_shadows) { + Model* model = MODEL_GET(renderable.model); + + uniforms.model = renderable.affine; // update the model transform + + size_t num_meshes = Mesh_darray_len(model->meshes); + for (u32 mesh_i = 0; mesh_i < num_meshes; mesh_i++) { + Mesh mesh = model->meshes->data[mesh_i]; + + GPU_EncodeBindShaderData(&shadow_encoder, 0, shader_data); + GPU_EncodeSetVertexBuffer(&shadow_encoder, mesh.vertex_buffer); + GPU_EncodeSetIndexBuffer(&shadow_encoder, mesh.index_buffer); + GPU_EncodeDrawIndexed(&shadow_encoder, mesh.geometry->indices->len); + } + } + } + + GPU_CmdEncoder_EndRender(&shadow_encoder); // end renderpass +} + +Handle Shadow_GetShadowMapTexture(Shadow_Storage* storage) { + return (Handle){ .raw = storage->depth_texture.raw }; +} diff --git a/src/new_render/shadows.h b/src/new_render/shadows.h index 82ded5c..81711de 100644 --- a/src/new_render/shadows.h +++ b/src/new_render/shadows.h @@ -6,9 +6,17 @@ #pragma once #include "defines.h" #include "ral.h" +#include "ral_impl.h" +#include "ral_types.h" #include "render_types.h" -typedef struct Shadow_Storage Shadow_Storage; +typedef struct Shadow_Storage { + GPU_Renderpass* shadowmap_pass; + GPU_Pipeline* pipeline; + bool debug_quad_enabled; + TextureHandle depth_texture; + // TODO: Some statistics tracking +} Shadow_Storage; typedef struct Camera Camera; typedef struct Mat4 Mat4; @@ -26,4 +34,5 @@ PUB Handle Shadow_GetShadowMapTexture(Shadow_Storage* storage); // --- Internal GPU_Renderpass* Shadow_RPassCreate(); // Creates the render pass GPU_Pipeline* Shadow_PipelineCreate(GPU_Renderpass* rpass); // Creates the pipeline -void Shadow_ShadowmapExecute(Shadow_Storage* storage, Mat4 light_space_transform, RenderEnt* entites, size_t entity_count); +void Shadow_ShadowmapExecute(Shadow_Storage* storage, Mat4 light_space_transform, RenderEnt* entities, size_t entity_count); +void Shadow_RenderDebugQuad(); |