rendering component seems to be working but odd transforms are happening with the perspective

This commit is contained in:
Peter Li 2025-04-18 22:07:31 -07:00
parent 98fafa971a
commit 4670f874f5
5 changed files with 154 additions and 43 deletions

View File

@ -24,6 +24,12 @@ pub fn initECS(self: *@This(), handle: core.SetHandle) void {
}
}
pub fn updateMesh(self: *@This()) void {
if (self.meshName.handle() != 0) {
self.setMeshByName(&self.meshName);
}
}
pub fn setMeshByName(self: *@This(), meshName: *core.Name) void {
self.mesh = rend.getMeshByName(meshName);
self.meshName = meshName.*;

View File

@ -73,6 +73,8 @@ pub const MeshPool = struct {
var name = new.name;
core.graphics_log("uploading {d} vertices and {d} indices", .{ vertexSpan.size, indexSpan.size });
core.engine_log("install mesh by name {d}", .{name.handle()});
try self.installedMeshes.put(self.allocator, name.handle(), .{
.vertex = vertexSpan,
.index = indexSpan,
@ -123,7 +125,7 @@ pub const MeshPool = struct {
//copyPass.uploadToGPUBuffer(source: [*c]const GPUTransferBufferLocation, destination: [*c]const GPUBufferRegion, cycle: bool)
copyPass.uploadToGPUBuffer(
&.{ .transfer_buffer = upload, .offset = 0 },
&.{ .buffer = destBuffer, .offset = newSpan.start, .size = newSpan.size },
&.{ .buffer = destBuffer, .offset = newSpan.start, .size = newSpan.size * @sizeOf(T) },
false,
);
@ -164,6 +166,7 @@ pub fn getMesh(name: []const u8) ?rend.IndexedMesh {
}
pub fn getMeshByName(name: *core.Name) ?rend.IndexedMesh {
core.engine_log("getMeshByName {d}", .{name.handle()});
return gMeshPool.installedMeshes.get(name.handle());
}

View File

@ -32,6 +32,8 @@ pub const Renderer = struct {
uploadCleanup: std.ArrayListUnmanaged(struct { ptr: *anyopaque, func: *const fn (*anyopaque) void }) = .{},
destroys: std.ArrayListUnmanaged(struct { ptr: *anyopaque, func: *const fn (*anyopaque) void }) = .{},
depthTexture: *gpu.GPUTexture = undefined,
pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This());
pub const MaxObjectCount = 50000;
@ -51,12 +53,27 @@ pub const Renderer = struct {
self.startRenderer() catch return error.BadInit;
}
pub fn registerRendererObject(self: *@This(), T: type) !void {
pub fn registerRendererObject(self: *@This(), T: type) !*T {
const object = try T.create(self.device, self.allocator, .{});
try self.uploads.append(self.allocator, .{ .ptr = object, .func = T.onUpload });
try self.uploadCleanup.append(self.allocator, .{ .ptr = object, .func = T.onUploadCleanup });
try self.destroys.append(self.allocator, .{ .ptr = object, .func = T.destroy });
return object;
}
fn createDepthTexture(self: *@This()) !void {
var gci = std.mem.zeroes(gpu.GPUTextureCreateInfo);
gci.type = .texturetype2d;
gci.format = .textureformatD16Unorm;
gci.width = @intCast(self.scissor.w);
gci.height = @intCast(self.scissor.h);
gci.layer_count_or_depth = 1;
gci.num_levels = 1;
gci.usage = .{ .textureusageDepthStencilTarget = true };
self.depthTexture = self.device.createGPUTexture(&gci);
}
pub fn startRenderer(self: *@This()) !void {
@ -75,10 +92,11 @@ pub const Renderer = struct {
core.engine_log("sgpu device created, using shader format: {s}", .{self.shaderSuffix});
try self.createPipeline();
// try self.createPipeline();
try self.createMeshPipeline();
try self.createDepthTexture();
try self.registerRendererObject(MeshPool);
self.meshPool = try self.registerRendererObject(MeshPool);
}
pub fn discoverFormats(self: *@This()) !void {
@ -101,7 +119,7 @@ pub const Renderer = struct {
}
fn addAttribute(list: *std.ArrayList(gpu.GPUVertexAttribute), offset: *u32, size: u32, format: gpu.GPUVertexElementFormat) !void {
try list.append(.{ .location = @intCast(list.items.len), .offset = offset.* + size, .format = format, .buffer_slot = 0 });
try list.append(.{ .location = @intCast(list.items.len), .offset = offset.*, .format = format, .buffer_slot = 0 });
offset.* = offset.* + size;
}
@ -134,6 +152,13 @@ pub const Renderer = struct {
.vertex_attributes = @ptrCast(attributes.items.ptr),
};
pci.depth_stencil_state.compare_op = .compareopLess;
pci.depth_stencil_state.enable_depth_test = true;
pci.depth_stencil_state.enable_depth_write = true;
pci.depth_stencil_state.write_mask = 0xff;
pci.target_info.has_depth_stencil_target = true;
pci.target_info.depth_stencil_format = .textureformatD16Unorm;
pci.target_info.num_color_targets = 1;
pci.target_info.color_target_descriptions = &[_]gpu.GPUColorTargetDescription{
.{
@ -161,16 +186,16 @@ pub const Renderer = struct {
});
}
pub fn uploadSSBOs(self: *@This(), copyPass: *gpu.GPUCopyPass) void {
const uploadMapped: [*]meshes_vert.Scene = self.device.mapGPUTransferBuffer(self.ssboSceneUpload, true);
pub fn uploadSSBOs(self: *@This(), copyPass: *gpu.GPUCopyPass) !void {
const uploadMapped: [*]meshes_vert.Scene = @ptrCast(@alignCast(self.device.mapGPUTransferBuffer(self.ssboSceneUpload, true)));
self.device.unmapGPUTransferBuffer(self.ssboSceneUpload);
const container = &rend.MeshComponent.BaseContainer;
const container = rend.MeshComponent.BaseContainer;
const uploadCount: usize = @min(container.dense.items.len, MaxObjectCount);
for (0..uploadCount) |i| {
// const object = &container.dense.items[i].value;
const objectId = container.dense.items[i].sparseIndex;
var transform = core.Transform.identity();
var transform = core.zm.identity();
if (core.Scene.SceneObjectContainer.get(objectId, ._repr)) |repr| {
transform = repr.transform;
@ -178,10 +203,13 @@ pub const Renderer = struct {
uploadMapped[i].Model = @bitCast(transform);
}
if (uploadCount == 0)
return;
copyPass.uploadToGPUBuffer(&.{ .transfer_buffer = self.ssboSceneUpload, .offset = 0 }, &.{
.buffer = self.ssboScene,
.offset = 0,
.size = uploadCount * @sizeOf(meshes_vert.Scene),
.size = @intCast(uploadCount * @sizeOf(meshes_vert.Scene)),
}, true);
}
@ -194,6 +222,8 @@ pub const Renderer = struct {
pci.vertex_shader = vertex;
pci.target_info.num_color_targets = 1;
pci.target_info.has_depth_stencil_target = true;
pci.target_info.depth_stencil_format = .textureformatD16Unorm;
pci.target_info.color_target_descriptions = &[_]gpu.GPUColorTargetDescription{
.{
.format = self.device.getGPUSwapchainTextureFormat(self.window),
@ -259,29 +289,42 @@ pub const Renderer = struct {
return rv;
}
pub fn uploadUniforms(self: *@This(), cmd: *gpu.GPUCommandBuffer) !void {
var data = std.mem.zeroes([@sizeOf(meshes_vert.Uniforms) / 8 + 1]usize);
const ptr: *meshes_vert.Uniforms = @ptrCast(@alignCast(&data));
if (self.activeCamera) |camera| {
ptr.ViewProjection = @bitCast(camera.final);
}
ptr.time = @floatCast(self.totalTime);
cmd.pushGPUVertexUniformData(0, &data, @sizeOf(meshes_vert.Uniforms));
}
pub fn frameUploads(self: *@This()) void {
const cmd = self.device.acquireGPUCommandBuffer();
const buffer = self.device.mapGPUTransferBuffer(self.colorBufferTransfer, true);
// const buffer = self.device.mapGPUTransferBuffer(self.colorBufferTransfer, true);
var b: [*][4]f32 = @ptrCast(@alignCast(buffer));
// var b: [*][4]f32 = @ptrCast(@alignCast(buffer));
b[0] = .{ @floatCast(std.math.sin(self.totalTime * 3 * 2 + 0.8) * 0.2 + 0.8), 0.4, 0.4, 1.0 };
b[1] = .{ 0.4, @floatCast(std.math.sin(self.totalTime * 2 * 2 + 0.3) * 0.2 + 0.8), 0.4, 1.0 };
b[2] = .{ 0.4, 0.4, @floatCast(std.math.sin(self.totalTime * 4 * 2) * 0.2 + 0.8), 1.0 };
// b[0] = .{ @floatCast(std.math.sin(self.totalTime * 3 * 2 + 0.8) * 0.2 + 0.8), 0.4, 0.4, 1.0 };
// b[1] = .{ 0.4, @floatCast(std.math.sin(self.totalTime * 2 * 2 + 0.3) * 0.2 + 0.8), 0.4, 1.0 };
// b[2] = .{ 0.4, 0.4, @floatCast(std.math.sin(self.totalTime * 4 * 2) * 0.2 + 0.8), 1.0 };
self.device.unmapGPUTransferBuffer(self.colorBufferTransfer);
// self.device.unmapGPUTransferBuffer(self.colorBufferTransfer);
if (self.activeCamera) |camera| {
camera.resolve();
}
// map and upload Uniforms here
const copyPass = cmd.beginGPUCopyPass();
copyPass.uploadToGPUBuffer(&.{ .transfer_buffer = self.colorBufferTransfer, .offset = 0 }, &.{
.buffer = self.colorBuffer,
.offset = 0,
.size = 4 * 12,
}, true);
// copyPass.uploadToGPUBuffer(&.{ .transfer_buffer = self.colorBufferTransfer, .offset = 0 }, &.{
// .buffer = self.colorBuffer,
// .offset = 0,
// .size = 4 * 12,
// }, true);
try self.uploadSSBOs(copyPass);
for (self.uploads.items) |upload| {
upload.func(upload.ptr, copyPass);
@ -302,6 +345,7 @@ pub const Renderer = struct {
const cmd = self.device.acquireGPUCommandBuffer();
self.frameUploads();
try self.uploadUniforms(cmd);
var swapchainTexture: *gpu.GPUTexture = undefined;
if (cmd.waitAndAcquireGPUSwapchainTexture(self.window, &swapchainTexture, null, null)) {
@ -311,11 +355,44 @@ pub const Renderer = struct {
targetInfo.load_op = .loadopClear;
targetInfo.store_op = .storeopStore;
const renderpass = cmd.beginGPURenderPass(&targetInfo, 1, null);
renderpass.bindGPUGraphicsPipeline(self.testPipeline);
renderpass.bindGPUVertexStorageBuffers(0, &self.colorBuffer, 1);
var depthTarget = std.mem.zeroes(gpu.GPUDepthStencilTargetInfo);
depthTarget.texture = self.depthTexture;
depthTarget.load_op = .loadopClear;
depthTarget.store_op = .storeopDontCare;
depthTarget.clear_depth = 1.0;
depthTarget.clear_stencil = 0;
const renderpass = cmd.beginGPURenderPass(&targetInfo, 1, &depthTarget);
//renderpass.bindGPUGraphicsPipeline(self.testPipeline);
renderpass.bindGPUGraphicsPipeline(self.meshPipe);
renderpass.bindGPUVertexStorageBuffers(0, &self.ssboScene, 1);
renderpass.bindGPUVertexBuffers(0, &.{ .buffer = self.meshPool.vertexBuffer, .offset = 0 }, 1);
renderpass.bindGPUIndexBuffer(&.{ .buffer = self.meshPool.indexBuffer, .offset = 0 }, .indexelementsize32bit);
renderpass.setGPUScissor(&self.scissor);
renderpass.drawGPUPrimitives(3, 1, 0, 0);
//rendering each mesh
{
const container = rend.MeshComponent.BaseContainer;
const uploadCount: usize = @min(container.dense.items.len, MaxObjectCount);
for (0..uploadCount) |i| {
// core.engine_log("pushing draw {d}", .{i});
const component = &container.dense.items[i].value;
if (component.mesh == null) {
component.updateMesh();
}
if (component.mesh) |mesh| {
// core.engine_log("pushing draw for instance {d}", .{i});
renderpass.drawGPUIndexedPrimitives(mesh.index.size, 1, mesh.index.start, @intCast(mesh.vertex.start), @intCast(i));
}
}
}
// renderpass.drawGPUPrimitives(3, 1, 0, 0);
renderpass.endGPURenderPass();
}
@ -323,7 +400,7 @@ pub const Renderer = struct {
}
pub fn deinit(self: *@This()) void {
self.device.releaseGPUGraphicsPipeline(self.testPipeline);
// self.device.releaseGPUGraphicsPipeline(self.testPipeline);
for (self.destroys.items) |d| {
d.func(d.ptr);

15
lib/sdl3/src/gpu.zig vendored
View File

@ -959,17 +959,17 @@ pub const GPUCommandBuffer = opaque {
}
// SDL_PushGPUVertexUniformData
pub inline fn pushGPUVertexUniformData(command_buffer: *GPUCommandBuffer, slot_index: u32, data: [*c]const void, length: u32) void {
pub inline fn pushGPUVertexUniformData(command_buffer: *GPUCommandBuffer, slot_index: u32, data: ?*anyopaque, length: u32) void {
c.SDL_PushGPUVertexUniformData(@ptrCast(command_buffer), @bitCast(slot_index), @ptrCast(data), @bitCast(length));
}
// SDL_PushGPUFragmentUniformData
pub inline fn pushGPUFragmentUniformData(command_buffer: *GPUCommandBuffer, slot_index: u32, data: [*c]const void, length: u32) void {
pub inline fn pushGPUFragmentUniformData(command_buffer: *GPUCommandBuffer, slot_index: u32, data: ?*anyopaque, length: u32) void {
c.SDL_PushGPUFragmentUniformData(@ptrCast(command_buffer), @bitCast(slot_index), @ptrCast(data), @bitCast(length));
}
// SDL_PushGPUComputeUniformData
pub inline fn pushGPUComputeUniformData(command_buffer: *GPUCommandBuffer, slot_index: u32, data: [*c]const void, length: u32) void {
pub inline fn pushGPUComputeUniformData(command_buffer: *GPUCommandBuffer, slot_index: u32, data: ?*anyopaque, length: u32) void {
c.SDL_PushGPUComputeUniformData(@ptrCast(command_buffer), @bitCast(slot_index), @ptrCast(data), @bitCast(length));
}
@ -1051,13 +1051,18 @@ pub const GPURenderPass = opaque {
}
// SDL_BindGPUVertexBuffers
pub inline fn bindGPUVertexBuffers(render_pass: *GPURenderPass, first_slot: u32, bindings: [*c]const GPUBufferBinding, num_bindings: u32) void {
pub inline fn bindGPUVertexBuffers(
render_pass: *GPURenderPass,
first_slot: u32,
bindings: [*c]const GPUBufferBinding,
num_bindings: u32,
) void {
c.SDL_BindGPUVertexBuffers(@ptrCast(render_pass), @bitCast(first_slot), @ptrCast(bindings), @bitCast(num_bindings));
}
// SDL_BindGPUIndexBuffer
pub inline fn bindGPUIndexBuffer(render_pass: *GPURenderPass, binding: [*c]const GPUBufferBinding, index_element_size: GPUIndexElementSize) void {
c.SDL_BindGPUIndexBuffer(@ptrCast(render_pass), @ptrCast(binding), @bitCast(index_element_size));
c.SDL_BindGPUIndexBuffer(@ptrCast(render_pass), @ptrCast(binding), @intFromEnum(index_element_size));
}
// SDL_BindGPUVertexSamplers

View File

@ -1,12 +1,14 @@
allocator: std.mem.Allocator,
camera: core.Entity = undefined,
cameraSpeed: f32 = 10.0,
cameraSpeed: f32 = 100.0,
moveInput: *core.Axis2dBinding = undefined,
moveVector: core.Vectorf = .{},
verticalMove: f32 = 0.0,
pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This());
pub fn init(allocator: std.mem.Allocator) !*@This() {
@ -23,11 +25,11 @@ const assetReferences = [_]assets.AssetImportReference{
"m_empire",
.{ .path = "meshes/lost_empire.obj" },
),
assets.MakeImportRefOptions(
"Mesh",
"m_fox",
.{ .path = "gltf-samples/Fox/glTF/Fox.gltf" },
),
// assets.MakeImportRefOptions(
// "Mesh",
// "m_fox",
// .{ .path = "gltf-samples/Fox/glTF/Fox.gltf" },
// ),
};
pub fn prepare(self: *@This()) !void {
@ -46,9 +48,14 @@ pub fn prepare(self: *@This()) !void {
exitInput.activate();
self.camera = try core.createEntity();
const scene = self.camera.addComponent(core.Scene).?;
_ = scene;
_ = self.camera.addComponent(core.Scene).?;
const camera = self.camera.addComponent(rend.CameraComponent).?;
const lostEmpire = try core.createEntity();
_ = lostEmpire.addComponent(core.Scene);
const empireMesh = lostEmpire.addComponent(rend.MeshComponent).?;
empireMesh.setMesh("m_empire");
rend.setActiveCamera(camera);
self.moveInput = try core.Axis2dBinding.create(core.MakeName("movement"));
@ -60,6 +67,18 @@ pub fn prepare(self: *@This()) !void {
_ = self.moveInput.data.addListener(self, onMove);
self.moveInput.activate();
const verticalInput = try core.Axis1dBinding.create(core.MakeName("movementVertical"));
verticalInput.addKey(.e, 1.0);
verticalInput.addKey(.q, -1.0);
_ = verticalInput.data.addListener(self, verticalMovement);
verticalInput.activate();
}
fn verticalMovement(ctx: ?*anyopaque, axis: f32) void {
const self: *@This() = @ptrCast(@alignCast(ctx));
self.verticalMove = axis;
}
fn onMove(ctx: ?*anyopaque, axis: core.Vector2f) void {
@ -77,8 +96,9 @@ pub fn onExit(ctx: ?*anyopaque, action: core.ActionEvent) void {
pub fn tick(self: *@This(), dt: f64) void {
const fdt: f32 = @floatCast(dt);
if (self.camera.get(core.Scene)) |scene| {
scene.getPosRot().position = scene.getPosRot().position.add(self.moveVector.fmul(self.cameraSpeed * fdt));
core.engine_log(" camera position >> {any}", .{scene.getPosRot().position});
const vector = core.Vectorf{ .x = self.moveVector.x, .z = self.moveVector.z, .y = self.verticalMove };
scene.getPosRot().position = scene.getPosRot().position.add(vector.fmul(self.cameraSpeed * fdt));
// core.engine_log(" camera position >> {any}", .{scene.getPosRot().position});
}
}
@ -88,7 +108,7 @@ pub fn deinit(self: *@This()) void {
pub fn main() anyerror!void {
try backlog.initializeAndRunStandardProgram(@This(), .{
.name = "Hello World",
.name = "SDL GPU IS HERE TO LOVE YOUR MOTHER",
.enabledModules = .{
.physics = true,
},