From 117bdf0c003a65166ebef56f021530e47f93f7b3 Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Wed, 1 Jul 2026 20:18:32 -0500 Subject: [PATCH] Fov tweaks --- src/dusk/rpg/rpg.c | 2 +- src/dusk/rpg/rpgcamera.c | 2 +- src/dusk/rpg/rpgcamera.h | 2 + src/dusk/scene/overworld/sceneoverworld.c | 63 ++++++++++++++++++++--- src/dusk/scene/overworld/sceneoverworld.h | 15 ++++-- 5 files changed, 72 insertions(+), 12 deletions(-) diff --git a/src/dusk/rpg/rpg.c b/src/dusk/rpg/rpg.c index c27581f9..5f33467b 100644 --- a/src/dusk/rpg/rpg.c +++ b/src/dusk/rpg/rpg.c @@ -49,7 +49,7 @@ errorret_t rpgInit(void) { entity_t *npc = &ENTITIES[npcIndex]; entityInit(npc, ENTITY_TYPE_NPC); npcSetMoveType(npc, NPC_MOVE_TYPE_PATH); - npc->position = (worldpos_t){ 8, 8, 0 }; + npc->position = (worldpos_t){ 8, 8, 1 }; npc->interact.type = ENTITY_INTERACT_PRINT; npc->interact.data.message = "hello world"; { diff --git a/src/dusk/rpg/rpgcamera.c b/src/dusk/rpg/rpgcamera.c index 7660be51..e9014840 100644 --- a/src/dusk/rpg/rpgcamera.c +++ b/src/dusk/rpg/rpgcamera.c @@ -48,7 +48,7 @@ void rpgCameraUpdateProjection(void) { #endif glm_perspective( - glm_rad(45.0f), + glm_rad(RPG_CAMERA_FOV), SCREEN.aspect, 0.1f, 100.0f, diff --git a/src/dusk/rpg/rpgcamera.h b/src/dusk/rpg/rpgcamera.h index 7b68a007..ba2e9da8 100644 --- a/src/dusk/rpg/rpgcamera.h +++ b/src/dusk/rpg/rpgcamera.h @@ -9,6 +9,8 @@ #include "rpg/overworld/worldpos.h" #include "error/error.h" +#define RPG_CAMERA_FOV 35.0f + typedef enum { RPG_CAMERA_MODE_FREE, RPG_CAMERA_MODE_FOLLOW_ENTITY, diff --git a/src/dusk/scene/overworld/sceneoverworld.c b/src/dusk/scene/overworld/sceneoverworld.c index b005abb0..f84506e0 100644 --- a/src/dusk/scene/overworld/sceneoverworld.c +++ b/src/dusk/scene/overworld/sceneoverworld.c @@ -59,7 +59,7 @@ errorret_t sceneOverworldRender(scenedata_t *sceneData) { )); // Camera Eye - float_t fov = glm_rad(45.0f); + float_t fov = glm_rad(RPG_CAMERA_FOV); float_t pixelsPerUnit = TILE_SIZE_PIXELS; float_t worldH = (float_t)(SCREEN.height / SCREEN.scale3d) / pixelsPerUnit; float_t z = (worldH * 0.5f) / tanf(fov * 0.5f); @@ -81,8 +81,15 @@ errorret_t sceneOverworldRender(scenedata_t *sceneData) { ); errorChain(shaderSetMatrix(&SHADER_UNLIT, SHADER_UNLIT_VIEW, eye)); - // Chunks - errorChain(sceneOverworldDrawChunks()); + // Base terrain meshes, drawn with normal depth testing. + errorChain(sceneOverworldDrawChunksBase()); + + // Entities are drawn with depth testing fully disabled so sloped tiles + // (ramps) never clip them; entity-vs-entity overlap falls back to + // array draw order instead of true depth. + errorChain(displaySetState((displaystate_t){ + .flags = DISPLAY_STATE_FLAG_CULL + })); // Entities { @@ -115,16 +122,59 @@ errorret_t sceneOverworldRender(scenedata_t *sceneData) { } } + // Other chunk meshes (trees, buildings, etc), drawn last with normal + // depth testing so they correctly occlude entities standing beneath + // them. + errorChain(displaySetState((displaystate_t){ + .flags = DISPLAY_STATE_FLAG_DEPTH_TEST | DISPLAY_STATE_FLAG_CULL + })); + errorChain(sceneOverworldDrawChunksProps()); + errorOk(); } -errorret_t sceneOverworldDrawChunks() { +errorret_t sceneOverworldDrawChunksBase() { for(chunkindex_t i = 0; i < MAP_CHUNK_COUNT; i++) { chunk_t *chunk = MAP.chunkOrder[i]; if(chunk == NULL) continue; if(chunk->meshCount == 0) continue; + if(chunk->modelEntries[0] == NULL) continue; + if(chunk->modelEntries[0]->state != ASSET_ENTRY_STATE_LOADED) continue; - for(uint8_t m = 0; m < chunk->meshCount; m++) { + assetmodeloutput_t *model = &chunk->modelEntries[0]->data.model; + if(model->meshEntry == NULL) continue; + + texture_t *tex = model->texEntry != NULL + ? &model->texEntry->data.texture + : NULL; + + shadermaterial_t mat = { + .unlit = { .color = model->color, .texture = tex } + }; + errorChain(shaderSetMatrix( + &SHADER_UNLIT, SHADER_UNLIT_MODEL, chunk->meshModels[0] + )); + errorChain(shaderSetMaterial(&SHADER_UNLIT, &mat)); + errorChain(meshDraw( + &model->meshEntry->data.mesh.mesh, 0, -1 + )); + } + + // Restore identity model so subsequent renders (e.g. entities) are + // not affected by the last chunk transform. + mat4 identity; + glm_mat4_identity(identity); + errorChain(shaderSetMatrix(&SHADER_UNLIT, SHADER_UNLIT_MODEL, identity)); + + errorOk(); +} + +errorret_t sceneOverworldDrawChunksProps() { + for(chunkindex_t i = 0; i < MAP_CHUNK_COUNT; i++) { + chunk_t *chunk = MAP.chunkOrder[i]; + if(chunk == NULL) continue; + + for(uint8_t m = 1; m < chunk->meshCount; m++) { if(chunk->modelEntries[m] == NULL) continue; if(chunk->modelEntries[m]->state != ASSET_ENTRY_STATE_LOADED) continue; @@ -148,8 +198,7 @@ errorret_t sceneOverworldDrawChunks() { } } - // Restore identity model so subsequent renders (e.g. entities) are - // not affected by the last chunk transform. + // Restore identity model in case anything renders after props. mat4 identity; glm_mat4_identity(identity); errorChain(shaderSetMatrix(&SHADER_UNLIT, SHADER_UNLIT_MODEL, identity)); diff --git a/src/dusk/scene/overworld/sceneoverworld.h b/src/dusk/scene/overworld/sceneoverworld.h index e6c7ce4e..03e58dbe 100644 --- a/src/dusk/scene/overworld/sceneoverworld.h +++ b/src/dusk/scene/overworld/sceneoverworld.h @@ -29,12 +29,21 @@ errorret_t sceneOverworldInit(scenedata_t *sceneData); errorret_t sceneOverworldUpdate(scenedata_t *sceneData); /** - * Draws all loaded chunks in two passes: base meshes first (shared texture, - * no binds between chunks), then each chunk's additional meshes. + * Draws the base (tile) mesh of every loaded chunk, with normal depth + * testing. Must be called before entities are rendered. * * @return An error if drawing failed, or errorOk() on success. */ -errorret_t sceneOverworldDrawChunks(); +errorret_t sceneOverworldDrawChunksBase(); + +/** + * Draws every loaded chunk's additional meshes (trees, buildings, etc), + * with normal depth testing so they correctly occlude entities standing + * beneath them. Must be called after entities are rendered. + * + * @return An error if drawing failed, or errorOk() on success. + */ +errorret_t sceneOverworldDrawChunksProps(); /** * Renders the overworld scene.