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 | |
parent | 529a603128d5e9dc4701322f44961f165e2183e1 (diff) |
wip shadows
-rw-r--r-- | src/animation.h | 14 | ||||
-rw-r--r-- | src/core/core.c | 7 | ||||
-rw-r--r-- | src/core/core.h | 15 | ||||
-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 | ||||
-rw-r--r-- | src/ral/ral_common.c | 24 | ||||
-rw-r--r-- | src/ral/ral_impl.h | 7 | ||||
-rw-r--r-- | src/ral/ral_types.h | 5 |
12 files changed, 249 insertions, 88 deletions
diff --git a/src/animation.h b/src/animation.h index 9c7faab..4371279 100644 --- a/src/animation.h +++ b/src/animation.h @@ -6,14 +6,14 @@ KITC_DECL_TYPED_ARRAY(f32) -// typedef enum interpolation { INTERPOLATION_LINEAR, INTERPOLATION_COUNT } interpolation; +typedef enum Interpolation { INTERPOLATION_LINEAR, INTERPOLATION_COUNT } Interpolation; -// typedef enum keyframe_kind { -// KEYFRAME_ROTATION, -// KEYFRAME_TRANSLATION, -// KEYFRAME_SCALE, -// KEYFRAME_WEIGHTS, -// } keyframe_kind; +typedef enum KeyframeKind { + KEYFRAME_ROTATION, + KEYFRAME_TRANSLATION, + KEYFRAME_SCALE, + KEYFRAME_WEIGHTS, +} KeyframeKind; // typedef union keyframe { // quat rotation; diff --git a/src/core/core.c b/src/core/core.c index 385479d..6ccd0d0 100644 --- a/src/core/core.c +++ b/src/core/core.c @@ -17,13 +17,6 @@ Core g_core; /** @brief global `Core` that other files can use */ -struct Core { - const char* app_name; - GLFWwindow* window; - Renderer* renderer; - Input_State input; -}; - /** @brief Gets the global `Core` singleton */ inline Core* GetCore() { return &g_core; } diff --git a/src/core/core.h b/src/core/core.h index 78dcd14..b0f8dbe 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -2,12 +2,25 @@ #include "input.h" #include "render_types.h" +#include "mem.h" #include "scene.h" #include "screenspace.h" #include "terrain.h" #include "text.h" -typedef struct Core Core; +TYPED_POOL(Model, Model) +#define MODEL_GET(h) (Model_pool_get(&g_core.models, h)) + +typedef struct GLFWwindow GLFWwindow; + +typedef struct Core { + const char* app_name; + GLFWwindow* window; + Renderer* renderer; + Input_State input; + Model_pool models; +} Core; +extern Core g_core; struct Renderer; 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(); diff --git a/src/ral/ral_common.c b/src/ral/ral_common.c index 8ff282e..35bf15f 100644 --- a/src/ral/ral_common.c +++ b/src/ral/ral_common.c @@ -19,23 +19,23 @@ void ResourcePools_Init(arena* a, struct ResourcePools* res_pools) { } VertexDescription static_3d_vertex_description() { - VertexDescription builder = { .debug_label = "Standard static 3d vertex format" }; - VertexDesc_AddAttr(&builder, "inPosition", ATTR_F32x3); - VertexDesc_AddAttr(&builder, "inNormal", ATTR_F32x3); - VertexDesc_AddAttr(&builder, "inTexCoords", ATTR_F32x2); - builder.use_full_vertex_size = true; - return builder; + VertexDescription builder = { .debug_label = "Standard static 3d vertex format" }; + VertexDesc_AddAttr(&builder, "inPosition", ATTR_F32x3); + VertexDesc_AddAttr(&builder, "inNormal", ATTR_F32x3); + VertexDesc_AddAttr(&builder, "inTexCoords", ATTR_F32x2); + builder.use_full_vertex_size = true; + return builder; } void VertexDesc_AddAttr(VertexDescription* builder, const char* name, VertexAttribType type) { - u32 i = builder->attributes_count; + u32 i = builder->attributes_count; - size_t size = VertexAttribSize(type); - builder->attributes[i] = type; - builder->stride += size; - builder->attr_names[i] = name; + size_t size = VertexAttribSize(type); + builder->attributes[i] = type; + builder->stride += size; + builder->attr_names[i] = name; - builder->attributes_count++; + builder->attributes_count++; } size_t VertexAttribSize(VertexAttribType attr) { diff --git a/src/ral/ral_impl.h b/src/ral/ral_impl.h index a896eff..3c3eaa5 100644 --- a/src/ral/ral_impl.h +++ b/src/ral/ral_impl.h @@ -8,6 +8,7 @@ #include "ral_types.h" struct GLFWwindow; +struct ResourcePools; // Forward declare structs - these must be defined in the backend implementation typedef struct GPU_Swapchain GPU_Swapchain; @@ -20,8 +21,6 @@ typedef struct GPU_CmdBuffer GPU_CmdBuffer; // Ready for submission typedef struct GPU_Buffer GPU_Buffer; typedef struct GPU_Texture GPU_Texture; -struct ResourcePools; - bool GPU_Backend_Init(const char* window_name, struct GLFWwindow* window, struct ResourcePools* res_pools); void GPU_Backend_Shutdown(); @@ -40,6 +39,8 @@ PUB void GraphicsPipeline_Destroy(GPU_Pipeline* pipeline); // --- Command buffer PUB GPU_CmdEncoder GPU_CmdEncoder_Create(); PUB void GPU_CmdEncoder_Destroy(GPU_CmdEncoder* encoder); +PUB void GPU_CmdEncoder_Begin(GPU_CmdEncoder* encoder); +PUB void GPU_CmdEncoder_Finish(GPU_CmdEncoder* encoder); PUB void GPU_CmdEncoder_BeginRender(GPU_CmdEncoder* encoder, GPU_Renderpass* renderpass); PUB void GPU_CmdEncoder_EndRender(GPU_CmdEncoder* encoder); PUB GPU_CmdEncoder* GPU_GetDefaultEncoder(); @@ -67,7 +68,7 @@ void copy_buffer_to_image_oneshot(BufferHandle src, TextureHandle dst); // --- Render commands PUB void GPU_EncodeBindPipeline(GPU_CmdEncoder* encoder, GPU_Pipeline* pipeline); -PUB void GPU_EncodeBindShaderData(GPU_CmdEncoder* encoder, u32 group, ShaderData* data); +PUB void GPU_EncodeBindShaderData(GPU_CmdEncoder* encoder, u32 group, ShaderData data); void GPU_EncodeSetDefaults(GPU_CmdEncoder* encoder); PUB void GPU_EncodeSetVertexBuffer(GPU_CmdEncoder* encoder, BufferHandle buf); PUB void GPU_EncodeSetIndexBuffer(GPU_CmdEncoder* encoder, BufferHandle buf); diff --git a/src/ral/ral_types.h b/src/ral/ral_types.h index 188951a..4470700 100644 --- a/src/ral/ral_types.h +++ b/src/ral/ral_types.h @@ -152,6 +152,7 @@ typedef enum ShaderVisibility { typedef struct ShaderDesc {} ShaderDesc; typedef enum ShaderBindingKind { + BINDING_BYTES, BINDING_BUFFER, BINDING_BUFFER_ARRAY, BINDING_TEXTURE, @@ -165,14 +166,14 @@ typedef struct ShaderBinding { ShaderBindingKind kind; ShaderVisibility vis; union { - struct { u32 size; } bytes; + struct { u32 size; void* data; } bytes; struct { BufferHandle handle; } buffer; struct { TextureHandle handle; } texture; } data; } ShaderBinding; typedef struct ShaderDataLayout { - ShaderBinding* bindings; + ShaderBinding bindings[MAX_SHADER_BINDINGS]; size_t binding_count; } ShaderDataLayout; |