NYXGFX/examples/simple_3D/simple_3D.zig

262 lines
6.5 KiB
Zig
Raw Normal View History

2026-08-12 20:31:05 +01:00
//! ----------------------------------------------------
//! ----------------------------------------------------
const vk = @import("vulkan");
2026-08-12 20:31:05 +01:00
const std = @import("std");
const sdl = @import("sdl");
const math = @import("math");
const cmn = @import("common");
2026-08-12 20:31:05 +01:00
const Gfx = @import("gfx");
/// ----------------------------------------------------
/// ----------------------------------------------------
const Camera = struct {
projection: math.Mat4x4,
view: math.Mat4x4,
};
/// ----------------------------------------------------
/// ----------------------------------------------------
const Model = struct {
matrix: math.Mat4x4,
};
/// ----------------------------------------------------
/// ----------------------------------------------------
pub fn main(init: std.process.Init) !void {
//
// DATA
//
var material: cmn.UnlitMaterial = .{ .albedo = .{ 1.0, 0.2, 0.2, 1.0 } };
2026-08-12 20:31:05 +01:00
const camera: Camera = .{
.projection = .perspective(std.math.degreesToRadians(90), 800.0 / 600.0, 0.01, 1000),
.view = .lookAt(.new(.{ 1, 1, -2 }), .new(.{ 0, 0, 1 }), .new(.{ 0, 1, 0 })),
};
2026-08-19 14:47:03 +01:00
var model: Model = .{
2026-08-12 20:31:05 +01:00
.matrix = math.Mat4x4.translate(
0,
0,
0,
)
.mul(math.Quat.fromEuler(.init(0, 0, 0)).toMat4())
.mul(math.Mat4x4.scale(
1,
1,
1,
)),
};
//
// SDL
//
if (!sdl.SDL_Init(sdl.SDL_INIT_VIDEO)) return error.FailedToInitSDL;
defer sdl.SDL_Quit();
const window = sdl.SDL_CreateWindow("NYXGFX", 800, 600, 0) orelse return error.FailedTomakeWindow;
defer sdl.SDL_DestroyWindow(window);
const props = sdl.SDL_GetWindowProperties(window);
const display = sdl.SDL_GetPointerProperty(props, sdl.SDL_PROP_WINDOW_X11_DISPLAY_POINTER, null);
const xwindow = sdl.SDL_GetNumberProperty(props, sdl.SDL_PROP_WINDOW_X11_WINDOW_NUMBER, 0);
//
// GFX
//
var gfx: Gfx = try .init(
init.gpa,
init.io,
);
2026-08-12 20:31:05 +01:00
defer gfx.deinit();
2026-08-19 14:47:03 +01:00
//
// CORE
//
const instance = try gfx.makeInstance(.{
.vulkan = .{
.api_version = .v1_3,
2026-08-19 14:47:03 +01:00
.vk_13_features = .{},
},
});
2026-08-12 20:31:05 +01:00
const surface = try gfx.makeSurface(.{
2026-08-19 14:47:03 +01:00
.window = .{
.xlib = .{
.window = @intCast(xwindow),
.display = display.?,
},
},
2026-08-19 14:47:03 +01:00
.instance = instance,
});
const adapter = try gfx.makeAdapter(.{
.instance = instance,
});
const device = try gfx.makeDevice(.{
.instance = instance,
.adapter = adapter,
.surface = surface,
});
2026-08-19 14:47:03 +01:00
const swapchain = try gfx.makeSwapchain(.{
.surface = surface,
.adapter = adapter,
.device = device,
});
//
// DEBUG
//
2026-08-12 20:31:05 +01:00
if (gfx.getAdapterInfo(adapter)) |info| {
std.debug.print("Name: {s} | Type: {s}\n", .{ info.name, @tagName(info.gpu_type) });
}
2026-08-19 14:47:03 +01:00
//
// TEXTURES
//
2026-08-12 20:31:05 +01:00
const texture = try gfx.makeTexture(.{
2026-08-19 14:47:03 +01:00
.image = .{ .path = "examples/assets/textures/texture.jpg" },
2026-08-12 20:31:05 +01:00
.sampler = .{ .min_filter = .linear, .address_u = .repeat },
2026-08-19 14:47:03 +01:00
.adapter = adapter,
.device = device,
});
//
// BUFFERS
//
const vbuf = try gfx.makeBuffer(cmn.Cube.vertices, .vertex, adapter, device);
const ibuf = try gfx.makeBuffer(cmn.Cube.indices, .index, adapter, device);
2026-08-12 20:31:05 +01:00
2026-08-19 14:47:03 +01:00
//
// SHADERS
//
2026-08-12 20:31:05 +01:00
const simple_vert = try gfx.makeShader("examples/assets/shaders/compiled/3D.vert.spv", device);
const simple_frag = try gfx.makeShader("examples/assets/shaders/compiled/3D.frag.spv", device);
2026-08-19 14:47:03 +01:00
//
// PIPELINES
//
2026-08-12 20:31:05 +01:00
const pipeline = try gfx.makePipeline(.{
.vertex_attributes = &.{
.{ .location = 0, .format = .vec3, .offset = @offsetOf(cmn.Vertex, "pos") },
.{ .location = 1, .format = .vec3, .offset = @offsetOf(cmn.Vertex, "normal") },
.{ .location = 2, .format = .vec2, .offset = @offsetOf(cmn.Vertex, "uv") },
2026-08-12 20:31:05 +01:00
},
.vertex_binding = .{ .stride = @sizeOf(cmn.Vertex) },
2026-08-12 20:31:05 +01:00
.uniforms = &.{
.{ .name = "camera", .size = @sizeOf(Camera) },
.{ .name = "model", .size = @sizeOf(Model) },
},
.textures = &.{
texture,
},
.depth_format = .d32_sfloat,
.vert_shader = simple_vert,
.frag_shader = simple_frag,
.device = device,
.swapchain = swapchain,
});
2026-08-19 14:47:03 +01:00
//
// MISC
//
2026-08-12 20:31:05 +01:00
var event: sdl.SDL_Event = undefined;
var running: bool = true;
var i: f32 = 0;
while (running) {
2026-08-19 14:47:03 +01:00
//
// INPUTS
//
2026-08-12 20:31:05 +01:00
while (sdl.SDL_PollEvent(&event)) {
switch (event.type) {
sdl.SDL_EVENT_QUIT => running = false,
else => {},
}
}
i += 0.001;
i = @mod(i, 1);
material.albedo[1] = i;
try pipeline.setUniform("camera", Camera{
.projection = camera.projection.transpose(),
.view = camera.view.transpose(),
});
2026-08-19 14:47:03 +01:00
//
// FRAME
//
2026-08-12 20:31:05 +01:00
try gfx.beginFrame(swapchain, device);
defer gfx.endFrame(swapchain, device) catch unreachable;
2026-08-19 14:47:03 +01:00
//
// PASS
//
2026-08-12 20:31:05 +01:00
if (gfx.beginPass(swapchain, .{
.clear_color = .{ 0.01, 0.01, 0.01, 1.0 },
.depth_enabled = true,
})) |pass| {
defer pass.end();
2026-08-19 14:47:03 +01:00
for (0..4) |x| {
model = .{
.matrix = math.Mat4x4.translate(
0,
0,
@floatFromInt(x),
)
.mul(math.Quat.fromEuler(.init(
@as(f32, @floatFromInt(x)) * 0.1,
@as(f32, @floatFromInt(x)) * 0.15,
@as(f32, @floatFromInt(x)) * 0.13,
)).toMat4())
.mul(math.Mat4x4.scale(
1,
1,
1,
)),
};
try pipeline.bind();
try vbuf.bind();
try ibuf.bind();
try pipeline.setUniform("model", Model{
.matrix = model.matrix.transpose(),
});
pass.drawIndexed(cmn.Cube.indices.len, 1, 0, 0, 0);
}
2026-08-12 20:31:05 +01:00
}
if (gfx.beginPass(swapchain, .{
.load_op = .load,
})) |pass| {
defer pass.end();
}
}
}