summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoromniscient <17525998+omnisci3nce@users.noreply.github.com>2024-07-21 17:48:00 +1000
committeromniscient <17525998+omnisci3nce@users.noreply.github.com>2024-07-21 17:48:00 +1000
commit66b1e02847e08b8e66e9969f0a3d138c15cc70f4 (patch)
treea598a4a1716fa985ab4359a60f6a2c93d2ee390b
parent9f1bfa75490bbdf22dd57ff17352d2736a0891fa (diff)
terrain/hmap skeleton
-rw-r--r--assets/shaders/terrain.frag7
-rw-r--r--assets/shaders/terrain.vert13
-rw-r--r--examples/game_demo/game_demo.c11
-rw-r--r--src/core/camera.c8
-rw-r--r--src/new_render/render.c16
-rw-r--r--src/new_render/render.h6
-rw-r--r--src/new_render/shadows.c4
-rw-r--r--src/ral/backends/opengl/backend_opengl.c2
-rw-r--r--src/systems/terrain.c143
-rw-r--r--src/systems/terrain.h24
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