> texture asset loader implemented
This commit is contained in:
parent
ac2c9c0613
commit
2ec0cd8c31
|
|
@ -166,13 +166,18 @@ pub const Engine = struct {
|
|||
try self.destroyListSimple.append(self.allocator, newObjectRef);
|
||||
}
|
||||
|
||||
if (params.can_tick) {
|
||||
if (!@hasDecl(T, "tick")) {
|
||||
return error.RequestedTickNotAvailable; // tried to register a tickable for an object which does not implement tick
|
||||
if (params.can_tick) |t| {
|
||||
if (t and !@hasDecl(T, "tick")) {
|
||||
return error.RequestedTickNotAvailable;
|
||||
}
|
||||
|
||||
// register to tick table
|
||||
try self.tickables.append(self.allocator, newIndex);
|
||||
if (t) {
|
||||
try self.tickables.append(self.allocator, newIndex);
|
||||
}
|
||||
} else {
|
||||
if (@hasDecl(T, "tick")) {
|
||||
try self.tickables.append(self.allocator, newIndex);
|
||||
}
|
||||
}
|
||||
|
||||
if (@hasDecl(T, "engineDraw")) {
|
||||
|
|
@ -379,7 +384,7 @@ pub const Engine = struct {
|
|||
};
|
||||
|
||||
pub const NeonObjectParams = struct {
|
||||
can_tick: bool = false,
|
||||
can_tick: ?bool = null,
|
||||
responds_to_events: bool = false,
|
||||
isCore: bool = false,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -135,7 +135,6 @@ pub const Scene = struct {
|
|||
pub fn setPosition(self: @This(), position: core.Vectorf) void {
|
||||
if (SceneObjectContainer.get(self.handle, .posRot)) |posRot| {
|
||||
posRot.*.position = position;
|
||||
// core.engine_log("setposition scucess handle.index = 0x{x}", .{self.handle.index});
|
||||
} else {
|
||||
core.engine_log("setposition failed handle.index = 0x{x} generation = {d} alive={any}", .{ self.handle.index, self.handle.generation, self.handle.alive });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,8 +37,8 @@ Output main(Input input)
|
|||
|
||||
float4 pos = float4(input.Position, 1.0);
|
||||
|
||||
pos.x += 0.2 * sin(time * 0.5 ) * pos.y * 0.5;
|
||||
pos.y += 0.2 * cos(time * 0.5 ) * pos.z * 0.5;
|
||||
// pos.x += 0.2 * sin(time * 0.5 ) * pos.y * 0.5;
|
||||
// pos.y += 0.2 * cos(time * 0.5 ) * pos.z * 0.5;
|
||||
|
||||
output.Position = mul(ViewProjection, mul(scene[input.Instance].Model, pos));
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
}
|
||||
],
|
||||
"types" : {
|
||||
"_9" : {
|
||||
"_8" : {
|
||||
"name" : "Scene",
|
||||
"members" : [
|
||||
{
|
||||
|
|
@ -18,12 +18,12 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"_8" : {
|
||||
"_7" : {
|
||||
"name" : "type.StructuredBuffer.Scene",
|
||||
"members" : [
|
||||
{
|
||||
"name" : "_m0",
|
||||
"type" : "_9",
|
||||
"type" : "_8",
|
||||
"array" : [
|
||||
0
|
||||
],
|
||||
|
|
@ -35,7 +35,7 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"_11" : {
|
||||
"_10" : {
|
||||
"name" : "type.Uniforms",
|
||||
"members" : [
|
||||
{
|
||||
|
|
@ -74,7 +74,7 @@
|
|||
],
|
||||
"ssbos" : [
|
||||
{
|
||||
"type" : "_8",
|
||||
"type" : "_7",
|
||||
"name" : "scene",
|
||||
"readonly" : true,
|
||||
"block_size" : 0,
|
||||
|
|
@ -84,7 +84,7 @@
|
|||
],
|
||||
"ubos" : [
|
||||
{
|
||||
"type" : "_11",
|
||||
"type" : "_10",
|
||||
"name" : "type.Uniforms",
|
||||
"block_size" : 68,
|
||||
"set" : 1,
|
||||
|
|
|
|||
|
|
@ -30,6 +30,9 @@ pub const setActiveCamera = renderer.setActiveCamera;
|
|||
pub const createRendererObject = renderer.createRendererObject;
|
||||
pub const registerRendererObject = renderer.registerRendererObject;
|
||||
|
||||
pub const getTexture = renderer.getTexture;
|
||||
pub const texture = @import("texture/texture.zig");
|
||||
|
||||
var rendAllocator: std.mem.Allocator = undefined;
|
||||
pub fn getAllocator() std.mem.Allocator {
|
||||
return rendAllocator;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,128 @@
|
|||
// not to be confused with a real texture pool
|
||||
// but this texture list is just a container where all
|
||||
// textures are installed into the renderer
|
||||
//
|
||||
// this thing also servers as both the asset loader
|
||||
// as well as the engine interface
|
||||
//
|
||||
|
||||
pub var LoaderInterfaceVTable = assets.AssetLoaderInterface.from("Texture", @This());
|
||||
pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This());
|
||||
|
||||
allocator: std.mem.Allocator,
|
||||
device: *gpu.GPUDevice = undefined,
|
||||
|
||||
map: std.AutoHashMapUnmanaged(u32, *Texture) = .{},
|
||||
|
||||
pub fn create(allocator: std.mem.Allocator) !*@This() {
|
||||
const self = try allocator.create(@This());
|
||||
self.* = .{
|
||||
.allocator = allocator,
|
||||
};
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn setup(self: *@This(), device: *gpu.GPUDevice) !void {
|
||||
core.engine_log("Texture List Added", .{});
|
||||
try assets.gAssetSys.registerLoader(self);
|
||||
self.device = device;
|
||||
}
|
||||
|
||||
pub fn loadAsset(self: *@This(), assetRef: assets.AssetRef, propertiesBag: ?assets.AssetPropertiesBag) assets.AssetLoaderError!void {
|
||||
var name = assetRef.name;
|
||||
core.engine_log("loading texture {s}", .{name.utf8()});
|
||||
if (propertiesBag) |bag| {
|
||||
const installed = self.uploadTextureFromPath(name, bag.path) catch return error.UnableToLoad;
|
||||
self.map.put(self.allocator, name.handle(), installed) catch return error.UnableToLoad;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn uploadTextureFromPath(self: *@This(), name: core.Name, path: []const u8) !*Texture {
|
||||
var png = try core.png.PngContents.initFromFS(core.fs(), self.allocator, path);
|
||||
defer png.deinit();
|
||||
|
||||
const cmd = self.device.acquireGPUCommandBuffer();
|
||||
|
||||
const gpuTexture = self.device.createGPUTexture(&std.mem.zeroInit(gpu.GPUTextureCreateInfo, .{
|
||||
.type = .texturetype2d,
|
||||
.format = .textureformatR8g8b8a8UnormSrgb,
|
||||
.usage = .{ .textureusageSampler = true },
|
||||
.width = png.size.x,
|
||||
.height = png.size.y,
|
||||
.layer_count_or_depth = 1,
|
||||
.num_levels = 1,
|
||||
}));
|
||||
|
||||
const transferBuffer = self.device.createGPUTransferBuffer(&.{
|
||||
.usage = .transferbufferusageUpload,
|
||||
.size = png.size.x * png.size.y * @sizeOf(u32),
|
||||
.props = 0,
|
||||
});
|
||||
|
||||
{
|
||||
const data: [*]u8 = @ptrCast(self.device.mapGPUTransferBuffer(transferBuffer, false));
|
||||
for (png.pixels, 0..) |pixel, i| {
|
||||
data[i] = pixel;
|
||||
}
|
||||
}
|
||||
|
||||
self.device.unmapGPUTransferBuffer(transferBuffer);
|
||||
|
||||
const copyPass = cmd.beginGPUCopyPass();
|
||||
// copyPass.uploadToGPUTexture(source: [*c]const GPUTextureTransferInfo, destination: [*c]const GPUTextureRegion, cycle: bool)
|
||||
copyPass.uploadToGPUTexture(
|
||||
&.{
|
||||
.transfer_buffer = transferBuffer,
|
||||
.offset = 0,
|
||||
.pixels_per_row = png.size.x,
|
||||
.rows_per_layer = png.size.y,
|
||||
},
|
||||
&std.mem.zeroInit(gpu.GPUTextureRegion, .{
|
||||
.texture = gpuTexture,
|
||||
.w = png.size.x,
|
||||
.h = png.size.y,
|
||||
.d = 1,
|
||||
}),
|
||||
false,
|
||||
);
|
||||
|
||||
copyPass.endGPUCopyPass();
|
||||
if (!cmd.submitGPUCommandBuffer()) {
|
||||
return error.CopyFailed;
|
||||
}
|
||||
self.device.releaseGPUTransferBuffer(transferBuffer);
|
||||
|
||||
const tex = try self.allocator.create(Texture);
|
||||
tex.* = .{
|
||||
.texture = gpuTexture,
|
||||
.id = 0,
|
||||
.format = .f32_rgba,
|
||||
.usage = .{},
|
||||
.size = png.size,
|
||||
.name = name,
|
||||
};
|
||||
return tex;
|
||||
}
|
||||
|
||||
pub fn discardAll(self: *@This()) void {
|
||||
_ = self;
|
||||
}
|
||||
|
||||
pub fn destroy(self: *@This()) void {
|
||||
var iter = self.map.valueIterator();
|
||||
while (iter.next()) |x| {
|
||||
self.allocator.destroy(x.*);
|
||||
}
|
||||
self.map.deinit(self.allocator);
|
||||
self.allocator.destroy(self);
|
||||
}
|
||||
|
||||
const std = @import("std");
|
||||
const core = @import("core");
|
||||
const rend = @import("../rend.zig");
|
||||
const texture = rend.texture;
|
||||
const Texture = texture.Texture;
|
||||
const sdl3 = @import("sdl3");
|
||||
const gpu = sdl3.gpu;
|
||||
const assets = @import("assets");
|
||||
|
|
@ -68,10 +68,12 @@ pub const MeshPool = struct {
|
|||
while (self.meshUpdates.popFromUnlocked()) |u| {
|
||||
switch (u) {
|
||||
.new => |new| {
|
||||
var name = new.name;
|
||||
core.engine_log("uploading mesh => {s}", .{name.utf8()});
|
||||
|
||||
const indexSpan = try self.addTransfer(copyPass, self.indexBuffer, u32, &self.indexSpans, new.indices);
|
||||
const vertexSpan = try self.addTransfer(copyPass, self.vertexBuffer, meshes.MeshVertex, &self.vertexSpans, new.vertices);
|
||||
|
||||
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()});
|
||||
|
|
@ -79,7 +81,7 @@ pub const MeshPool = struct {
|
|||
.vertex = vertexSpan,
|
||||
.index = indexSpan,
|
||||
.name = new.name,
|
||||
.jointRemap = null, // joint remaps... parse the installed skeletal meshes to generate this remap
|
||||
.jointRemap = null, // joint remaps... TODO parse the installed skeletal meshes to generate this remap
|
||||
});
|
||||
},
|
||||
.free => |free| {
|
||||
|
|
@ -118,17 +120,19 @@ pub const MeshPool = struct {
|
|||
|
||||
var mappedSlice: []T = undefined;
|
||||
mappedSlice.ptr = @ptrCast(@alignCast(self.device.mapGPUTransferBuffer(upload, false)));
|
||||
defer self.device.unmapGPUTransferBuffer(upload);
|
||||
mappedSlice.len = uploadSlice.len;
|
||||
std.mem.copyForwards(T, mappedSlice, uploadSlice);
|
||||
self.device.unmapGPUTransferBuffer(upload);
|
||||
|
||||
//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 * @sizeOf(T) },
|
||||
&.{ .buffer = destBuffer, .offset = newSpan.start * @sizeOf(T), .size = newSpan.size * @sizeOf(T) },
|
||||
false,
|
||||
);
|
||||
|
||||
core.engine_log("uploading {s} buffer span {d}[{d}] ({d} bytes)", .{ @typeName(T), newSpan.start, newSpan.size, newSpan.size * @sizeOf(T) });
|
||||
|
||||
return newSpan;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@ pub const Renderer = struct {
|
|||
|
||||
depthTexture: *gpu.GPUTexture = undefined,
|
||||
|
||||
textureList: *TextureList = undefined,
|
||||
|
||||
// transients DO NOT TOUCH
|
||||
swapchainTexture: *gpu.GPUTexture = undefined,
|
||||
|
||||
|
|
@ -57,8 +59,6 @@ pub const Renderer = struct {
|
|||
return self;
|
||||
}
|
||||
|
||||
// pub fn createRendererObjectArgs(self: *@This(), T: type) !*T {
|
||||
|
||||
// registers a pre-existing render object, does not add to destroys
|
||||
pub fn registerRendererObject(self: *@This(), T: type, object: *anyopaque) !void {
|
||||
if (@hasDecl(T, "onUpload")) {
|
||||
|
|
@ -78,6 +78,13 @@ pub const Renderer = struct {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn createRendererEngineObject(self: *@This(), T: type) !*T {
|
||||
const object = try core.createObject(T, .{});
|
||||
try object.setup(self.device);
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
pub fn createRendererObject(self: *@This(), T: type) !*T {
|
||||
const object = try T.create(self.device, self.allocator, .{});
|
||||
|
||||
|
|
@ -123,6 +130,7 @@ pub const Renderer = struct {
|
|||
try self.createDepthTexture();
|
||||
|
||||
self.meshPool = try self.createRendererObject(MeshPool);
|
||||
self.textureList = try self.createRendererEngineObject(TextureList);
|
||||
}
|
||||
|
||||
pub fn discoverFormats(self: *@This()) !void {
|
||||
|
|
@ -473,6 +481,8 @@ const ShaderLoadArgs = sdl3.shaderTypes.ShaderLoadArgs;
|
|||
pub const mesh_pool = @import("mesh-pool.zig");
|
||||
pub const MeshPool = mesh_pool.MeshPool;
|
||||
|
||||
pub const TextureList = @import("TextureList.zig");
|
||||
|
||||
// debug api
|
||||
|
||||
pub fn reloadShaders() !void {
|
||||
|
|
@ -515,3 +525,5 @@ pub const getMesh = mesh_pool.getMesh;
|
|||
pub const getMeshByName = mesh_pool.getMeshByName;
|
||||
|
||||
pub const pushMeshUpdate = mesh_pool.pushMeshUpdate;
|
||||
|
||||
pub const GPUTextureType = gpu.GPUTexture;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
pub const TextureFormat = enum(u8) {
|
||||
f32_rgba,
|
||||
u8_rgba,
|
||||
};
|
||||
pub const TextureUsage = struct {
|
||||
mesh: bool = false,
|
||||
};
|
||||
|
||||
// handle to a texture resource in the engine.
|
||||
pub const Texture = struct {
|
||||
id: u32 = 0, // 0 is unknown texture.
|
||||
format: TextureFormat = .f32_rgba, // format of the texture
|
||||
usage: TextureUsage = .{},
|
||||
size: core.Vector2u,
|
||||
name: core.Name,
|
||||
texture: *GPUTextureType,
|
||||
};
|
||||
|
||||
const core = @import("core");
|
||||
const rend = @import("../rend.zig");
|
||||
const renderer = rend.renderer;
|
||||
const GPUTextureType = renderer.GPUTextureType;
|
||||
Binary file not shown.
|
|
@ -34,12 +34,8 @@ struct main0_in
|
|||
vertex main0_out main0(main0_in in [[stage_in]], constant type_Uniforms& Uniforms [[buffer(0)]], const device type_StructuredBuffer_Scene& scene [[buffer(1)]], uint gl_InstanceIndex [[instance_id]])
|
||||
{
|
||||
main0_out out = {};
|
||||
float4 _44 = float4(in.in_var_TEXCOORD0, 1.0);
|
||||
float _47 = Uniforms.time * 0.5;
|
||||
_44.x = in.in_var_TEXCOORD0.x + (((0.20000000298023223876953125 * sin(_47)) * in.in_var_TEXCOORD0.y) * 0.5);
|
||||
_44.y = in.in_var_TEXCOORD0.y + (((0.20000000298023223876953125 * cos(_47)) * in.in_var_TEXCOORD0.z) * 0.5);
|
||||
out.out_var_TEXCOORD0 = in.in_var_TEXCOORD3;
|
||||
out.gl_Position = Uniforms.ViewProjection * (scene._m0[gl_InstanceIndex].Model * _44);
|
||||
out.gl_Position = Uniforms.ViewProjection * (scene._m0[gl_InstanceIndex].Model * float4(in.in_var_TEXCOORD0, 1.0));
|
||||
return out;
|
||||
}
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -25,11 +25,16 @@ 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" },
|
||||
),
|
||||
assets.MakeImportRefOptions(
|
||||
"Texture",
|
||||
"t_empire",
|
||||
.{ .path = "textures/texture_sample.png" },
|
||||
),
|
||||
};
|
||||
|
||||
pub fn prepare(self: *@This()) !void {
|
||||
|
|
@ -59,6 +64,15 @@ pub fn prepare(self: *@This()) !void {
|
|||
empireMesh.setMesh("m_empire");
|
||||
}
|
||||
|
||||
{
|
||||
const fox = try core.createEntity();
|
||||
const scene = fox.addComponent(core.Scene).?;
|
||||
_ = scene;
|
||||
// scene.setScale();
|
||||
const mesh = fox.addComponent(rend.MeshComponent).?;
|
||||
mesh.setMesh("m_fox");
|
||||
}
|
||||
|
||||
rend.setActiveCamera(camera);
|
||||
|
||||
self.moveInput = try core.Axis2dBinding.create(core.MakeName("movement"));
|
||||
|
|
|
|||
Loading…
Reference in New Issue