Compare commits
9 Commits
175f4da59b
...
raycast
| Author | SHA1 | Date | |
|---|---|---|---|
| 108de25eb5 | |||
| beccaf8465 | |||
| fd7162259b | |||
|
1d70f3ae20
|
|||
|
5d48ed9c19
|
|||
|
1f97d81133
|
|||
|
1757fc4b96
|
|||
|
3b8c50a361
|
|||
|
2c67896cf2
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
build/
|
||||
code/compile_commands.json
|
||||
code/.cache
|
||||
.vscode
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
#include "impl/arena.c"
|
||||
#include "impl/string.c"
|
||||
#include "impl/math.c"
|
||||
|
||||
@@ -6,5 +6,6 @@
|
||||
#include "macros.h"
|
||||
#include "arena.h"
|
||||
#include "string.h"
|
||||
#include "math.h"
|
||||
|
||||
#endif // LD_CORE_CORE_H_
|
||||
|
||||
163
code/core/impl/math.c
Normal file
163
code/core/impl/math.c
Normal file
@@ -0,0 +1,163 @@
|
||||
V2f V2F(F32 x, F32 y) {
|
||||
V2f result = { x, y };
|
||||
return result;
|
||||
}
|
||||
|
||||
V3f V3F(F32 x, F32 y, F32 z) {
|
||||
V3f result = { x, y, z };
|
||||
return result;
|
||||
}
|
||||
|
||||
V4f V4F(F32 x, F32 y, F32 z, F32 w) {
|
||||
V4f result = { x, y, z, w };
|
||||
return result;
|
||||
}
|
||||
|
||||
R2f R2F(V2f min, V2f max) {
|
||||
R2f result = { min, max };
|
||||
return result;
|
||||
}
|
||||
|
||||
V3f V3f_Neg(V3f x) {
|
||||
V3f result = { -x.x, -x.y, -x.z };
|
||||
return result;
|
||||
}
|
||||
|
||||
V3f V3f_Scale(V3f x, F32 s) {
|
||||
V3f result = { s * x.x, s * x.y, s * x.z };
|
||||
return result;
|
||||
}
|
||||
|
||||
F32 V3f_Dot(V3f a, V3f b) {
|
||||
F32 result = (a.x * b.x) + (a.y * b.y) + (a.z * b.z);
|
||||
return result;
|
||||
}
|
||||
|
||||
F32 V4f_Dot(V4f a, V4f b) {
|
||||
F32 result = (a.x * b.x) + (a.y * b.y) + (a.z * b.z) + (a.w * b.w);
|
||||
return result;
|
||||
}
|
||||
|
||||
Mat4x4F M4x4F_Rows(V3f x, V3f y, V3f z) {
|
||||
Mat4x4F result = {
|
||||
x.x, x.y, x.z, 0,
|
||||
y.x, y.y, y.z, 0,
|
||||
z.x, z.y, z.z, 0,
|
||||
0, 0, 0, 1
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Mat4x4F M4x4F_Columns(V3f x, V3f y, V3f z) {
|
||||
Mat4x4F result = {
|
||||
x.x, y.x, z.x, 0,
|
||||
x.y, y.y, z.y, 0,
|
||||
x.z, y.z, z.z, 0,
|
||||
0, 0, 0, 1
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Mat4x4F M4x4F_Mul(Mat4x4F a, Mat4x4F b) {
|
||||
Mat4x4F result;
|
||||
|
||||
for (U32 r = 0; r < 4; ++r) {
|
||||
for (U32 c = 0; c < 4; ++c) {
|
||||
result.m[r][c] =
|
||||
(a.m[r][0] * b.m[0][c]) + (a.m[r][1] * b.m[1][c]) +
|
||||
(a.m[r][2] * b.m[2][c]) + (a.m[r][3] * b.m[3][c]);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
V4f M4x4F_VMul4(Mat4x4F m, V4f v) {
|
||||
V4f result;
|
||||
result.x = V4f_Dot(m.r[0], v);
|
||||
result.y = V4f_Dot(m.r[1], v);
|
||||
result.z = V4f_Dot(m.r[2], v);
|
||||
result.w = V4f_Dot(m.r[3], v);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
V3f M4x4F_VMul3(Mat4x4F m, V3f v) {
|
||||
V4f tx;
|
||||
tx.xyz = v;
|
||||
tx.w = 1.0f;
|
||||
|
||||
V3f result = M4x4F_VMul4(m, tx).xyz;
|
||||
return result;
|
||||
}
|
||||
|
||||
Mat4x4FInv M4x4F_Perspective(F32 fov, F32 aspect, F32 nearp, F32 farp) {
|
||||
F32 focal_length = 1.0f / tanf(0.5f * (PI_F32 * (fov / 360.0f)));
|
||||
|
||||
F32 a = focal_length;
|
||||
F32 b = focal_length * aspect;
|
||||
|
||||
F32 c = -(nearp + farp) / (farp - nearp);
|
||||
F32 d = -(2.0f * nearp * farp) / (farp - nearp);
|
||||
|
||||
Mat4x4FInv result = {
|
||||
// fwd
|
||||
{
|
||||
a, 0, 0, 0,
|
||||
0, b, 0, 0,
|
||||
0, 0, c, d,
|
||||
0, 0, -1, 0
|
||||
},
|
||||
// inv
|
||||
{
|
||||
(1 / a), 0, 0, 0,
|
||||
0, (1 / b), 0, 0,
|
||||
0, 0, 0, -1,
|
||||
0, 0, (1/ d), (c / d)
|
||||
}
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Mat4x4FInv M4x4F_CameraView(V3f x, V3f y, V3f z, V3f p) {
|
||||
Mat4x4FInv result;
|
||||
|
||||
// Construct orthonomal basis from axes
|
||||
//
|
||||
result.fwd = M4x4F_Rows(x, y, z);
|
||||
V3f txp = V3f_Neg(M4x4F_VMul3(result.fwd, p));
|
||||
|
||||
// Translate by txp
|
||||
//
|
||||
result.fwd.r[0].w += txp.x;
|
||||
result.fwd.r[1].w += txp.y;
|
||||
result.fwd.r[2].w += txp.z;
|
||||
|
||||
// Calculate inverse axes
|
||||
//
|
||||
V3f ix = V3f_Scale(x, 1.0f / V3f_Dot(x, x));
|
||||
V3f iy = V3f_Scale(y, 1.0f / V3f_Dot(y, y));
|
||||
V3f iz = V3f_Scale(z, 1.0f / V3f_Dot(z, y));
|
||||
|
||||
// Calculate inverse position
|
||||
//
|
||||
V3f ip;
|
||||
ip.x = (txp.x * ix.x) + (txp.y * iy.x) + (txp.z * iz.x);
|
||||
ip.y = (txp.x * ix.y) + (txp.y * iy.y) + (txp.z * iz.y);
|
||||
ip.z = (txp.x * ix.z) + (txp.y * iy.z) + (txp.z * iz.z);
|
||||
|
||||
result.inv = M4x4F_Columns(ix, iy, iz);
|
||||
|
||||
// Translate by ip
|
||||
//
|
||||
result.inv.r[0].w -= ip.x;
|
||||
result.inv.r[1].w -= ip.y;
|
||||
result.inv.r[2].w -= ip.z;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <assert.h>
|
||||
|
||||
#define Assert(exp) assert(exp)
|
||||
#define StaticAssert(exp) static_assert(exp, #exp)
|
||||
|
||||
#define ArraySize(x) (sizeof(x) / sizeof((x)[0]))
|
||||
#define Min(a, b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
117
code/core/math.h
Normal file
117
code/core/math.h
Normal file
@@ -0,0 +1,117 @@
|
||||
#if !defined(LD_CORE_MATH_H_)
|
||||
#define LD_CORE_MATH_H_
|
||||
|
||||
#define PI_F32 (3.14159265358979323846264338f)
|
||||
#define TAU_F32 (2.0f * PI_F32)
|
||||
|
||||
typedef union V2f V2f;
|
||||
union V2f {
|
||||
struct {
|
||||
F32 x, y;
|
||||
};
|
||||
|
||||
struct {
|
||||
F32 u, v;
|
||||
};
|
||||
|
||||
struct {
|
||||
F32 w, h;
|
||||
};
|
||||
|
||||
F32 e[2];
|
||||
};
|
||||
|
||||
typedef union V2i V2i;
|
||||
union V2i {
|
||||
struct {
|
||||
U32 x, y;
|
||||
};
|
||||
|
||||
struct {
|
||||
U32 w, h;
|
||||
};
|
||||
|
||||
U32 e[2];
|
||||
};
|
||||
|
||||
typedef union V3f V3f;
|
||||
union V3f {
|
||||
struct {
|
||||
F32 x, y, z;
|
||||
};
|
||||
|
||||
struct {
|
||||
F32 r, g, b;
|
||||
};
|
||||
|
||||
struct {
|
||||
F32 w, h, d;
|
||||
};
|
||||
|
||||
struct {
|
||||
V2f xy;
|
||||
F32 _z;
|
||||
};
|
||||
|
||||
F32 e[3];
|
||||
};
|
||||
|
||||
typedef union V4f V4f;
|
||||
union V4f {
|
||||
struct {
|
||||
F32 x, y, z, w;
|
||||
};
|
||||
|
||||
struct {
|
||||
F32 r, g, b, a;
|
||||
};
|
||||
|
||||
struct {
|
||||
V3f xyz;
|
||||
F32 _w;
|
||||
};
|
||||
|
||||
F32 e[4];
|
||||
};
|
||||
|
||||
typedef union Mat4x4F Mat4x4F;
|
||||
union Mat4x4F {
|
||||
F32 m[4][4];
|
||||
F32 e[16];
|
||||
V4f r[4];
|
||||
};
|
||||
|
||||
typedef struct Mat4x4FInv Mat4x4FInv;
|
||||
struct Mat4x4FInv {
|
||||
Mat4x4F fwd;
|
||||
Mat4x4F inv;
|
||||
};
|
||||
|
||||
typedef struct R2f R2f;
|
||||
struct R2f {
|
||||
V2f min;
|
||||
V2f max;
|
||||
};
|
||||
|
||||
function V2f V2F(F32 x, F32 y);
|
||||
function V3f V3F(F32 x, F32 y, F32 z);
|
||||
function V4f V4F(F32 x, F32 y, F32 z, F32 w);
|
||||
|
||||
function R2f R2F(V2f min, V2f max);
|
||||
|
||||
function V3f V3f_Neg(V3f x);
|
||||
function V3f V3f_Scale(V3f x, F32 s);
|
||||
|
||||
function F32 V3f_Dot(V3f a, V3f b);
|
||||
function F32 V4f_Dot(V4f a, V4f b);
|
||||
|
||||
function Mat4x4F M4x4F_Rows(V3f x, V3f y, V3f z);
|
||||
function Mat4x4F M4x4F_Columns(V3f x, V3f y, V3f z);
|
||||
|
||||
function V4f M4x4F_VMul4(Mat4x4F m, V4f v);
|
||||
function V3f M4x4F_VMul3(Mat4x4F m, V3f v);
|
||||
|
||||
function Mat4x4FInv M4x4F_Perspective(F32 fov, F32 aspect, F32 nearp, F32 farp);
|
||||
function Mat4x4FInv M4x4F_CameraView(V3f x, V3f y, V3f z, V3f p);
|
||||
|
||||
#endif // LD_CORE_MATH_H_
|
||||
@@ -29,18 +29,6 @@ struct Str8 {
|
||||
U8 *data;
|
||||
};
|
||||
|
||||
typedef struct V2f V2f;
|
||||
struct V2f {
|
||||
F32 x;
|
||||
F32 y;
|
||||
};
|
||||
|
||||
typedef struct V2i V2i;
|
||||
struct V2i {
|
||||
U32 x;
|
||||
U32 y;
|
||||
};
|
||||
|
||||
#define U8_MAX ((U8) -1)
|
||||
#define U16_MAX ((U16) -1)
|
||||
#define U32_MAX ((U32) -1)
|
||||
|
||||
132
code/draw/core.c
Normal file
132
code/draw/core.c
Normal file
@@ -0,0 +1,132 @@
|
||||
void D_Begin(D_Context *draw, Vk_Frame *frame, U32 max_rects) {
|
||||
Vk_Buffer *rbo = &frame->rbo;
|
||||
|
||||
draw->rbo = rbo;
|
||||
draw->n_rects = 0;
|
||||
draw->max_rects = max_rects;
|
||||
draw->rects = rbo->data;
|
||||
}
|
||||
|
||||
void D_End(D_Context *draw, Vk_Frame *frame) {
|
||||
VkCommandBuffer cmd = frame->cmd;
|
||||
Vk_Pipeline *basic = &draw->pipelines[0];
|
||||
|
||||
// We can probably stop doing this at some point
|
||||
VkDescriptorSet set;
|
||||
VkDescriptorSetAllocateInfo alloc_info = { 0 };
|
||||
alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
||||
alloc_info.descriptorPool = frame->descriptors;
|
||||
alloc_info.descriptorSetCount = 1;
|
||||
alloc_info.pSetLayouts = &basic->layout.set;
|
||||
|
||||
vk.AllocateDescriptorSets(vk.device, &alloc_info, &set);
|
||||
|
||||
// 'update' the descriptor sets for binding
|
||||
M_TempScope(0, 0) {
|
||||
VkWriteDescriptorSet writes[2] = { 0 };
|
||||
|
||||
VkDescriptorBufferInfo rbo_info = { 0 };
|
||||
rbo_info.buffer = draw->rbo->handle;
|
||||
rbo_info.offset = 0;
|
||||
rbo_info.range = VK_WHOLE_SIZE;
|
||||
|
||||
VkDescriptorImageInfo *image_info = M_ArenaPush(temp.arena, VkDescriptorImageInfo, .count = draw->n_images);
|
||||
|
||||
for (U32 it = 0; it < draw->n_images; ++it) {
|
||||
image_info[it].imageView = draw->images[it].image.view;
|
||||
image_info[it].sampler = vk.sampler;
|
||||
image_info[it].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
}
|
||||
|
||||
writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
writes[0].dstSet = set;
|
||||
writes[0].dstBinding = 0;
|
||||
writes[0].descriptorCount = 1;
|
||||
writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
||||
writes[0].pBufferInfo = &rbo_info;
|
||||
|
||||
writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
writes[1].dstSet = set;
|
||||
writes[1].dstBinding = 1;
|
||||
writes[1].descriptorCount = draw->n_images;
|
||||
writes[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
writes[1].pImageInfo = image_info;
|
||||
|
||||
vk.UpdateDescriptorSets(vk.device, ArraySize(writes), writes, 0, 0);
|
||||
}
|
||||
|
||||
vk.CmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, basic->handle);
|
||||
vk.CmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, basic->layout.pipeline, 0, 1, &set, 0, 0);
|
||||
vk.CmdPushConstants(cmd, basic->layout.pipeline, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(Mat4x4F), &draw->camera->proj.fwd);
|
||||
|
||||
VkViewport viewport = { 0, 0, (F32) draw->window_width, (F32) draw->window_height, 0.0f, 1.0f };
|
||||
VkRect2D scissor = { 0, 0, draw->window_width, draw->window_height };
|
||||
|
||||
vk.CmdSetViewport(cmd, 0, 1, &viewport);
|
||||
vk.CmdSetScissor(cmd, 0, 1, &scissor);
|
||||
|
||||
vk.CmdDraw(cmd, 6, draw->n_rects, 0, 0);
|
||||
}
|
||||
|
||||
internal U32 V4f_UnormColour(V4f c) {
|
||||
// @Todo: SRGB handling
|
||||
U32 result =
|
||||
((U8) (255.0f * c.a)) << 24 |
|
||||
((U8) (255.0f * c.r)) << 16 |
|
||||
((U8) (255.0f * c.g)) << 8 |
|
||||
((U8) (255.0f * c.b)) << 0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void _D_Rect(D_Context *draw, D_RectOpts *opts) {
|
||||
if (draw->n_rects < draw->max_rects) {
|
||||
D_Rect *rect = &draw->rects[draw->n_rects];
|
||||
|
||||
rect->texture = opts->texture;
|
||||
|
||||
rect->x = opts->p.x;
|
||||
rect->y = opts->p.y;
|
||||
|
||||
rect->uv[0] = opts->uv.min.x;
|
||||
rect->uv[1] = opts->uv.min.y;
|
||||
rect->uv[2] = opts->uv.max.x;
|
||||
rect->uv[3] = opts->uv.max.y;
|
||||
|
||||
rect->angle = opts->angle;
|
||||
|
||||
if (opts->flags & D_RECT_PER_VERTEX_COLOUR) {
|
||||
rect->c[0] = V4f_UnormColour(opts->vtxc[0]);
|
||||
rect->c[1] = V4f_UnormColour(opts->vtxc[1]);
|
||||
rect->c[2] = V4f_UnormColour(opts->vtxc[2]);
|
||||
rect->c[3] = V4f_UnormColour(opts->vtxc[3]);
|
||||
}
|
||||
else {
|
||||
U32 unorm = V4f_UnormColour(opts->c);
|
||||
|
||||
rect->c[0] = unorm;
|
||||
rect->c[1] = unorm;
|
||||
rect->c[2] = unorm;
|
||||
rect->c[3] = unorm;
|
||||
}
|
||||
|
||||
if (opts->flags & D_RECT_IGNORE_ASPECT) {
|
||||
rect->w = opts->w;
|
||||
rect->h = opts->h;
|
||||
}
|
||||
else {
|
||||
Vk_Image *image = &draw->images[opts->texture].image;
|
||||
|
||||
if (image->width > image->height) {
|
||||
rect->w = opts->scale * ((F32) image->width / (F32) image->height);
|
||||
rect->h = opts->scale;
|
||||
}
|
||||
else {
|
||||
rect->w = opts->scale;
|
||||
rect->h = opts->scale * ((F32) image->height / (F32) image->width);
|
||||
}
|
||||
}
|
||||
|
||||
draw->n_rects += 1;
|
||||
}
|
||||
}
|
||||
85
code/draw/core.h
Normal file
85
code/draw/core.h
Normal file
@@ -0,0 +1,85 @@
|
||||
#if !defined(LD_DRAW_CORE_H_)
|
||||
#define LD_DRAW_CORE_H_
|
||||
|
||||
#define D_MAX_RECTS 1024
|
||||
|
||||
typedef struct D_Image D_Image;
|
||||
struct D_Image {
|
||||
Str8 name;
|
||||
Vk_Image image;
|
||||
};
|
||||
|
||||
typedef struct D_Rect D_Rect;
|
||||
struct D_Rect {
|
||||
U32 texture;
|
||||
|
||||
U32 c[4]; // per-vertex colours
|
||||
F32 uv[4];
|
||||
|
||||
F32 angle;
|
||||
F32 x, y;
|
||||
F32 w, h;
|
||||
|
||||
U32 p0, p1;
|
||||
};
|
||||
|
||||
StaticAssert(sizeof(D_Rect) == 64);
|
||||
|
||||
struct G_Camera;
|
||||
|
||||
typedef struct D_Context D_Context;
|
||||
struct D_Context {
|
||||
Vk_Buffer *rbo;
|
||||
|
||||
U32 n_pipelines;
|
||||
Vk_Pipeline *pipelines;
|
||||
|
||||
U32 n_images;
|
||||
D_Image *images;
|
||||
|
||||
U32 max_rects;
|
||||
U32 n_rects;
|
||||
D_Rect *rects;
|
||||
|
||||
U32 window_width;
|
||||
U32 window_height;
|
||||
|
||||
struct G_Camera *camera;
|
||||
};
|
||||
|
||||
typedef U32 D_RectFlags;
|
||||
enum D_RectFlags {
|
||||
D_RECT_IGNORE_ASPECT = (1 << 0), // by default only width is used as a "dimension"
|
||||
D_RECT_PER_VERTEX_COLOUR = (1 << 1), // split colours per vertex
|
||||
};
|
||||
|
||||
typedef struct D_RectOpts D_RectOpts;
|
||||
struct D_RectOpts {
|
||||
D_RectFlags flags;
|
||||
|
||||
U32 texture;
|
||||
|
||||
R2f uv;
|
||||
V2f p;
|
||||
|
||||
F32 angle;
|
||||
|
||||
union {
|
||||
F32 w, h;
|
||||
F32 scale, _h;
|
||||
V2f dim;
|
||||
};
|
||||
|
||||
union {
|
||||
V4f c;
|
||||
V4f vtxc[4];
|
||||
};
|
||||
};
|
||||
|
||||
function void D_Begin(D_Context *draw, Vk_Frame *frame, U32 max_rects);
|
||||
function void D_End(D_Context *draw, Vk_Frame *frame);
|
||||
|
||||
function void _D_Rect(D_Context *draw, D_RectOpts *opts);
|
||||
#define D_Rect(draw, x, y, ...) _D_Rect(draw, &(D_RectOpts) { .p = V2F(x, y), .uv = R2F(V2F(0, 0), V2F(1, 1)), .scale = 1, .c = V4F(1, 1, 1, 1), ##__VA_ARGS__ })
|
||||
|
||||
#endif // LD_DRAW_CORE_H_
|
||||
161
code/first.c
161
code/first.c
@@ -11,15 +11,18 @@
|
||||
#include "os/core.h"
|
||||
|
||||
#include "vulkan/core.h"
|
||||
#include "draw/core.h"
|
||||
|
||||
#include "game/core.h"
|
||||
|
||||
#include "game/world.h"
|
||||
#include "game/impl/world.c"
|
||||
#include "game/impl/npc.c"
|
||||
#include "game/testnavmesh.h"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
if (!SDL_Init(SDL_INIT_VIDEO))
|
||||
{
|
||||
@@ -37,7 +40,6 @@ int main(int argc, char **argv) {
|
||||
Vk_Setup(window);
|
||||
|
||||
G_State *game = 0;
|
||||
G_Image *img = 0;
|
||||
{
|
||||
M_Arena *arena = M_ArenaAlloc(GB(64), .initial = MB(4));
|
||||
game = M_ArenaPush(arena, G_State);
|
||||
@@ -47,75 +49,71 @@ int main(int argc, char **argv) {
|
||||
G_ImagesLoad(game);
|
||||
G_PipelinesLoad(game);
|
||||
|
||||
for (U32 it = 0; it < game->n_images; ++it) {
|
||||
if (Str8_Equal(game->images[it].name, S("saloon_ext"), 0)) {
|
||||
img = &game->images[it];
|
||||
break;
|
||||
}
|
||||
}
|
||||
G_Camera *camera = &game->camera;
|
||||
|
||||
if (!img) { img = &game->images[0]; }
|
||||
camera->x = V3F(1, 0, 0);
|
||||
camera->y = V3F(0, 1, 0);
|
||||
camera->z = V3F(0, 0, 1);
|
||||
camera->p = V3F(0, 0, 48);
|
||||
|
||||
Vk_Buffer *vbo = &game->vbo;
|
||||
vbo->size = KB(4096);
|
||||
vbo->usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
|
||||
vbo->host_visible = true;
|
||||
camera->fov = 60.0f;
|
||||
|
||||
Vk_BufferCreate(vbo);
|
||||
camera->nearp = 0.01f;
|
||||
camera->farp = 1000.0f;
|
||||
|
||||
G_Vertex *vertices = cast(G_Vertex *) vbo->data;
|
||||
|
||||
vertices[0] = (G_Vertex) { -0.25f, -0.25f, 1.0f, 1.0f, 0.0f, 0.0f, 0xFFFFFFFF, 0};
|
||||
vertices[1] = (G_Vertex) { 0.25f, -0.25f, 1.0f, 1.0f, 1.0f, 0.0f, 0xFFFFFFFF, 0};
|
||||
vertices[2] = (G_Vertex) { -0.25f, 0.25f, 1.0f, 1.0f, 0.0f, 1.0f, 0xFFFFFFFF, 0};
|
||||
|
||||
vertices[3] = (G_Vertex) { 0.25f, -0.25f, 1.0f, 1.0f, 1.0f, 0.0f, 0xFFFFFFFF, 0};
|
||||
vertices[4] = (G_Vertex) { 0.25f, 0.25f, 1.0f, 1.0f, 1.0f, 1.0f, 0xFFFFFFFF, 0};
|
||||
vertices[5] = (G_Vertex) { -0.25f, 0.25f, 1.0f, 1.0f, 0.0f, 1.0f, 0xFFFFFFFF, 0};
|
||||
game->draw.camera = camera;
|
||||
}
|
||||
|
||||
Vk_Buffer rbo = {0};
|
||||
rbo.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
|
||||
rbo.size = KB(4);
|
||||
rbo.host_visible = true;
|
||||
|
||||
Vk_BufferCreate(&rbo);
|
||||
|
||||
bool running = true;
|
||||
Player player;
|
||||
player.pos.x = 0;
|
||||
player.pos.y = 0;
|
||||
World world = {
|
||||
.npcCount = 2,
|
||||
.npcs = {
|
||||
{
|
||||
.collision = {{10, 10}, {10, 10}},
|
||||
.name = S("Matt"),
|
||||
.mode = NPC_ACTION_WAITING,
|
||||
.waitTime = 0,
|
||||
.maxWaitTime = 5,
|
||||
.currentNavNode = 87
|
||||
},{
|
||||
.collision = {{15, 15}, {10, 10}},
|
||||
.name = S("James"),
|
||||
.mode = NPC_ACTION_WAITING,
|
||||
.waitTime = 0,
|
||||
.maxWaitTime = 10,
|
||||
.currentNavNode = 0
|
||||
}
|
||||
},
|
||||
.navMesh = TestNavMesh,
|
||||
.npcPOI = {100}
|
||||
};
|
||||
World world = {
|
||||
.npcCount = 2,
|
||||
.npcs = {
|
||||
{.collision = {{10, 10}, {10, 10}},
|
||||
.name = S("Matt"),
|
||||
.mode = NPC_ACTION_WAITING,
|
||||
.waitTime = 0,
|
||||
.maxWaitTime = 5,
|
||||
.currentNavNode = 87},
|
||||
{.collision = {{15, 15}, {10, 10}},
|
||||
.name = S("James"),
|
||||
.mode = NPC_ACTION_WAITING,
|
||||
.waitTime = 0,
|
||||
.maxWaitTime = 10,
|
||||
.currentNavNode = 0}},
|
||||
.navMesh = &TestNavMesh,
|
||||
.npcPOI = {100},
|
||||
.player = {.pos = {0, 0}}};
|
||||
|
||||
printf("%zu size in bytes\n", sizeof(TestNavMesh));
|
||||
|
||||
while (running)
|
||||
{
|
||||
SDL_Event e;
|
||||
while (SDL_PollEvent(&e))
|
||||
{
|
||||
PlayerUpdate(&e, &player);
|
||||
if (e.type == SDL_EVENT_QUIT)
|
||||
{
|
||||
running = false;
|
||||
}
|
||||
ProcessEvents(&e, &world);
|
||||
}
|
||||
UpdateNPCs(1.0/60.0, &world);
|
||||
UpdateWorld(1.0 / 60.0, &world);
|
||||
|
||||
int w, h;
|
||||
SDL_GetWindowSizeInPixels(window, &w, &h);
|
||||
|
||||
game->draw.window_width = w;
|
||||
game->draw.window_height = h;
|
||||
|
||||
G_CalulateCamera(&game->camera, (F32)w / (F32)h);
|
||||
|
||||
Vk_Frame *frame = Vk_FrameBegin(window);
|
||||
VkCommandBuffer cmd = frame->cmd;
|
||||
|
||||
@@ -142,62 +140,16 @@ int main(int argc, char **argv) {
|
||||
|
||||
vk.CmdBeginRendering(cmd, &rendering_info);
|
||||
|
||||
Vk_Pipeline *basic = &game->pipelines[0];
|
||||
D_Begin(&game->draw, frame, D_MAX_RECTS);
|
||||
|
||||
VkDescriptorSet set;
|
||||
VkDescriptorSetAllocateInfo alloc_info = { 0 };
|
||||
alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
||||
alloc_info.descriptorPool = frame->descriptors;
|
||||
alloc_info.descriptorSetCount = 1;
|
||||
alloc_info.pSetLayouts = &basic->layout.set;
|
||||
D_Rect(&game->draw, 0.0f, 0.0f, .texture = 1);
|
||||
D_Rect(&game->draw, -8.0f, 0.0f, .texture = 2, .scale = 2.0f);
|
||||
D_Rect(&game->draw, 6.0f, 0.0f, .texture = 3);
|
||||
|
||||
vk.AllocateDescriptorSets(vk.device, &alloc_info, &set);
|
||||
|
||||
// 'update' the descriptor sets for binding
|
||||
{
|
||||
VkWriteDescriptorSet writes[2] = { 0 };
|
||||
|
||||
VkDescriptorBufferInfo vbo_info = { 0 };
|
||||
vbo_info.buffer = game->vbo.handle;
|
||||
vbo_info.offset = 0;
|
||||
vbo_info.range = 256;
|
||||
|
||||
VkDescriptorImageInfo image_info = { 0 };
|
||||
image_info.imageView = img->image.view;
|
||||
image_info.sampler = vk.sampler;
|
||||
image_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
|
||||
writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
writes[0].dstSet = set;
|
||||
writes[0].dstBinding = 0;
|
||||
writes[0].descriptorCount = 1;
|
||||
writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
||||
writes[0].pBufferInfo = &vbo_info;
|
||||
|
||||
writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||
writes[1].dstSet = set;
|
||||
writes[1].dstBinding = 1;
|
||||
writes[1].descriptorCount = 1;
|
||||
writes[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
writes[1].pImageInfo = &image_info;
|
||||
|
||||
vk.UpdateDescriptorSets(vk.device, ArraySize(writes), writes, 0, 0);
|
||||
}
|
||||
|
||||
vk.CmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, basic->handle);
|
||||
vk.CmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, basic->layout.pipeline, 0, 1, &set, 0, 0);
|
||||
|
||||
VkViewport viewport = { 0, 0, (F32) w, (F32) h, 0.0f, 1.0f };
|
||||
VkRect2D scissor = { 0, 0, w, h };
|
||||
|
||||
vk.CmdSetViewport(cmd, 0, 1, &viewport);
|
||||
vk.CmdSetScissor(cmd, 0, 1, &scissor);
|
||||
|
||||
vk.CmdDraw(cmd, 6, 1, 0, 0);
|
||||
D_End(&game->draw, frame);
|
||||
|
||||
vk.CmdEndRendering(cmd);
|
||||
|
||||
|
||||
Vk_FrameEnd();
|
||||
}
|
||||
|
||||
@@ -210,4 +162,5 @@ int main(int argc, char **argv) {
|
||||
#include "core/core.c"
|
||||
#include "os/core.c"
|
||||
#include "vulkan/core.c"
|
||||
#include "draw/core.c"
|
||||
#include "game/core.c"
|
||||
|
||||
@@ -3,15 +3,15 @@
|
||||
#include "../core/types.h"
|
||||
#include "../core/macros.h"
|
||||
|
||||
|
||||
typedef struct AABB AABB;
|
||||
struct AABB {
|
||||
struct AABB
|
||||
{
|
||||
V2f pos;
|
||||
V2f size;
|
||||
};
|
||||
|
||||
|
||||
function bool AABB_Collide(AABB a, AABB b);
|
||||
function bool AABB_Point(AABB a, V2f v);
|
||||
function bool AABB_Slab(V2f origin, V2f point, AABB a);
|
||||
|
||||
#endif // LD_GAME_AABB_H_
|
||||
#endif // LD_GAME_AABB_H_
|
||||
|
||||
59
code/game/bandit.h
Normal file
59
code/game/bandit.h
Normal file
@@ -0,0 +1,59 @@
|
||||
#if !defined(LD_GAME_BANDIT_H_)
|
||||
#define LD_GAME_BANDIT_H_
|
||||
|
||||
typedef enum BANDIT_ACTION BANDIT_ACTION;
|
||||
enum BANDIT_ACTION {
|
||||
BANDIT_WAITING,
|
||||
BANDIT_WALKING,
|
||||
BANDIT_RUNNING,
|
||||
BANDIT_SHOOTOUT,
|
||||
};
|
||||
|
||||
typedef struct Bandit Bandit;
|
||||
struct Bandit {
|
||||
//// Personal
|
||||
AABB collision;
|
||||
Str8 name;
|
||||
|
||||
//// Actions
|
||||
BANDIT_ACTION mode;
|
||||
// How long they've been waiting.
|
||||
F32 waitTime;
|
||||
// How long they will wait in this location.
|
||||
F32 maxWaitTime;
|
||||
|
||||
// Places the bandit walks to / from
|
||||
// E.g. hide outs, home, saloon
|
||||
U32 pointsOfInterest[12];
|
||||
//// Navigation
|
||||
// The bandits's current path
|
||||
NavPath path;
|
||||
// Which node the bandit is on in the path
|
||||
U32 currentNavNode;
|
||||
// The current index of the bandit's current node
|
||||
U32 pathIndex;
|
||||
// Target navNode index the bandit is walking to
|
||||
U32 targetNavNode;
|
||||
// How long the bandit has been walking to the next index
|
||||
F32 walkTimer;
|
||||
|
||||
// How many shots they can take.
|
||||
U32 health;
|
||||
// How paranoid they are about being hunted,
|
||||
// this will make them more trigger happy.
|
||||
F32 paranoidLevel;
|
||||
// Max 6?
|
||||
U8 bullets;
|
||||
// How long it its between shots.
|
||||
F32 shootDelay;
|
||||
// After each shot this is set to shootDelay;
|
||||
F32 shootCooldownTimer;
|
||||
// How long it takes them to reload.
|
||||
F32 reloadTime;
|
||||
// Accuracy, their shots can vary between this angle either side (rads)
|
||||
F32 accuracyRange;
|
||||
// A the circle around the bandit where they will trigger the quicktime reaction scene
|
||||
F32 agroRadius;
|
||||
};
|
||||
|
||||
#endif // LD_GAME_BANDIT_H_
|
||||
129
code/game/core.c
129
code/game/core.c
@@ -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, ©);
|
||||
|
||||
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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -1,15 +1,36 @@
|
||||
#include "game/aabb.h"
|
||||
#include "core/types.h"
|
||||
#include <math.h>
|
||||
|
||||
bool AABB_Collide(AABB a, AABB b) {
|
||||
bool AABB_Collide(AABB a, AABB b)
|
||||
{
|
||||
bool collision_x = a.pos.x + a.size.x >= b.pos.x && b.pos.x + b.size.x >= a.pos.x;
|
||||
bool collision_y = a.pos.y + a.size.x >= b.pos.y && b.pos.y + b.size.y >= a.pos.y;
|
||||
return collision_x && collision_y;
|
||||
}
|
||||
|
||||
bool AABB_Point(AABB a, V2f v) {
|
||||
bool AABB_Point(AABB a, V2f v)
|
||||
{
|
||||
bool collision_x = a.pos.x + a.size.x >= v.x && a.pos.x <= v.x;
|
||||
bool collision_y = a.pos.x + a.size.y >= v.y && a.pos.y <= v.y;
|
||||
return collision_x && collision_y;
|
||||
}
|
||||
|
||||
bool AABB_Slab(V2f origin, V2f point, AABB a)
|
||||
{
|
||||
V2f start = a.pos;
|
||||
V2f finish = {a.pos.x + a.size.x, a.pos.y + a.size.y};
|
||||
V2f invdirection = {1 / (origin.x - point.x), 1 / (origin.y - point.y)};
|
||||
// x
|
||||
F32 tLow = (start.x - origin.x) * invdirection.x;
|
||||
F32 tHigh = (finish.x - origin.x) * invdirection.x;
|
||||
F32 tMin = min(tLow, tHigh);
|
||||
F32 tMax = max(tLow, tHigh);
|
||||
// y
|
||||
tLow = (start.y - origin.y) * invdirection.y;
|
||||
tHigh = (finish.y - origin.y) * invdirection.y;
|
||||
|
||||
tMin = max(tMin, min(tLow, tHigh));
|
||||
tMax = min(tMax, max(tLow, tHigh));
|
||||
|
||||
return tMax >= tMin;
|
||||
}
|
||||
@@ -6,7 +6,8 @@
|
||||
#define MAX_UNFINISHED 128
|
||||
|
||||
typedef struct navSearchNodeState navSearchNodeState;
|
||||
struct navSearchNodeState{
|
||||
struct navSearchNodeState
|
||||
{
|
||||
bool visited;
|
||||
U64 distance;
|
||||
U32 shortest;
|
||||
@@ -14,16 +15,18 @@ struct navSearchNodeState{
|
||||
};
|
||||
|
||||
typedef struct navSearchState navSearchState;
|
||||
struct navSearchState{
|
||||
struct navSearchState
|
||||
{
|
||||
navSearchNodeState nodeStates[NAV_MAX_NODES];
|
||||
};
|
||||
|
||||
navSearchState initState(U32 start, U32 meshSize) {
|
||||
navSearchState state = {};
|
||||
for(U32 i = 0; i < meshSize; i++) {
|
||||
navSearchState initState(U32 start, U32 meshSize)
|
||||
{
|
||||
navSearchState state;
|
||||
for (U32 i = 0; i < meshSize; i++)
|
||||
{
|
||||
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;
|
||||
}
|
||||
@@ -31,21 +34,26 @@ navSearchState initState(U32 start, U32 meshSize) {
|
||||
return state;
|
||||
}
|
||||
|
||||
U32 getLowestState(U32 unfinishedIndexes[128], U32 unfinishedCount, navSearchState state, U32 *offset) {
|
||||
U32 lowest = U32_MAX;
|
||||
U32 getLowestState(U32 unfinishedIndexes[128], U32 unfinishedCount, navSearchState state, U32 *offset)
|
||||
{
|
||||
U32 lowest = U32_MAX;
|
||||
U32 lowestI = U32_MAX;
|
||||
bool startFound = false;
|
||||
for(U32 i = *offset; i < unfinishedCount; i++) {
|
||||
for (U32 i = *offset; i < unfinishedCount; i++)
|
||||
{
|
||||
navSearchNodeState checkNode = state.nodeStates[unfinishedIndexes[i]];
|
||||
if(checkNode.visited) {
|
||||
if(!startFound) {
|
||||
if (checkNode.visited)
|
||||
{
|
||||
if (!startFound)
|
||||
{
|
||||
*offset = i;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
startFound = true;
|
||||
if (lowest > checkNode.distance) {
|
||||
lowest = cast(U32) checkNode.distance;
|
||||
if (lowest > checkNode.distance)
|
||||
{
|
||||
lowest = cast(U32) checkNode.distance;
|
||||
lowestI = unfinishedIndexes[i];
|
||||
}
|
||||
}
|
||||
@@ -53,8 +61,9 @@ 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
|
||||
@@ -64,33 +73,42 @@ NavPath Nav_Path(NavMesh mesh, U32 start, U32 end) {
|
||||
U32 unfinishedOffset = 0;
|
||||
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];
|
||||
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);
|
||||
if(testNode->distance > distance) {
|
||||
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];
|
||||
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);
|
||||
if (testNode->distance > distance)
|
||||
{
|
||||
testNode->distance = distance;
|
||||
testNode->shortest = lowestNodeIndex;
|
||||
}
|
||||
if(!testNode->addedToUnvisited) {
|
||||
unfinishedIndexes[unfinishedCount] = connection.NodeIndex;
|
||||
if (!testNode->addedToUnvisited)
|
||||
{
|
||||
unfinishedIndexes[unfinishedCount] = connection->NodeIndex;
|
||||
unfinishedCount++;
|
||||
testNode->addedToUnvisited = true;
|
||||
}
|
||||
}
|
||||
state.nodeStates[lowestNodeIndex].visited = true;
|
||||
lowestNodeIndex = getLowestState(unfinishedIndexes, unfinishedCount, state, &unfinishedOffset);
|
||||
if(lowestNodeIndex == end) {
|
||||
if (lowestNodeIndex == end)
|
||||
{
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
NavPath res_path = {0};
|
||||
U32 index = end;
|
||||
while(index!=start) {
|
||||
while (index != start)
|
||||
{
|
||||
res_path.indexes[res_path.nodeCount] = index;
|
||||
res_path.nodeCount++;
|
||||
index = state.nodeStates[index].shortest;
|
||||
|
||||
@@ -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,17 +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;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateNPCs(F32 delta, World *world) {
|
||||
for(int i = 0; i < world->npcCount; i++) {
|
||||
updateNPC(delta, &world->npcs[i], world);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,22 +1,37 @@
|
||||
#include "../player.h"
|
||||
#include <SDL3/SDL_keycode.h>
|
||||
#include <stdio.h>
|
||||
|
||||
void PlayerUpdate(SDL_Event *event, Player *player)
|
||||
{
|
||||
SDL_KeyboardEvent key = event->key;
|
||||
if (key.key == SDLK_W)
|
||||
{
|
||||
player->pos.y += 10;
|
||||
}
|
||||
if (key.key == SDLK_A)
|
||||
{
|
||||
player->pos.x -= 10;
|
||||
}
|
||||
if (key.key == SDLK_D)
|
||||
{
|
||||
player->pos.x += 10;
|
||||
}
|
||||
if (key.key == SDLK_S)
|
||||
{
|
||||
player->pos.y -= 10;
|
||||
}
|
||||
SDL_KeyboardEvent key = event->key;
|
||||
SDL_MouseButtonEvent mouseBtn = event->button;
|
||||
switch (key.key)
|
||||
{
|
||||
case SDLK_W:
|
||||
{
|
||||
player->pos.y += 10;
|
||||
break;
|
||||
}
|
||||
case SDLK_A:
|
||||
{
|
||||
player->pos.x -= 10;
|
||||
break;
|
||||
}
|
||||
case SDLK_D:
|
||||
{
|
||||
player->pos.x += 10;
|
||||
break;
|
||||
}
|
||||
case SDLK_S:
|
||||
{
|
||||
player->pos.y -= 10;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (mouseBtn.clicks == 1)
|
||||
{
|
||||
// shooting
|
||||
player->bulletsLoaded -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
22
code/game/impl/world.c
Normal file
22
code/game/impl/world.c
Normal file
@@ -0,0 +1,22 @@
|
||||
#include "../world.h"
|
||||
#include "../npc.h"
|
||||
#include "../player.h"
|
||||
#include <SDL3/SDL_events.h>
|
||||
|
||||
void UpdateWorld(F32 delta, World *world)
|
||||
{
|
||||
// UpdateNPCs(delta, world);
|
||||
}
|
||||
|
||||
void UpdateNPCs(F32 delta, World *world)
|
||||
{
|
||||
for (int i = 0; i < world->npcCount; i++)
|
||||
{
|
||||
updateNPC(delta, &world->npcs[i], world);
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessEvents(SDL_Event *event, World *world)
|
||||
{
|
||||
PlayerUpdate(event, &world->player);
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
#define LD_GAME_NPC_H_
|
||||
#include "aabb.h"
|
||||
#include "nav.h"
|
||||
#include "npc_look.h"
|
||||
#include "../core/types.h"
|
||||
|
||||
#define NPC_SPEED 0.2
|
||||
#define NPC_SPEED 0.2f
|
||||
|
||||
typedef enum NPC_ACTION NPC_ACTION;
|
||||
enum NPC_ACTION {
|
||||
@@ -14,18 +15,36 @@ enum NPC_ACTION {
|
||||
NPC_ACTION_WALKING,
|
||||
};
|
||||
|
||||
|
||||
typedef struct NPC NPC;
|
||||
struct NPC {
|
||||
//// Personal
|
||||
AABB collision;
|
||||
Str8 name;
|
||||
NPC_LOOK look;
|
||||
|
||||
//// Actions
|
||||
NPC_ACTION mode;
|
||||
// How long they've been waiting
|
||||
F32 waitTime;
|
||||
// How long they will wait until changing action
|
||||
F32 maxWaitTime;
|
||||
|
||||
//// Navigation
|
||||
// The NPC's current path
|
||||
NavPath path;
|
||||
// Which node the NPC is on in the path
|
||||
U32 currentNavNode;
|
||||
// The current index of the NPC's current node
|
||||
U32 pathIndex;
|
||||
// Target navNode index the npc is walking to
|
||||
U32 targetNavNode;
|
||||
// How long the npc has been walking to the next index
|
||||
F32 walkTimer;
|
||||
|
||||
//// Knowledge
|
||||
// What the NPC knows about the bandit.
|
||||
NPC_LOOK banditKnowledge;
|
||||
};
|
||||
|
||||
#endif // LD_GAME_NPC_H_
|
||||
|
||||
82
code/game/npc_look.h
Normal file
82
code/game/npc_look.h
Normal file
@@ -0,0 +1,82 @@
|
||||
#if !defined(LD_GAME_NPC_LOOK_H_)
|
||||
#define LD_GAME_NPC_LOOK_H_
|
||||
|
||||
typedef struct NPC_LOOK NPC_LOOK;
|
||||
typedef enum NPC_HAIR_COLOUR NPC_HAIR_COLOUR;
|
||||
typedef enum NPC_JACKET_COLOUR NPC_JACKET_COLOUR;
|
||||
typedef enum NPC_JEANS_COLOUR NPC_JEANS_COLOUR;
|
||||
typedef enum NPC_EYE_COLOUR NPC_EYE_COLOUR;
|
||||
typedef enum NPC_SKIN_TONE NPC_SKIN_TONE;
|
||||
typedef enum NPC_HAT NPC_HAT;
|
||||
typedef enum NPC_FACIAL_FEATURE NPC_FACIAL_FEATURE;
|
||||
|
||||
enum NPC_HAIR_COLOUR {
|
||||
NPC_HAIR_COLOUR_UNKNOWN,
|
||||
NPC_HAIR_COLOUR_BLONDE,
|
||||
NPC_HAIR_COLOUR_BLACK,
|
||||
NPC_HAIR_COLOUR_BRUNETTE,
|
||||
NPC_HAIR_COLOUR_GIGNER,
|
||||
};
|
||||
|
||||
enum NPC_JACKET_COLOUR {
|
||||
NPC_JACKET_COLOUR_UNKNOWN,
|
||||
NPC_JACKET_COLOUR_TAN,
|
||||
NPC_JACKET_COLOUR_BLUE,
|
||||
NPC_JACKET_COLOUR_WHITE,
|
||||
};
|
||||
|
||||
enum NPC_JEANS_COLOUR {
|
||||
NPC_JEANS_COLOUR_UNKNOWN,
|
||||
NPC_JEANS_COLOUR_TAN,
|
||||
NPC_JEANS_COLOUR_BLACK,
|
||||
NPC_JEANS_COLOUR_BLUE,
|
||||
NPC_JEANS_COLOUR_WHITE,
|
||||
};
|
||||
|
||||
enum NPC_EYE_COLOUR {
|
||||
NPC_EYE_COLOUR_UNKNOWN,
|
||||
NPC_EYE_COLOUR_GREEN,
|
||||
NPC_EYE_COLOUR_BLUE,
|
||||
NPC_EYE_COLOUR_BROWN,
|
||||
};
|
||||
|
||||
enum NPC_SHOE_COLOUR {
|
||||
NPC_SHOE_COLOUR_UNKNOWN,
|
||||
NPC_SHOE_COLOUR_BLACK,
|
||||
NPC_SHOE_COLOUR_BROWN,
|
||||
NPC_SHOE_COLOUR_WHITE,
|
||||
NPC_SHOE_COLOUR_NAVY,
|
||||
};
|
||||
|
||||
enum NPC_SKIN_TONE {
|
||||
NPC_SKIN_TONE_UNKNOWN,
|
||||
NPC_SKIN_TONE_WHITE,
|
||||
NPC_SKIN_TONE_BLACK,
|
||||
};
|
||||
|
||||
enum NPC_FACIAL_FEATURE {
|
||||
NPC_FACIAL_FEATURE_UNKNOWN,
|
||||
NPC_FACIAL_FEATURE_BEARD,
|
||||
NPC_FACIAL_FEATURE_MUSTACHE,
|
||||
NPC_FACIAL_FEATURE_GLASSES,
|
||||
};
|
||||
|
||||
enum NPC_HAT {
|
||||
NPC_HAT_UNKNOWN,
|
||||
NPC_HAT_TEN_GALLON,
|
||||
NPC_TOP_HAT,
|
||||
NPC_FLAT_CAP,
|
||||
NPC_NONE,
|
||||
};
|
||||
|
||||
struct NPC_LOOK {
|
||||
NPC_HAIR_COLOUR hair;
|
||||
NPC_JACKET_COLOUR jacket;
|
||||
NPC_JEANS_COLOUR jeans;
|
||||
NPC_EYE_COLOUR eyes;
|
||||
NPC_SKIN_TONE skinTone;
|
||||
NPC_HAT hat;
|
||||
NPC_FACIAL_FEATURE facialFeature;
|
||||
};
|
||||
|
||||
#endif // LD_GAME_NPC_LOOK_H_
|
||||
@@ -10,6 +10,7 @@ typedef struct Player Player;
|
||||
struct Player
|
||||
{
|
||||
V2f pos;
|
||||
U32 bulletsLoaded;
|
||||
};
|
||||
|
||||
function void PlayerUpdate(SDL_Event *event, Player *player);
|
||||
|
||||
45000
code/game/testnavmesh.h
45000
code/game/testnavmesh.h
File diff suppressed because it is too large
Load Diff
@@ -1,24 +1,40 @@
|
||||
#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,
|
||||
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;
|
||||
|
||||
//// Player
|
||||
Player player;
|
||||
|
||||
//// NPCs
|
||||
U32 npcCount;
|
||||
NPC npcs[128];
|
||||
NavMesh navMesh;
|
||||
|
||||
////Bandit
|
||||
// The bandit the player is after.
|
||||
Bandit bandit;
|
||||
|
||||
// NPC points of interest, places to walk to.
|
||||
U32 npcPOI[256];
|
||||
};
|
||||
|
||||
function void updateWorld(F32 delta, World *world);
|
||||
function void UpdateWorld(F32 delta, World *world);
|
||||
function void ProcessEvents(SDL_Event *event, World *world);
|
||||
function void UpdateNPCs(F32 delta, World *world);
|
||||
function void updateNPC(F32 delta, NPC *npc, World *world);
|
||||
|
||||
#endif // LD_GAME_WORLD_H_
|
||||
|
||||
@@ -180,6 +180,7 @@ bool Vk_Setup(SDL_Window *window) {
|
||||
features12.storageBuffer8BitAccess = VK_TRUE;
|
||||
features12.uniformAndStorageBuffer8BitAccess = VK_TRUE;
|
||||
features12.descriptorIndexing = VK_TRUE;
|
||||
features12.runtimeDescriptorArray = VK_TRUE;
|
||||
|
||||
// @Todo: we will probably need to enable some of the 'nonuniform' indexing features
|
||||
|
||||
@@ -371,6 +372,16 @@ bool Vk_Setup(SDL_Window *window) {
|
||||
|
||||
vk.CreateDescriptorPool(vk.device, &descriptor_pool, 0, &frame->descriptors);
|
||||
|
||||
// rect buffer
|
||||
//
|
||||
|
||||
Vk_Buffer *rbo = &frame->rbo;
|
||||
rbo->usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
|
||||
rbo->size = D_MAX_RECTS * sizeof(D_Rect);
|
||||
rbo->host_visible = true;
|
||||
|
||||
Vk_BufferCreate(rbo);
|
||||
|
||||
VkSemaphoreCreateInfo semaphore = { 0 };
|
||||
semaphore.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
|
||||
|
||||
@@ -546,7 +557,7 @@ internal VkDeviceMemory Vk_Allocate(VkMemoryRequirements *mreq, VkMemoryProperty
|
||||
}
|
||||
}
|
||||
|
||||
if (type_index != -1) {
|
||||
if (type_index != U32_MAX) {
|
||||
VkMemoryAllocateInfo alloc_info = { 0 };
|
||||
alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||
alloc_info.allocationSize = mreq->size;
|
||||
@@ -555,6 +566,7 @@ internal VkDeviceMemory Vk_Allocate(VkMemoryRequirements *mreq, VkMemoryProperty
|
||||
vk.AllocateMemory(vk.device, &alloc_info, 0, &result);
|
||||
}
|
||||
|
||||
Assert(result != VK_NULL_HANDLE);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -565,6 +577,7 @@ void Vk_BufferCreate(Vk_Buffer *buffer) {
|
||||
create_info.size = buffer->size;
|
||||
|
||||
vk.CreateBuffer(vk.device, &create_info, 0, &buffer->handle);
|
||||
Assert(buffer->handle != VK_NULL_HANDLE);
|
||||
|
||||
VkMemoryRequirements req;
|
||||
vk.GetBufferMemoryRequirements(vk.device, buffer->handle, &req);
|
||||
@@ -579,6 +592,7 @@ void Vk_BufferCreate(Vk_Buffer *buffer) {
|
||||
if (buffer->host_visible) {
|
||||
vk.MapMemory(vk.device, buffer->memory, 0, buffer->size, 0, &buffer->data);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Vk_ImageCreate(Vk_Image *image) {
|
||||
|
||||
@@ -96,6 +96,8 @@ struct Vk_Frame {
|
||||
U32 next_scratch;
|
||||
Vk_CommandBuffer scratch[VK_NUM_SCRATCH];
|
||||
|
||||
Vk_Buffer rbo;
|
||||
|
||||
U32 image; // swapchain image index
|
||||
};
|
||||
|
||||
|
||||
@@ -62,7 +62,10 @@
|
||||
VK_FUNC(CmdDraw);
|
||||
VK_FUNC(CmdSetViewport);
|
||||
VK_FUNC(CmdSetScissor);
|
||||
VK_FUNC(CmdDrawIndexed);
|
||||
VK_FUNC(CmdBindIndexBuffer);
|
||||
|
||||
VK_FUNC(CmdPushConstants);
|
||||
VK_FUNC(CmdCopyBufferToImage);
|
||||
VK_FUNC(CmdPipelineBarrier2);
|
||||
VK_FUNC(CmdBeginRendering);
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
#version 460 core
|
||||
|
||||
#extension GL_EXT_nonuniform_qualifier : enable
|
||||
|
||||
layout(location = 0) in vec2 frag_uv;
|
||||
layout(location = 1) in vec4 frag_c;
|
||||
layout(location = 2) in flat uint texid;
|
||||
|
||||
layout(location = 0) out vec4 framebuffer;
|
||||
|
||||
layout(binding = 1) uniform sampler2D u_image;
|
||||
layout(binding = 1) uniform sampler2D u_images[];
|
||||
|
||||
void main() {
|
||||
framebuffer = frag_c * texture(u_image, frag_uv);
|
||||
framebuffer = frag_c * texture(u_images[texid], frag_uv);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,28 @@
|
||||
|
||||
#extension GL_EXT_scalar_block_layout : enable
|
||||
|
||||
uint indices[6] = { 0, 1, 3, 0, 3, 2 };
|
||||
|
||||
vec2 verticies[4] = vec2[](
|
||||
vec2(-0.5, -0.5),
|
||||
vec2( 0.5, -0.5),
|
||||
vec2(-0.5, 0.5),
|
||||
vec2( 0.5, 0.5)
|
||||
);
|
||||
|
||||
struct G_Rect {
|
||||
uint id;
|
||||
|
||||
uint c[4];
|
||||
float uv[4];
|
||||
|
||||
float angle;
|
||||
float x, y;
|
||||
float w, h;
|
||||
|
||||
float _pad0, _pad1;
|
||||
};
|
||||
|
||||
struct Vertex {
|
||||
vec4 p;
|
||||
vec2 uv;
|
||||
@@ -9,20 +31,34 @@ struct Vertex {
|
||||
uint pad;
|
||||
};
|
||||
|
||||
layout(push_constant, row_major)
|
||||
uniform Global {
|
||||
mat4 proj;
|
||||
};
|
||||
|
||||
layout(binding = 0, scalar)
|
||||
readonly buffer Vertices {
|
||||
Vertex vtx[];
|
||||
readonly buffer Rect {
|
||||
G_Rect rects[];
|
||||
};
|
||||
|
||||
layout(location = 0) out vec2 frag_uv;
|
||||
layout(location = 1) out vec4 frag_c;
|
||||
layout(location = 2) out flat uint texid;
|
||||
|
||||
vec4 unorm_colour(uint c) {
|
||||
vec4 result = vec4((c >> 0) & 0xFF, (c >> 8) & 0xFF, (c >> 16) & 0xFF, (c >> 24) & 0xFF) / 255.0f;
|
||||
return result;
|
||||
}
|
||||
|
||||
void main() {
|
||||
Vertex v = vtx[gl_VertexIndex];
|
||||
G_Rect rect = rects[gl_InstanceIndex];
|
||||
uint idx = indices[gl_VertexIndex];
|
||||
|
||||
gl_Position = v.p;
|
||||
vec2 p = (verticies[idx] * vec2(rect.w, rect.h)) + vec2(rect.x, rect.y);
|
||||
|
||||
frag_uv = v.uv;
|
||||
frag_c = vec4((v.c >> 24) & 0xFF, (v.c >> 16) & 0xFF, (v.c >> 8) & 0xFF, (v.c >> 0) & 0xFF) / 255.0f;
|
||||
frag_c = frag_c.abgr;
|
||||
gl_Position = proj * vec4(p, 1.0f, 1.0f);
|
||||
|
||||
frag_uv = vec2(rect.uv[(idx & 1) << 1], rect.uv[1 + (uint(idx / 2) << 1)]);
|
||||
frag_c = unorm_colour(rect.c[idx]);
|
||||
texid = rect.id;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user