summaryrefslogtreecommitdiff
path: root/archive/src/render/render.c
diff options
context:
space:
mode:
authoromniscient <17525998+omnisci3nce@users.noreply.github.com>2024-10-05 12:48:05 +1000
committeromniscient <17525998+omnisci3nce@users.noreply.github.com>2024-10-05 12:48:05 +1000
commitdfb6adbcbcc7d50b770b6d5ea82efdd8f8c32e25 (patch)
treea470b91a90716d7ea46fde53ed395449c24583a2 /archive/src/render/render.c
parent54354e32c6498cc7f8839ab4deb1208d37216cc5 (diff)
delete documentation workflow
Diffstat (limited to 'archive/src/render/render.c')
-rw-r--r--archive/src/render/render.c359
1 files changed, 359 insertions, 0 deletions
diff --git a/archive/src/render/render.c b/archive/src/render/render.c
new file mode 100644
index 0000000..af636a8
--- /dev/null
+++ b/archive/src/render/render.c
@@ -0,0 +1,359 @@
+/**
+ * @brief
+ */
+
+#include "render.h"
+#include <assert.h>
+#include <glfw3.h>
+#include <stdio.h>
+#include "camera.h"
+#include "core.h"
+#include "grid.h"
+#include "immdraw.h"
+#include "log.h"
+#include "maths.h"
+#include "maths_types.h"
+#include "mem.h"
+#include "pbr.h"
+#include "ral_common.h"
+#include "ral_impl.h"
+#include "ral_types.h"
+#include "render_types.h"
+#include "shadows.h"
+#include "terrain.h"
+
+#define STB_IMAGE_IMPLEMENTATION
+#include <stb_image.h>
+
+#define FRAME_ARENA_SIZE MB(1)
+#define POOL_SIZE_BYTES \
+ MB(10) // we will reserve 10 megabytes up front to store resource, mesh, and material pools
+#define MAX_MESHES 1024
+#define MAX_MATERIALS 256
+
+extern Core g_core;
+
+struct Renderer {
+ struct GLFWwindow* window;
+ RendererConfig config;
+ GPU_Device device;
+ GPU_Swapchain swapchain;
+ GPU_Renderpass* default_renderpass;
+ bool frame_aborted;
+ RenderMode render_mode;
+ RenderScene scene;
+ PBR_Storage* pbr;
+ Shadow_Storage* shadows;
+ Terrain_Storage* terrain;
+ Grid_Storage* grid;
+ Immdraw_Storage* immediate;
+ // Text_Storage* text;
+ ResourcePools* resource_pools;
+ Mesh_pool mesh_pool;
+ Material_pool material_pool;
+ arena frame_arena;
+ TextureHandle white_1x1;
+ TextureHandle black_1x1;
+};
+
+Renderer* get_renderer() { return g_core.renderer; }
+
+bool Renderer_Init(RendererConfig config, Renderer* ren, GLFWwindow** out_window,
+ GLFWwindow* optional_window) {
+ INFO("Renderer init");
+ ren->render_mode = RENDER_MODE_DEFAULT;
+
+ ren->frame_arena = arena_create(malloc(FRAME_ARENA_SIZE), FRAME_ARENA_SIZE);
+
+ // init resource pools
+ DEBUG("Initialise GPU resource pools");
+ arena pool_arena = arena_create(malloc(POOL_SIZE_BYTES), POOL_SIZE_BYTES);
+ ren->resource_pools = arena_alloc(&pool_arena, sizeof(struct ResourcePools));
+ ResourcePools_Init(&pool_arena, ren->resource_pools);
+ ren->mesh_pool = Mesh_pool_create(&pool_arena, MAX_MESHES, sizeof(Mesh));
+ ren->material_pool = Material_pool_create(&pool_arena, MAX_MATERIALS, sizeof(Material));
+
+ // GLFW window creation
+ GLFWwindow* window;
+ if (optional_window != NULL) {
+ INFO("GLFWwindow pointer was provided!!!! Skipping generic glfw init..");
+ window = optional_window;
+ } else {
+ INFO("No GLFWwindow provided - creating one");
+ // 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
+
+ window = glfwCreateWindow(config.scr_width, config.scr_height, config.window_name, NULL, NULL);
+ INFO("Window created");
+ if (window == NULL) {
+ ERROR("Failed to create GLFW window\n");
+ glfwTerminate();
+ return false;
+ }
+ }
+
+ ren->window = window;
+ *out_window = window;
+
+ glfwMakeContextCurrent(ren->window);
+
+ DEBUG("Set up GLFW window callbacks");
+ glfwSetWindowSizeCallback(window, Render_WindowSizeChanged);
+
+ // set the RAL backend up
+ if (!GPU_Backend_Init(config.window_name, window, ren->resource_pools)) {
+ return false;
+ }
+
+ 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);
+ SetCamera(default_cam);
+ DirectionalLight default_light = { /* TODO */ };
+ SetMainLight(default_light);
+
+ // create our renderpasses
+ ren->shadows = malloc(sizeof(Shadow_Storage));
+ Shadow_Init(ren->shadows, 1024, 1024);
+
+ ren->pbr = calloc(1, sizeof(PBR_Storage));
+ PBR_Init(ren->pbr);
+
+ ren->terrain = calloc(1, sizeof(Terrain_Storage));
+ Terrain_Init(ren->terrain);
+
+ // FIXME
+ // ren->grid = calloc(1, sizeof(Grid_Storage));
+ // Grid_Init(ren->grid);
+
+ ren->immediate = calloc(1, sizeof(Immdraw_Storage));
+ Immdraw_Init(ren->immediate);
+
+ // load default textures
+ ren->white_1x1 = TextureLoadFromFile("assets/textures/white1x1.png");
+ ren->black_1x1 = TextureLoadFromFile("assets/textures/black1x1.png");
+
+ return true;
+}
+
+void Renderer_Shutdown(Renderer* ren) {
+ free(ren->shadows);
+ DEBUG("Freed Shadows storage");
+ free(ren->pbr);
+ DEBUG("Freed PBR storage");
+ free(ren->terrain);
+ DEBUG("Freed Terrain storage");
+ free(ren->immediate);
+ DEBUG("Freed Immdraw storage");
+ arena_free_storage(&ren->frame_arena);
+ DEBUG("Freed frame allocator buffer");
+}
+size_t Renderer_GetMemReqs() { return sizeof(Renderer); }
+
+void Render_WindowSizeChanged(GLFWwindow* window, i32 new_width, i32 new_height) {
+ (void)window;
+ INFO("Window size changed callback");
+ // Renderer* ren = Core_GetRenderer(&g_core);
+ GPU_Swapchain_Resize(new_width, new_height);
+}
+
+void Render_FrameBegin(Renderer* ren) {
+ arena_free_all(&ren->frame_arena);
+ ren->frame_aborted = false;
+ if (!GPU_Backend_BeginFrame()) {
+ ren->frame_aborted = true;
+ WARN("Frame aborted");
+ return;
+ }
+}
+void Render_FrameEnd(Renderer* ren) {
+ if (ren->frame_aborted) {
+ return;
+ }
+
+ GPU_CmdEncoder* enc = GPU_GetDefaultEncoder();
+
+ GPU_Backend_EndFrame();
+}
+void Render_RenderEntities(RenderEnt* entities, size_t entity_count) {
+ Renderer* ren = get_renderer();
+ RenderScene scene = ren->scene;
+
+ // FUTURE: Depth pre-pass
+
+ Shadow_Storage* shadow_storage = Render_GetShadowStorage();
+ shadow_storage->enabled = false;
+ TextureHandle sun_shadowmap =
+ shadow_storage->enabled ? Shadow_GetShadowMapTexture(shadow_storage) : INVALID_TEX_HANDLE;
+
+ PBR_Execute(ren->pbr, scene.camera, sun_shadowmap, 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, 0);
+ if (data) {
+ DEBUG("loaded texture: %s", path);
+ } else {
+ WARN("failed to load texture");
+ }
+
+ // printf("width: %d height: %d num channels: %d\n", width, height, num_channels);
+
+ 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,
+ .num_channels = num_channels,
+ .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) {
+ 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
+ if (geometry->has_indices) {
+ 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; // clone geometry data and store on Mesh struct
+ if (free_on_upload) {
+ Geometry_Destroy(geometry);
+ }
+ return m;
+}
+
+void Geometry_Destroy(Geometry* geometry) {
+ if (geometry->indices) {
+ u32_darray_free(geometry->indices);
+ }
+ if (geometry->vertices) {
+ Vertex_darray_free(geometry->vertices);
+ }
+}
+PUB MeshHandle Mesh_Insert(Mesh* mesh) { return Mesh_pool_insert(Render_GetMeshPool(), mesh); }
+PUB MaterialHandle Material_Insert(Material* material) {
+ return Material_pool_insert(Render_GetMaterialPool(), material);
+}
+Mesh* Mesh_Get(MeshHandle handle) { return Mesh_pool_get(Render_GetMeshPool(), handle); }
+
+void Mesh_DebugPrint(Mesh* mesh) {
+ printf("Mesh %d vertices %d indices %d joints \n", mesh->geometry.vertices->len,
+ mesh->geometry.indices->len);
+}
+
+size_t ModelExtractRenderEnts(RenderEnt_darray* entities, ModelHandle model_handle, Mat4 affine,
+ RenderEntityFlags flags) {
+ Model* model = MODEL_GET(model_handle);
+ for (u32 i = 0; i < model->mesh_count; i++) {
+ Mesh* m = Mesh_pool_get(Render_GetMeshPool(), model->meshes[i]);
+ RenderEnt data = { .mesh = model->meshes[i],
+ .material = m->material,
+ .affine = affine,
+ // .bounding_box
+ .flags = flags };
+ RenderEnt_darray_push(entities, data);
+ }
+ return model->mesh_count; // how many RenderEnts we pushed
+}
+
+void SetCamera(Camera camera) { g_core.renderer->scene.camera = camera; }
+void SetMainLight(DirectionalLight light) { g_core.renderer->scene.sun = light; }
+
+arena* GetRenderFrameArena(Renderer* r) { return &r->frame_arena; }
+
+RenderScene* Render_GetScene() {
+ Renderer* ren = Core_GetRenderer(&g_core);
+ return &ren->scene;
+}
+
+Shadow_Storage* Render_GetShadowStorage() {
+ Renderer* ren = Core_GetRenderer(&g_core);
+ return ren->shadows;
+}
+
+Terrain_Storage* Render_GetTerrainStorage() {
+ Renderer* ren = Core_GetRenderer(&g_core);
+ return ren->terrain;
+}
+
+Grid_Storage* Render_GetGridStorage() {
+ Renderer* ren = Core_GetRenderer(&g_core);
+ return ren->grid;
+}
+
+Immdraw_Storage* Render_GetImmdrawStorage() {
+ Renderer* ren = Core_GetRenderer(&g_core);
+ return ren->immediate;
+}
+
+TextureHandle Render_GetWhiteTexture() {
+ Renderer* ren = Core_GetRenderer(&g_core);
+ return ren->white_1x1;
+}
+
+/** @return an arena allocator that gets cleared at the beginning of every render frame */
+arena* Render_GetFrameArena() {
+ Renderer* ren = Core_GetRenderer(&g_core);
+ return &ren->frame_arena;
+}
+
+Mesh_pool* Render_GetMeshPool() {
+ Renderer* ren = Core_GetRenderer(&g_core);
+ return &ren->mesh_pool;
+}
+Material_pool* Render_GetMaterialPool() {
+ Renderer* ren = Core_GetRenderer(&g_core);
+ return &ren->material_pool;
+}
+
+void Render_SetRenderMode(RenderMode mode) {
+ Renderer* ren = Core_GetRenderer(&g_core);
+ ren->render_mode = mode;
+}