diff options
| author | Patrick | 2026-10-05 19:01:09 +0200 |
|---|---|---|
| committer | Patrick | 2026-10-05 19:01:09 +0200 |
| commit | bd3f5d3455ed523f58fd292b33db2cece1013cdf (patch) | |
| tree | 5b3b111eda73f59befcb4b0ecd80af5105ad522d /src/main.zig | |
| parent | 2e19a1b44b366547563f5c5686455a1227a8fcbd (diff) | |
| download | sg3-bd3f5d3455ed523f58fd292b33db2cece1013cdf.tar.gz sg3-bd3f5d3455ed523f58fd292b33db2cece1013cdf.zip | |
Diffstat (limited to 'src/main.zig')
| -rw-r--r-- | src/main.zig | 205 |
1 files changed, 127 insertions, 78 deletions
diff --git a/src/main.zig b/src/main.zig index 238785c..d0f369a 100644 --- a/src/main.zig +++ b/src/main.zig @@ -19,15 +19,16 @@ const shd = @import("shaders/main.glsl.zig"); const state = struct { var alloc: std.mem.Allocator = undefined; var io: std.Io = undefined; + const Width = 800; const Height = 800; - const offscreen = struct { - var pass: sg.Pass = .{}; + const SampleCount = 1; + var show: i32 = 0; + + const raymarch = struct { + var pass_action: sg.PassAction = .{}; var pip: sg.Pipeline = .{}; var bind: sg.Bindings = .{}; - var vs: shd.VsParams = .{ - .position = .{ 0, 0 }, - }; var fs: shd.FsParams = .{ .resolution = .{ Width, Height }, .rayCount = 24, @@ -39,10 +40,18 @@ const state = struct { var pixels_updated: bool = true; var pixels_img: sg.Image = undefined; }; - const display = struct { + const nearest = struct { var pass_action: sg.PassAction = .{}; - var pip: sg.Pipeline = .{}; + var pass: sg.Pass = .{}; + var pip1: sg.Pipeline = .{}; + var pip2: sg.Pipeline = .{}; var bind: sg.Bindings = .{}; + + var render_tex1: sg.View = .{}; + var render_tex2: sg.View = .{}; + var input_tex1: sg.View = .{}; + var input_tex2: sg.View = .{}; + var depth_img: sg.Image = .{}; }; }; @@ -58,56 +67,65 @@ export fn init() void { sappimgui.setup(); ig.igGetIO().*.ConfigFlags |= ig.ImGuiConfigFlags_DockingEnable; - state.offscreen.pass.action.colors[0] = .{ + state.raymarch.pass_action.colors[0] = .{ .load_action = .LOAD, .store_action = .STORE, }; - state.offscreen.pass.action.depth = .{ + state.raymarch.pass_action.depth = .{ .load_action = .LOAD, .store_action = .STORE, }; - state.display.pass_action.colors[0] = .{ + state.nearest.pass_action.colors[0] = .{ .load_action = .CLEAR, }; - const offscreen_width = state.Width; - const offscreen_height = state.Height; - const offscreen_sample_count = 1; - const color_img = sg.makeImage(.{ + state.raymarch.pixels_img = sg.makeImage(.{ + .usage = .{ .dynamic_update = true }, + .width = state.Width, + .height = state.Height, + .sample_count = state.SampleCount, + .pixel_format = .RGBA8, + }); + const nearest_tex1 = sg.makeImage(.{ .usage = .{ .color_attachment = true }, - .width = offscreen_width, - .height = offscreen_height, - .sample_count = offscreen_sample_count, + .width = state.Width, + .height = state.Height, + .sample_count = state.SampleCount, .pixel_format = .RGBA8, }); - state.offscreen.pixels_img = sg.makeImage(.{ - .usage = .{ .dynamic_update = true }, - .width = offscreen_width, - .height = offscreen_height, - .sample_count = offscreen_sample_count, + const nearest_tex2 = sg.makeImage(.{ + .usage = .{ .color_attachment = true }, + .width = state.Width, + .height = state.Height, + .sample_count = state.SampleCount, .pixel_format = .RGBA8, }); - const depth_img = sg.makeImage(.{ + const nearest_depth_img = sg.makeImage(.{ .usage = .{ .depth_stencil_attachment = true }, - .width = offscreen_width, - .height = offscreen_height, - .sample_count = offscreen_sample_count, + .width = state.Width, + .height = state.Height, + .sample_count = state.SampleCount, .pixel_format = .DEPTH, }); - - state.offscreen.pass.attachments.colors[0] = sg.makeView(.{ - .color_attachment = .{ .image = color_img }, + state.nearest.render_tex1 = sg.makeView(.{ + .color_attachment = .{ .image = nearest_tex1 }, }); - state.offscreen.pass.attachments.depth_stencil = sg.makeView(.{ - .depth_stencil_attachment = .{ .image = depth_img }, + state.nearest.render_tex2 = sg.makeView(.{ + .color_attachment = .{ .image = nearest_tex2 }, + }); + state.nearest.input_tex1 = sg.makeView(.{ + .texture = .{ .image = nearest_tex1 }, + }); + state.nearest.input_tex2 = sg.makeView(.{ + .texture = .{ .image = nearest_tex2 }, }); - state.offscreen.bind.views[shd.VIEW_off_tex] = sg.makeView(.{ - .texture = .{ .image = state.offscreen.pixels_img }, + state.raymarch.bind.views[shd.VIEW_off_tex] = sg.makeView(.{ + .texture = .{ .image = state.raymarch.pixels_img }, }); - state.display.bind.views[shd.VIEW_scr_tex] = sg.makeView(.{ - .texture = .{ .image = color_img }, + state.nearest.pass.attachments.depth_stencil = sg.makeView(.{ + .depth_stencil_attachment = .{ .image = nearest_depth_img }, }); const vbuf = sg.makeBuffer(.{ .data = sg.asRange(&[6]f32{ @@ -115,53 +133,63 @@ export fn init() void { -1.0, 3.0, 3.0, -1.0, }) }); - state.offscreen.bind.vertex_buffers[0] = vbuf; - state.display.bind.vertex_buffers[0] = vbuf; + state.raymarch.bind.vertex_buffers[0] = vbuf; + state.nearest.bind.vertex_buffers[0] = vbuf; // shader and pipeline object for the default render pass - state.offscreen.pip = sg.makePipeline(.{ - .shader = sg.makeShader(shd.offscreenShaderDesc(sg.queryBackend())), + state.raymarch.pip = sg.makePipeline(.{ + .shader = sg.makeShader(shd.raymarchShaderDesc(sg.queryBackend())), .layout = init: { var l = sg.VertexLayoutState{}; - l.attrs[shd.ATTR_offscreen_vpos] = .{ .format = .FLOAT2 }; + l.attrs[shd.ATTR_raymarch_vpos] = .{ .format = .FLOAT2 }; break :init l; }, .cull_mode = .BACK, - .sample_count = offscreen_sample_count, .depth = .{ .pixel_format = .DEPTH, .compare = .LESS_EQUAL, .write_enabled = true, }, - .colors = init: { - var c: [sg.max_color_attachments]sg.ColorTargetState = @splat(.{}); - c[0].pixel_format = .RGBA8; - break :init c; - }, }); - state.display.pip = sg.makePipeline(.{ - .shader = sg.makeShader(shd.defaultShaderDesc(sg.queryBackend())), + state.nearest.pip1 = sg.makePipeline(.{ + .shader = sg.makeShader(shd.nearestShaderDesc(sg.queryBackend())), .layout = init: { var l = sg.VertexLayoutState{}; - l.attrs[shd.ATTR_default_vpos] = .{ .format = .FLOAT2 }; + l.attrs[shd.ATTR_nearest_vpos] = .{ .format = .FLOAT2 }; break :init l; }, .cull_mode = .BACK, + .sample_count = state.SampleCount, .depth = .{ + .pixel_format = .DEPTH, .compare = .LESS_EQUAL, .write_enabled = true, }, + .colors = init: { + var c: [sg.max_color_attachments]sg.ColorTargetState = @splat(.{}); + c[0].pixel_format = .RGBA8; + break :init c; + }, + }); + state.nearest.pip2 = sg.makePipeline(.{ + .shader = sg.makeShader(shd.nearestShaderDesc(sg.queryBackend())), + .layout = init: { + var l = sg.VertexLayoutState{}; + l.attrs[shd.ATTR_nearest_vpos] = .{ .format = .FLOAT2 }; + break :init l; + }, + .cull_mode = .BACK, }); // a sampler object for sampling the render target texture - state.offscreen.bind.samplers[shd.SMP_off_smp] = sg.makeSampler(.{ + state.raymarch.bind.samplers[shd.SMP_off_smp] = sg.makeSampler(.{ .min_filter = .LINEAR, .mag_filter = .LINEAR, .wrap_u = .REPEAT, .wrap_v = .REPEAT, }); - state.display.bind.samplers[shd.SMP_scr_smp] = sg.makeSampler(.{ + state.nearest.bind.samplers[shd.SMP_scr_smp] = sg.makeSampler(.{ .min_filter = .LINEAR, .mag_filter = .LINEAR, .wrap_u = .REPEAT, @@ -195,51 +223,72 @@ export fn frame() void { // const dt: f32 = @floatCast(sapp.frameDuration() * 60); // const aspect = sapp.widthf() / sapp.heightf(); - state.offscreen.fs.resolution[0] = sapp.widthf(); - state.offscreen.fs.resolution[1] = sapp.heightf(); + state.raymarch.fs.resolution[0] = sapp.widthf(); + state.raymarch.fs.resolution[1] = sapp.heightf(); if (ig.igBegin("abc", null, 0)) { - // vs - _ = ig.igDragFloat2("position", &state.offscreen.vs.position); - + // general + _ = ig.igInputInt("show", &state.show); // fs - _ = ig.igInputInt("rayCount", &state.offscreen.fs.rayCount); - _ = ig.igInputInt("maxSteps", &state.offscreen.fs.maxSteps); - _ = ig.igDragFloatEx("size", &state.offscreen.fs.size, 1, 0, 1000, "%f", 0); + _ = ig.igInputInt("rayCount", &state.raymarch.fs.rayCount); + _ = ig.igInputInt("maxSteps", &state.raymarch.fs.maxSteps); + _ = ig.igDragFloatEx("size", &state.raymarch.fs.size, 1, 0, 1000, "%f", 0); if (ig.igButton("load png")) { var x: c_int = 0; var y: c_int = 0; var n: c_int = 0; const img = stbi.stbi_load("test.png", &x, &y, &n, 0); - @memcpy(&state.offscreen.pixels, img); + @memcpy(&state.raymarch.pixels, img); stbi.stbi_image_free(img); - state.offscreen.pixels_updated = true; + state.raymarch.pixels_updated = true; } } ig.igEnd(); - if (state.offscreen.pixels_updated) { - state.offscreen.pixels_updated = false; + if (state.raymarch.pixels_updated) { + state.raymarch.pixels_updated = false; var imageData: sg.ImageData = .{}; - imageData.mip_levels[0] = sg.asRange(&state.offscreen.pixels); - sg.updateImage(state.offscreen.pixels_img, imageData); + imageData.mip_levels[0] = sg.asRange(&state.raymarch.pixels); + sg.updateImage(state.raymarch.pixels_img, imageData); } - sg.beginPass(state.offscreen.pass); - sg.applyPipeline(state.offscreen.pip); - sg.applyBindings(state.offscreen.bind); - sg.applyUniforms(shd.UB_vs_params, sg.asRange(&state.offscreen.vs)); - sg.applyUniforms(shd.UB_fs_params, sg.asRange(&state.offscreen.fs)); - sg.draw(0, 3, 1); - sg.endPass(); + if (state.show == 0) { + sg.beginPass(.{ .action = state.raymarch.pass_action, .swapchain = sglue.swapchain() }); + sg.applyPipeline(state.raymarch.pip); + sg.applyBindings(state.raymarch.bind); + sg.applyUniforms(shd.UB_fs_params, sg.asRange(&state.raymarch.fs)); + sg.draw(0, 3, 1); + simgui.render(); + sg.endPass(); + } else if (state.show == 1) { + // render to tex1 + state.nearest.pass.attachments.colors[0] = state.nearest.render_tex1; + state.nearest.bind.views[shd.VIEW_scr_tex] = state.nearest.input_tex2; + sg.beginPass(state.nearest.pass); + sg.applyPipeline(state.nearest.pip1); + sg.applyBindings(state.nearest.bind); + sg.draw(0, 3, 1); + sg.endPass(); - sg.beginPass(.{ .action = state.display.pass_action, .swapchain = sglue.swapchain() }); - sg.applyPipeline(state.display.pip); - sg.applyBindings(state.display.bind); - sg.draw(0, 3, 1); - simgui.render(); - sg.endPass(); + // render from tex1 to tex2 + state.nearest.pass.attachments.colors[0] = state.nearest.render_tex2; + state.nearest.bind.views[shd.VIEW_scr_tex] = state.nearest.input_tex1; + sg.beginPass(state.nearest.pass); + sg.applyPipeline(state.nearest.pip1); + sg.applyBindings(state.nearest.bind); + sg.draw(0, 3, 1); + sg.endPass(); + + // render from tex2 to screen + state.nearest.bind.views[shd.VIEW_scr_tex] = state.nearest.input_tex2; + sg.beginPass(.{.action = state.nearest.pass_action, .swapchain = sglue.swapchain() }); + sg.applyPipeline(state.nearest.pip2); + sg.applyBindings(state.nearest.bind); + sg.draw(0, 3, 1); + simgui.render(); + sg.endPass(); + } sg.commit(); } |
