treesummaryrefslogcommitdiff
path: root/src/main.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.zig')
-rw-r--r--src/main.zig229
1 files changed, 196 insertions, 33 deletions
diff --git a/src/main.zig b/src/main.zig
index 9f68540..d714e3f 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -4,6 +4,8 @@
// Render to an offscreen rendertarget texture, and use this texture
// for rendering to the display.
//------------------------------------------------------------------------------
+const std = @import("std");
+const stbi = @import("stbi");
const sokol = @import("sokol");
const slog = sokol.log;
const sg = sokol.gfx;
@@ -17,12 +19,32 @@ const mat4 = @import("math.zig").Mat4;
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 = .{};
+ var pip: sg.Pipeline = .{};
+ var bind: sg.Bindings = .{};
+ var vs: shd.VsParams = .{
+ .position = .{ 0, 0 },
+ };
+ var fs: shd.FsParams = .{
+ .resolution = .{ Width, Height },
+ .rayCount = 16,
+ .maxSteps = 4,
+ .size = 1.0,
+ };
+
+ var pixels: [state.Width * state.Height * 4]u8 = @splat(255);
+ var pixels_updated: bool = true;
+ var pixels_img: sg.Image = undefined;
+ };
const display = 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 = .{.color = .{1,0,0,1}};
};
};
@@ -32,25 +54,74 @@ export fn init() void {
.logger = .{ .func = slog.func },
});
- simgui.setup(.{});
+ simgui.setup(.{
+ .logger = .{ .func = slog.func },
+ });
sappimgui.setup();
ig.igGetIO().*.ConfigFlags |= ig.ImGuiConfigFlags_DockingEnable;
- // default pass action: clear to blue-ish
+ state.offscreen.pass.action.colors[0] = .{
+ .load_action = .LOAD,
+ .store_action = .STORE,
+ };
+ state.offscreen.pass.action.depth = .{
+ .load_action = .LOAD,
+ .store_action = .STORE,
+ };
+
state.display.pass_action.colors[0] = .{
.load_action = .CLEAR,
- .clear_value = .{ .r = 1, .g = 0, .b = 0, .a = 1.0 },
};
- const vbuf = sg.makeBuffer(.{.data = sg.asRange(&[6]f32 {
+ const offscreen_width = state.Width;
+ const offscreen_height = state.Height;
+ const offscreen_sample_count = 1;
+ const color_img = sg.makeImage(.{
+ .usage = .{ .color_attachment = true },
+ .width = offscreen_width,
+ .height = offscreen_height,
+ .sample_count = offscreen_sample_count,
+ .pixel_format = .RGBA8,
+ });
+ state.offscreen.pixels_img = sg.makeImage(.{
+ .usage = .{ .dynamic_update = true },
+ .width = offscreen_width,
+ .height = offscreen_height,
+ .sample_count = offscreen_sample_count,
+ .pixel_format = .RGBA8,
+ });
+ const depth_img = sg.makeImage(.{
+ .usage = .{ .depth_stencil_attachment = true },
+ .width = offscreen_width,
+ .height = offscreen_height,
+ .sample_count = offscreen_sample_count,
+ .pixel_format = .DEPTH,
+ });
+
+ state.offscreen.pass.attachments.colors[0] = sg.makeView(.{
+ .color_attachment = .{ .image = color_img },
+ });
+ state.offscreen.pass.attachments.depth_stencil = sg.makeView(.{
+ .depth_stencil_attachment = .{ .image = depth_img },
+ });
+
+ state.offscreen.bind.views[shd.VIEW_off_tex] = sg.makeView(.{
+ .texture = .{ .image = state.offscreen.pixels_img },
+ });
+ state.display.bind.views[shd.VIEW_scr_tex] = sg.makeView(.{
+ .texture = .{ .image = color_img },
+ });
+
+ const vbuf = sg.makeBuffer(.{ .data = sg.asRange(&[6]f32{
-1.0, -1.0,
- -1.0, 3.0,
- 3.0, -1.0,
- })});
+ -1.0, 3.0,
+ 3.0, -1.0,
+ }) });
+ state.offscreen.bind.vertex_buffers[0] = vbuf;
state.display.bind.vertex_buffers[0] = vbuf;
// shader and pipeline object for the default render pass
- state.display.pip = sg.makePipeline(.{
+ state.offscreen.pip = sg.makePipeline(.{
.shader = sg.makeShader(shd.offscreenShaderDesc(sg.queryBackend())),
.layout = init: {
var l = sg.VertexLayoutState{};
@@ -58,44 +129,143 @@ export fn init() void {
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())),
+ .layout = init: {
+ var l = sg.VertexLayoutState{};
+ l.attrs[shd.ATTR_default_vpos] = .{ .format = .FLOAT2 };
+ break :init l;
+ },
+ .cull_mode = .BACK,
.depth = .{
.compare = .LESS_EQUAL,
.write_enabled = true,
},
});
+
+ // a sampler object for sampling the render target texture
+ state.offscreen.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(.{
+ .min_filter = .LINEAR,
+ .mag_filter = .LINEAR,
+ .wrap_u = .REPEAT,
+ .wrap_v = .REPEAT,
+ });
}
export fn event(ev: [*c]const sapp.Event) void {
sappimgui.trackEvent(ev.*);
- // forward input events to sokol-imgui
_ = simgui.handleEvent(ev.*);
+
+ switch (ev.*.type) {
+ .KEY_DOWN => {
+ if (ev.*.key_code == .ESCAPE) {
+ sapp.requestQuit();
+ }
+ },
+ else => {},
+ }
}
+// fn load_bmp(path: []const u8, buffer: []u8) !void {
+// var file = try std.Io.Dir.cwd().openFile(state.io, path, .{});
+// var read_buffer: [1024]u8 = undefined;
+// var reader = file.reader(state.io, &read_buffer).interface;
+// var bfType = try reader.takeInt(u16, .little);
+// var bfSize = try reader.takeInt(u32, .little);
+// var bfReserved = try reader.takeInt(u32, .little);
+// var bfOffBits = try reader.takeInt(u32, .little);
+// var biSize = try reader.takeInt(u32, .little);
+// var biWidth = try reader.takeInt(u32, .little);
+// var biHeight = try reader.takeInt(u32, .little);
+// var biPlanes = try reader.takeInt(u16, .little);
+// var biBitCount = try reader.takeInt(u16, .little);
+// var biCompression = try reader.takeInt(u32, .little);
+// var biSizeImage = try reader.takeInt(u32, .little);
+// var biXPelsPerMeter = try reader.takeInt(u32, .little);
+// var biYPelsPerMeter = try reader.takeInt(u32, .little);
+// var biClrUsed = try reader.takeInt(u32, .little);
+// var biClrImportant = try reader.takeInt(u32, .little);
+//
+// if (buffer.len < biWidth * biHeight * biBitCount / 8) {
+// return error.BufferTooSmall;
+// }
+//
+//
+// }
+
export fn frame() void {
// call simgui.newFrame() before any ImGui calls
+ sappimgui.trackFrame();
simgui.newFrame(.{
.width = sapp.width(),
.height = sapp.height(),
.delta_time = sapp.frameDuration(),
.dpi_scale = sapp.dpiScale(),
});
- sappimgui.trackFrame();
// const dt: f32 = @floatCast(sapp.frameDuration() * 60);
// const aspect = sapp.widthf() / sapp.heightf();
-
- if (ig.igBegin("abc", null, 0))
- {
- _ = ig.igDragFloat2("position", &state.display.vs.position);
- _ = ig.igColorEdit4("color", &state.display.fs.color, 0);
- ig.igEnd();
+ state.offscreen.fs.resolution[0] = sapp.widthf();
+ state.offscreen.fs.resolution[1] = sapp.heightf();
+
+ if (ig.igBegin("abc", null, 0)) {
+ // vs
+ _ = ig.igDragFloat2("position", &state.offscreen.vs.position);
+
+ // fs
+ _ = ig.igInputInt("rayCount", &state.offscreen.fs.rayCount);
+ _ = ig.igInputInt("maxSteps", &state.offscreen.fs.maxSteps);
+ _ = ig.igDragFloatEx("size", &state.offscreen.fs.size, 0.1, 0, 100, "%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);
+ stbi.stbi_image_free(img);
+ state.offscreen.pixels_updated = true;
+ }
+ }
+ ig.igEnd();
+
+ if (state.offscreen.pixels_updated) {
+ state.offscreen.pixels_updated = false;
+ var imageData: sg.ImageData = .{};
+ imageData.mip_levels[0] = sg.asRange(&state.offscreen.pixels);
+ sg.updateImage(state.offscreen.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();
+
sg.beginPass(.{ .action = state.display.pass_action, .swapchain = sglue.swapchain() });
sg.applyPipeline(state.display.pip);
sg.applyBindings(state.display.bind);
- sg.applyUniforms(shd.UB_vs_params, sg.asRange(&state.display.vs));
- sg.applyUniforms(shd.UB_fs_params, sg.asRange(&state.display.fs));
sg.draw(0, 3, 1);
simgui.render();
sg.endPass();
@@ -109,27 +279,20 @@ export fn cleanup() void {
sg.shutdown();
}
-pub fn main() void {
+pub fn main(_init: std.process.Init) void {
+ state.alloc = _init.arena.allocator();
+ state.io = _init.io;
+
sapp.run(.{
.init_cb = init,
.frame_cb = frame,
.event_cb = event,
.cleanup_cb = cleanup,
.sample_count = 4,
- .width = 800,
- .height = 600,
+ .width = state.Width,
+ .height = state.Height,
.icon = .{ .sokol_default = true },
.window_title = "offscreen.zig",
.logger = .{ .func = slog.func },
});
}
-
-fn computeVsParams(rx: f32, ry: f32, aspect: f32, eye_dist: f32) shd.VsParams {
- const proj = mat4.persp(45, aspect, 0.01, 10);
- const view = mat4.lookat(.{ .x = 0, .y = 0, .z = eye_dist }, vec3.zero(), vec3.up());
- const view_proj = mat4.mul(proj, view);
- const rxm = mat4.rotate(rx, .{ .x = 1, .y = 0, .z = 0 });
- const rym = mat4.rotate(ry, .{ .x = 0, .y = 1, .z = 0 });
- const model = mat4.mul(rxm, rym);
- return shd.VsParams{ .mvp = mat4.mul(view_proj, model) };
-}