diff options
author | omnisci3nce <omniscient.oce@gmail.com> | 2024-07-17 23:12:42 +1000 |
---|---|---|
committer | omnisci3nce <omniscient.oce@gmail.com> | 2024-07-17 23:12:42 +1000 |
commit | c3737fff1be704e14a2bada69bbf8a6709c5f670 (patch) | |
tree | aa2225901f26598b07855a65a944354fbedc40b1 | |
parent | f8641a5cc4c8baf1f0a7be3685afc219d90143d9 (diff) |
wip shader layouts for common stuff
-rw-r--r-- | .gitignore | 5 | ||||
-rw-r--r-- | assets/shaders/pbr_textured.vert | 16 | ||||
-rw-r--r-- | assets/shaders/skybox.vert | 11 | ||||
-rw-r--r-- | examples/game_demo/game_demo.c | 38 | ||||
-rw-r--r-- | src/core/core.c | 2 | ||||
-rw-r--r-- | src/maths/primitives.c | 2 | ||||
-rw-r--r-- | src/new_render/pbr.c | 82 | ||||
-rw-r--r-- | src/new_render/pbr.h | 20 | ||||
-rw-r--r-- | src/new_render/render.c | 57 | ||||
-rw-r--r-- | src/new_render/render.h | 4 | ||||
-rw-r--r-- | src/new_render/render_types.h | 37 | ||||
-rw-r--r-- | src/new_render/shader_layouts.h | 55 | ||||
-rw-r--r-- | src/new_render/shadows.c | 21 | ||||
-rw-r--r-- | src/new_render/shadows.h | 6 | ||||
-rw-r--r-- | src/new_render/skybox.c | 61 | ||||
-rw-r--r-- | src/new_render/skybox.h | 46 | ||||
-rw-r--r-- | src/ral/backends/opengl/backend_opengl.c | 18 | ||||
-rw-r--r-- | src/ral/ral_impl.h | 1 | ||||
-rw-r--r-- | src/ral/ral_types.h | 8 | ||||
-rw-r--r-- | src/render/ral.h | 184 | ||||
-rw-r--r-- | src/render/render_types.h | 181 | ||||
-rw-r--r-- | src/resources/gltf.c | 8 | ||||
-rw-r--r-- | src/resources/loaders.h | 4 | ||||
-rw-r--r-- | src/std/mem.c | 2 |
24 files changed, 430 insertions, 439 deletions
@@ -7,4 +7,7 @@ _temp .clangd .DS_Store compile_commands.json -node_modules/
\ No newline at end of file +node_modules/ + +# in case we accidentally use something not licensed properly, we will keep demo game assets ignored. +assets/demo/ diff --git a/assets/shaders/pbr_textured.vert b/assets/shaders/pbr_textured.vert index d0f8fd5..391cef3 100644 --- a/assets/shaders/pbr_textured.vert +++ b/assets/shaders/pbr_textured.vert @@ -5,12 +5,14 @@ layout(location = 0) in vec3 inPosition; layout(location = 1) in vec3 inNormal; layout(location = 2) in vec2 inTexCoords; -// Uniforms -uniform MVP_Matrices { - mat4 model; // TODO: make model a push constant/raw uniform +uniform Camera { mat4 view; mat4 proj; -} mvp; +} cam; + +uniform Model { + mat4 inner; +} model; // Outputs layout(location = 0) out vec3 fragWorldPos; @@ -18,9 +20,9 @@ layout(location = 1) out vec3 fragNormal; layout(location = 2) out vec2 fragTexCoords; void main() { - fragWorldPos = vec3(mvp.model * vec4(inPosition, 1.0)); - fragNormal = mat3(transpose(inverse(mvp.model))) * inNormal; // world-space normal + fragWorldPos = vec3(model.inner * vec4(inPosition, 1.0)); + fragNormal = mat3(transpose(inverse(model.inner))) * inNormal; // world-space normal fragTexCoords = inTexCoords; - gl_Position = mvp.proj * mvp.view * mvp.model * vec4(inPosition, 1.0); + gl_Position = cam.proj * cam.view * model.inner * vec4(inPosition, 1.0); } diff --git a/assets/shaders/skybox.vert b/assets/shaders/skybox.vert new file mode 100644 index 0000000..e9149d8 --- /dev/null +++ b/assets/shaders/skybox.vert @@ -0,0 +1,11 @@ +#version 410 core + +layout(location = 0) in vec3 inPos; + +uniform In { + vec3 textureDir; +} inc; + +void main() { + +}
\ No newline at end of file diff --git a/examples/game_demo/game_demo.c b/examples/game_demo/game_demo.c index ef72cc6..10dd2be 100644 --- a/examples/game_demo/game_demo.c +++ b/examples/game_demo/game_demo.c @@ -6,7 +6,10 @@ #include <assert.h> #include "camera.h" #include "core.h" +#include "loaders.h" #include "maths.h" +#include "primitives.h" +#include "ral_types.h" #include "render.h" #include "render_scene.h" #include "render_types.h" @@ -15,9 +18,9 @@ #include "terrain.h" #include "transform_hierarchy.h" -static const char* faces[6] = { "assets/demo/skybox/left.jpg", "assets/demo/skybox/right.jpg", - "assets/demo/skybox/front.jpg", "assets/demo/skybox/back.jpg", - "assets/demo/skybox/top.jpg", "assets/demo/skybox/bottom.jpg" }; +static const char* faces[6] = { "assets/demo/skybox/right.jpg", "assets/demo/skybox/left.jpg", + "assets/demo/skybox/top.jpg", "assets/demo/skybox/bottom.jpg", + "assets/demo/skybox/back.jpg", "assets/demo/skybox/front.jpg" }; int main() { Core_Bringup(); @@ -44,11 +47,34 @@ int main() { // assert(Terrain_IsActive()); // --- Skybox - // Skybox skybox = Skybox_Create(faces, 6); + Skybox skybox = Skybox_Create(faces, 6); // --- Models - // ModelHandle player_model = ModelLoad("Player Model", "assets/demo/player.gltf"); + // ModelHandle player_model = ModelLoad_gltf("Player Model", "assets/demo/player.gltf"); // ModelHandle sword_model = ModelLoad("Sword Model", "assets/demo/sword.gltf"); + // create a wooden crate + Geometry cube_geo = Geo_CreateCuboid(f32x3(2.0, 2.0, 2.0)); + Mesh crate_mesh = Mesh_Create(&cube_geo, false); // dont free as we may use later + TextureHandle albedo_map = TextureLoadFromFile("assets/demo/crate/Wood_Crate_001_basecolor.jpg"); + TextureHandle roughness_map = + TextureLoadFromFile("assets/demo/crate/Wood_Crate_001_roughness.jpg"); + TextureHandle normal_map = TextureLoadFromFile("assets/demo/crate/Wood_Crate_001_normal.jpg"); + TextureHandle ao_map = + TextureLoadFromFile("assets/demo/crate/Wood_Crate_001_ambientOcclusion.jpg"); + Material crate_mat = { .name = "Wood_Crate", + .kind = MAT_PBR, + .metal_roughness_combined = true, + .pbr_albedo_map = albedo_map, + .pbr_metallic_map = roughness_map, + .pbr_normal_map = normal_map, + .pbr_ao_map = ao_map }; + + RenderEnt crate_renderable = { + .mesh = &crate_mesh, .material = &crate_mat, .affine = mat4_ident(), .casts_shadows = true + }; + + RenderEnt entities[] = { crate_renderable }; + size_t entity_count = 1; // --- Transforms // TransformHierarchy* scene_tree = TransformHierarchy_Create(); @@ -65,7 +91,7 @@ int main() { // BEGIN Draw calls // draw the player model with shadows - // Render_RenderEntities(entities, 1); + Render_RenderEntities(entities, entity_count); // Render_DrawTerrain(); // Skybox_Draw(&skybox); diff --git a/src/core/core.c b/src/core/core.c index de67b56..9945083 100644 --- a/src/core/core.c +++ b/src/core/core.c @@ -44,7 +44,7 @@ void Core_Bringup() { size_t model_data_max = 1024 * 1024 * 1024; arena model_arena = arena_create(malloc(model_data_max), model_data_max); - // model_pool model_pool = model_pool_create(&model_arena, 256, sizeof(model)); + Model_pool model_pool = Model_pool_create(&model_arena, 256, sizeof(Model)); // g_core.models = model_pool; // INFO("Created model pool allocator"); diff --git a/src/maths/primitives.c b/src/maths/primitives.c index e74afcb..04977a6 100644 --- a/src/maths/primitives.c +++ b/src/maths/primitives.c @@ -62,7 +62,7 @@ static const Vec3 FRONT_BOT_RIGHT = (Vec3){ 1, 0, 1 }; static const Vec3 FRONT_TOP_LEFT = (Vec3){ 0, 1, 1 }; static const Vec3 FRONT_TOP_RIGHT = (Vec3){ 1, 1, 1 }; -Geometry geo_create_cuboid(f32x3 extents) { +Geometry Geo_CreateCuboid(f32x3 extents) { Vertex_darray* vertices = Vertex_darray_new(36); // back faces diff --git a/src/new_render/pbr.c b/src/new_render/pbr.c new file mode 100644 index 0000000..b1ca005 --- /dev/null +++ b/src/new_render/pbr.c @@ -0,0 +1,82 @@ +#include "pbr.h" +#include "file.h" +#include "log.h" +#include "ral_common.h" +#include "ral_impl.h" +#include "ral_types.h" +#include "shader_layouts.h" + +void PBR_Init(PBR_Storage* storage) { + INFO("PBR shaders init"); + storage->pbr_pass = PBR_RPassCreate(); + storage->pbr_pipeline = PBR_PipelineCreate(storage->pbr_pass); +} + +GPU_Renderpass* PBR_RPassCreate() { + GPU_RenderpassDesc desc = { .default_framebuffer = true }; + return GPU_Renderpass_Create(desc); +} + +GPU_Pipeline* PBR_PipelineCreate(GPU_Renderpass* rpass) { + arena scratch = arena_create(malloc(1024 * 1024), 1024 * 1024); + + Str8 vert_path = str8("assets/shaders/pbr_textured.vert"); + Str8 frag_path = str8("assets/shaders/pbr_textured.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 camera_data = { .get_layout = &Binding_Camera_GetLayout }; + ShaderData model_data = { .get_layout = &Binding_Model_GetLayout }; + ShaderData material_data = { .get_layout = &PBRMaterial_GetLayout }; + + GraphicsPipelineDesc desc = { + .debug_name = "PBR Pipeline", + .vertex_desc = static_3d_vertex_description(), + .data_layouts = {camera_data,model_data,material_data}, + .data_layouts_count = 3, + .vs = { .debug_name = "PBR (textured) Vertex Shader", + .filepath = vert_path, + .code = vertex_shader.contents }, + .fs = { .debug_name = "PBR (textured) Fragment Shader", + .filepath = frag_path, + .code = fragment_shader.contents, + }, + .depth_test = true, + .wireframe = false, + }; + return GPU_GraphicsPipeline_Create(desc, rpass); +} + +ShaderDataLayout PBRMaterial_GetLayout(void* data) { + PBRMaterialUniforms* d = (PBRMaterialUniforms*)data; + bool has_data = data != NULL; + + ShaderBinding b1 = { + .label = "albedoMap", + .kind = BINDING_TEXTURE, + }; + ShaderBinding b2 = { + .label = "metallicRoughnessMap", + .kind = BINDING_TEXTURE, + }; + ShaderBinding b3 = { + .label = "aoMap", + .kind = BINDING_TEXTURE, + }; + ShaderBinding b4 = { + .label = "normalMap", + .kind = BINDING_TEXTURE, + }; + + if (has_data) { + b1.data.texture.handle = d->mat.pbr_albedo_map; + b2.data.texture.handle = d->mat.pbr_metallic_map; + b3.data.texture.handle = d->mat.pbr_ao_map; + b4.data.texture.handle = d->mat.pbr_normal_map; + } + + return (ShaderDataLayout){ .bindings = { b1, b2, b3, b4 }, .binding_count = 4 }; +}
\ No newline at end of file diff --git a/src/new_render/pbr.h b/src/new_render/pbr.h index 7573563..4ee6810 100644 --- a/src/new_render/pbr.h +++ b/src/new_render/pbr.h @@ -4,16 +4,23 @@ */ #pragma once +#include "backend_opengl.h" #include "defines.h" #include "camera.h" #include "maths_types.h" -#include "ral/ral.h" -#include "ral/ral_common.h" - -// PBR; +#include "ral_types.h" +#include "render_types.h" // --- Public API -typedef struct PBR_Storage PBR_Storage; // Stores all necessary data and handles +typedef struct PBR_Storage { + GPU_Renderpass* pbr_pass; + GPU_Pipeline* pbr_pipeline; + +} PBR_Storage; // Stores all necessary data and handles + +typedef struct PBRMaterialUniforms { + Material mat; +} PBRMaterialUniforms; PUB void PBR_Init(PBR_Storage* storage); @@ -45,7 +52,6 @@ typedef struct PBR_Textures { // --- Internal typedef struct MaterialMap MaterialMap; -typedef struct RenderEnt RenderEnt; GPU_Renderpass* PBR_RPassCreate(); GPU_Pipeline* PBR_PipelineCreate(GPU_Renderpass* rpass); @@ -59,4 +65,4 @@ void PBR_Execute( ); -// Internally this will need to update material parameters +ShaderDataLayout PBRMaterial_GetLayout(void* data);
\ No newline at end of file diff --git a/src/new_render/render.c b/src/new_render/render.c index 1fef610..1213f1d 100644 --- a/src/new_render/render.c +++ b/src/new_render/render.c @@ -18,6 +18,9 @@ #include "render_types.h" #include "shadows.h" +#define STB_IMAGE_IMPLEMENTATION +#include <stb_image.h> + extern Core g_core; struct Renderer { @@ -91,6 +94,9 @@ bool Renderer_Init(RendererConfig config, Renderer* ren, GLFWwindow** out_window ren->shadows = malloc(sizeof(Shadow_Storage)); Shadow_Init(ren->shadows, u32x2(512, 512)); + ren->pbr = malloc(sizeof(PBR_Storage)); + PBR_Init(ren->pbr); + return true; } @@ -118,13 +124,50 @@ void Render_RenderEntities(RenderEnt* entities, size_t entity_count) { Renderer* ren = get_renderer(); 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); + // TOOD: -- 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); +} + +TextureData TextureDataLoad(const char* path, bool invert_y) { + TRACE("Load texture %s", path); + + // load the file data + int width, height, num_channels; + stbi_set_flip_vertically_on_load(invert_y); + +#pragma GCC diagnostic ignored "-Wpointer-sign" + char* data = stbi_load(path, &width, &height, &num_channels, STBI_rgb_alpha); + if (data) { + DEBUG("loaded texture: %s", path); + } else { + WARN("failed to load texture"); + } + + unsigned int channel_type; + GPU_TextureFormat format; + if (num_channels == 4) { + channel_type = GL_RGBA; + format = TEXTURE_FORMAT_8_8_8_8_RGBA_UNORM; + } else { + channel_type = GL_RGB; + format = TEXTURE_FORMAT_8_8_8_RGB_UNORM; + } + TextureDesc desc = { .extents = { width, height }, + .format = format, + .tex_type = TEXTURE_TYPE_2D }; + + return (TextureData){ .description = desc, .image_data = data }; +} + +TextureHandle TextureLoadFromFile(const char* path) { + TextureData tex_data = TextureDataLoad(path, false); + TextureHandle h = GPU_TextureCreate(tex_data.description, true, tex_data.image_data); + return h; } Mesh Mesh_Create(Geometry* geometry, bool free_on_upload) { diff --git a/src/new_render/render.h b/src/new_render/render.h index fa05fec..de84eda 100644 --- a/src/new_render/render.h +++ b/src/new_render/render.h @@ -41,7 +41,9 @@ PUB void Render_RenderEntities(RenderEnt* entities, size_t entity_count); // --- Resources -PUB TextureHandle TextureUpload(); +PUB TextureData TextureDataLoad(const char* path, bool invert_y); +PUB void TextureUpload(TextureHandle handle, size_t n_bytes, const void* data); +PUB TextureHandle TextureLoadFromFile(const char* path); PUB ModelHandle ModelLoad(const char* debug_name, const char* filepath); // --- Rendering Data diff --git a/src/new_render/render_types.h b/src/new_render/render_types.h index 81cf1c3..376e512 100644 --- a/src/new_render/render_types.h +++ b/src/new_render/render_types.h @@ -30,6 +30,7 @@ typedef struct Mesh { BufferHandle vertex_buffer; BufferHandle index_buffer; Geometry* geometry; // NULL means it has been freed CPU-side + i32 material_index; // -1 => no material bool is_uploaded; // has the data been uploaded to the GPU } Mesh; #ifndef TYPED_MESH_ARRAY @@ -44,8 +45,8 @@ typedef struct TextureData { // --- Supported materials typedef enum MaterialKind { - MAT_BLINN_PHONG, - MAT_PBR, + MAT_BLINN_PHONG, // NOTE: we're dropping support for this + MAT_PBR, // uses textures for PBR properties MAT_PBR_PARAMS, // uses float values to represent a surface uniformly MAT_COUNT } MaterialKind; @@ -54,13 +55,35 @@ static const char* material_kind_names[] = { "Blinn Phong", "PBR (Textures)", "P typedef struct Material { char name[64]; + MaterialKind kind; + // parameterised pbr + Vec3 param_albedo; + f32 param_metallic; + f32 param_roughness; + f32 param_ao; + // textured pbr + TextureHandle pbr_albedo_map; + TextureHandle pbr_normal_map; + bool metal_roughness_combined; + TextureHandle pbr_metallic_map; + TextureHandle pbr_roughness_map; + TextureHandle pbr_ao_map; } Material; +#ifndef TYPED_MATERIAL_ARRAY +KITC_DECL_TYPED_ARRAY(Material) +#define TYPED_MATERIAL_ARRAY +#endif typedef struct Model { + Str8 name; // meshes Mesh_darray* meshes; - // materials + Material_darray* materials; } Model; +#ifndef TYPED_MODEL_ARRAY +KITC_DECL_TYPED_ARRAY(Model) +#define TYPED_MODEL_ARRAY +#endif // TODO: function to create a model from a single mesh (like when using primitives) @@ -84,8 +107,14 @@ typedef struct DirectionalLight { // A renderable 'thing' typedef struct RenderEnt { - ModelHandle model; + Mesh* mesh; + Material* material; Mat4 affine; // In the future this should be updated by the transform graph // Bbox_3D bounding_box; bool casts_shadows; } RenderEnt; + +#ifndef TYPED_RENDERENT_ARRAY +KITC_DECL_TYPED_ARRAY(RenderEnt) +#define TYPED_RENDERENT_ARRAY +#endif
\ No newline at end of file diff --git a/src/new_render/shader_layouts.h b/src/new_render/shader_layouts.h index d1ed1cc..e34e790 100644 --- a/src/new_render/shader_layouts.h +++ b/src/new_render/shader_layouts.h @@ -1,3 +1,58 @@ #pragma once #include "maths_types.h" #include "ral_types.h" + +/** @brief shader layout for camera matrices */ +typedef struct Binding_Camera { + Mat4 view; + Mat4 projection; +} Binding_Camera; + +typedef struct Binding_Model { + Mat4 model; +} Binding_Model; + +/** @brief data that is handy to have in any shader */ +typedef struct Binding_Globals { + +} Binding_Globals; + +typedef struct pbr_point_light { + Vec3 pos; + f32 pad; + Vec3 color; + f32 pad2; +} pbr_point_light; + +typedef struct Binding_PointLights { + pbr_point_light pointLights[4]; + Vec4 viewPos; +} Binding_PointLights; + +static ShaderDataLayout Binding_Camera_GetLayout(void* data) { + Binding_Camera* d = data; + bool has_data = data != NULL; + + ShaderBinding b1 = { + .label = "Camera", + .kind = BINDING_BYTES + }; + if (has_data) { + b1.data.bytes.data = d; + } + return (ShaderDataLayout) {.bindings = {b1 }, .binding_count = 1}; +} + +static ShaderDataLayout Binding_Model_GetLayout(void* data) { + Binding_Model* d = data; + bool has_data = data != NULL; + + ShaderBinding b1 = { + .label = "Model", + .kind = BINDING_BYTES + }; + if (has_data) { + b1.data.bytes.data = d; + } + return (ShaderDataLayout) {.bindings = {b1 }, .binding_count = 1}; +}
\ No newline at end of file diff --git a/src/new_render/shadows.c b/src/new_render/shadows.c index 612fd34..24bfb57 100644 --- a/src/new_render/shadows.c +++ b/src/new_render/shadows.c @@ -11,11 +11,6 @@ #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; @@ -102,19 +97,15 @@ void Shadow_ShadowmapExecute(Shadow_Storage* storage, Mat4 light_space_transform 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); + // 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); - } + Mesh* mesh = renderable.mesh; + 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); } } diff --git a/src/new_render/shadows.h b/src/new_render/shadows.h index 4dc20e2..9e8a6ad 100644 --- a/src/new_render/shadows.h +++ b/src/new_render/shadows.h @@ -5,7 +5,6 @@ #pragma once #include "defines.h" -#include "ral.h" #include "ral_impl.h" #include "ral_types.h" #include "render_types.h" @@ -18,6 +17,11 @@ typedef struct Shadow_Storage { // TODO: Some statistics tracking } Shadow_Storage; +typedef struct ShadowUniforms { + Mat4 light_space; + Mat4 model; +} ShadowUniforms; + typedef struct Camera Camera; typedef struct Mat4 Mat4; diff --git a/src/new_render/skybox.c b/src/new_render/skybox.c new file mode 100644 index 0000000..6afefc3 --- /dev/null +++ b/src/new_render/skybox.c @@ -0,0 +1,61 @@ +#include "skybox.h" +#include <assert.h> +#include "glad/glad.h" +#include "ral_common.h" +#include "ral_impl.h" +#include "ral_types.h" +#include "render.h" +#include "render_types.h" + +Skybox Skybox_Create(const char** face_paths, int n) { + assert(n == 6); // ! we're only supporting a full cubemap for now + + // -- cubemap texture + TextureHandle handle; + GPU_Texture* tex = GPU_TextureAlloc(&handle); + glBindTexture(GL_TEXTURE_CUBE_MAP, tex->id); + + int width, height, nrChannels; + // unsigned char *data; + for (unsigned int i = 0; i < n; i++) { + TextureData data = TextureDataLoad( + face_paths[i], + false); // stbi_load(textures_faces[i].c_str(), &width, &height, &nrChannels, 0); + assert(data.description.format == TEXTURE_FORMAT_8_8_8_RGB_UNORM); + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, data.description.extents.x, + data.description.extents.y, 0, GL_RGB, GL_UNSIGNED_BYTE, data.image_data); + } + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + + // shader pipeline + + VertexDescription pos_only = { .debug_label = "Position only verts" }; + VertexDesc_AddAttr(&pos_only, "inPos", ATTR_F32x3); + pos_only.use_full_vertex_size = true; + + ShaderData shader_data = { .data = NULL, .get_layout = &Skybox_GetLayout }; + + GraphicsPipelineDesc pipeline_desc = { + .debug_name = "Skybox pipeline", + .vertex_desc = pos_only, + .data_layouts = { shader_data }, + .data_layouts_count = 1, + .vs = { + + }, + .fs = { + + }, + .wireframe = false, + .depth_test = true, + }; + + return (Skybox){ + .texture = handle, + + }; +}
\ No newline at end of file diff --git a/src/new_render/skybox.h b/src/new_render/skybox.h index 9bdc2ec..ec06658 100644 --- a/src/new_render/skybox.h +++ b/src/new_render/skybox.h @@ -7,20 +7,6 @@ #include "defines.h" #include "ral_types.h" -typedef struct CubeMapData { - void* top_image_data; - void* bottom_image_data; - void* left_image_data; - void* right_image_data; - void* front_image_data; - void* back_image_data; - u32 width, height, num_channels; -} CubeMapData; - -PUB void CubeMapData_Load(const char** face_paths, int n); // should always pass n = 6 for now -PUB void CubeMapData_Free(CubeMapData* cubemap); // Frees all the image data for a cubemap -PUB TextureHandle CubeMapData_Upload(CubeMapData* cubemap); - typedef struct Skybox { BufferHandle vertex_buffer; TextureHandle texture; @@ -30,3 +16,35 @@ typedef struct Skybox { PUB Skybox Skybox_Create(const char** face_paths, int n); // should always pass n = 6 for now PUB void Skybox_Draw(Skybox* skybox); + +typedef struct SkyboxUniforms { + Vec3 in_pos; + TextureHandle cubemap; +} SkyboxUniforms; + +static ShaderDataLayout Skybox_GetLayout(void* data) { + SkyboxUniforms* d = (SkyboxUniforms*)data; // cold cast + bool has_data = data != NULL; + + ShaderBinding b1 = { + .label = "In", + .vis = VISIBILITY_VERTEX, + .kind = BINDING_BYTES, + .data = {.bytes = {.size = sizeof(Vec3)}} + }; + + ShaderBinding b2 = { + .label = "cubemap", + .vis = VISIBILITY_FRAGMENT, + .kind = BINDING_SAMPLER, + }; + + if (has_data) { + b1.data.bytes.data = &d->in_pos; + b2.data.texture.handle = d->cubemap; + } + return (ShaderDataLayout) { + .bindings = { b1, b2}, + .binding_count = 2 + }; +}
\ No newline at end of file diff --git a/src/ral/backends/opengl/backend_opengl.c b/src/ral/backends/opengl/backend_opengl.c index cbfd855..ecf0e80 100644 --- a/src/ral/backends/opengl/backend_opengl.c +++ b/src/ral/backends/opengl/backend_opengl.c @@ -174,7 +174,7 @@ BufferHandle GPU_BufferCreate(u64 size, GPU_BufferType buf_type, GPU_BufferFlags const void* data) { // "allocating" the cpu-side buffer struct BufferHandle handle; - GPU_Buffer* buffer = Buffer_pool_alloc(&context.resource_pools, &handle); + GPU_Buffer* buffer = Buffer_pool_alloc(&context.resource_pools->buffers, &handle); buffer->size = size; buffer->vao = 0; @@ -269,6 +269,22 @@ TextureHandle GPU_TextureCreate(TextureDesc desc, bool create_view, const void* return handle; } +GPU_Texture* GPU_TextureAlloc(TextureHandle* out_handle) { + TextureHandle handle; + GPU_Texture* texture = Texture_pool_alloc(&context.resource_pools->textures, &handle); + DEBUG("Allocated texture with handle %d", handle.raw); + + GLuint gl_texture_id; + glGenTextures(1, &gl_texture_id); + texture->id = gl_texture_id; + + if (out_handle != NULL) { + *out_handle = handle; + } + + return texture; +} + void GPU_TextureDestroy(TextureHandle handle) { glDeleteTextures(1, &handle.raw); } // TODO: void GPU_TextureUpload(TextureHandle handle, size_t n_bytes, const void* data) diff --git a/src/ral/ral_impl.h b/src/ral/ral_impl.h index 7cc9459..9343962 100644 --- a/src/ral/ral_impl.h +++ b/src/ral/ral_impl.h @@ -52,6 +52,7 @@ PUB void GPU_BufferUpload(BufferHandle buffer, size_t n_bytes, const void* data) // --- Textures PUB TextureHandle GPU_TextureCreate(TextureDesc desc, bool create_view, const void* data); +PUB GPU_Texture* GPU_TextureAlloc(TextureHandle* out_handle); PUB void GPU_TextureDestroy(TextureHandle handle); PUB void GPU_TextureUpload(TextureHandle handle, size_t n_bytes, const void* data); diff --git a/src/ral/ral_types.h b/src/ral/ral_types.h index ffcc2cd..092bb2b 100644 --- a/src/ral/ral_types.h +++ b/src/ral/ral_types.h @@ -55,6 +55,7 @@ typedef enum GPU_TextureType { typedef enum GPU_TextureFormat { TEXTURE_FORMAT_8_8_8_8_RGBA_UNORM, + TEXTURE_FORMAT_8_8_8_RGB_UNORM, TEXTURE_FORMAT_DEPTH_DEFAULT, TEXTURE_FORMAT_COUNT } GPU_TextureFormat; @@ -144,6 +145,11 @@ typedef struct VertexDescription { } VertexDescription; // --- Shaders +typedef enum PipelineKind { + PIPELINE_GRAPHICS, + PIPELINE_COMPUTE, +} PipelineKind; + typedef enum ShaderVisibility { VISIBILITY_VERTEX = 1 << 0, VISIBILITY_FRAGMENT = 1 << 1, @@ -164,7 +170,7 @@ typedef enum ShaderBindingKind { BINDING_BUFFER_ARRAY, BINDING_TEXTURE, BINDING_TEXTURE_ARRAY, - // TODO: sampler + BINDING_SAMPLER, BINDING_COUNT } ShaderBindingKind; diff --git a/src/render/ral.h b/src/render/ral.h deleted file mode 100644 index fc3c96c..0000000 --- a/src/render/ral.h +++ /dev/null @@ -1,184 +0,0 @@ -/** - * @file ral.h - * @author your name (you@domain.com) - * @brief Render Abstraction Layer - * @details API that a graphics backend *must* implement - * @version 0.1 - * @date 2024-03-31 - * - * @copyright Copyright (c) 2024 - * - */ -#pragma once - -#include "buf.h" -#include "defines.h" -#include "mem.h" -#include "ral_types.h" -#include "str.h" - -// Unrelated forward declares -struct GLFWwindow; - -// Forward declare structs - these must be defined in the backend implementation -typedef struct gpu_swapchain gpu_swapchain; -typedef struct gpu_device gpu_device; -typedef struct gpu_pipeline_layout gpu_pipeline_layout; -typedef struct gpu_pipeline gpu_pipeline; -typedef struct gpu_renderpass gpu_renderpass; -typedef struct gpu_cmd_encoder gpu_cmd_encoder; // Recording -typedef struct gpu_cmd_buffer gpu_cmd_buffer; // Ready for submission -typedef struct gpu_buffer gpu_buffer; -typedef struct gpu_texture gpu_texture; - -// #define MAX_SHADER_DATA_LAYOUTS 5 -// #define MAX_BUFFERS 256 -// #define MAX_TEXTURES 256 -// #define MAX_PIPELINES 128 -// #define MAX_RENDERPASSES 128 - -// TYPED_POOL(gpu_buffer, buffer); -// TYPED_POOL(gpu_texture, texture); - -// TYPED_POOL(gpu_pipeline_layout, pipeline_layout); -// TYPED_POOL(gpu_pipeline, pipeline); -// TYPED_POOL(gpu_renderpass, renderpass); - -// // --- Handy macros -// #define BUFFER_GET(h) (buffer_pool_get(&context.resource_pools->buffers, h)) -// #define TEXTURE_GET(h) (texture_pool_get(&context.resource_pools->textures, h)) - -// --- Pools -// typedef struct gpu_backend_pools { -// pipeline_pool pipelines; -// pipeline_layout_pool pipeline_layouts; -// renderpass_pool renderpasses; -// } gpu_backend_pools; -// void backend_pools_init(arena* a, gpu_backend_pools* backend_pools); - -// struct resource_pools { -// buffer_pool buffers; -// texture_pool textures; -// }; -// void resource_pools_init(arena* a, struct resource_pools* res_pools); - -// --- Pipeline description -typedef enum pipeline_kind { - PIPELINE_GRAPHICS, - PIPELINE_COMPUTE, -} pipeline_kind; - -typedef struct shader_desc { - const char* debug_name; - str8 filepath; // Where it came from - str8 code; // Either GLSL or SPIRV bytecode - bool is_spirv; - bool is_combined_vert_frag; // Contains both vertex and fragment stages -} shader_desc; - -shader_desc shader_quick_load(const char* filepath); -/** @brief Hot reloads shaders for the given pipeline. Returns how long it took in milliseconds */ -u64 gpu_pipeline_reload_shaders(gpu_pipeline* pipeline); // TODO - -struct graphics_pipeline_desc { - const char* debug_name; - vertex_description vertex_desc; - shader_desc vs; /** @brief Vertex shader stage */ - shader_desc fs; /** @brief Fragment shader stage */ - - // Roughly equivalent to a descriptor set layout each. each layout can have multiple bindings - // examples: - // - uniform buffer reprensenting view projection matrix - // - texture for shadow map - shader_data data_layouts[MAX_SHADER_DATA_LAYOUTS]; - u32 data_layouts_count; - - // gpu_pipeline_layout* layout; - gpu_renderpass* renderpass; - - bool wireframe; - bool depth_test; -}; - -typedef struct gpu_renderpass_desc { - bool default_framebuffer; - bool has_color_target; - texture_handle color_target; // for now only support one - bool has_depth_stencil; - texture_handle depth_stencil; -} gpu_renderpass_desc; - -// --- Lifecycle functions -// bool gpu_backend_init(const char* window_name, struct GLFWwindow* window); -// void gpu_backend_shutdown(); -void resource_pools_init(arena* a, struct resource_pools* res_pools); - -// bool gpu_device_create(gpu_device* out_device); -// void gpu_device_destroy(); - -// // --- Render Pipeline -// gpu_pipeline* gpu_graphics_pipeline_create(struct graphics_pipeline_desc description); -// void gpu_pipeline_destroy(gpu_pipeline* pipeline); - -// // --- Renderpass -// gpu_renderpass* gpu_renderpass_create(const gpu_renderpass_desc* description); -// void gpu_renderpass_destroy(gpu_renderpass* pass); - -// // --- Swapchain -// bool gpu_swapchain_create(gpu_swapchain* out_swapchain); -// void gpu_swapchain_destroy(gpu_swapchain* swapchain); - -// --- Command buffer -gpu_cmd_encoder gpu_cmd_encoder_create(); -void gpu_cmd_encoder_destroy(gpu_cmd_encoder* encoder); -void gpu_cmd_encoder_begin(gpu_cmd_encoder encoder); -void gpu_cmd_encoder_begin_render(gpu_cmd_encoder* encoder, gpu_renderpass* renderpass); -void gpu_cmd_encoder_end_render(gpu_cmd_encoder* encoder); -void gpu_cmd_encoder_begin_compute(); -gpu_cmd_encoder* gpu_get_default_cmd_encoder(); - -/** @brief Finish recording and return a command buffer that can be submitted to a queue */ -gpu_cmd_buffer gpu_cmd_encoder_finish(gpu_cmd_encoder* encoder); - -void gpu_queue_submit(gpu_cmd_buffer* buffer); - -// --- Data copy commands -/** @brief Copy data from one buffer to another */ -void encode_buffer_copy(gpu_cmd_encoder* encoder, buffer_handle src, u64 src_offset, - buffer_handle dst, u64 dst_offset, u64 copy_size); -/** @brief Upload CPU-side data as array of bytes to a GPU buffer */ -void buffer_upload_bytes(buffer_handle gpu_buf, bytebuffer cpu_buf, u64 offset, u64 size); - -/** @brief Copy data from buffer to buffer using a one time submit command buffer and a wait */ -void copy_buffer_to_buffer_oneshot(buffer_handle src, u64 src_offset, buffer_handle dst, - u64 dst_offset, u64 copy_size); -/** @brief Copy data from buffer to an image using a one time submit command buffer */ -void copy_buffer_to_image_oneshot(buffer_handle src, texture_handle dst); - -// --- Render commands -void encode_bind_pipeline(gpu_cmd_encoder* encoder, pipeline_kind kind, gpu_pipeline* pipeline); -void encode_bind_shader_data(gpu_cmd_encoder* encoder, u32 group, shader_data* data); -void encode_set_default_settings(gpu_cmd_encoder* encoder); -void encode_set_vertex_buffer(gpu_cmd_encoder* encoder, buffer_handle buf); -void encode_set_index_buffer(gpu_cmd_encoder* encoder, buffer_handle buf); -void encode_set_bind_group(); // TODO -void encode_draw(gpu_cmd_encoder* encoder, u64 count); -void encode_draw_indexed(gpu_cmd_encoder* encoder, u64 index_count); -void encode_clear_buffer(gpu_cmd_encoder* encoder, buffer_handle buf); - -// --- Buffers -// --- Vertex formats -bytebuffer vertices_as_bytebuffer(arena* a, vertex_format format, vertex_darray* vertices); - -void vertex_desc_add(vertex_description* builder, const char* name, vertex_attrib_type type); - -// --- TEMP -bool gpu_backend_begin_frame(); -void gpu_backend_end_frame(); -void gpu_temp_draw(size_t n_verts); - -// TODO: --- Compute - -// --- Helpers -vertex_description static_3d_vertex_description(); -size_t vertex_attrib_size(vertex_attrib_type attr); diff --git a/src/render/render_types.h b/src/render/render_types.h deleted file mode 100644 index b25fa14..0000000 --- a/src/render/render_types.h +++ /dev/null @@ -1,181 +0,0 @@ -/** - * @file render_types.h - * @author your name (you@domain.com) - * @brief - * @version 0.1 - * @date 2024-04-27 - * - * @copyright Copyright (c) 2024 - * - */ -#pragma once - -#include "colours.h" -#include "defines.h" -#include "ral.h" -#include "ral_types.h" -#if defined(CEL_PLATFORM_WINDOWS) -// #include "backend_dx11.h" -#endif -#if defined(CEL_REND_BACKEND_VULKAN) -#include "backend_vulkan.h" -#elif defined(CEL_REND_BACKEND_METAL) -#include "backend_metal.h" -#elif defined(CEL_REND_BACKEND_OPENGL) -#include "backend_opengl.h" -#endif - -struct GLFWwindow; - -typedef struct geometry_data { - vertex_format format; - vertex_darray* vertices; // TODO: make it not a pointer - bool has_indices; - u32_darray* indices; - rgba colour; /** Optional: set vertex colours */ -} geometry_data; - -typedef struct u32_opt { - u32 value; - bool has_value; -} u32_opt; - -// 'Upload' a geometry_data (to GPU) -> get back a mesh -typedef struct mesh { - buffer_handle vertex_buffer; - buffer_handle index_buffer; - geometry_data* geometry; // NULL means it has been freed - u32_opt material_index; - bool is_uploaded; - bool is_latent; -} mesh; - -#ifndef TYPED_MESH_ARRAY -KITC_DECL_TYPED_ARRAY(mesh) -#define TYPED_MESH_ARRAY -#endif - -/* Hot reloading: -C side - reload_model(): - - load model from disk using existing loader - - remove from transform graph so it isnt tried to be drawn -*/ - -typedef struct texture { -} texture; - -typedef struct texture_data { - texture_desc description; - void* image_data; -} texture_data; - -typedef enum material_kind { - MAT_BLINN_PHONG, - MAT_PBR, - MAT_PBR_PARAMS, // uses float values to represent a surface uniformly - MAT_COUNT -} material_kind; -static const char* material_kind_names[] = { "Blinn Phong", "PBR (Textures)", "PBR (Params)", - "Count (This should be an error)" }; - -typedef struct blinn_phong_material { - char name[256]; - texture diffuse_texture; - char diffuse_tex_path[256]; - texture specular_texture; - char specular_tex_path[256]; - vec3 ambient_colour; - vec3 diffuse; - vec3 specular; - f32 spec_exponent; - bool is_loaded; - bool is_uploaded; -} blinn_phong_material; -// typedef blinn_phong_material material; - -typedef struct pbr_parameters { - vec3 albedo; - f32 metallic; - f32 roughness; - f32 ao; -} pbr_parameters; - -typedef struct pbr_material { - texture_handle albedo_map; - texture_handle normal_map; - bool metal_roughness_combined; - texture_handle metallic_map; - texture_handle roughness_map; - texture_handle ao_map; -} pbr_material; - -typedef struct material { - material_kind kind; - union { - blinn_phong_material blinn_phong; - pbr_parameters pbr_params; - pbr_material pbr; - } mat_data; - char* name; -} material; - -#ifndef TYPED_MATERIAL_ARRAY -KITC_DECL_TYPED_ARRAY(material) -#define TYPED_MATERIAL_ARRAY -#endif - -CORE_DEFINE_HANDLE(model_handle); - -typedef struct model { - str8 name; - mesh_darray* meshes; - material_darray* materials; -} model; - -TYPED_POOL(model, model) - -// FIXME: the default blinn-phong material. MUST be initialised with the function below -// FIXME: extern material DEFAULT_MATERIAL; -void default_material_init(); - -#ifndef TYPED_MODEL_ARRAY -KITC_DECL_TYPED_ARRAY(model) -#define TYPED_MODEL_ARRAY -#endif - -#ifndef TYPED_ANIMATION_CLIP_ARRAY -#include "animation.h" -KITC_DECL_TYPED_ARRAY(animation_clip) -#define TYPED_ANIMATION_CLIP_ARRAY -#endif - -/** @brief Describes all the data required for the renderer to start executing draws */ -typedef struct render_entity { - /* buffer_handle index_buffer; */ - /* u32 index_count; */ - /* u32 index_offset; */ - /* buffer_handle vertex_buffer; */ - model_handle model; - transform tf; -} render_entity; - -#ifndef TYPED_RENDER_ENTITY_ARRAY -KITC_DECL_TYPED_ARRAY(render_entity) -#define TYPED_RENDER_ENTITY_ARRAY -#endif - -// --- Lights -typedef struct point_light { - vec3 position; - f32 constant, linear, quadratic; - vec3 ambient; - vec3 diffuse; - vec3 specular; -} point_light; - -typedef struct directional_light { - vec3 direction; - vec3 ambient; - vec3 diffuse; - vec3 specular; -} directional_light; diff --git a/src/resources/gltf.c b/src/resources/gltf.c index 69ae9e1..56d5660 100644 --- a/src/resources/gltf.c +++ b/src/resources/gltf.c @@ -50,10 +50,10 @@ ModelHandle model_load_gltf(const char *path, bool invert_texture_y) { const char *file_string = string_from_file(path); ModelHandle handle; - // Model *model = model_pool_alloc(&g_core.models, &handle); - // model->name = str8_cstr_view(path); - // model->meshes = mesh_darray_new(1); - // model->materials = material_darray_new(1); + Model *model = Model_pool_alloc(&g_core.models, &handle); + model->name = Str8_cstr_view(path); + model->meshes = Mesh_darray_new(1); + model->materials = Material_darray_new(1); // bool success = // model_load_gltf_str(file_string, path, relative_path.path, model, invert_texture_y); diff --git a/src/resources/loaders.h b/src/resources/loaders.h index 3ec41fa..677e2a7 100644 --- a/src/resources/loaders.h +++ b/src/resources/loaders.h @@ -5,8 +5,8 @@ #include "str.h" // --- Public API -PUB ModelHandle Model_Load_obj(const char *path, bool invert_texture_y); -PUB ModelHandle Model_Load_gltf(const char *path, bool invert_texture_y); +PUB ModelHandle ModelLoad_obj(const char *path, bool invert_texture_y); +PUB ModelHandle ModelLoad_gltf(const char *path, bool invert_texture_y); // --- Internal bool model_load_gltf_str(const char *file_string, const char *filepath, Str8 relative_path, diff --git a/src/std/mem.c b/src/std/mem.c index 5cc4304..4a4454a 100644 --- a/src/std/mem.c +++ b/src/std/mem.c @@ -93,7 +93,7 @@ void* void_pool_alloc(void_pool* pool, u32* out_raw_handle) { return NULL; } if (pool->free_list_head == NULL) { - ERROR("Pool is full (head = null)"); + ERROR("%s Pool is full (head = null)", pool->debug_label); return NULL; } void_pool_header* free_node = pool->free_list_head; |