some restructuring, fix a crash

This commit is contained in:
matthew 2025-08-02 08:47:19 +10:00
parent 625b75f2c6
commit d88413860b
15 changed files with 138 additions and 50 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -26,6 +26,7 @@ struct Game
Pipeline ui_pipeline; Pipeline ui_pipeline;
GlobalUniforms globals; GlobalUniforms globals;
PushConst pc;
f32 delta; f32 delta;
Timer timer; Timer timer;
@ -35,6 +36,7 @@ struct Game
Model model; Model model;
} }
Game Game
InitGame(PlatformWindow* window) InitGame(PlatformWindow* window)
{ {
@ -42,6 +44,11 @@ InitGame(PlatformWindow* window)
rd: InitRenderer(window), rd: InitRenderer(window),
window: window, window: window,
timer: CreateTimer(), timer: CreateTimer(),
globals: {
light_direction: Vec3(-0.57735),
light_color: Vec4(0.8, 0.8, 0.8, 1.0),
ambient_color: Vec4(0.7, 0.7, 0.7, 1.0),
},
}; };
GfxPipelineInfo triangle_info = { GfxPipelineInfo triangle_info = {
@ -123,7 +130,7 @@ Update(Game* g, Camera* cam)
Extent ext = GetExtent(&g.rd); Extent ext = GetExtent(&g.rd);
g.globals.view_matrix = ViewMatrix(cam); g.globals.view_matrix = ViewMatrix(cam);
Perspective(&g.globals.projection_matrix, Radians(70.0), cast(f32)(ext.x), cast(f32)(ext.y), 10000.0, 0.1); Perspective(&g.globals.projection_matrix, Radians(90.0), cast(f32)(ext.x), cast(f32)(ext.y), 0.1, 10000.0);
g.globals.projection_matrix[1, 1] *= -1.0; g.globals.projection_matrix[1, 1] *= -1.0;
g.globals.view_projection = g.globals.projection_matrix * g.globals.view_matrix; g.globals.view_projection = g.globals.projection_matrix * g.globals.view_matrix;
@ -138,6 +145,7 @@ RotationMatrix(Camera* cam)
Quat pitch_rotation, yaw_rotation; Quat pitch_rotation, yaw_rotation;
QuatFromAxis(&pitch_rotation, cam.pitch, Vec3(1.0, 0.0, 0.0)); QuatFromAxis(&pitch_rotation, cam.pitch, Vec3(1.0, 0.0, 0.0));
QuatFromAxis(&yaw_rotation, cam.yaw, Vec3(0.0, -1.0, 0.0)); QuatFromAxis(&yaw_rotation, cam.yaw, Vec3(0.0, -1.0, 0.0));
Mat4 pitch_mat = cast(Mat4)(yaw_rotation) * cast(Mat4)(pitch_rotation);
return cast(Mat4)(yaw_rotation) * cast(Mat4)(pitch_rotation); return cast(Mat4)(yaw_rotation) * cast(Mat4)(pitch_rotation);
} }
@ -185,11 +193,28 @@ Cycle(Game* g)
Bind(&g.rd, &g.pbr_pipeline); Bind(&g.rd, &g.pbr_pipeline);
DrawModel(&g.rd, &g.model); Quat q;
static f32 angle = 0.0;
angle += 1.0 * g.delta;
QuatFromAxis(&q, angle, Vec3(0.0, 1.0, 0.0));
g.pc.model_matrix = cast(Mat4)(q);
DrawModel(g, &g.model);
FinishFrame(&g.rd); FinishFrame(&g.rd);
} }
pragma(inline): void
DrawModel(Game* g, Model* model)
{
BindBuffers(&g.rd, &model.index_buffer, &model.vertex_buffer);
foreach(i, part; model.parts)
{
g.pc.mat_id = part.mat;
PushConstants(&g.rd, &g.pc);
DrawIndexed(&g.rd, part.length, 1, part.offset);
}
}
void void
Destroy(Game* g) Destroy(Game* g)
{ {

View File

@ -18,21 +18,19 @@ import core.stdc.string : memcpy;
void main(string[] argv) void main(string[] argv)
{ {
PlatformWindow window = CreateWindow("Video Game", 1920, 1080); PlatformWindow window = CreateWindow("Video Game", 1920, 1080);
Game g = InitGame(&window); Game g = InitGame(&window);
scope(exit) Destroy(&g);
while (true) while (true)
{ {
HandleEvents(&window); HandleEvents(&window);
if (window.close) if (window.close)
{ {
Logf("quitting");
break; break;
} }
Cycle(&g); Cycle(&g);
} }
Destroy(&g);
} }

View File

@ -94,7 +94,8 @@ void CheckErr(PlatformWindow *window, xcb_void_cookie_t *cookie, xcb_generic_err
pureFree(err); pureFree(err);
}; };
PlatformWindow CreateWindow(string name, u16 width, u16 height) PlatformWindow
CreateWindow(string name, u16 width, u16 height)
{ {
PlatformWindow window = { PlatformWindow window = {
w: width, w: width,
@ -210,6 +211,9 @@ PlatformWindow CreateWindow(string name, u16 width, u16 height)
xcb_xfixes_query_version(window.conn, 4, 0); xcb_xfixes_query_version(window.conn, 4, 0);
LockCursor(&window);
UnlockCursor(&window);
return window; return window;
}; };
@ -345,6 +349,8 @@ HandleEvents(PlatformWindow* window)
case XCB_BUTTON_PRESS: case XCB_BUTTON_PRESS:
case XCB_BUTTON_RELEASE: case XCB_BUTTON_RELEASE:
{ {
if (window.input_count == window.inputs.length) continue;
xcb_button_press_event_t* mouse_event = cast(xcb_button_press_event_t*)e; xcb_button_press_event_t* mouse_event = cast(xcb_button_press_event_t*)e;
bool pressed = e.response_type == XCB_BUTTON_PRESS; bool pressed = e.response_type == XCB_BUTTON_PRESS;
Input input = Input.None; Input input = Input.None;
@ -367,6 +373,7 @@ HandleEvents(PlatformWindow* window)
case XCB_MOTION_NOTIFY: case XCB_MOTION_NOTIFY:
{ {
if (ignore_mouse_events) continue; if (ignore_mouse_events) continue;
if (window.input_count == window.inputs.length) continue;
xcb_motion_notify_event_t* move_event = cast(xcb_motion_notify_event_t*)e; xcb_motion_notify_event_t* move_event = cast(xcb_motion_notify_event_t*)e;

View File

@ -4,7 +4,7 @@ import assets;
import util; import util;
import alloc; import alloc;
import vulkan; import vulkan;
import vulkan : Destroy, Init, Draw, DrawIndexed, Bind, BindUIBuffers, BeginRender, SetUniform, PrepComputeDrawImage, Dispatch, FinishFrame, BeginFrame, WaitIdle; import vulkan : Destroy, Init, Draw, DrawIndexed, Bind, BindUIBuffers, BeginRender, SetUniform, PrepComputeDrawImage, Dispatch, FinishFrame, BeginFrame, WaitIdle, PushConstants, BindBuffers;
import assets; import assets;
import std.math.traits : isNaN; import std.math.traits : isNaN;
import util : Logf; import util : Logf;
@ -56,6 +56,9 @@ struct GlobalUniforms
Mat4 view_matrix = Mat4Identity(); Mat4 view_matrix = Mat4Identity();
Mat4 projection_matrix = Mat4Identity(); Mat4 projection_matrix = Mat4Identity();
Mat4 view_projection = Mat4Identity(); Mat4 view_projection = Mat4Identity();
Vec4 light_color;
Vec4 ambient_color;
align(16): Vec3 light_direction;
Vec2 res; Vec2 res;
} }
@ -64,12 +67,6 @@ struct ShaderUniforms
f32 placeholder; f32 placeholder;
} }
struct PushConst
{
Mat4 model_matrix;
u32 mat_id;
}
enum PipelineType : int enum PipelineType : int
{ {
Graphics, Graphics,
@ -114,8 +111,12 @@ struct Renderer
UIVertex[] ui_vertex_buf; UIVertex[] ui_vertex_buf;
u32[] ui_index_buf; u32[] ui_index_buf;
u32 ui_count; u32 ui_count;
}
PushConst push_const; struct PushConst
{
Mat4 model_matrix;
u32 mat_id;
} }
struct Extent struct Extent
@ -179,22 +180,6 @@ InitRenderer(PlatformWindow* window)
return rd; return rd;
} }
pragma(inline): void
DrawModel(Renderer* rd, Model* model)
{
BindBuffers(&rd.vk, &model.index_buffer, &model.vertex_buffer);
rd.push_const.model_matrix = Mat4Identity();
Translate(&rd.push_const.model_matrix, Vec3(0.0, 0.0, 0.0));
foreach(i, part; model.parts)
{
rd.push_const.mat_id = part.mat;
PushConstants(&rd.vk, &rd.push_const);
DrawIndexed(rd, part.length, 1, part.offset);
}
}
pragma(inline): Extent pragma(inline): Extent
GetExtent(Renderer* rd) GetExtent(Renderer* rd)
{ {
@ -289,6 +274,18 @@ DrawRect(Renderer* rd, f32 p0_x, f32 p0_y, f32 p1_x, f32 p1_y, Vec4 col)
rd.ui_count += 1; rd.ui_count += 1;
} }
pragma(inline): void
BindBuffers(Renderer* rd, Buffer* index_buffer, Buffer* vertex_buffer)
{
BindBuffers(&rd.vk, index_buffer, vertex_buffer);
}
pragma(inline): void
PushConstants(Renderer* rd, PushConst* pc)
{
PushConstants(&rd.vk, pc);
}
pragma(inline): Pipeline pragma(inline): Pipeline
BuildGfxPipeline(Renderer* rd, GfxPipelineInfo* info) BuildGfxPipeline(Renderer* rd, GfxPipelineInfo* info)
{ {
@ -473,6 +470,38 @@ LoadModel(Renderer* rd, string name)
indices[i2] = i2; indices[i2] = i2;
} }
for(u64 i = 0; i < indices.length; i += 3)
{
u32 i0 = indices[i+0];
u32 i1 = indices[i+1];
u32 i2 = indices[i+2];
Vec3 edge1 = vertices[i1].pos - vertices[i0].pos;
Vec3 edge2 = vertices[i2].pos - vertices[i0].pos;
Vec2 delta_uv1 = vertices[i1].uv - vertices[i0].uv;
Vec2 delta_uv2 = vertices[i2].uv - vertices[i0].uv;
f32 dividend = delta_uv1.x * delta_uv2.y - delta_uv2.x * delta_uv1.y;
f32 fc = 1.0 / dividend;
Vec3 tangent = Vec3(
fc * (delta_uv2.y * edge1.x - delta_uv1.y * edge2.x),
fc * (delta_uv2.y * edge1.y - delta_uv1.y * edge2.y),
fc * (delta_uv2.y * edge1.z - delta_uv1.y * edge2.z)
);
Normalize(&tangent);
f32 handedness = ((delta_uv1.y * delta_uv2.x - delta_uv2.y * delta_uv1.x) < 0.0) ? -1.0 : 1.0;
Vec3 t = tangent * handedness;
vertices[i0].tangent = Vec4(t, handedness);
vertices[i1].tangent = Vec4(t, handedness);
vertices[i2].tangent = Vec4(t, handedness);
}
assert(vertices.length > 0 && indices.length > 0, "Error loading model"); assert(vertices.length > 0 && indices.length > 0, "Error loading model");
CreateBuffer(&rd.vk, &model.vertex_buffer, BT.Vertex, vertices.length * Vertex.sizeof, false); CreateBuffer(&rd.vk, &model.vertex_buffer, BT.Vertex, vertices.length * Vertex.sizeof, false);

View File

@ -5,12 +5,30 @@
#include "structures.layout" #include "structures.layout"
layout (location = 0) in vec4 in_col; layout (location = 0) in struct FragDataIn {
layout (location = 1) in vec2 in_uv; vec3 normal;
vec2 uv;
} FragData;
layout (location = 0) out vec4 FragColor; layout (location = 0) out vec4 FragColor;
vec4 CalculateDirectionalLight(vec4 diff_col, vec4 diff_samp, vec4 light_col, vec3 dir, vec3 normal)
{
float diffuse_factor = max(dot(normal, -dir), 0.0);
vec4 ambient = vec4(vec3(G.ambient_color * diff_col), diff_samp.a);
vec4 diffuse = vec4(vec3(light_col * diffuse_factor), diff_samp.a);
diffuse *= diff_samp;
ambient *= diff_samp;
return (ambient + diffuse);
}
void main() void main()
{ {
FragColor = in_col; vec4 col = Materials[nonuniformEXT(PC.mat_id)].diffuse;
vec4 tex_col = texture(sampler2D(Textures[nonuniformEXT(Materials[nonuniformEXT(PC.mat_id)].albedo_texture)], SamplerNearest), FragData.uv);
FragColor = CalculateDirectionalLight(col, tex_col, G.light_color, G.light_direction, FragData.normal);
} }

View File

@ -11,8 +11,10 @@ layout (location = 2) in vec3 in_pos;
layout (location = 3) in vec3 in_normal; layout (location = 3) in vec3 in_normal;
layout (location = 4) in vec2 in_uv; layout (location = 4) in vec2 in_uv;
layout (location = 0) out vec4 out_col; layout (location = 0) out struct FragDataOut {
layout (location = 1) out vec2 out_uv; vec3 normal;
vec2 uv;
} FragData;
mat4 y_matrix = mat4( mat4 y_matrix = mat4(
1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0,
@ -25,14 +27,6 @@ void main()
{ {
gl_Position = G.projection_matrix * G.view_matrix * PC.model_matrix * vec4(in_pos, 1.0); gl_Position = G.projection_matrix * G.view_matrix * PC.model_matrix * vec4(in_pos, 1.0);
vec4 col = Materials[nonuniformEXT(PC.mat_id)].diffuse; FragData.uv = in_uv;
FragData.normal = mat3(PC.model_matrix) * in_normal;
if (Materials[nonuniformEXT(PC.mat_id)].albedo_has_texture)
{
vec4 tex_col = texture(sampler2D(Textures[nonuniformEXT(Materials[nonuniformEXT(PC.mat_id)].albedo_texture)], SamplerNearest), in_uv);
col = col * tex_col;
}
out_col = col;
out_uv = in_uv;
} }

View File

@ -6,6 +6,9 @@ layout (set = 0, binding = 0) uniform GlobalUniforms {
mat4 view_matrix; mat4 view_matrix;
mat4 projection_matrix; mat4 projection_matrix;
mat4 view_projection; mat4 view_projection;
vec4 light_color;
vec4 ambient_color;
vec3 light_direction;
vec2 res; vec2 res;
} G; } G;

View File

@ -702,7 +702,7 @@ struct Quat
U opCast(U)() if (is(U: Mat4)) U opCast(U)() if (is(U: Mat4))
{ {
f32 norm = Normalize(&vec); f32 norm = Norm(&vec);
f32 s = norm > 0.0 ? 2.0 / norm : 0.0; f32 s = norm > 0.0 ? 2.0 / norm : 0.0;
f32 _x = x; f32 _x = x;
@ -818,22 +818,36 @@ Dot(Vec4* l, Vec4* r)
} }
pragma(inline): f32 pragma(inline): f32
Normalize(Vec3* v) Norm(Vec3* v)
{ {
return sqrtf(Dot(v, v)); return sqrtf(Dot(v, v));
} }
pragma(inline): f32 pragma(inline): f32
Normalize(Vec4* v) Norm(Vec4* v)
{ {
// TODO: SIMD this // TODO: SIMD this
return sqrtf(Dot(v, v)); return sqrtf(Dot(v, v));
} }
pragma(inline): void
Normalize(T)(T* vec) if (is(T: Vec2) || is(T: Vec3) || is(T: Vec4))
{
f32 length = Norm(vec);
mixin(GenerateLoop!("vec.v[@] /= length;", vec._N)());
}
pragma(inline): Vector
Normalize(T)(T vec) if (is(T: Vec2) || is(T: Vec3) || is(T: Vec4))
{
Normalize(&vec);
return vec;
}
pragma(inline): void pragma(inline): void
NormalizeTo(Vec3* v, Vec3* dst) NormalizeTo(Vec3* v, Vec3* dst)
{ {
f32 norm = Normalize(v); f32 norm = Norm(v);
if (norm < f32.epsilon) if (norm < f32.epsilon)
{ {