Skip to content

Instantly share code, notes, and snippets.

Last active January 20, 2019 23:49
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
What would you like to do?

I just yanked out a few lines from my code and put it into a simplified context, but I hope it's still possible to understand. The code is working if I take out the @compileError and replace it with unreachable, but having a type-checked function for interfacing with shaders was one of my goals when I started this project.

const math = @import("math.zig");
const c = @import("c.zig");
const Uniforms = struct {
uProjection: math.Mat3,
uScale: math.Vec2
const Program = struct {
uniform_locations: [2]c.GLint,
pub fn setUniform(self: Self, name: []const u8, value: var) void {
const ValueT = @typeOf(value);
const fields = @typeInfo(Uniforms).Struct.fields;
inline for (fields) |field, i| {
const name_match = std.mem.eql(u8,, name);
const type_match = field.field_type == ValueT;
const location = self.uniform_locations[i];
if (name_match) {
if (!type_match) {
// This gets called on every iteration, not only when the names match.
@compileError("Types don't match");
switch (field.field_type) {
f32 => c.glUniform1f(location, value),
math.Mat3 => {
const matrix_ptr = @ptrCast([*]const math.float, @alignCast(4, &[0]));
c.glUniformMatrix3fv(location, 1, c.GL_FALSE, matrix_ptr);
math.Vec2 => c.glUniform2f(location, value.x, value.y),
else => unreachable
// This return is neccessary, because otherwise the compiler complains:
// `control flow attempts to use compile-time variable at runtime
pub fn main() void {
const p = Program {
.uniform_locations= []c.GLint {0, 1}
const mat = math.Mat3.projection(20, 20);
const scale = math.vec2(1, 1);
p.setUniform("uProjection", mat);
p.setUniform("uScale", scale);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment