228 lines
5.2 KiB
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);
|
|
}
|