Merge remote-tracking branch 'origin'

This commit is contained in:
2025-10-05 14:46:04 +01:00
22 changed files with 23267 additions and 22663 deletions

View File

@@ -1,5 +1,9 @@
// @Todo: These should move to draw/core.c
//
void G_ImagesLoad(G_State *game) {
M_TempScope(0, 0) {
D_Context *draw = &game->draw;
Str8 exe_path = FS_SystemPath(temp.arena, FS_SYSTEM_PATH_EXE);
Str8 path = Sf(temp.arena, "%.*s/assets", Sv(exe_path));
@@ -17,15 +21,99 @@ void G_ImagesLoad(G_State *game) {
Vk_CommandBuffer *cmds = Vk_CommandBufferPush();
// We reserve the first texture for the "white" texture
draw->n_images = 1;
for (FS_Entry *it = assets.first; it != 0; it = it->next) {
if (Str8_EndsWith(it->basename, S("png"))) {
game->n_images += 1;
draw->n_images += 1;
}
}
VkBufferImageCopy copy = { 0 };
game->images = M_ArenaPush(game->arena, G_Image, .count = game->n_images);
game->n_images = 0;
draw->images = M_ArenaPush(game->arena, D_Image, .count = draw->n_images);
draw->n_images = 1;
// Upload the white texture
{
D_Image *white = &draw->images[0];
U32 white_data[] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
M_CopySize(base, white_data, sizeof(white_data));
copy.bufferOffset = offset;
copy.bufferRowLength = 0;
copy.bufferImageHeight = 0;
copy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
copy.imageSubresource.mipLevel = 0;
copy.imageSubresource.baseArrayLayer = 0;
copy.imageSubresource.layerCount = 1;
copy.imageExtent.width = 2;
copy.imageExtent.height = 2;
copy.imageExtent.depth = 1;
base += sizeof(white_data);
offset += sizeof(white_data);
white->name = S("_WHITE");
white->image.width = 2;
white->image.height = 2;
white->image.format = VK_FORMAT_R8G8B8A8_SRGB;
white->image.usage = VK_IMAGE_USAGE_SAMPLED_BIT;
Vk_ImageCreate(&white->image);
// We could combine all of these 'pre-transfer' and 'post-transfer' layers into one
// batch, it would simply mean doing three loops over the images and setting them all up
// and submitting them in one go. It doesn't really matter for now
//
VkImageMemoryBarrier2 transfer = { 0 };
VkImageMemoryBarrier2 shader_read = { 0 };
transfer.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2;
transfer.srcStageMask = VK_PIPELINE_STAGE_2_NONE;
transfer.srcAccessMask = VK_ACCESS_2_NONE;
transfer.dstStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT;
transfer.dstAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT;
transfer.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
transfer.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
transfer.image = white->image.handle;
transfer.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
transfer.subresourceRange.layerCount = 1;
transfer.subresourceRange.levelCount = 1;
shader_read.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2;
shader_read.srcStageMask = VK_PIPELINE_STAGE_2_TRANSFER_BIT;
shader_read.srcAccessMask = VK_ACCESS_2_TRANSFER_WRITE_BIT;
shader_read.dstStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT;
shader_read.dstAccessMask = VK_ACCESS_2_SHADER_SAMPLED_READ_BIT;
shader_read.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
shader_read.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
shader_read.image = white->image.handle;
shader_read.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
shader_read.subresourceRange.layerCount = 1;
shader_read.subresourceRange.levelCount = 1;
VkDependencyInfo dep = { 0 };
dep.sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO;
dep.imageMemoryBarrierCount = 1;
dep.pImageMemoryBarriers = &transfer;
vk.CmdPipelineBarrier2(cmds->handle, &dep);
vk.CmdCopyBufferToImage(cmds->handle, staging.handle, white->image.handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &copy);
dep.pImageMemoryBarriers = &shader_read;
vk.CmdPipelineBarrier2(cmds->handle, &dep);
}
// Image upload is sbi_load -> copy to staging -> upload to gpu texture
@@ -35,7 +123,7 @@ void G_ImagesLoad(G_State *game) {
stbi_uc *data = stbi_load((const char *) it->path.data, &w, &h, &c, 4);
if (data) {
G_Image *image = &game->images[game->n_images];
D_Image *image = &draw->images[draw->n_images];
U64 image_sz = 4 * w * h;
@@ -59,7 +147,7 @@ void G_ImagesLoad(G_State *game) {
Assert(offset <= staging.size);
game->n_images += 1;
draw->n_images += 1;
image->name = Str8_Copy(game->arena, Str8_RemoveAfterLast(it->basename, '.'));
@@ -126,9 +214,11 @@ void G_ImagesLoad(G_State *game) {
}
void G_PipelinesLoad(G_State *game) {
game->pipelines = M_ArenaPush(game->arena, Vk_Pipeline, .count = 1);
D_Context *draw = &game->draw;
Vk_Pipeline *basic = &game->pipelines[0];
draw->pipelines = M_ArenaPush(game->arena, Vk_Pipeline, .count = 1);
Vk_Pipeline *basic = &draw->pipelines[0];
VkShaderModule vshader = 0, fshader = 0;
M_TempScope(0, 0) {
@@ -161,20 +251,27 @@ void G_PipelinesLoad(G_State *game) {
bindings[1].binding = 1;
bindings[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
bindings[1].descriptorCount = 1;
bindings[1].descriptorCount = game->draw.n_images;
bindings[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
VkDescriptorSetLayoutCreateInfo set_info = { 0 };
set_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
set_info.bindingCount = 2;
set_info.bindingCount = ArraySize(bindings);
set_info.pBindings = bindings;
vk.CreateDescriptorSetLayout(vk.device, &set_info, 0, &basic->layout.set);
VkPushConstantRange push_range = { 0 };
push_range.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
push_range.offset = 0;
push_range.size = 128;
VkPipelineLayoutCreateInfo layout_create = { 0 };
layout_create.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
layout_create.setLayoutCount = 1;
layout_create.pSetLayouts = &basic->layout.set;
layout_create.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
layout_create.setLayoutCount = 1;
layout_create.pSetLayouts = &basic->layout.set;
layout_create.pushConstantRangeCount = 1;
layout_create.pPushConstantRanges = &push_range;
vk.CreatePipelineLayout(vk.device, &layout_create, 0, &basic->layout.pipeline);
}
@@ -193,6 +290,14 @@ void G_PipelinesLoad(G_State *game) {
Vk_PipelineCreate(basic);
}
void G_CalulateCamera(G_Camera *camera, F32 aspect) {
Mat4x4FInv proj = M4x4F_Perspective(camera->fov, aspect, camera->nearp, camera->farp);
Mat4x4FInv view = M4x4F_CameraView(camera->x, camera->y, camera->z, camera->p);
camera->proj.fwd = M4x4F_Mul(proj.fwd, view.fwd);
camera->proj.inv = M4x4F_Mul(view.inv, proj.inv);
}
#include "impl/aabb.c"
#include "impl/nav.c"
#include "impl/player.c"

View File

@@ -1,36 +1,30 @@
#if !defined(LD_GAME_CORE_H_)
#define LD_GAME_CORE_H_
typedef struct G_Vertex G_Vertex;
struct G_Vertex {
F32 x, y, z, w;
F32 u, v;
U32 c;
U32 pad;
};
typedef struct G_Camera G_Camera;
struct G_Camera {
V3f x, y, z;
V3f p;
typedef struct G_Image G_Image;
struct G_Image {
Str8 name;
Vk_Image image;
F32 fov;
F32 nearp, farp;
Mat4x4FInv proj;
};
typedef struct G_State G_State;
struct G_State {
M_Arena *arena;
U32 n_images;
G_Image *images;
U32 n_pipelines;
Vk_Pipeline *pipelines;
Vk_Buffer vbo;
D_Context draw;
G_Camera camera;
};
function void G_ImagesLoad(G_State *game);
function void G_PipelinesLoad(G_State *game);
function void G_CalulateCamera(G_Camera *camera, F32 aspect);
#include "aabb.h"
#include "player.h"
#include "nav.h"

View File

@@ -21,11 +21,10 @@ struct navSearchState{
navSearchState initState(U32 start, U32 meshSize) {
navSearchState state = {};
for(U32 i = 0; i < meshSize; i++) {
state.nodeStates[i].visited = false;
state.nodeStates[i].visited = false;
state.nodeStates[i].addedToUnvisited = false;
// underflow to the max :)
state.nodeStates[i].distance = U64_MAX;
state.nodeStates[i].shortest = 0;
state.nodeStates[i].distance = U64_MAX;
state.nodeStates[i].shortest = 0;
}
state.nodeStates[start].distance = 0;
return state;
@@ -53,8 +52,8 @@ U32 getLowestState(U32 unfinishedIndexes[128], U32 unfinishedCount, navSearchSta
}
// Generate a path to follow between the start and end node.
NavPath Nav_Path(NavMesh mesh, U32 start, U32 end) {
navSearchState state = initState(start, mesh.nodeCount);
NavPath Nav_Path(NavMesh *mesh, U32 start, U32 end) {
navSearchState state = initState(start, mesh->nodeCount);
U32 unfinishedCount = 1;
U32 unfinishedIndexes[NAV_MAX_NODES] = {start};
// I don't want to spend time removing items from
@@ -65,19 +64,19 @@ NavPath Nav_Path(NavMesh mesh, U32 start, U32 end) {
U32 lowestNodeIndex = start;
bool found = false;
while(!found) {
for(int connectionI = 0 ; connectionI < mesh.nodes[lowestNodeIndex].connectionCount; connectionI++) {
NavConnection connection = mesh.nodes[lowestNodeIndex].connections[connectionI];
navSearchNodeState *testNode = &state.nodeStates[connection.NodeIndex];
for(int connectionI = 0 ; connectionI < mesh->nodes[lowestNodeIndex].connectionCount; connectionI++) {
NavConnection *connection = &mesh->nodes[lowestNodeIndex].connections[connectionI];
navSearchNodeState *testNode = &state.nodeStates[connection->NodeIndex];
if(testNode->visited) {continue;}
U32 distance = cast(U32) (state.nodeStates[lowestNodeIndex].distance + connection.Cost);
distance += cast(U32) (mesh.nodes[end].pos.x - mesh.nodes[connection.NodeIndex].pos.x);
distance += cast(U32) (mesh.nodes[end].pos.y - mesh.nodes[connection.NodeIndex].pos.y);
U32 distance = cast(U32) (state.nodeStates[lowestNodeIndex].distance + connection->Cost);
distance += cast(U32) (mesh->nodes[end].pos.x - mesh->nodes[connection->NodeIndex].pos.x);
distance += cast(U32) (mesh->nodes[end].pos.y - mesh->nodes[connection->NodeIndex].pos.y);
if(testNode->distance > distance) {
testNode->distance = distance;
testNode->shortest = lowestNodeIndex;
}
if(!testNode->addedToUnvisited) {
unfinishedIndexes[unfinishedCount] = connection.NodeIndex;
unfinishedIndexes[unfinishedCount] = connection->NodeIndex;
unfinishedCount++;
testNode->addedToUnvisited = true;
}

View File

@@ -1,6 +1,7 @@
#include "../npc.h"
#include "../world.h"
#include "../../core/types.h"
#include "game/npc.h"
#include "game/world.h"
#include "core/types.h"
#include <stdio.h>
void updateNPC(F32 delta, NPC *npc, World *world) {
@@ -15,7 +16,7 @@ void updateNPC(F32 delta, NPC *npc, World *world) {
npc->path = Nav_Path(world->navMesh, npc->currentNavNode, npc->targetNavNode);
printf("done\n");
npc->walkTimer = 0;
printf("%*.s started walking to %d\n", Sv(npc->name), npc->targetNavNode);
printf("%.*s started walking to %d\n", Sv(npc->name), npc->targetNavNode);
}
break;
case NPC_ACTION_WALKING:
@@ -33,11 +34,10 @@ void updateNPC(F32 delta, NPC *npc, World *world) {
npc->pathIndex+=1;
npc->currentNavNode = npc->path.indexes[npc->pathIndex];
}
NavNode cNav = world->navMesh.nodes[npc->currentNavNode];
NavNode tNav = world->navMesh.nodes[npc->pathIndex];
NavNode cNav = world->navMesh->nodes[npc->currentNavNode];
NavNode tNav = world->navMesh->nodes[npc->pathIndex];
npc->collision.pos.x = cNav.pos.x * (1 - npc->walkTimer/NPC_SPEED) + tNav.pos.x * npc->walkTimer/NPC_SPEED;
npc->collision.pos.y = cNav.pos.y * (1 - npc->walkTimer/NPC_SPEED) + tNav.pos.y * npc->walkTimer/NPC_SPEED;
break;
}
}

View File

@@ -34,7 +34,6 @@ struct NavMesh{
NavNode nodes[NAV_MAX_NODES];
};
function NavPath Nav_Path(NavMesh mesh, U32 start, U32 end);
function NavPath Nav_Path(NavMesh *mesh, U32 start, U32 end);
#endif

View File

@@ -5,7 +5,7 @@
#include "npc_look.h"
#include "../core/types.h"
#define NPC_SPEED 0.1
#define NPC_SPEED 0.2f
typedef enum NPC_ACTION NPC_ACTION;
enum NPC_ACTION {

File diff suppressed because it is too large Load Diff

View File

@@ -1,19 +1,21 @@
#if !defined(LD_GAME_WORLD_H_)
#define LD_GAME_WORLD_H_
#include "player.h"
#include "npc.h"
#include "bandit.h"
// Areas are which
enum AREA {
WORLD_AREA_OUTSIDE = 1,
WORLD_AREA_SALOON = 1 << 1,
// Areas are which
typedef U32 World_Area;
enum World_Area {
WORLD_AREA_OUTSIDE = (1 << 0),
WORLD_AREA_SALOON = (1 << 1),
};
typedef struct World World;
struct World {
//// Static stuff
NavMesh navMesh;
NavMesh *navMesh;
//// Player
Player player;