diff options
Diffstat (limited to 'src/new_render')
-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 |
10 files changed, 340 insertions, 49 deletions
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 |