Gears/src/gears/game.d

228 lines
5.2 KiB
D

import aliases;
import includes;
import renderer : Destroy;
import renderer;
import util;
import platform;
import math;
struct Camera
{
Vec3 velocity = Vec3(0.0);
Vec3 pos = Vec3(0.0, 0.0, 0.0);
f32 yaw = 0.0;
f32 pitch = 0.0;
}
struct Game
{
Renderer rd;
PlatformWindow* window;
Pipeline pbr_pipeline;
Pipeline triangle_pipeline;
Pipeline compute_pipeline;
Pipeline ui_pipeline;
GlobalUniforms globals;
PushConst pc;
f32 delta;
Timer timer;
Camera camera;
Model model;
}
Game
InitGame(PlatformWindow* window)
{
Game g = {
rd: InitRenderer(window),
window: window,
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 = {
vertex_shader: "shaders/triangle.vert.spv",
frag_shader: "shaders/triangle.frag.spv",
};
GfxPipelineInfo ui_info = {
vertex_shader: "shaders/gui.vert.spv",
frag_shader: "shaders/gui.frag.spv",
input_rate: IR.Instance,
input_rate_stride: UIVertex.sizeof,
vertex_attributes: [
{ binding: 0, location: 0, format: FMT.RG_F32, offset: 0 },
{ binding: 0, location: 1, format: FMT.RG_F32, offset: UIVertex.p1.offsetof },
{ binding: 0, location: 2, format: FMT.RGBA_F32, offset: UIVertex.col.offsetof },
{ binding: 0, location: 3, format: FMT.UINT, offset: UIVertex.texture.offsetof },
],
};
GfxPipelineInfo pbr_info = {
vertex_shader: "shaders/pbr.vert.spv",
frag_shader: "shaders/pbr.frag.spv",
input_rate_stride: Vertex.sizeof,
vertex_attributes: [
{ binding: 0, location: 0, format: FMT.RGBA_F32, offset: 0 },
{ binding: 0, location: 1, format: FMT.RGBA_F32, offset: Vertex.tangent.offsetof },
{ binding: 0, location: 2, format: FMT.RGB_F32, offset: Vertex.pos.offsetof },
{ binding: 0, location: 3, format: FMT.RGB_F32, offset: Vertex.normal.offsetof },
{ binding: 0, location: 4, format: FMT.RG_F32, offset: Vertex.uv.offsetof },
],
};
CompPipelineInfo gradient_info = {
shader: "shaders/gradient.comp.spv",
};
g.pbr_pipeline = BuildGfxPipeline(&g.rd, &pbr_info);
g.triangle_pipeline = BuildGfxPipeline(&g.rd, &triangle_info);
g.ui_pipeline = BuildGfxPipeline(&g.rd, &ui_info);
g.compute_pipeline = BuildCompPipeline(&g.rd, &gradient_info);
PrintShader(&g.rd, &g.pbr_pipeline, VK_SHADER_STAGE_VERTEX_BIT);
g.model = LoadModel(&g.rd, "models/Tree01.m3d");
return g;
}
void
ProcessInputs(Game* g, Camera* cam)
{
foreach(i; 0 .. g.window.input_count)
{
bool pressed = g.window.inputs[i].pressed;
switch(g.window.inputs[i].key)
{
case Input.W: cam.velocity.z = pressed ? -1.0 : 0.0; break;
case Input.S: cam.velocity.z = pressed ? +1.0 : 0.0; break;
case Input.A: cam.velocity.x = pressed ? -1.0 : 0.0; break;
case Input.D: cam.velocity.x = pressed ? +1.0 : 0.0; break;
case Input.MouseMotion:
{
// (0, 0) top left
cam.yaw -= cast(f32)(g.window.inputs[i].rel_x) / 200.0;
cam.pitch += cast(f32)(g.window.inputs[i].rel_y) / 200.0;
} break;
default: break;
}
}
}
void
Update(Game* g, Camera* cam)
{
Mat4 rotation = RotationMatrix(cam);
cam.pos += (rotation * Vec4(cam.velocity, 0.0)).xyz * g.delta;
Extent ext = GetExtent(&g.rd);
g.globals.view_matrix = ViewMatrix(cam);
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.view_projection = g.globals.projection_matrix * g.globals.view_matrix;
g.globals.res.x = cast(f32)ext.x;
g.globals.res.y = cast(f32)ext.y;
}
pragma(inline): Mat4
RotationMatrix(Camera* cam)
{
Quat pitch_rotation, yaw_rotation;
QuatFromAxis(&pitch_rotation, cam.pitch, Vec3(1.0, 0.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);
}
pragma(inline): Mat4
ViewMatrix(Camera* cam)
{
Mat4 translation;
Translate(&translation, cam.pos);
Mat4 rotation = RotationMatrix(cam);
return Inverse(translation * rotation);
}
void
Cycle(Game* g)
{
g.delta = DeltaTime(&g.timer);
ProcessInputs(g, &g.camera);
Update(g, &g.camera);
BeginFrame(&g.rd);
Bind(&g.rd, &g.compute_pipeline);
SetUniform(&g.rd, &g.globals);
//DrawRect(&g.rd, 150.0, 300.0, 500.0, 700.0, Vec4(0.0, 0.0, 1.0, 1.0));
//PrepComputeDrawImage(&g.rd);
//Dispatch(&g.rd);
BeginRender(&g.rd);
Bind(&g.rd, &g.ui_pipeline);
BindUIBuffers(&g.rd);
//DrawUI(&g.rd);
Bind(&g.rd, &g.triangle_pipeline);
//Draw(&g.rd, 3, 1);
Bind(&g.rd, &g.pbr_pipeline);
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);
}
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
Destroy(Game* g)
{
WaitIdle(&g.rd);
Destroy(&g.rd, &g.pbr_pipeline);
Destroy(&g.rd, &g.triangle_pipeline);
Destroy(&g.rd, &g.ui_pipeline);
Destroy(&g.rd, &g.compute_pipeline);
Destroy(&g.rd);
}