Added camera uniforms for projection and view matrix

This commit is contained in:
Lorenzo Torres 2025-08-04 17:23:00 +02:00
parent 59e3997056
commit dcb2ee0584
7 changed files with 92 additions and 28 deletions

View file

@ -3,6 +3,7 @@ const Allocator = std.mem.Allocator;
const components = @import("components.zig");
const sparse = @import("sparse.zig");
const Renderer = @import("renderer");
const Camera = @import("renderer").Camera;
const Input = @import("sideros").Input;
const ecs = @import("ecs.zig");
@ -11,6 +12,7 @@ pub const SystemGroup = []const System;
pub const SyncGroup = []const System;
pub const Resources = struct {
camera: Camera,
renderer: Renderer,
input: Input,
delta_time: f64 = 0.0,

View file

@ -45,6 +45,10 @@ pub fn main() !void {
//defer w.destroy();
const resources = ecs.Resources{
.camera = .{
.position = .{0.0, 0.0, 100},
.target = .{0.0, 0.0, 0.0},
},
.renderer = undefined,
.input = .{ .key_pressed = .{false} ** @intFromEnum(Input.KeyCode.menu) },
};

View file

@ -8,15 +8,15 @@ pub const Matrix = struct {
rows: [4]@Vector(4, f32),
pub fn lookAt(eye: @Vector(3, f32), target: @Vector(3, f32), arbitrary_up: @Vector(3, f32)) Matrix {
const forward = normalize(eye - target);
const right = normalize(cross(arbitrary_up, forward));
const up = cross(forward, right);
const forward = normalize(target - eye);
const right = normalize(cross(forward, arbitrary_up));
const up = cross(right, forward);
const view = [_]@Vector(4, f32){
@Vector(4, f32){ right[0], right[1], right[2], 0.0 },
@Vector(4, f32){ up[0], up[1], up[2], 0.0 },
@Vector(4, f32){ forward[0], forward[1], forward[2], 0.0 },
@Vector(4, f32){ 0.0, 0.0, 1.0, eye[2] },
@Vector(4, f32){ right[0], up[0], -forward[0], 0.0 },
@Vector(4, f32){ right[1], up[1], -forward[1], 0.0 },
@Vector(4, f32){ right[2], up[2], -forward[2], 0.0 },
@Vector(4, f32){ -dot(eye, right), -dot(eye, up), -dot(eye, forward), 1.0 },
};
return Matrix{
@ -25,11 +25,17 @@ pub const Matrix = struct {
}
pub fn perspective(fov: f32, aspect: f32, near: f32, far: f32) Matrix {
const focal_length = 1.0 / tan(fov / 2.0);
const x = focal_length / aspect;
const y = -focal_length;
const a = near / (far - near);
const b = far * a;
const projection = [_]@Vector(4, f32){
@Vector(4, f32){ 1.0 / (aspect * tan(fov / 2.0)), 0.0, 0.0, 0.0 },
@Vector(4, f32){ 0.0, 1.0 / tan(fov / 2.0), 0.0, 0.0 },
@Vector(4, f32){ 0.0, 0.0, -((far + near) / (far - near)), -((2 * far * near) / (far - near)) },
@Vector(4, f32){ 0.0, 0.0, -1.0, 1.0 },
@Vector(4, f32){ x, 0.0, 0.0, 0.0 },
@Vector(4, f32){ 0.0, y, 0.0, 0.0 },
@Vector(4, f32){ 0.0, 0.0, a, b },
@Vector(4, f32){ 0.0, 0.0, 1.0, 0.0 },
};
return Matrix{

View file

@ -12,21 +12,18 @@ pub const Uniform = struct {
model: math.Matrix,
};
uniform: Uniform,
position: @Vector(3, f32),
target: @Vector(3, f32),
direction: @Vector(3, f32),
right: @Vector(3, f32),
front: @Vector(3, f32),
up: @Vector(3, f32),
target: @Vector(3, f32) = .{0.0, 0.0, 0.0},
front: @Vector(3, f32) = .{0.0, 0.0, 1.0 },
up: @Vector(3, f32) = .{0.0, 1.0, 0.0 },
speed: f32 = 2.5,
pub fn getProjection(width: usize, height: usize) math.Matrix {
return math.Matrix.perspective(math.rad(45.0), (@as(f32, @floatFromInt(width)) / @as(f32, @floatFromInt(height))), 0.1, 10.0);
return math.Matrix.perspective(math.rad(45.0), (@as(f32, @floatFromInt(width)) / @as(f32, @floatFromInt(height))), 0.1, 100.0);
}
pub fn getView(self: Camera) math.Matrix {
math.lookAt(self.position, self.position + self.front, self.up);
return math.Matrix.lookAt(self.position, self.target, self.up);
}
pub fn moveCamera(pool: *ecs.Pool) void {

View file

@ -1,8 +1,10 @@
const c = @import("sideros").c;
const math = @import("sideros").math;
const ecs = @import("ecs");
const std = @import("std");
const vk = @import("vulkan.zig");
pub const Mesh = @import("Mesh.zig");
pub const Camera = @import("Camera.zig");
const Allocator = std.mem.Allocator;
const Renderer = @This();
@ -76,6 +78,10 @@ pub fn deinit(self: Renderer) void {
// TODO: render is maybe a bad name? something like present() or submit() is better?
pub fn render(pool: *ecs.Pool) anyerror!void {
var renderer = pool.resources.renderer;
var camera = pool.resources.camera;
const view_memory = renderer.graphics_pipeline.view_memory;
@memcpy(view_memory[0..@sizeOf(math.Matrix)], std.mem.asBytes(&camera.getView()));
try renderer.device.waitFence(renderer.current_frame);
const image = try renderer.swapchain.nextImage(renderer.device, renderer.current_frame);

View file

@ -304,6 +304,8 @@ pub fn GraphicsPipeline(comptime n: usize) type {
descriptor_set: c.VkDescriptorSet,
descriptor_set_layout: c.VkDescriptorSetLayout,
projection_buffer: Buffer,
view_buffer: Buffer,
view_memory: [*c]u8,
const Self = @This();
@ -373,7 +375,8 @@ pub fn GraphicsPipeline(comptime n: usize) type {
.rasterizerDiscardEnable = c.VK_FALSE,
.polygonMode = c.VK_POLYGON_MODE_FILL,
.lineWidth = 1.0,
.cullMode = c.VK_CULL_MODE_BACK_BIT,
//.cullMode = c.VK_CULL_MODE_BACK_BIT,
.cullMode = c.VK_CULL_MODE_NONE,
.frontFace = c.VK_FRONT_FACE_COUNTER_CLOCKWISE,
.depthBiasEnable = c.VK_FALSE,
};
@ -404,20 +407,27 @@ pub fn GraphicsPipeline(comptime n: usize) type {
.blendConstants = .{ 0.0, 0.0, 0.0, 0.0 },
};
const set_binding = c.VkDescriptorSetLayoutBinding{
const projection_binding = c.VkDescriptorSetLayoutBinding{
.binding = 0,
.descriptorType = c.VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
.descriptorCount = 1,
.stageFlags = c.VK_SHADER_STAGE_VERTEX_BIT,
};
const bindings = [_]c.VkDescriptorSetLayoutBinding{set_binding};
const view_binding = c.VkDescriptorSetLayoutBinding{
.binding = 1,
.descriptorType = c.VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
.descriptorCount = 1,
.stageFlags = c.VK_SHADER_STAGE_VERTEX_BIT,
};
const bindings = [_]c.VkDescriptorSetLayoutBinding{projection_binding, view_binding};
var descriptor_set_layout: c.VkDescriptorSetLayout = undefined;
const descriptor_set_layout_info = c.VkDescriptorSetLayoutCreateInfo{
.sType = c.VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
.bindingCount = 1,
.bindingCount = 2,
.pBindings = bindings[0..].ptr,
};
@ -462,7 +472,7 @@ pub fn GraphicsPipeline(comptime n: usize) type {
var size = c.VkDescriptorPoolSize{
.type = c.VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
.descriptorCount = 1,
.descriptorCount = 2,
};
const descriptor_pool_info = c.VkDescriptorPoolCreateInfo{
@ -520,6 +530,38 @@ pub fn GraphicsPipeline(comptime n: usize) type {
c.vkUpdateDescriptorSets(device.handle, 1, &write_descriptor_set, 0, null);
const view_buffer = try device.createBuffer(BufferUsage{ .uniform_buffer = true, .transfer_dst = true }, BufferFlags{ .device_local = true }, @sizeOf(math.Matrix));
var view_data: [*c]u8 = undefined;
try mapError(c.vkMapMemory(
device.handle,
view_buffer.memory,
0,
view_buffer.size,
0,
@ptrCast(&view_data),
));
const view_descriptor_buffer_info = c.VkDescriptorBufferInfo{
.buffer = view_buffer.handle,
.offset = 0,
.range = view_buffer.size,
};
const write_view_descriptor_set = c.VkWriteDescriptorSet{
.sType = c.VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = descriptor_set,
.dstBinding = 1,
.dstArrayElement = 0,
.descriptorCount = 1,
.descriptorType = c.VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
.pBufferInfo = &view_descriptor_buffer_info,
};
c.vkUpdateDescriptorSets(device.handle, 1, &write_view_descriptor_set, 0, null);
return Self{
.layout = layout,
.handle = pipeline,
@ -527,6 +569,8 @@ pub fn GraphicsPipeline(comptime n: usize) type {
.descriptor_set = descriptor_set,
.descriptor_set_layout = descriptor_set_layout,
.projection_buffer = projection_buffer,
.view_buffer = view_buffer,
.view_memory = view_data,
};
}