const std = @import("std"); const sokol = @import("sokol"); const sg = sokol.gfx; const shader = @import("shaders/triangle2.glsl.zig"); var pass_action: sg.PassAction = .{}; const state = struct { var bind: sg.Bindings = .{}; var pip: sg.Pipeline = .{}; var vsParams: shader.VsParams = .{ .aspectRatio = 0.5 }; var fsParams: shader.FsParams = .{ .offset = .{ 0, 0, 0 } }; var indexCount: u16 = 0; }; export fn init() void { sg.setup(.{ .logger = .{ .func = sokol.log.func }, .environment = sokol.glue.environment(), }); sokol.time.setup(); std.log.info("Vertex buffers len: {}", .{state.bind.vertex_buffers.len}); const vertexCount = 100; const radius: f32 = 0.7; const cX: f32 = 0; const cY: f32 = 0; const attributesCount = 7; var triangleVerts = std.mem.zeroes([vertexCount * attributesCount]f32); const angleDiff: f32 = 1 / @as(f32, @floatFromInt(vertexCount)); var pcg = std.Random.Pcg.init(123); const rand = pcg.random(); for (0..vertexCount) |i| { const pi: f32 = @floatCast(std.math.pi); const angle: f32 = @as(f32, @floatFromInt(i)) * angleDiff * pi * 2; const x = radius * @cos(angle) + cX; const y = radius * @sin(angle) + cY; const si = i * attributesCount; triangleVerts[si + 0] = x; triangleVerts[si + 1] = y; triangleVerts[si + 2] = 0.5; triangleVerts[si + 3] = rand.float(f32); triangleVerts[si + 4] = rand.float(f32); triangleVerts[si + 5] = rand.float(f32); triangleVerts[si + 6] = 1; } // var triangleVerts = [_]f32{ // // positions colors // 0.0, 0.5, 0.5, 1.0, 0.0, 0.0, 1.0, // 0.5, -0.5, 0.5, 0.0, 1.0, 0.0, 1.0, // -0.5, -0.5, 0.5, 0.0, 0.0, 1.0, 1.0, // 0.7, 0.5, 0.5, 0.0, 1.0, 0.0, 1.0, // }; state.bind.vertex_buffers[0] = sg.makeBuffer(.{ .data = sg.asRange(&triangleVerts), }); const trisCount = vertexCount - 2; var indexBuffer: [trisCount * 3]u16 = undefined; state.indexCount = indexBuffer.len; // const indexBuffer = [_]u16{ // 0, 1, 2, // 0, 2, 3, // }; for (0..trisCount) |tri| { const triu: u16 = @intCast(tri); indexBuffer[tri * 3 + 0] = 0; indexBuffer[tri * 3 + 1] = triu + 1; indexBuffer[tri * 3 + 2] = triu + 2; } state.bind.index_buffer = sg.makeBuffer(.{ .type = .INDEXBUFFER, .data = sg.asRange(&indexBuffer), }); var pip_desc: sg.PipelineDesc = .{ .index_type = .UINT16, .shader = sg.makeShader(shader.triangleShaderDesc(sg.queryBackend())), }; pip_desc.layout.attrs[0].format = .FLOAT3; pip_desc.layout.attrs[1].format = .FLOAT4; state.pip = sg.makePipeline(pip_desc); pass_action.colors[0] = .{ .load_action = .CLEAR, .clear_value = .{}, }; std.log.info("Backend: {}\n", .{sg.queryBackend()}); sokol.app.showMouse(false); } fn timef() f32 { return @floatCast(sokol.time.sec(sokol.time.now())); } var time: f32 = 0; export fn frame() void { const dt: f32 = @floatCast(sokol.app.frameDuration()); time += dt; const col = &pass_action.colors[0].clear_value; col.g = @abs(@sin(time)); col.r = @abs(@cos(time)); state.vsParams.aspectRatio = sokol.app.heightf() / sokol.app.widthf(); sg.beginPass(.{ .action = pass_action, .swapchain = sokol.glue.swapchain() }); sg.applyPipeline(state.pip); state.fsParams.offset[0] = col.r; sg.applyUniforms(.FS, shader.SLOT_fs_params, sg.asRange(&state.fsParams)); sg.applyUniforms(.VS, shader.SLOT_vs_params, sg.asRange(&state.vsParams)); sg.applyBindings(state.bind); sg.draw(0, state.indexCount, 1); sg.endPass(); sg.commit(); } export fn cleanup() void { std.log.info("Ended", .{}); } const Event = sokol.app.Event; export fn event(eptr: [*c]const Event) void { const e: *const Event = @ptrCast(eptr); const buttonPressed = e.type == .MOUSE_DOWN or e.type == .KEY_DOWN; const mouseMoved = e.type == .MOUSE_MOVE and (@abs(e.mouse_dx) > 2 or @abs(e.mouse_dy) > 2); if (buttonPressed or mouseMoved) { sokol.app.quit(); } } pub fn main() !void { sokol.app.run(.{ .init_cb = init, .frame_cb = frame, .cleanup_cb = cleanup, .event_cb = event, .width = 800, .height = 600, .fullscreen = true, .icon = .{ .sokol_default = true }, .window_title = "sokol hello", .logger = .{ .func = sokol.log.func }, }); }