diff options
author | Omni <omniscient.oce@gmail.com> | 2024-06-22 23:06:19 +1000 |
---|---|---|
committer | Omni <omniscient.oce@gmail.com> | 2024-06-22 23:06:19 +1000 |
commit | 39e7122b5cd1e0d56a4a7cfd3c4114032d14e9b6 (patch) | |
tree | b879e9796146f2a1d57cf9d44cfb3a6991b5d8cc | |
parent | a2b43f8f93365874ba46dfaacd59df9e197c32e7 (diff) |
creating shadowmap pipeline
-rw-r--r-- | assets/shaders/shadows.frag | 5 | ||||
-rw-r--r-- | assets/shaders/shadows.vert | 19 | ||||
-rw-r--r-- | examples/shadow_maps/ex_shadow_maps.c | 14 | ||||
-rw-r--r-- | src/renderer/backends/opengl/backend_opengl.c | 18 | ||||
-rw-r--r-- | src/renderer/renderpasses.c | 87 | ||||
-rw-r--r-- | src/renderer/renderpasses.h | 2 |
6 files changed, 134 insertions, 11 deletions
diff --git a/assets/shaders/shadows.frag b/assets/shaders/shadows.frag new file mode 100644 index 0000000..0876b66 --- /dev/null +++ b/assets/shaders/shadows.frag @@ -0,0 +1,5 @@ +#version 410 core + +void main() { + gl_FragDepth = gl_FragCoord.z; +}
\ No newline at end of file diff --git a/assets/shaders/shadows.vert b/assets/shaders/shadows.vert new file mode 100644 index 0000000..00b1a81 --- /dev/null +++ b/assets/shaders/shadows.vert @@ -0,0 +1,19 @@ +#version 410 core + +// Vertex attributes +layout(location = 0) in vec3 inPosition; +layout(location = 1) in vec3 inNormal; +layout(location = 2) in vec2 inTexCoords; + +// Uniforms +uniform Model { + mat4 mat; +}; + +uniform LightSpace { + mat4 mat; +}; + +void main() { + gl_Position = LightSpace.mat * Model.mat * vec4(inPosition, 1.0); +} diff --git a/examples/shadow_maps/ex_shadow_maps.c b/examples/shadow_maps/ex_shadow_maps.c index e4f7f8a..1423d7a 100644 --- a/examples/shadow_maps/ex_shadow_maps.c +++ b/examples/shadow_maps/ex_shadow_maps.c @@ -17,6 +17,11 @@ const vec3 pointlight_positions[4] = { }; point_light point_lights[4]; +/* + TODO: +- keyboard button to switch between main camera and light camera +*/ + int main() { core_bringup(); arena scratch = arena_create(malloc(1024 * 1024), 1024 * 1024); @@ -28,8 +33,13 @@ int main() { ren_shadowmaps shadows = { .width = 1000, .height = 1000 }; // ren_shadowmaps_init(&shadows); - // Meshes - mesh cubes[4]; + // Set up the scene + // We want: + // 1. a ground plane + // 2. lights + // 3. some boxes + + mesh scene[5]; for (int i = 0; i < 4; i++) { geometry_data geo = geo_create_cuboid(f32x3(2,2,2)); cubes[i] = mesh_create(&geo, true); diff --git a/src/renderer/backends/opengl/backend_opengl.c b/src/renderer/backends/opengl/backend_opengl.c index 8f52674..ea10acb 100644 --- a/src/renderer/backends/opengl/backend_opengl.c +++ b/src/renderer/backends/opengl/backend_opengl.c @@ -152,6 +152,11 @@ gpu_renderpass* gpu_renderpass_create(const gpu_renderpass_desc* description) { glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, depth_attachment->id, 0); } + if (description->has_depth_stencil && !description->has_color_target) { + glDrawBuffer(GL_NONE); + glReadBuffer(GL_NONE); + } + glBindFramebuffer(GL_FRAMEBUFFER, 0); // reset to default framebuffer return renderpass; @@ -336,6 +341,10 @@ texture_handle gpu_texture_create(texture_desc desc, bool create_view, const voi glBindTexture(GL_TEXTURE_2D, gl_texture_id); + GLint internal_format = desc.format == CEL_TEXTURE_FORMAT_DEPTH_DEFAULT ? GL_DEPTH_COMPONENT : GL_RGB; + GLenum format = desc.format == CEL_TEXTURE_FORMAT_DEPTH_DEFAULT ? GL_DEPTH_COMPONENT : GL_RGBA; + GLenum data_type = desc.format == CEL_TEXTURE_FORMAT_DEPTH_DEFAULT ? GL_FLOAT : GL_UNSIGNED_BYTE; + // set the texture wrapping parameters glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // set texture wrapping to GL_REPEAT (default wrapping method) @@ -345,12 +354,15 @@ texture_handle gpu_texture_create(texture_desc desc, bool create_view, const voi glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); if (data) { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, desc.extents.x, desc.extents.y, 0, - GL_RGBA, // TODO: convert format to GL enum - GL_UNSIGNED_BYTE, data); + glTexImage2D(GL_TEXTURE_2D, 0, internal_format, desc.extents.x, desc.extents.y, 0, + format, + data_type, data); glGenerateMipmap(GL_TEXTURE_2D); } else { WARN("No image data provided"); + glTexImage2D(GL_TEXTURE_2D, 0, internal_format, desc.extents.x, desc.extents.y, 0, + format, + data_type, NULL); } glBindTexture(GL_TEXTURE_2D, 0); diff --git a/src/renderer/renderpasses.c b/src/renderer/renderpasses.c index d28df3d..3f2152f 100644 --- a/src/renderer/renderpasses.c +++ b/src/renderer/renderpasses.c @@ -13,10 +13,15 @@ #include "maths_types.h" #include "ral.h" #include "ral_types.h" +#include "file.h" #define SHADOW_WIDTH 1000 #define SHADOW_HEIGHT 1000 +void ren_shadowmaps_init(ren_shadowmaps* storage) { + storage->rpass = shadowmaps_renderpass_create(); + storage->static_pipeline = shadowmaps_pipeline_create(storage->rpass); +} gpu_renderpass* shadowmaps_renderpass_create() { // Create depthmap texture @@ -37,11 +42,83 @@ gpu_renderpass* shadowmaps_renderpass_create() { return gpu_renderpass_create(&shadows_desc); } -gpu_pipeline* shadowmaps_pipeline_create() { - // struct graphics_pipeline_desc desc = { - // . - // }; - // gpu_graphics_pipeline_create(struct graphics_pipeline_desc description) +// == shader bindings +typedef struct model_uniform { + mat4 model; +} model_uniform; + +typedef struct lightspace_tf_uniform { + mat4 lightSpaceMatrix; +} lightspace_tf_uniform; + +shader_data_layout model_uniform_layout(void* data) { + bool has_data = data != NULL; + + shader_binding b1 = { + .label = "Model", + .type = SHADER_BINDING_BYTES, + .stores_data = has_data, + .data = {.bytes.size = sizeof(model_uniform)} + }; + if (has_data) { + b1.data.bytes.data = data; + } + return (shader_data_layout){ .name = "model_uniform", .bindings = {b1}, .bindings_count = 1}; +} +shader_data_layout lightspace_uniform_layout(void* data) { + bool has_data = data != NULL; + + shader_binding b1 = { + .label = "LightSpace", + .type = SHADER_BINDING_BYTES, + .stores_data = has_data, + .data = {.bytes.size = sizeof(lightspace_tf_uniform)} + }; + if (has_data) { + b1.data.bytes.data = data; + } + return (shader_data_layout){ .name = "lightspace_tf_uniform", .bindings = {b1}, .bindings_count = 1}; +} + +// ================== + +gpu_pipeline* shadowmaps_pipeline_create(gpu_renderpass* rpass) { + arena scratch = arena_create(malloc(1024 * 1024), 1024 * 1024); + + str8 vert_path = str8lit("assets/shaders/shadows.vert"); + str8 frag_path = str8lit("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"); + } + + // We'll have two data layouts. 1. for the light-space transform, and 2. for the model matrix + shader_data model_uniform = {.data = NULL, .shader_data_get_layout = &model_uniform_layout }; + shader_data lightspace_uniform = {.data = NULL, .shader_data_get_layout = &lightspace_uniform_layout }; + + struct graphics_pipeline_desc desc = { + .debug_name = "Shadowmap drawing pipeline", + .vertex_desc = static_3d_vertex_description(), + .data_layouts = { model_uniform, lightspace_uniform }, + .data_layouts_count = 2, + .vs = { + .debug_name = "Shadows Vert shader", + .filepath = vert_path, + .code = vertex_shader.contents, + .is_spirv = true + }, + .fs = { + .debug_name = "Shadows Frag shader", + .filepath = vert_path, + .code = vertex_shader.contents, + .is_spirv = true + }, + .renderpass = rpass + }; + + arena_free_storage(&scratch); + return gpu_graphics_pipeline_create(desc); } void renderpass_shadowmap_execute(gpu_renderpass* pass, render_entity* entities, size_t entity_count) { diff --git a/src/renderer/renderpasses.h b/src/renderer/renderpasses.h index 4a689e6..3ee3b6e 100644 --- a/src/renderer/renderpasses.h +++ b/src/renderer/renderpasses.h @@ -32,6 +32,6 @@ typedef struct ren_shadowmaps { void ren_shadowmaps_init(ren_shadowmaps* storage); gpu_renderpass* shadowmaps_renderpass_create(); -gpu_pipeline* shadowmaps_pipeline_create(); +gpu_pipeline* shadowmaps_pipeline_create(gpu_renderpass* rpass); void renderpass_shadowmap_execute(gpu_renderpass* pass, render_entity* entities, size_t entity_count); |