summaryrefslogtreecommitdiff
path: root/src/new_render
diff options
context:
space:
mode:
Diffstat (limited to 'src/new_render')
-rw-r--r--src/new_render/pbr.c82
-rw-r--r--src/new_render/pbr.h20
-rw-r--r--src/new_render/render.c57
-rw-r--r--src/new_render/render.h4
-rw-r--r--src/new_render/render_types.h37
-rw-r--r--src/new_render/shader_layouts.h55
-rw-r--r--src/new_render/shadows.c21
-rw-r--r--src/new_render/shadows.h6
-rw-r--r--src/new_render/skybox.c61
-rw-r--r--src/new_render/skybox.h46
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