From 6ba0a13a9bb362a87425d1b77b83a791e0d33bc0 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 5 Apr 2022 08:25:36 -0700 Subject: [PATCH] opengl: simplify vertex attribute setting --- src/TextRenderer.zig | 9 +++----- src/opengl/Buffer.zig | 51 +++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 52 insertions(+), 8 deletions(-) diff --git a/src/TextRenderer.zig b/src/TextRenderer.zig index 87e4d9979..35a8e7934 100644 --- a/src/TextRenderer.zig +++ b/src/TextRenderer.zig @@ -168,12 +168,9 @@ pub fn render( var binding = try vbo.bind(.ArrayBuffer); defer binding.unbind(); try binding.setData(vertices.items, .DynamicDraw); - try binding.enableVertexAttribArray(0); - try binding.vertexAttribPointer(0, 3, gl.c.GL_FLOAT, false, 9 * @sizeOf(f32), null); - try binding.enableVertexAttribArray(1); - try binding.vertexAttribPointer(1, 2, gl.c.GL_FLOAT, false, 9 * @sizeOf(f32), @intToPtr(*const anyopaque, 3 * @sizeOf(f32))); - try binding.enableVertexAttribArray(2); - try binding.vertexAttribPointer(2, 4, gl.c.GL_FLOAT, false, 9 * @sizeOf(f32), @intToPtr(*const anyopaque, 5 * @sizeOf(f32))); + try binding.attribute(0, 3, [9]f32, 0); + try binding.attribute(1, 2, [9]f32, 3); + try binding.attribute(2, 4, [9]f32, 5); try gl.drawArrays(gl.c.GL_TRIANGLES, 0, @intCast(c_int, vertices.items.len * 6)); try gl.VertexArray.unbind(); diff --git a/src/opengl/Buffer.zig b/src/opengl/Buffer.zig index 5f5afe070..0d514d5f2 100644 --- a/src/opengl/Buffer.zig +++ b/src/opengl/Buffer.zig @@ -101,11 +101,58 @@ pub const Binding = struct { }; } - pub inline fn enableVertexAttribArray(_: Binding, idx: c.GLuint) !void { + pub inline fn enableAttribArray(_: Binding, idx: c.GLuint) !void { c.glEnableVertexAttribArray(idx); } - pub inline fn vertexAttribPointer( + /// Shorthand for vertexAttribPointer that is specialized towards the + /// common use case of specifying an array of homogeneous types that + /// don't need normalization. This also enables the attribute at idx. + pub fn attribute( + b: Binding, + idx: c.GLuint, + size: c.GLint, + comptime T: type, + offset: usize, + ) !void { + const info: struct { + // Type of the each component in the array. + typ: c.GLenum, + + // The byte offset between each full set of attributes. + stride: c.GLsizei, + + // The size of each component used in calculating the offset. + offset: usize, + } = switch (@typeInfo(T)) { + .Array => |ary| .{ + .typ = switch (ary.child) { + f32 => c.GL_FLOAT, + else => @compileError("unsupported array child type"), + }, + .offset = @sizeOf(ary.child), + .stride = @sizeOf(T), + }, + else => @compileError("unsupported type"), + }; + + const offsetPtr = if (offset > 0) + @intToPtr(*const anyopaque, offset * info.offset) + else + null; + + try b.attributeAdvanced( + idx, + size, + info.typ, + false, + info.stride, + offsetPtr, + ); + try b.enableAttribArray(idx); + } + + pub inline fn attributeAdvanced( _: Binding, idx: c.GLuint, size: c.GLint,