diff options
author | omniscient <17525998+omnisci3nce@users.noreply.github.com> | 2024-07-21 17:48:00 +1000 |
---|---|---|
committer | omniscient <17525998+omnisci3nce@users.noreply.github.com> | 2024-07-21 17:48:00 +1000 |
commit | 66b1e02847e08b8e66e9969f0a3d138c15cc70f4 (patch) | |
tree | a598a4a1716fa985ab4359a60f6a2c93d2ee390b | |
parent | 9f1bfa75490bbdf22dd57ff17352d2736a0891fa (diff) |
terrain/hmap skeleton
-rw-r--r-- | assets/shaders/terrain.frag | 7 | ||||
-rw-r--r-- | assets/shaders/terrain.vert | 13 | ||||
-rw-r--r-- | examples/game_demo/game_demo.c | 11 | ||||
-rw-r--r-- | src/core/camera.c | 8 | ||||
-rw-r--r-- | src/new_render/render.c | 16 | ||||
-rw-r--r-- | src/new_render/render.h | 6 | ||||
-rw-r--r-- | src/new_render/shadows.c | 4 | ||||
-rw-r--r-- | src/ral/backends/opengl/backend_opengl.c | 2 | ||||
-rw-r--r-- | src/systems/terrain.c | 143 | ||||
-rw-r--r-- | src/systems/terrain.h | 24 |
10 files changed, 201 insertions, 33 deletions
diff --git a/assets/shaders/terrain.frag b/assets/shaders/terrain.frag new file mode 100644 index 0000000..5bce13b --- /dev/null +++ b/assets/shaders/terrain.frag @@ -0,0 +1,7 @@ +#version 410 core + +out vec4 FragColor; + +void main() { + FragColor = vec4(1.0); +}
\ No newline at end of file diff --git a/assets/shaders/terrain.vert b/assets/shaders/terrain.vert new file mode 100644 index 0000000..5af1560 --- /dev/null +++ b/assets/shaders/terrain.vert @@ -0,0 +1,13 @@ +#version 410 core + +layout(location = 0) in vec3 inPosition; + +uniform Camera { + mat4 view; + mat4 proj; + vec4 viewPos; +} cam; + +void main() { + gl_Position = cam.proj * cam.view * vec4(inPosition, 1.0); +}
\ No newline at end of file diff --git a/examples/game_demo/game_demo.c b/examples/game_demo/game_demo.c index 734bff1..9036fbe 100644 --- a/examples/game_demo/game_demo.c +++ b/examples/game_demo/game_demo.c @@ -16,6 +16,7 @@ #include "render_types.h" #include "shadows.h" #include "skybox.h" +#include "terrain.h" 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", @@ -31,7 +32,7 @@ int main() { // TODO: Move camera with model // --- Render Scene - Vec3 camera_pos = vec3(0.0, 4.0, -8.0); + Vec3 camera_pos = vec3(-8.0, 10.0, 0.); Camera cam = Camera_Create(camera_pos, vec3_normalise(vec3_negate(camera_pos)), VEC3_Y, 45.0); SetCamera(cam); // update the camera in RenderScene @@ -41,8 +42,9 @@ int main() { SetMainLight(sun); // --- Terrain - // Heightmap terrain = Heightmap_FromImage(str8("assets/demo/heightmap.png")); - // Terrain_LoadHeightmap(terrain, true); + Heightmap hmap = Heightmap_FromImage(str8("assets/test_heightmap.png")); + Terrain_Storage* terrain = Render_GetTerrainStorage(); + Terrain_LoadHeightmap(terrain, hmap, false); // assert(Terrain_IsActive()); // --- Skybox @@ -101,6 +103,7 @@ int main() { Shadow_Run(entities, entity_count); + /* if (draw_debug) { // draw the player model with shadows Render_RenderEntities(entities, entity_count); @@ -109,6 +112,8 @@ int main() { } else { Shadow_DrawDebugQuad(); } + */ + Terrain_Draw(terrain); // END Draw calls Frame_Draw(); diff --git a/src/core/camera.c b/src/core/camera.c index 7f04207..e3e812c 100644 --- a/src/core/camera.c +++ b/src/core/camera.c @@ -45,6 +45,14 @@ void Camera_Update(Camera *camera) { Vec3 displacement = vec3_mult(camera->front, -speed); camera->position = vec3_add(camera->position, displacement); } + if (key_is_pressed(KEYCODE_Q)) { + Vec3 displacement = vec3_mult(camera->up, speed); + camera->position = vec3_add(camera->position, displacement); + } + if (key_is_pressed(KEYCODE_E)) { + Vec3 displacement = vec3_mult(camera->up, -speed); + camera->position = vec3_add(camera->position, displacement); + } // Mouse if (MouseBtn_Held(MOUSEBTN_LEFT)) { diff --git a/src/new_render/render.c b/src/new_render/render.c index eea9ad1..08ef2c0 100644 --- a/src/new_render/render.c +++ b/src/new_render/render.c @@ -16,6 +16,7 @@ #include "render_scene.h" #include "render_types.h" #include "shadows.h" +#include "terrain.h" #define STB_IMAGE_IMPLEMENTATION #include <stb_image.h> @@ -34,7 +35,7 @@ struct Renderer { RenderScene scene; PBR_Storage* pbr; Shadow_Storage* shadows; - // Terrain_Storage terrain; + Terrain_Storage* terrain; // Text_Storage text; ResourcePools* resource_pools; arena frame_arena; @@ -104,6 +105,9 @@ bool Renderer_Init(RendererConfig config, Renderer* ren, GLFWwindow** out_window ren->pbr = malloc(sizeof(PBR_Storage)); PBR_Init(ren->pbr); + ren->terrain = malloc(sizeof(Terrain_Storage)); + Terrain_Init(ren->terrain); + return true; } @@ -112,6 +116,8 @@ void Renderer_Shutdown(Renderer* ren) { DEBUG("Freed Shadows storage"); free(ren->pbr); DEBUG("Freed PBR storage"); + free(ren->terrain); + DEBUG("Freed Terrain storage"); arena_free_storage(&ren->frame_arena); DEBUG("Freed frame allocator buffer"); } @@ -147,7 +153,8 @@ void Render_RenderEntities(RenderEnt* entities, size_t entity_count) { RenderScene scene = ren->scene; Shadow_Storage* shadow_storage = Render_GetShadowStorage(); - TextureHandle depthmap = shadow_storage->enabled ? Shadow_GetShadowMapTexture(shadow_storage) : INVALID_TEX_HANDLE; + TextureHandle depthmap = + shadow_storage->enabled ? Shadow_GetShadowMapTexture(shadow_storage) : INVALID_TEX_HANDLE; PBR_Execute(ren->pbr, scene.camera, depthmap, entities, entity_count); } @@ -239,4 +246,9 @@ RenderScene* Render_GetScene() { 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; }
\ No newline at end of file diff --git a/src/new_render/render.h b/src/new_render/render.h index 0231975..233c934 100644 --- a/src/new_render/render.h +++ b/src/new_render/render.h @@ -70,8 +70,10 @@ PUB void Render_DrawTerrain(); // --- Getters (not in love with this but I'm finding keeping Renderer internals private to be okay) arena* GetRenderFrameArena(Renderer* r); -typedef struct Shadow_Storage Shadow_Storage; typedef struct RenderScene RenderScene; +typedef struct Shadow_Storage Shadow_Storage; +typedef struct Terrain_Storage Terrain_Storage; RenderScene* Render_GetScene(); -Shadow_Storage* Render_GetShadowStorage();
\ No newline at end of file +Shadow_Storage* Render_GetShadowStorage(); +Terrain_Storage* Render_GetTerrainStorage();
\ No newline at end of file diff --git a/src/new_render/shadows.c b/src/new_render/shadows.c index df25e05..f62950b 100644 --- a/src/new_render/shadows.c +++ b/src/new_render/shadows.c @@ -209,6 +209,4 @@ void Shadow_ShadowmapExecute(Shadow_Storage* storage, Mat4 light_space_transform GPU_CmdEncoder_EndRender(&shadow_encoder); // end renderpass } -TextureHandle Shadow_GetShadowMapTexture(Shadow_Storage* storage) { - return storage->depth_texture; -} +TextureHandle Shadow_GetShadowMapTexture(Shadow_Storage* storage) { return storage->depth_texture; } diff --git a/src/ral/backends/opengl/backend_opengl.c b/src/ral/backends/opengl/backend_opengl.c index ec01214..7929a16 100644 --- a/src/ral/backends/opengl/backend_opengl.c +++ b/src/ral/backends/opengl/backend_opengl.c @@ -246,6 +246,8 @@ BufferHandle GPU_BufferCreate(u64 size, GPU_BufferType buf_type, GPU_BufferFlags return handle; } +void GPU_BufferDestroy(BufferHandle handle) { glDeleteBuffers(1, &handle.raw); } + TextureHandle GPU_TextureCreate(TextureDesc desc, bool create_view, const void* data) { // "allocating" the cpu-side struct TextureHandle handle; diff --git a/src/systems/terrain.c b/src/systems/terrain.c index 9a49fad..f916442 100644 --- a/src/systems/terrain.c +++ b/src/systems/terrain.c @@ -2,27 +2,134 @@ * @brief */ #include "terrain.h" -#include "ral.h" +#include <assert.h> +#include "file.h" +#include "glad/glad.h" +#include "log.h" +#include "maths.h" +#include "mem.h" +#include "ral_impl.h" +#include "ral_types.h" +#include "render.h" +#include "render_scene.h" +#include "shader_layouts.h" +#include "str.h" -struct Terrain_Storage { - arena terrain_allocator; - Heightmap* heightmap; // NULL = no heightmap - GPU_Renderpass* hmap_renderpass; - GPU_Pipeline* hmap_pipeline; -}; +#define TERRAIN_GRID_U 64 +#define TERRAIN_GRID_V 64 -bool Terrain_Init(Terrain_Storage* storage) { return true; } +bool Terrain_Init(Terrain_Storage* storage) { + storage->grid_dimensions = u32x2(TERRAIN_GRID_U, TERRAIN_GRID_V); + storage->hmap_loaded = false; -void Terrain_Shutdown(Terrain_Storage* storage); + GPU_RenderpassDesc rpass_desc = { + .default_framebuffer = true, + }; + storage->hmap_renderpass = GPU_Renderpass_Create(rpass_desc); -/* bool terrain_system_init(terrain_state* state) { */ -/* gpu_renderpass_desc rpass_desc = { */ -/* .default_framebuffer = true, */ -/* }; */ -/* struct graphics_pipeline_desc pipeline_desc = { */ + VertexDescription builder = { .debug_label = "pos only" }; + VertexDesc_AddAttr(&builder, "inPosition", ATTR_F32x3); + builder.use_full_vertex_size = true; -/* }; */ + arena scratch = arena_create(malloc(1024 * 1024), 1024 * 1024); -/* state->hmap_renderpass = gpu_renderpass_create(&rpass_desc); */ -/* state->hmap_pipeline = gpu_graphics_pipeline_create(pipeline_desc); */ -/* } */ + Str8 vert_path = str8("assets/shaders/terrain.vert"); + Str8 frag_path = str8("assets/shaders/terrain.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 }; + + GraphicsPipelineDesc pipeline_desc = { + .debug_name = "terrain rendering pipeline", + .vertex_desc = builder, + .data_layouts = { camera_data }, + .data_layouts_count = 1, + .vs = { + .debug_name = "terrain vertex shader", + .filepath = vert_path, + .code = vertex_shader.contents, + }, + .fs = { + .debug_name = "terrain fragment shader", + .filepath = frag_path, + .code = fragment_shader.contents, + }, + .wireframe = true, + }; + storage->hmap_pipeline = GPU_GraphicsPipeline_Create(pipeline_desc, storage->hmap_renderpass); + + return true; +} + +void Terrain_Shutdown(Terrain_Storage* storage) {} + +void Terrain_LoadHeightmap(Terrain_Storage* storage, Heightmap hmap, bool free_on_upload) { + // If there's a current one we will delete it and reallocate buffers + if (storage->hmap_loaded) { + GPU_BufferDestroy(storage->vertex_buffer); + GPU_BufferDestroy(storage->index_buffer); + } + + size_t num_vertices = storage->grid_dimensions.x * storage->grid_dimensions.y; + storage->num_vertices = num_vertices; + + Vertex_darray* vertices = Vertex_darray_new(num_vertices); + u32 index = 0; + for (u32 i = 0; i < storage->grid_dimensions.x; i++) { + for (u32 j = 0; j < storage->grid_dimensions.y; j++) { + assert(index < num_vertices); + Vertex v = { .pos_only.position = vec3_create(i, 0.0, j) }; + Vertex_darray_push(vertices, v); + index++; + } + } + + BufferHandle vertices_handle = GPU_BufferCreate(num_vertices * sizeof(Vertex), BUFFER_VERTEX, + BUFFER_FLAG_GPU, vertices->data); + + storage->vertex_buffer = vertices_handle; +} + +Heightmap Heightmap_FromImage(Str8 filepath) { + size_t max_size = MB(16); + arena arena = arena_create(malloc(max_size), max_size); + str8_opt maybe_file = str8_from_file(&arena, filepath); + + assert(maybe_file.has_value); + + TextureData hmap_tex = TextureDataLoad(Str8_to_cstr(&arena, filepath), false); + + arena_free_storage(&arena); + + return (Heightmap){ + .pixel_dimensions = hmap_tex.description.extents, + .filepath = filepath, + .image_data = hmap_tex.image_data, + .is_uploaded = false, + }; +} + +void Terrain_Draw(Terrain_Storage* storage) { + GPU_CmdEncoder* enc = GPU_GetDefaultEncoder(); + GPU_EncodeBindPipeline(enc, storage->hmap_pipeline); + RenderScene* scene = Render_GetScene(); + + Mat4 view, proj; + u32x2 dimensions = GPU_Swapchain_GetDimensions(); + Camera_ViewProj(&scene->camera, (f32)dimensions.x, (f32)dimensions.y, &view, &proj); + Binding_Camera camera_data = { .view = view, + .projection = proj, + .viewPos = vec4(scene->camera.position.x, scene->camera.position.y, + scene->camera.position.z, 1.0) }; + GPU_EncodeBindShaderData( + enc, 0, (ShaderData){ .data = &camera_data, .get_layout = &Binding_Camera_GetLayout }); + + GPU_EncodeSetVertexBuffer(enc, storage->vertex_buffer); + + // GPU_EncodeDraw(enc, storage->num_vertices); + glDrawArrays(GL_POINTS, 0, storage->num_vertices); +} diff --git a/src/systems/terrain.h b/src/systems/terrain.h index 2d6ff4a..a38e45e 100644 --- a/src/systems/terrain.h +++ b/src/systems/terrain.h @@ -15,17 +15,29 @@ Future: #include "maths_types.h" #include "mem.h" #include "ral.h" +#include "ral_types.h" #include "render.h" #include "str.h" typedef struct Heightmap { Str8 filepath; - u32x2 size; + u32x2 pixel_dimensions; void* image_data; bool is_uploaded; } Heightmap; -typedef struct Terrain_Storage Terrain_Storage; + typedef struct Terrain_Storage { + // arena terrain_allocator; + u32x2 grid_dimensions; + u32 num_vertices; + Heightmap heightmap; // NULL = no heightmap + GPU_Renderpass* hmap_renderpass; + GPU_Pipeline* hmap_pipeline; + + bool hmap_loaded; + BufferHandle vertex_buffer; + BufferHandle index_buffer; +} Terrain_Storage; // --- Public API PUB bool Terrain_Init(Terrain_Storage* storage); @@ -34,7 +46,7 @@ PUB void Terrain_Draw( Terrain_Storage* storage); // NOTE: For now it renders directly to main framebuffer /** @brief Sets the active heightmap to be rendered and collided against. */ -PUB void Terrain_LoadHeightmap(Heightmap hmap, bool free_on_upload); +PUB void Terrain_LoadHeightmap(Terrain_Storage* storage, Heightmap hmap, bool free_on_upload); PUB Heightmap Heightmap_FromImage(Str8 filepath); PUB Heightmap Heightmap_FromPerlin(/* TODO: perlin noise generation parameters */); @@ -51,5 +63,7 @@ f32 Heightmap_HeightXZ(Heightmap* hmap, f32 x, f32 z); /** @brief Calculate the normal vector of a vertex at a particular coordinate in the heightmap */ Vec3 Heightmap_NormalXZ(Heightmap* hmap, f32 x, f32 z); -/** @brief Generate the `geometry_data` for a heightmap ready to be uploaded to the GPU */ -Geometry geo_heightmap(arena* a, Heightmap heightmap); +// /** @brief Generate the `geometry_data` for a heightmap ready to be uploaded to the GPU */ +// Geometry geo_heightmap(arena* a, Heightmap heightmap); + +ShaderDataLayout TerrainUniforms_GetLayout(void* data);
\ No newline at end of file |