treesummaryrefslogcommitdiff
path: root/src/main.zig
blob: 9f68540c4fe92cef0d8196283f4abe0386e14c75 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
//------------------------------------------------------------------------------
//  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) };
}