//------------------------------------------------------------------------------ // offscreen.zig // // Render to an offscreen rendertarget texture, and use this texture // for rendering to the display. //------------------------------------------------------------------------------ const sokol = @import("sokol"); const slog = sokol.log; const sg = sokol.gfx; const sapp = sokol.app; const sglue = sokol.glue; const simgui = sokol.imgui; const sappimgui = sokol.appimgui; const ig = @import("cimgui_docking"); const vec3 = @import("math.zig").Vec3; const mat4 = @import("math.zig").Mat4; const shd = @import("shaders/main.glsl.zig"); const state = struct { 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}}; }; }; export fn init() void { sg.setup(.{ .environment = sglue.environment(), .logger = .{ .func = slog.func }, }); simgui.setup(.{}); sappimgui.setup(); ig.igGetIO().*.ConfigFlags |= ig.ImGuiConfigFlags_DockingEnable; // default pass action: clear to blue-ish 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 { -1.0, -1.0, -1.0, 3.0, 3.0, -1.0, })}); state.display.bind.vertex_buffers[0] = vbuf; // shader and pipeline object for the default render pass state.display.pip = sg.makePipeline(.{ .shader = sg.makeShader(shd.offscreenShaderDesc(sg.queryBackend())), .layout = init: { var l = sg.VertexLayoutState{}; l.attrs[shd.ATTR_offscreen_vpos] = .{ .format = .FLOAT2 }; break :init l; }, .cull_mode = .BACK, .depth = .{ .compare = .LESS_EQUAL, .write_enabled = true, }, }); } export fn event(ev: [*c]const sapp.Event) void { sappimgui.trackEvent(ev.*); // forward input events to sokol-imgui _ = simgui.handleEvent(ev.*); } export fn frame() void { // call simgui.newFrame() before any ImGui calls 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(); } 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(); sg.commit(); } export fn cleanup() void { sappimgui.shutdown(); simgui.shutdown(); sg.shutdown(); } pub fn main() void { sapp.run(.{ .init_cb = init, .frame_cb = frame, .event_cb = event, .cleanup_cb = cleanup, .sample_count = 4, .width = 800, .height = 600, .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) }; }