window shall be... colored

This commit is contained in:
abux 2026-07-10 17:22:28 +01:00
parent 660065c556
commit 676231e0d8
10 changed files with 183 additions and 9 deletions

0
src/component/mesh.zig Normal file
View file

View file

@ -4,3 +4,7 @@ pub const Camera = @import("camera.zig");
// --- MATERIALS --- // --- MATERIALS ---
pub const PBRMaterial = @import("pbr_material.zig"); pub const PBRMaterial = @import("pbr_material.zig");
pub const UnlitMaterial = @import("unlit_material.zig"); pub const UnlitMaterial = @import("unlit_material.zig");
// --- MODEL ---
pub const Mesh = @import("mesh.zig");
pub const Shape = @import("shape.zig");

0
src/component/shape.zig Normal file
View file

View file

@ -1,6 +1,7 @@
//! ---------------------------------------------------- //! ----------------------------------------------------
//! ---------------------------------------------------- //! ----------------------------------------------------
const std = @import("std");
const App = @import("app"); const App = @import("app");
const system = @import("system/root.zig"); const system = @import("system/root.zig");
const resource = @import("resource/root.zig"); const resource = @import("resource/root.zig");
@ -31,6 +32,9 @@ fn build(
try ctx.app.resources.set(resource.RenderQueue.init(ctx.app.alloc)); try ctx.app.resources.set(resource.RenderQueue.init(ctx.app.alloc));
{ // TEST { // TEST
try ctx.app.world.spawn(.{
component.Camera{},
});
try ctx.app.world.spawn(.{ try ctx.app.world.spawn(.{
component.PBRMaterial{}, component.PBRMaterial{},
}); });
@ -47,6 +51,7 @@ fn build(
system.frame.begin, system.frame.begin,
system.frame.prepare, system.frame.prepare,
system.frame.draw,
}); });
// --- DEINIT --- // --- DEINIT ---
@ -55,9 +60,13 @@ fn build(
struct { // TODO: Clean this shit up 🥀 struct { // TODO: Clean this shit up 🥀
pub fn sys(_ctx: App.scheduler.Context) !void { pub fn sys(_ctx: App.scheduler.Context) !void {
if (_ctx.app.resources.getPtr(resource.Cache)) |cache| { const res = try _ctx.app.resources.getMany(struct {
cache.deinit(); cache: *resource.Cache,
} render_queue: *resource.RenderQueue,
});
res.cache.deinit();
res.render_queue.deinit();
} }
}.sys, }.sys,

View file

@ -20,6 +20,15 @@ pub const ShaderID = union(enum) {
/// ---------------------------------------------------- /// ----------------------------------------------------
pub const PipelineKey = struct { pub const PipelineKey = struct {
shader: ShaderID, shader: ShaderID,
pub fn format(
self: @This(),
writer: *std.Io.Writer,
) std.Io.Writer.Error!void {
try writer.print("shader({s})", .{
@tagName(self.shader),
});
}
}; };
// //
@ -48,6 +57,13 @@ pub fn deinit(self: *Self) void {
} }
} }
{ // PIPELINES
var it = self.pipelines.iterator();
while (it.next()) |entry| {
wgpu.wgpuRenderPipelineRelease(entry.value.*);
}
}
self.shaders.deinit(); self.shaders.deinit();
self.pipelines.deinit(); self.pipelines.deinit();
} }

View file

@ -24,6 +24,10 @@ pub fn init(alloc: std.mem.Allocator) Self {
/// ---------------------------------------------------- /// ----------------------------------------------------
/// ---------------------------------------------------- /// ----------------------------------------------------
pub fn deinit(self: *Self) void { pub fn deinit(self: *Self) void {
for (self.data.items) |*queue| {
queue.deinit();
}
self.data.deinit(self.alloc); self.data.deinit(self.alloc);
} }
@ -32,3 +36,12 @@ pub fn deinit(self: *Self) void {
pub fn clear(self: *Self) void { pub fn clear(self: *Self) void {
self.data.clearRetainingCapacity(); self.data.clearRetainingCapacity();
} }
/// ----------------------------------------------------
/// ----------------------------------------------------
pub fn append(
self: *Self,
queue: CameraRenderQueue,
) !void {
try self.data.append(self.alloc, queue);
}

View file

@ -72,7 +72,7 @@ pub fn init(ctx: App.scheduler.Context) !void {
} }
// --- DEBUG LIMITS --- // --- DEBUG LIMITS ---
std.debug.print("\x1b[35m┏━ ADAPTER LIMITS ━┓\x1b[0m\n", .{}); std.debug.print("\x1b[35m┏━ ADAPTER LIMITS\x1b[0m\n", .{});
std.debug.print("\x1b[35m┃\x1b[0m Texture Dimentions: ({})1D, ({})2D, ({})3D, ({})Array Layers\n", .{ std.debug.print("\x1b[35m┃\x1b[0m Texture Dimentions: ({})1D, ({})2D, ({})3D, ({})Array Layers\n", .{
limits.maxTextureDimension1D, limits.maxTextureDimension1D,
limits.maxTextureDimension2D, limits.maxTextureDimension2D,
@ -82,7 +82,7 @@ pub fn init(ctx: App.scheduler.Context) !void {
std.debug.print("\x1b[35m┗━\x1b[0m\n", .{}); std.debug.print("\x1b[35m┗━\x1b[0m\n", .{});
// --- DEBUG INFO --- // --- DEBUG INFO ---
std.debug.print("\x1b[35m┏━ ADAPTER INFO ━┓\x1b[0m\n", .{}); std.debug.print("\x1b[35m┏━ ADAPTER INFO\x1b[0m\n", .{});
std.debug.print( std.debug.print(
"\x1b[35m┃\x1b[0m Device: {s}\n" ++ "\x1b[35m┃\x1b[0m Device: {s}\n" ++
"\x1b[35m┃\x1b[0m Backend: {s}\n", "\x1b[35m┃\x1b[0m Backend: {s}\n",
@ -143,6 +143,7 @@ pub fn init(ctx: App.scheduler.Context) !void {
.format = caps.formats[0], .format = caps.formats[0],
.width = res.window.width, .width = res.window.width,
.height = res.window.height, .height = res.window.height,
.usage = wgpu.WGPUTextureUsage_RenderAttachment,
}, },
); );
} }

View file

@ -10,6 +10,7 @@ const component = @import("../component/root.zig");
const Window = @import("../resource/window.zig"); const Window = @import("../resource/window.zig");
const Device = @import("../resource/device.zig"); const Device = @import("../resource/device.zig");
const RenderFrame = @import("../resource/render_frame.zig"); const RenderFrame = @import("../resource/render_frame.zig");
const RenderQueue = @import("../resource/render_queue.zig");
const Cache = @import("../resource/cache.zig"); const Cache = @import("../resource/cache.zig");
const PBRShader = @import("../renderer.zig").PBRShader; const PBRShader = @import("../renderer.zig").PBRShader;
@ -66,6 +67,7 @@ pub fn end(ctx: App.scheduler.Context) !void {
window: *Window, window: *Window,
device: *Device, device: *Device,
render_frame: *RenderFrame, render_frame: *RenderFrame,
render_queue: *RenderQueue,
}); });
if (res.render_frame.encoder) |encoder| { if (res.render_frame.encoder) |encoder| {
@ -103,11 +105,71 @@ pub fn end(ctx: App.scheduler.Context) !void {
// --- RESET FRAME --- // --- RESET FRAME ---
res.render_frame.reset(); res.render_frame.reset();
res.render_queue.clear();
// --- DEBUG --- // --- DEBUG ---
sdl.SDL_Delay(2000); // TODO: Remove sdl.SDL_Delay(2000); // TODO: Remove
} }
// TODO: Clean this shit up...
/// ----------------------------------------------------
/// ----------------------------------------------------
pub fn draw(ctx: App.scheduler.Context) !void {
// --- GET RESOURCES ---
const res = try ctx.app.resources.getMany(struct {
window: *Window,
device: *Device,
cache: *Cache,
render_frame: *RenderFrame,
render_queue: *RenderQueue,
});
// --- QUERY ---
var query = ctx.app.world.query(struct {
camera: *component.Camera,
}, .{});
while (query.next()) |e| {
_ = e;
try res.render_queue.append(
.init(ctx.app.alloc),
);
// TODO: Add opaques Mesh etc
// const camera_queue = &res.render_queue.data.items[res.render_queue.data.items.len - 1];
// try camera_queue.opaques.append(
// res.render_queue.alloc,
// undefined,
// );
}
for (res.render_queue.data.items) |camera_queue| {
// --- RENDERPASS ---
const pass = wgpu.wgpuCommandEncoderBeginRenderPass(res.render_frame.encoder, &wgpu.WGPURenderPassDescriptor{
.colorAttachmentCount = 1,
.colorAttachments = &wgpu.WGPURenderPassColorAttachment{
.view = res.render_frame.color_view, // TODO: Color View
.loadOp = wgpu.WGPULoadOp_Clear,
.storeOp = wgpu.WGPUStoreOp_Store,
.clearValue = .{
.r = 0.2,
.g = 0.2,
.b = 0.8,
.a = 1.0,
},
.depthSlice = wgpu.WGPU_DEPTH_SLICE_UNDEFINED,
},
});
defer {
wgpu.wgpuRenderPassEncoderEnd(pass);
wgpu.wgpuRenderPassEncoderRelease(pass);
}
_ = camera_queue;
}
}
/// ---------------------------------------------------- /// ----------------------------------------------------
/// ---------------------------------------------------- /// ----------------------------------------------------
pub fn prepare(ctx: App.scheduler.Context) !void { pub fn prepare(ctx: App.scheduler.Context) !void {
@ -116,8 +178,10 @@ pub fn prepare(ctx: App.scheduler.Context) !void {
window: *Window, window: *Window,
device: *Device, device: *Device,
cache: *Cache, cache: *Cache,
render_frame: *RenderFrame,
}); });
// TODO: Clean this shit up | Latr go over each shader, then create pipelines
// 1) Prepare Shaders // 1) Prepare Shaders
// 2) Prepare Pipelines // 2) Prepare Pipelines
@ -171,12 +235,78 @@ pub fn prepare(ctx: App.scheduler.Context) !void {
); );
// TODO: Only show on debug mode // TODO: Only show on debug mode
std.debug.print("\x1b[35m┣━ SHADER\x1b[0m {s}\n", .{@tagName( std.debug.print("\x1b[35m┏━ MATERIAL\x1b[0m\n", .{});
std.debug.print("\x1b[35m┃ Shader: \x1b[0m {s}\n", .{@tagName(
shader_id, shader_id,
)}); )});
} }
// --- PIPELINE KEY ---
const pipe_key: Cache.PipelineKey = .{
.shader = shader_id,
};
// TODO: Pipelines // TODO: Pipelines
if (!res.cache.pipelines.contains(pipe_key)) {
// --- GET SHADER MODULE ---
const shader_module = res.cache.shaders.getPtr(
pipe_key.shader,
) orelse return error.NoShader;
// --- PIPELINE ---
const pipe = wgpu.wgpuDeviceCreateRenderPipeline(
res.device.raw,
&wgpu.WGPURenderPipelineDescriptor{
.vertex = .{
.module = shader_module.*,
.entryPoint = .{ .data = "vs_main", .length = wgpu.WGPU_STRLEN },
},
.fragment = &wgpu.WGPUFragmentState{
.module = shader_module.*,
.entryPoint = .{ .data = "fs_main", .length = wgpu.WGPU_STRLEN },
.targetCount = 1,
.targets = &wgpu.WGPUColorTargetState{
.format = wgpu.wgpuTextureGetFormat(res.render_frame.surface_tex.texture),
.blend = &wgpu.WGPUBlendState{
.color = .{
.srcFactor = wgpu.WGPUBlendFactor_SrcAlpha,
.dstFactor = wgpu.WGPUBlendFactor_OneMinusSrcAlpha,
.operation = wgpu.WGPUBlendOperation_Add,
},
.alpha = .{
.srcFactor = wgpu.WGPUBlendFactor_Zero,
.dstFactor = wgpu.WGPUBlendFactor_One,
.operation = wgpu.WGPUBlendOperation_Add,
},
},
.writeMask = wgpu.WGPUColorWriteMask_All,
},
},
.primitive = .{ // TODO: Get these from material config or sum
.topology = wgpu.WGPUPrimitiveTopology_TriangleList,
.stripIndexFormat = wgpu.WGPUIndexFormat_Undefined,
.frontFace = wgpu.WGPUFrontFace_CCW,
.cullMode = wgpu.WGPUCullMode_Back,
},
.multisample = .{
.count = 1,
.mask = ~@as(u32, 0),
},
},
) orelse return error.RenderPipeline;
errdefer wgpu.wgpuRenderPipelineRelease(pipe);
// --- ADD NEW --
try res.cache.pipelines.put(
pipe_key,
pipe,
);
// TODO: Only show on debug mode
std.debug.print("\x1b[35m┃ Pipeline: \x1b[0m{f}\n", .{pipe_key});
std.debug.print("\x1b[35m┗━ \x1b[0m\n", .{});
}
} }
} }
} }

View file

@ -40,4 +40,3 @@ pub fn clear(self: *Self) void {
self.opaques.clearRetainingCapacity(); self.opaques.clearRetainingCapacity();
self.transparents.clearRetainingCapacity(); self.transparents.clearRetainingCapacity();
} }

View file

@ -170,6 +170,8 @@ pub fn Registry(
// LOOKUP // LOOKUP
// //
// TODO: Change idx to handle.idx
/// ---------------------------------------------------- /// ----------------------------------------------------
/// ---------------------------------------------------- /// ----------------------------------------------------
pub fn contains(self: Self, key: K) bool { pub fn contains(self: Self, key: K) bool {
@ -186,8 +188,8 @@ pub fn Registry(
/// ---------------------------------------------------- /// ----------------------------------------------------
/// ---------------------------------------------------- /// ----------------------------------------------------
pub fn getPtr(self: *Self, key: K) ?*V { pub fn getPtr(self: *Self, key: K) ?*V {
const idx = self.lookup.get(key) orelse return null; const handle = self.lookup.get(key) orelse return null;
return &self.entries.items[idx].value; return &self.entries.items[@intCast(handle.idx)].value;
} }
/// ---------------------------------------------------- /// ----------------------------------------------------