aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authors-ol <s-ol@users.noreply.github.com>2020-01-26 19:49:25 +0000
committers-ol <s-ol@users.noreply.github.com>2020-01-26 19:49:25 +0000
commit885a8652cb8a433a18811d90048d11c1ec67b60e (patch)
tree52b845a825c91ec878983eb1078b4bd48f27ec73 /src
parentremove offset default uniform (diff)
downloadglsl-view-885a8652cb8a433a18811d90048d11c1ec67b60e.tar.gz
glsl-view-885a8652cb8a433a18811d90048d11c1ec67b60e.zip
break OSC in favor of uniform caching
Diffstat (limited to 'src')
-rw-r--r--src/config.zig4
-rw-r--r--src/control.zig61
-rw-r--r--src/debug_gl.zig22
-rw-r--r--src/gl.zig401
-rw-r--r--src/main.zig22
-rw-r--r--src/output.zig49
6 files changed, 472 insertions, 87 deletions
diff --git a/src/config.zig b/src/config.zig
index e2af1e9..ad4a181 100644
--- a/src/config.zig
+++ b/src/config.zig
@@ -28,7 +28,7 @@ pub const OSCConfig = union(enum) {
tcp,
unix,
};
-
+
Manual: struct {
protocol: Protocol = Protocol.udp,
port: u16 = 9000,
@@ -60,7 +60,7 @@ pub const Config = struct {
const file = try fs.cwd().openFile(filename, .{});
var buffer: [1024]u8 = undefined;
const len: usize = try file.read(buffer[0..]);
- c.yaml_parser_set_input_string(&parser, &buffer[0], len);
+ c.yaml_parser_set_input_string(&parser, buffer[0..].ptr, len);
var config: Config = .{
.width = 1920,
diff --git a/src/control.zig b/src/control.zig
index 3d36d8f..cec6f80 100644
--- a/src/control.zig
+++ b/src/control.zig
@@ -22,13 +22,13 @@ pub const ControlServer = struct {
.unix => c.LO_UNIX,
else => unreachable,
};
-
- std.debug.warn("listening for OSC messages on {} port {}\n", .{conf.protocol, conf.port});
- self.server = c.lo_server_new_with_proto(&port[0], proto, handle_error);
+
+ std.debug.warn("listening for OSC messages on {} port {}\n", .{ conf.protocol, conf.port });
+ self.server = c.lo_server_new_with_proto(port[0..].ptr, proto, handle_error);
},
.URL => |url| {
std.debug.warn("listening for OSC messages at {s}\n", .{url});
- self.server = c.lo_server_new_from_url(&url[0], handle_error);
+ self.server = c.lo_server_new_from_url(url[0..].ptr, handle_error);
},
else => unreachable,
}
@@ -58,32 +58,37 @@ pub const ControlServer = struct {
const path = _path[0..c.strlen(_path)];
const types = _types[0..@intCast(u32, argc)];
- if (std.mem.startsWith(u8, path, param_prefix)) {
- const param_name = path[param_prefix.len..];
-
- const uniform = self.shader.uniformLocation(@ptrCast([*]const u8, param_name.ptr)) catch {
- std.debug.warn("param {s} doesn't exist\n", .{param_name});
- return 0;
- };
-
- if (argc == 0) {
- std.debug.warn("param get: {s}\n", .{param_name});
- return 0;
+ if (std.mem.startsWith(u8, path, "/param/")) {
+ if (!std.mem.endsWith(u8, path, "/set")) {
+ std.debug.warn("unhandled OSC message {s} ({s})\n", .{ path, types });
+ return 1;
}
- if (std.mem.eql(u8, types, "f")) {
- self.shader.setUniform1f(uniform, argv[0].*.f);
- } else if (std.mem.eql(u8, types, "ff")) {
- self.shader.setUniform2f(uniform, argv[0].*.f, argv[1].*.f);
- } else if (std.mem.eql(u8, types, "fff")) {
- self.shader.setUniform3f(uniform, argv[0].*.f, argv[1].*.f, argv[2].*.f);
- } else if (std.mem.eql(u8, types, "ffff")) {
- self.shader.setUniform4f(uniform, argv[0].*.f, argv[1].*.f, argv[2].*.f, argv[3].*.f);
- } else if (std.mem.eql(u8, types, "i")) {
- self.shader.setUniform1i(uniform, argv[0].*.i);
- } else {
- std.debug.warn("unsupported types: {s}\n", .{types});
- }
+ const name_slice = path["/param/".len .. path.len - "/set".len];
+ // const uniform = self.shader.uniformLocation(name) catch {
+ // std.debug.warn("param {s} doesn't exist\n", .{uniform_name});
+ // return 0;
+ // };
+
+ // if (std.mem.eql(u8, types, "f")) {
+ // self.shader.setUniform1f(uniform, argv[0].*.f);
+ // } else if (std.mem.eql(u8, types, "ff")) {
+ // self.shader.setUniform2f(uniform, argv[0].*.f, argv[1].*.f);
+ // } else if (std.mem.eql(u8, types, "fff")) {
+ // self.shader.setUniform3f(uniform, argv[0].*.f, argv[1].*.f, argv[2].*.f);
+ // } else if (std.mem.eql(u8, types, "ffff")) {
+ // self.shader.setUniform4f(uniform, argv[0].*.f, argv[1].*.f, argv[2].*.f, argv[3].*.f);
+ // } else if (std.mem.eql(u8, types, "i")) {
+ // self.shader.setUniform1i(uniform, argv[0].*.i);
+ // } else if (std.mem.eql(u8, types, "ii")) {
+ // self.shader.setUniform2i(uniform, argv[0].*.i, argv[1].*.i);
+ // } else if (std.mem.eql(u8, types, "iii")) {
+ // self.shader.setUniform3i(uniform, argv[0].*.i, argv[1].*.i, argv[2].*.i);
+ // } else if (std.mem.eql(u8, types, "iiii")) {
+ // self.shader.setUniform4i(uniform, argv[0].*.i, argv[1].*.i, argv[2].*.i, argv[3].*.i);
+ // } else {
+ // std.debug.warn("unsupported types: {s}\n", .{types});
+ // }
return 0;
}
diff --git a/src/debug_gl.zig b/src/debug_gl.zig
index 2fdcda0..ebb552f 100644
--- a/src/debug_gl.zig
+++ b/src/debug_gl.zig
@@ -6,11 +6,27 @@ const builtin = @import("builtin");
pub const is_on = if (builtin.mode == builtin.Mode.ReleaseFast) c.GL_FALSE else c.GL_TRUE;
+fn glDebugMessage(source: c.GLenum, typ: c.GLenum, id: c.GLuint, severity: c.GLenum, length: c.GLsizei, _message: [*c]const u8, user: ?*const c_void) callconv(.C) void {
+ const message = _message[0..@intCast(usize, length)];
+ std.debug.warn("GL Callback [{}] {} / {}: {s}\n", .{ source, typ, severity, message });
+}
+
+pub fn init() void {
+ if (is_on == c.GL_TRUE) {
+ c.glEnable(c.GL_DEBUG_OUTPUT);
+ c.glDebugMessageCallback(glDebugMessage, null);
+ }
+}
+
pub fn assertNoError() void {
- if (builtin.mode != builtin.Mode.ReleaseFast) {
- const err = c.glGetError();
- if (err != c.GL_NO_ERROR) {
+ if (is_on == c.GL_TRUE) {
+ var err = c.glGetError();
+ while (err != c.GL_NO_ERROR) : (err = c.glGetError()) {
panic("GL error: {}\n", .{err});
+ } else {
+ return;
}
+
+ panic("GL Errors encountered.\n", .{err});
}
}
diff --git a/src/gl.zig b/src/gl.zig
index 659911e..474b87d 100644
--- a/src/gl.zig
+++ b/src/gl.zig
@@ -2,6 +2,292 @@ const std = @import("std");
const c_allocator = @import("std").heap.c_allocator;
const panic = @import("std").debug.panic;
const c = @import("c.zig");
+const cfg = @import("config.zig");
+
+const UniformType = enum(c.GLint) {
+ FLOAT = c.GL_FLOAT,
+ FLOAT_VEC2 = c.GL_FLOAT_VEC2,
+ FLOAT_VEC3 = c.GL_FLOAT_VEC3,
+ FLOAT_VEC4 = c.GL_FLOAT_VEC4,
+ DOUBLE = c.GL_DOUBLE,
+ DOUBLE_VEC2 = c.GL_DOUBLE_VEC2,
+ DOUBLE_VEC3 = c.GL_DOUBLE_VEC3,
+ DOUBLE_VEC4 = c.GL_DOUBLE_VEC4,
+ INT = c.GL_INT,
+ INT_VEC2 = c.GL_INT_VEC2,
+ INT_VEC3 = c.GL_INT_VEC3,
+ INT_VEC4 = c.GL_INT_VEC4,
+ UNSIGNED_INT = c.GL_UNSIGNED_INT,
+ UNSIGNED_INT_VEC2 = c.GL_UNSIGNED_INT_VEC2,
+ UNSIGNED_INT_VEC3 = c.GL_UNSIGNED_INT_VEC3,
+ UNSIGNED_INT_VEC4 = c.GL_UNSIGNED_INT_VEC4,
+ BOOL = c.GL_BOOL,
+ BOOL_VEC2 = c.GL_BOOL_VEC2,
+ BOOL_VEC3 = c.GL_BOOL_VEC3,
+ BOOL_VEC4 = c.GL_BOOL_VEC4,
+ FLOAT_MAT2 = c.GL_FLOAT_MAT2,
+ FLOAT_MAT3 = c.GL_FLOAT_MAT3,
+ FLOAT_MAT4 = c.GL_FLOAT_MAT4,
+ FLOAT_MAT2x3 = c.GL_FLOAT_MAT2x3,
+ FLOAT_MAT2x4 = c.GL_FLOAT_MAT2x4,
+ FLOAT_MAT3x2 = c.GL_FLOAT_MAT3x2,
+ FLOAT_MAT3x4 = c.GL_FLOAT_MAT3x4,
+ FLOAT_MAT4x2 = c.GL_FLOAT_MAT4x2,
+ FLOAT_MAT4x3 = c.GL_FLOAT_MAT4x3,
+ DOUBLE_MAT2 = c.GL_DOUBLE_MAT2,
+ DOUBLE_MAT3 = c.GL_DOUBLE_MAT3,
+ DOUBLE_MAT4 = c.GL_DOUBLE_MAT4,
+ DOUBLE_MAT2x3 = c.GL_DOUBLE_MAT2x3,
+ DOUBLE_MAT2x4 = c.GL_DOUBLE_MAT2x4,
+ DOUBLE_MAT3x2 = c.GL_DOUBLE_MAT3x2,
+ DOUBLE_MAT3x4 = c.GL_DOUBLE_MAT3x4,
+ DOUBLE_MAT4x2 = c.GL_DOUBLE_MAT4x2,
+ DOUBLE_MAT4x3 = c.GL_DOUBLE_MAT4x3,
+ SAMPLER_1D = c.GL_SAMPLER_1D,
+ SAMPLER_2D = c.GL_SAMPLER_2D,
+ SAMPLER_3D = c.GL_SAMPLER_3D,
+ SAMPLER_CUBE = c.GL_SAMPLER_CUBE,
+ SAMPLER_1D_SHADOW = c.GL_SAMPLER_1D_SHADOW,
+ SAMPLER_2D_SHADOW = c.GL_SAMPLER_2D_SHADOW,
+ SAMPLER_1D_ARRAY = c.GL_SAMPLER_1D_ARRAY,
+ SAMPLER_2D_ARRAY = c.GL_SAMPLER_2D_ARRAY,
+ SAMPLER_1D_ARRAY_SHADOW = c.GL_SAMPLER_1D_ARRAY_SHADOW,
+ SAMPLER_2D_ARRAY_SHADOW = c.GL_SAMPLER_2D_ARRAY_SHADOW,
+ SAMPLER_2D_MULTISAMPLE = c.GL_SAMPLER_2D_MULTISAMPLE,
+ SAMPLER_2D_MULTISAMPLE_ARRAY = c.GL_SAMPLER_2D_MULTISAMPLE_ARRAY,
+ SAMPLER_CUBE_SHADOW = c.GL_SAMPLER_CUBE_SHADOW,
+ SAMPLER_BUFFER = c.GL_SAMPLER_BUFFER,
+ SAMPLER_2D_RECT = c.GL_SAMPLER_2D_RECT,
+ SAMPLER_2D_RECT_SHADOW = c.GL_SAMPLER_2D_RECT_SHADOW,
+ INT_SAMPLER_1D = c.GL_INT_SAMPLER_1D,
+ INT_SAMPLER_2D = c.GL_INT_SAMPLER_2D,
+ INT_SAMPLER_3D = c.GL_INT_SAMPLER_3D,
+ INT_SAMPLER_CUBE = c.GL_INT_SAMPLER_CUBE,
+ INT_SAMPLER_1D_ARRAY = c.GL_INT_SAMPLER_1D_ARRAY,
+ INT_SAMPLER_2D_ARRAY = c.GL_INT_SAMPLER_2D_ARRAY,
+ INT_SAMPLER_2D_MULTISAMPLE = c.GL_INT_SAMPLER_2D_MULTISAMPLE,
+ INT_SAMPLER_2D_MULTISAMPLE_ARRAY = c.GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY,
+ INT_SAMPLER_BUFFER = c.GL_INT_SAMPLER_BUFFER,
+ INT_SAMPLER_2D_RECT = c.GL_INT_SAMPLER_2D_RECT,
+ UNSIGNED_INT_SAMPLER_1D = c.GL_UNSIGNED_INT_SAMPLER_1D,
+ UNSIGNED_INT_SAMPLER_2D = c.GL_UNSIGNED_INT_SAMPLER_2D,
+ UNSIGNED_INT_SAMPLER_3D = c.GL_UNSIGNED_INT_SAMPLER_3D,
+ UNSIGNED_INT_SAMPLER_CUBE = c.GL_UNSIGNED_INT_SAMPLER_CUBE,
+ UNSIGNED_INT_SAMPLER_1D_ARRAY = c.GL_UNSIGNED_INT_SAMPLER_1D_ARRAY,
+ UNSIGNED_INT_SAMPLER_2D_ARRAY = c.GL_UNSIGNED_INT_SAMPLER_2D_ARRAY,
+ UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE = c.GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE,
+ UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY = c.GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY,
+ UNSIGNED_INT_SAMPLER_BUFFER = c.GL_UNSIGNED_INT_SAMPLER_BUFFER,
+ UNSIGNED_INT_SAMPLER_2D_RECT = c.GL_UNSIGNED_INT_SAMPLER_2D_RECT,
+};
+
+const UniformValue = union(UniformType) {
+ FLOAT: f32,
+ FLOAT_VEC2: [2]f32,
+ FLOAT_VEC3: [3]f32,
+ FLOAT_VEC4: [4]f32,
+ DOUBLE: f64,
+ DOUBLE_VEC2: [2]f64,
+ DOUBLE_VEC3: [3]f64,
+ DOUBLE_VEC4: [4]f64,
+ INT: c_int, // i32 but bug
+ INT_VEC2: [2]c_int,
+ INT_VEC3: [3]c_int,
+ INT_VEC4: [4]c_int,
+ UNSIGNED_INT: c_uint,
+ UNSIGNED_INT_VEC2: [2]c_uint,
+ UNSIGNED_INT_VEC3: [3]c_uint,
+ UNSIGNED_INT_VEC4: [4]c_uint,
+ BOOL: c_uint,
+ BOOL_VEC2: [2]c_uint,
+ BOOL_VEC3: [3]c_uint,
+ BOOL_VEC4: [4]c_uint,
+ FLOAT_MAT2: [2 * 2]f32,
+ FLOAT_MAT3: [3 * 3]f32,
+ FLOAT_MAT4: [4 * 4]f32,
+ FLOAT_MAT2x3: [2 * 3]f32,
+ FLOAT_MAT2x4: [2 * 4]f32,
+ FLOAT_MAT3x2: [3 * 2]f32,
+ FLOAT_MAT3x4: [3 * 4]f32,
+ FLOAT_MAT4x2: [4 * 2]f32,
+ FLOAT_MAT4x3: [4 * 3]f32,
+ DOUBLE_MAT2: [2 * 2]f64,
+ DOUBLE_MAT3: [3 * 3]f64,
+ DOUBLE_MAT4: [4 * 4]f64,
+ DOUBLE_MAT2x3: [2 * 3]f64,
+ DOUBLE_MAT2x4: [2 * 4]f64,
+ DOUBLE_MAT3x2: [3 * 2]f64,
+ DOUBLE_MAT3x4: [3 * 4]f64,
+ DOUBLE_MAT4x2: [4 * 2]f64,
+ DOUBLE_MAT4x3: [4 * 3]f64,
+ SAMPLER_1D: c_int,
+ SAMPLER_2D: c_int,
+ SAMPLER_3D: c_int,
+ SAMPLER_CUBE: c_int,
+ SAMPLER_1D_SHADOW: c_int,
+ SAMPLER_2D_SHADOW: c_int,
+ SAMPLER_1D_ARRAY: c_int,
+ SAMPLER_2D_ARRAY: c_int,
+ SAMPLER_1D_ARRAY_SHADOW: c_int,
+ SAMPLER_2D_ARRAY_SHADOW: c_int,
+ SAMPLER_2D_MULTISAMPLE: c_int,
+ SAMPLER_2D_MULTISAMPLE_ARRAY: c_int,
+ SAMPLER_CUBE_SHADOW: c_int,
+ SAMPLER_BUFFER: c_int,
+ SAMPLER_2D_RECT: c_int,
+ SAMPLER_2D_RECT_SHADOW: c_int,
+ INT_SAMPLER_1D: c_int,
+ INT_SAMPLER_2D: c_int,
+ INT_SAMPLER_3D: c_int,
+ INT_SAMPLER_CUBE: c_int,
+ INT_SAMPLER_1D_ARRAY: c_int,
+ INT_SAMPLER_2D_ARRAY: c_int,
+ INT_SAMPLER_2D_MULTISAMPLE: c_int,
+ INT_SAMPLER_2D_MULTISAMPLE_ARRAY: c_int,
+ INT_SAMPLER_BUFFER: c_int,
+ INT_SAMPLER_2D_RECT: c_int,
+ UNSIGNED_INT_SAMPLER_1D: c_int,
+ UNSIGNED_INT_SAMPLER_2D: c_int,
+ UNSIGNED_INT_SAMPLER_3D: c_int,
+ UNSIGNED_INT_SAMPLER_CUBE: c_int,
+ UNSIGNED_INT_SAMPLER_1D_ARRAY: c_int,
+ UNSIGNED_INT_SAMPLER_2D_ARRAY: c_int,
+ UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE: c_int,
+ UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: c_int,
+ UNSIGNED_INT_SAMPLER_BUFFER: c_int,
+ UNSIGNED_INT_SAMPLER_2D_RECT: c_int,
+
+ pub fn init(utype: UniformType) UniformValue {
+ inline for (@typeInfo(UniformType).Enum.fields) |field| {
+ if (@intToEnum(UniformType, field.value) == utype)
+ return @unionInit(UniformValue, field.name, undefined);
+ }
+
+ unreachable;
+ }
+};
+
+const CachedUniform = struct {
+ value: UniformValue,
+ location: c.GLint,
+
+ pub fn init(shader: ShaderProgram, name: [*]const u8) !CachedUniform {
+ var index: c.GLuint = undefined;
+
+ c.glGetUniformIndices(shader.program_id, 1, &name, &index);
+ if (index == c.GL_INVALID_INDEX)
+ return error.invalidUniform;
+
+ var utype: c.GLint = undefined;
+ c.glGetActiveUniformsiv(shader.program_id, 1, &index, c.GL_UNIFORM_TYPE, &utype);
+
+ var self = CachedUniform{
+ .value = UniformValue.init(@intToEnum(UniformType, utype)),
+ .location = try shader.uniformLocation(name),
+ };
+
+ self.getShaderValue(shader);
+ return self;
+ }
+
+ // zig fmt: off
+ pub fn setShaderValue(self: *const CachedUniform, shader: ShaderProgram) void {
+ const program = shader.program_id;
+ const location = self.location;
+
+ switch (self.value) {
+ .FLOAT => |*value| c.glProgramUniform1fv(program, location, 1, value),
+ .FLOAT_VEC2 => |*value| c.glProgramUniform2fv(program, location, 1, value),
+ .FLOAT_VEC3 => |*value| c.glProgramUniform3fv(program, location, 1, value),
+ .FLOAT_VEC4 => |*value| c.glProgramUniform4fv(program, location, 1, value),
+ .DOUBLE => |*value| c.glProgramUniform1dv(program, location, 1, value),
+ .DOUBLE_VEC2 => |*value| c.glProgramUniform1dv(program, location, 1, value),
+ .DOUBLE_VEC3 => |*value| c.glProgramUniform2dv(program, location, 1, value),
+ .DOUBLE_VEC4 => |*value| c.glProgramUniform3dv(program, location, 1, value),
+ .INT => |*value| c.glProgramUniform1iv(program, location, 1, value),
+ .INT_VEC2 => |*value| c.glProgramUniform2iv(program, location, 1, value),
+ .INT_VEC3 => |*value| c.glProgramUniform3iv(program, location, 1, value),
+ .INT_VEC4 => |*value| c.glProgramUniform4iv(program, location, 1, value),
+ .UNSIGNED_INT => |*value| c.glProgramUniform1uiv(program, location, 1, value),
+ .UNSIGNED_INT_VEC2 => |*value| c.glProgramUniform2uiv(program, location, 1, value),
+ .UNSIGNED_INT_VEC3 => |*value| c.glProgramUniform3uiv(program, location, 1, value),
+ .UNSIGNED_INT_VEC4 => |*value| c.glProgramUniform4uiv(program, location, 1, value),
+ .BOOL => |*value| c.glProgramUniform1uiv(program, location, 1, value),
+ .BOOL_VEC2 => |*value| c.glProgramUniform2uiv(program, location, 1, value),
+ .BOOL_VEC3 => |*value| c.glProgramUniform3uiv(program, location, 1, value),
+ .BOOL_VEC4 => |*value| c.glProgramUniform4uiv(program, location, 1, value),
+ .FLOAT_MAT2 => |*value| c.glProgramUniformMatrix2fv(program, location, 1, c.GL_FALSE, value),
+ .FLOAT_MAT3 => |*value| c.glProgramUniformMatrix3fv(program, location, 1, c.GL_FALSE, value),
+ .FLOAT_MAT4 => |*value| c.glProgramUniformMatrix4fv(program, location, 1, c.GL_FALSE, value),
+ .FLOAT_MAT2x3 => |*value| c.glProgramUniformMatrix2x3fv(program, location, 1, c.GL_FALSE, value),
+ .FLOAT_MAT2x4 => |*value| c.glProgramUniformMatrix2x4fv(program, location, 1, c.GL_FALSE, value),
+ .FLOAT_MAT3x2 => |*value| c.glProgramUniformMatrix3x2fv(program, location, 1, c.GL_FALSE, value),
+ .FLOAT_MAT3x4 => |*value| c.glProgramUniformMatrix3x4fv(program, location, 1, c.GL_FALSE, value),
+ .FLOAT_MAT4x2 => |*value| c.glProgramUniformMatrix4x2fv(program, location, 1, c.GL_FALSE, value),
+ .FLOAT_MAT4x3 => |*value| c.glProgramUniformMatrix4x3fv(program, location, 1, c.GL_FALSE, value),
+ .DOUBLE_MAT2 => |*value| c.glProgramUniformMatrix2dv(program, location, 1, c.GL_FALSE, value),
+ .DOUBLE_MAT3 => |*value| c.glProgramUniformMatrix3dv(program, location, 1, c.GL_FALSE, value),
+ .DOUBLE_MAT4 => |*value| c.glProgramUniformMatrix4dv(program, location, 1, c.GL_FALSE, value),
+ .DOUBLE_MAT2x3 => |*value| c.glProgramUniformMatrix2x3dv(program, location, 1, c.GL_FALSE, value),
+ .DOUBLE_MAT2x4 => |*value| c.glProgramUniformMatrix2x4dv(program, location, 1, c.GL_FALSE, value),
+ .DOUBLE_MAT3x2 => |*value| c.glProgramUniformMatrix3x2dv(program, location, 1, c.GL_FALSE, value),
+ .DOUBLE_MAT3x4 => |*value| c.glProgramUniformMatrix3x4dv(program, location, 1, c.GL_FALSE, value),
+ .DOUBLE_MAT4x2 => |*value| c.glProgramUniformMatrix4x2dv(program, location, 1, c.GL_FALSE, value),
+ .DOUBLE_MAT4x3 => |*value| c.glProgramUniformMatrix4x3dv(program, location, 1, c.GL_FALSE, value),
+ .SAMPLER_1D, .SAMPLER_2D, .SAMPLER_3D, .SAMPLER_CUBE, .SAMPLER_1D_SHADOW, .SAMPLER_2D_SHADOW, .SAMPLER_1D_ARRAY, .SAMPLER_2D_ARRAY, .SAMPLER_1D_ARRAY_SHADOW, .SAMPLER_2D_ARRAY_SHADOW, .SAMPLER_2D_MULTISAMPLE, .SAMPLER_2D_MULTISAMPLE_ARRAY, .SAMPLER_CUBE_SHADOW, .SAMPLER_BUFFER, .SAMPLER_2D_RECT, .SAMPLER_2D_RECT_SHADOW, .INT_SAMPLER_1D, .INT_SAMPLER_2D, .INT_SAMPLER_3D, .INT_SAMPLER_CUBE, .INT_SAMPLER_1D_ARRAY, .INT_SAMPLER_2D_ARRAY, .INT_SAMPLER_2D_MULTISAMPLE, .INT_SAMPLER_2D_MULTISAMPLE_ARRAY, .INT_SAMPLER_BUFFER, .INT_SAMPLER_2D_RECT, .UNSIGNED_INT_SAMPLER_1D, .UNSIGNED_INT_SAMPLER_2D, .UNSIGNED_INT_SAMPLER_3D, .UNSIGNED_INT_SAMPLER_CUBE, .UNSIGNED_INT_SAMPLER_1D_ARRAY, .UNSIGNED_INT_SAMPLER_2D_ARRAY, .UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE, .UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, .UNSIGNED_INT_SAMPLER_BUFFER, .UNSIGNED_INT_SAMPLER_2D_RECT => |value| c.glProgramUniform1i(program, location, value),
+ else => unreachable,
+ }
+ }
+
+ pub fn getShaderValue(self: *CachedUniform, shader: ShaderProgram) void {
+ const program = shader.program_id;
+ const location = self.location;
+
+ switch (self.value) {
+ .FLOAT => |*value| c.glGetnUniformfv(program, location, @sizeOf(@TypeOf(value.*)), value),
+ .FLOAT_VEC2 => |*value| c.glGetnUniformfv(program, location, @sizeOf(@TypeOf(value.*)), value),
+ .FLOAT_VEC3 => |*value| c.glGetnUniformfv(program, location, @sizeOf(@TypeOf(value.*)), value),
+ .FLOAT_VEC4 => |*value| c.glGetnUniformfv(program, location, @sizeOf(@TypeOf(value.*)), value),
+ .DOUBLE => |*value| c.glGetnUniformdv(program, location, @sizeOf(@TypeOf(value.*)), value),
+ .DOUBLE_VEC2 => |*value| c.glGetnUniformdv(program, location, @sizeOf(@TypeOf(value.*)), value),
+ .DOUBLE_VEC3 => |*value| c.glGetnUniformdv(program, location, @sizeOf(@TypeOf(value.*)), value),
+ .DOUBLE_VEC4 => |*value| c.glGetnUniformdv(program, location, @sizeOf(@TypeOf(value.*)), value),
+ .INT => |*value| c.glGetnUniformiv(program, location, @sizeOf(@TypeOf(value.*)), value),
+ .INT_VEC2 => |*value| c.glGetnUniformiv(program, location, @sizeOf(@TypeOf(value.*)), value),
+ .INT_VEC3 => |*value| c.glGetnUniformiv(program, location, @sizeOf(@TypeOf(value.*)), value),
+ .INT_VEC4 => |*value| c.glGetnUniformiv(program, location, @sizeOf(@TypeOf(value.*)), value),
+ .UNSIGNED_INT => |*value| c.glGetnUniformuiv(program, location, @sizeOf(@TypeOf(value.*)), value),
+ .UNSIGNED_INT_VEC2 => |*value| c.glGetnUniformuiv(program, location, @sizeOf(@TypeOf(value.*)), value),
+ .UNSIGNED_INT_VEC3 => |*value| c.glGetnUniformuiv(program, location, @sizeOf(@TypeOf(value.*)), value),
+ .UNSIGNED_INT_VEC4 => |*value| c.glGetnUniformuiv(program, location, @sizeOf(@TypeOf(value.*)), value),
+ .BOOL => |*value| c.glGetnUniformuiv(program, location, @sizeOf(@TypeOf(value.*)), value),
+ .BOOL_VEC2 => |*value| c.glGetnUniformuiv(program, location, @sizeOf(@TypeOf(value.*)), value),
+ .BOOL_VEC3 => |*value| c.glGetnUniformuiv(program, location, @sizeOf(@TypeOf(value.*)), value),
+ .BOOL_VEC4 => |*value| c.glGetnUniformuiv(program, location, @sizeOf(@TypeOf(value.*)), value),
+ .FLOAT_MAT2 => |*value| c.glGetUniformfv(program, location, value),
+ .FLOAT_MAT3 => |*value| c.glGetUniformfv(program, location, value),
+ .FLOAT_MAT4 => |*value| c.glGetUniformfv(program, location, value),
+ .FLOAT_MAT2x3 => |*value| c.glGetUniformfv(program, location, value),
+ .FLOAT_MAT2x4 => |*value| c.glGetUniformfv(program, location, value),
+ .FLOAT_MAT3x2 => |*value| c.glGetUniformfv(program, location, value),
+ .FLOAT_MAT3x4 => |*value| c.glGetUniformfv(program, location, value),
+ .FLOAT_MAT4x2 => |*value| c.glGetUniformfv(program, location, value),
+ .FLOAT_MAT4x3 => |*value| c.glGetUniformfv(program, location, value),
+ .DOUBLE_MAT2 => |*value| c.glGetUniformdv(program, location, value),
+ .DOUBLE_MAT3 => |*value| c.glGetUniformdv(program, location, value),
+ .DOUBLE_MAT4 => |*value| c.glGetUniformdv(program, location, value),
+ .DOUBLE_MAT2x3 => |*value| c.glGetUniformdv(program, location, value),
+ .DOUBLE_MAT2x4 => |*value| c.glGetUniformdv(program, location, value),
+ .DOUBLE_MAT3x2 => |*value| c.glGetUniformdv(program, location, value),
+ .DOUBLE_MAT3x4 => |*value| c.glGetUniformdv(program, location, value),
+ .DOUBLE_MAT4x2 => |*value| c.glGetUniformdv(program, location, value),
+ .DOUBLE_MAT4x3 => |*value| c.glGetUniformdv(program, location, value),
+ .SAMPLER_1D, .SAMPLER_2D, .SAMPLER_3D, .SAMPLER_CUBE, .SAMPLER_1D_SHADOW, .SAMPLER_2D_SHADOW, .SAMPLER_1D_ARRAY, .SAMPLER_2D_ARRAY, .SAMPLER_1D_ARRAY_SHADOW, .SAMPLER_2D_ARRAY_SHADOW, .SAMPLER_2D_MULTISAMPLE, .SAMPLER_2D_MULTISAMPLE_ARRAY, .SAMPLER_CUBE_SHADOW, .SAMPLER_BUFFER, .SAMPLER_2D_RECT, .SAMPLER_2D_RECT_SHADOW, .INT_SAMPLER_1D, .INT_SAMPLER_2D, .INT_SAMPLER_3D, .INT_SAMPLER_CUBE, .INT_SAMPLER_1D_ARRAY, .INT_SAMPLER_2D_ARRAY, .INT_SAMPLER_2D_MULTISAMPLE, .INT_SAMPLER_2D_MULTISAMPLE_ARRAY, .INT_SAMPLER_BUFFER, .INT_SAMPLER_2D_RECT, .UNSIGNED_INT_SAMPLER_1D, .UNSIGNED_INT_SAMPLER_2D, .UNSIGNED_INT_SAMPLER_3D, .UNSIGNED_INT_SAMPLER_CUBE, .UNSIGNED_INT_SAMPLER_1D_ARRAY, .UNSIGNED_INT_SAMPLER_2D_ARRAY, .UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE, .UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, .UNSIGNED_INT_SAMPLER_BUFFER, .UNSIGNED_INT_SAMPLER_2D_RECT => |*value| c.glGetnUniformiv(program, location, @sizeOf(@TypeOf(value.*)), value),
+ else => unreachable,
+ }
+ }
+ // zig fmt: on
+};
pub const ShaderProgram = struct {
program_id: c.GLuint,
@@ -27,30 +313,6 @@ pub const ShaderProgram = struct {
return id;
}
- pub fn setUniform1i(self: ShaderProgram, uniform_id: c.GLint, value: c_int) void {
- c.glUniform1i(uniform_id, value);
- }
-
- pub fn setUniform1f(self: ShaderProgram, uniform_id: c.GLint, value: f32) void {
- c.glUniform1f(uniform_id, value);
- }
-
- pub fn setUniform2f(self: ShaderProgram, uniform_id: c.GLint, x: f32, y: f32) void {
- c.glUniform2f(uniform_id, x, y);
- }
-
- pub fn setUniform3f(self: ShaderProgram, uniform_id: c.GLint, x: f32, y: f32, z: f32) void {
- c.glUniform3f(uniform_id, x, y, z);
- }
-
- pub fn setUniform4f(self: ShaderProgram, uniform_id: c.GLint, x: f32, y: f32, z: f32, w: f32) void {
- c.glUniform4f(uniform_id, x, y, z, w);
- }
-
- pub fn setUniformMat4x4(self: ShaderProgram, uniform_id: c.GLint, value: [4][4]f32) void {
- c.glUniformMatrix4fv(uniform_id, 1, c.GL_FALSE, &value[0][0]);
- }
-
pub fn create(vert_source: []const u8, frag_source: []const u8) !ShaderProgram {
var self: ShaderProgram = undefined;
@@ -92,6 +354,69 @@ pub const ShaderProgram = struct {
}
};
+pub const UniformCache = struct {
+ uniforms: std.AutoHashMap([*]const u8, CachedUniform),
+ shader: *ShaderProgram,
+
+ pub fn init(allocator: *std.mem.Allocator, shader: *ShaderProgram) UniformCache {
+ return UniformCache{
+ .uniforms = std.AutoHashMap([*]const u8, CachedUniform).init(allocator),
+ .shader = shader,
+ };
+ }
+
+ pub fn deinit(self: *UniformCache) void {
+ self.uniforms.deinit();
+ }
+
+ pub fn refresh(self: *UniformCache) !void {
+ var uniform_count: c.GLint = undefined;
+ c.glGetProgramiv(self.shader.program_id, c.GL_ACTIVE_UNIFORMS, &uniform_count);
+
+ const count = self.uniforms.count();
+ var existing_names = try c_allocator.alloc([*]const u8, count);
+ defer c_allocator.free(existing_names);
+ var existing_indices = try c_allocator.alloc(c.GLuint, count);
+ defer c_allocator.free(existing_indices);
+
+ {
+ var it = self.uniforms.iterator();
+ var i: usize = 0;
+ while (it.next()) |entry| {
+ existing_names[i] = entry.key;
+ i += 1;
+ }
+ }
+
+ c.glGetUniformIndices(self.shader.program_id, @intCast(c.GLsizei, count), existing_names.ptr, existing_indices.ptr);
+
+ for (existing_indices) |index, i| {
+ const name = existing_names[i];
+ if (index == c.GL_INVALID_INDEX) {
+ _ = self.uniforms.remove(name);
+ // @TODO: remove OSC link
+ } else {
+ var uniform = self.uniforms.get(name).?.value;
+ uniform.location = self.shader.uniformLocation(name) catch unreachable;
+ uniform.setShaderValue(self.shader.*);
+ }
+ }
+ }
+
+ pub fn get(self: *UniformCache, name: [*]const u8) !?*CachedUniform {
+ var result = try self.uniforms.getOrPut(name);
+ if (!result.found_existing) {
+ result.kv.value = CachedUniform.init(self.shader.*, name) catch {
+ _ = self.uniforms.remove(name);
+ return null;
+ };
+ // @TODO: add OSC link
+ }
+
+ return &result.kv.value;
+ }
+};
+
fn initGlShader(source: []const u8, name: []const u8, kind: c.GLenum) !c.GLuint {
const shader_id = c.glCreateShader(kind);
errdefer c.glDeleteShader(shader_id);
@@ -179,7 +504,7 @@ pub const VertexObject = struct {
c.glGenBuffers(1, &self.buffer_id);
c.glBindBuffer(c.GL_ARRAY_BUFFER, self.buffer_id);
- c.glBufferData(c.GL_ARRAY_BUFFER, @intCast(c_long, @sizeOf(T) * vertices.len), @ptrCast(*const c_void, &vertices[0]), c.GL_STATIC_DRAW);
+ c.glBufferData(c.GL_ARRAY_BUFFER, @intCast(c_long, @sizeOf(T) * vertices.len), @ptrCast(*const c_void, vertices.ptr), c.GL_STATIC_DRAW);
return self;
}
@@ -191,17 +516,16 @@ pub const VertexObject = struct {
};
pub const Constants = struct {
- textureShader: ShaderProgram,
- normalizedQuad: VertexObject,
+ texture_shader: ShaderProgram,
+ normalized_quad: VertexObject,
main_window: *c.GLFWwindow,
+ aspect: f32,
+ config: *cfg.Config,
- pub fn create(main_window: *c.GLFWwindow) !Constants {
- var self: Constants = undefined;
-
+ pub fn create(main_window: *c.GLFWwindow, config: *cfg.Config) !Constants {
c.glfwMakeContextCurrent(main_window);
- self.main_window = main_window;
- self.textureShader = try ShaderProgram.create(
+ const shader = try ShaderProgram.create(
\\#version 330 core
\\
\\layout(location = 0) in vec2 position;
@@ -230,13 +554,18 @@ pub const Constants = struct {
1.0, -1.0,
1.0, 1.0,
};
- self.normalizedQuad = VertexObject.create(f32, vertices[0..], 2);
- return self;
+ return Constants{
+ .main_window = main_window,
+ .texture_shader = shader,
+ .normalized_quad = VertexObject.create(f32, vertices[0..], 2),
+ .config = config,
+ .aspect = @intToFloat(f32, config.width) / @intToFloat(f32, config.height),
+ };
}
pub fn destroy(self: *Constants) void {
- self.normalizedQuad.destroy();
- self.textureShader.destroy();
+ self.normalized_quad.destroy();
+ self.texture_shader.destroy();
}
};
diff --git a/src/main.zig b/src/main.zig
index 0530024..37104da 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -51,7 +51,7 @@ pub fn main() !void {
c.glfwMakeContextCurrent(window);
c.glfwSwapInterval(1);
- var constants = try gl.Constants.create(window);
+ var constants = try gl.Constants.create(window, &config);
defer constants.destroy();
var outputs = try std.ArrayList(*out.Output).initCapacity(&arena.allocator, config.outputs.len);
@@ -67,13 +67,12 @@ pub fn main() !void {
c.glClearColor(0.0, 0.0, 0.0, 1.0);
debug_gl.assertNoError();
+ debug_gl.init();
const start_time = c.glfwGetTime();
var prev_time = start_time;
- constants.normalizedQuad.bind(0);
-
- debug_gl.assertNoError();
+ constants.normalized_quad.bind(0);
var main_program = try gl.ShaderProgram.create(
\\#version 330 core
@@ -101,12 +100,17 @@ pub fn main() !void {
var last_stat = try shader_file.stat();
try reloadShader(&main_program, shader_file, last_stat.size);
+ var cache = gl.UniformCache.init(std.heap.c_allocator, &main_program);
+ defer cache.deinit();
+
var fbo = try gl.FramebufferObject.create(config.width, config.height);
defer fbo.destroy();
const control = try ctrl.ControlServer.init(&arena.allocator, config.osc);
defer control.destroy();
+ _ = try cache.get("radius\x00");
+
while (c.glfwWindowShouldClose(window) == c.GL_FALSE) {
c.glfwMakeContextCurrent(window);
c.glClear(c.GL_COLOR_BUFFER_BIT);
@@ -118,16 +122,22 @@ pub fn main() !void {
const stat = try shader_file.stat();
if (stat.mtime > last_stat.mtime) {
try reloadShader(&main_program, shader_file, stat.size);
+ try cache.refresh();
last_stat = stat;
}
+ if (try cache.get("offset\x00")) |offset| {
+ offset.value.FLOAT += 0.01;
+ offset.setShaderValue(main_program);
+ }
+
control.update(main_program);
fbo.bind();
c.glClear(c.GL_COLOR_BUFFER_BIT);
main_program.bind();
- constants.normalizedQuad.draw();
+ constants.normalized_quad.draw();
fbo.unbind();
for (outputs.toSlice()) |output, i| {
@@ -144,8 +154,6 @@ pub fn main() !void {
c.glfwPollEvents();
}
-
- debug_gl.assertNoError();
}
fn reloadShader(current: *gl.ShaderProgram, frag_file: fs.File, size: u64) !void {
diff --git a/src/output.zig b/src/output.zig
index c31c191..770c0ba 100644
--- a/src/output.zig
+++ b/src/output.zig
@@ -27,6 +27,8 @@ pub const WindowOutput = struct {
window: *c.GLFWwindow,
constants: *gl.Constants,
+ resized: bool = false,
+
pub fn create(allocator: *std.mem.Allocator, config: cfg.OutputConfig, constants: *gl.Constants) *Output {
const self = allocator.create(WindowOutput) catch unreachable;
@@ -40,38 +42,58 @@ pub const WindowOutput = struct {
},
};
- c.glfwSetWindowUserPointer(self.*.window, @ptrCast(*c_void, self));
- _ = c.glfwSetKeyCallback(self.*.window, keyCallback);
+ c.glfwSetWindowUserPointer(self.window, @ptrCast(*c_void, self));
+ _ = c.glfwSetKeyCallback(self.window, keyCallback);
+ _ = c.glfwSetFramebufferSizeCallback(self.window, sizeCallback);
- c.glfwMakeContextCurrent(self.*.window);
- constants.normalizedQuad.bind(0);
+ c.glfwMakeContextCurrent(self.window);
+ constants.normalized_quad.bind(0);
- return &self.*.output;
+ return &self.output;
}
fn update(output: *Output, texture_id: c.GLuint) bool {
const self = @fieldParentPtr(WindowOutput, "output", output);
- if (c.glfwWindowShouldClose(self.*.window) == c.GL_TRUE)
+ if (c.glfwWindowShouldClose(self.window) == c.GL_TRUE)
return true;
- c.glfwMakeContextCurrent(self.*.window);
+ c.glfwMakeContextCurrent(self.window);
c.glClear(c.GL_COLOR_BUFFER_BIT);
+ if (self.resized) {
+ var width: c_int = undefined;
+ var height: c_int = undefined;
+ var scaled_width: c_int = undefined;
+ var scaled_height: c_int = undefined;
+
+ c.glfwGetFramebufferSize(self.window, &width, &height);
+ const window_aspect = @intToFloat(f32, width) / @intToFloat(f32, height);
+ if (window_aspect >= self.constants.aspect) {
+ scaled_height = height;
+ scaled_width = @floatToInt(c_int, @intToFloat(f32, height) * self.constants.aspect);
+ } else {
+ scaled_width = width;
+ scaled_height = @floatToInt(c_int, @intToFloat(f32, width) / self.constants.aspect);
+ }
+
+ c.glViewport(@divFloor(width - scaled_width, 2), @divFloor(height - scaled_height, 2), scaled_width, scaled_height);
+ }
+
c.glBindTexture(c.GL_TEXTURE_2D, texture_id);
c.glDrawArrays(c.GL_TRIANGLE_STRIP, 0, 4);
- self.constants.textureShader.bind();
- self.constants.normalizedQuad.draw();
+ self.constants.texture_shader.bind();
+ self.constants.normalized_quad.draw();
- c.glfwSwapBuffers(self.*.window);
+ c.glfwSwapBuffers(self.window);
return false;
}
fn destroy(output: *Output) void {
const self = @fieldParentPtr(WindowOutput, "output", output);
- c.glfwDestroyWindow(self.*.window);
+ c.glfwDestroyWindow(self.window);
}
fn keyCallback(win: ?*c.GLFWwindow, key: c_int, scancode: c_int, action: c_int, mods: c_int) callconv(.C) void {
@@ -85,4 +107,9 @@ pub const WindowOutput = struct {
else => {},
}
}
+
+ fn sizeCallback(win: ?*c.GLFWwindow, width: c_int, height: c_int) callconv(.C) void {
+ const self = @ptrCast(*WindowOutput, @alignCast(@alignOf(WindowOutput), c.glfwGetWindowUserPointer(win).?));
+ self.resized = true;
+ }
};