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; f32 delta; Timer timer; Camera camera; Model model; } Game InitGame(PlatformWindow* window) { Game g = { rd: InitRenderer(window), window: window, timer: CreateTimer(), }; 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.n.offsetof }, { binding: 0, location: 2, format: FMT.RG_F32, offset: Vertex.uv.offsetof }, { binding: 0, location: 3, format: FMT.RGBA_UNORM, offset: Vertex.col.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(70.0), cast(f32)(ext.x), cast(f32)(ext.y), 10000.0, 0.1); 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)); 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); DrawModel(&g.rd, &g.model); FinishFrame(&g.rd); } 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); }