diff options
| author | s-ol <s-ol@users.noreply.github.com> | 2020-01-24 11:32:48 +0000 |
|---|---|---|
| committer | s-ol <s-ol@users.noreply.github.com> | 2020-01-24 11:32:48 +0000 |
| commit | 714cc2213950d845f56d8cc8814da5bd2b95c1a6 (patch) | |
| tree | b94e073275b2142d1af0ca90bc4006085f26c7cd | |
| parent | Code reorganisation (diff) | |
| download | glsl-view-714cc2213950d845f56d8cc8814da5bd2b95c1a6.tar.gz glsl-view-714cc2213950d845f56d8cc8814da5bd2b95c1a6.zip | |
hot reloading
| -rw-r--r-- | src/config.zig | 10 | ||||
| -rw-r--r-- | src/gl.zig | 58 | ||||
| -rw-r--r-- | src/main.zig | 58 | ||||
| -rw-r--r-- | src/output.zig | 2 |
4 files changed, 84 insertions, 44 deletions
diff --git a/src/config.zig b/src/config.zig index 8d296dc..7e1e78f 100644 --- a/src/config.zig +++ b/src/config.zig @@ -11,7 +11,10 @@ pub const OutputConfig = struct { type: OutputType, width: i32, height: i32, - fullscreen: bool, // only for `Window` + + // only for 'window' + monitor: []const u8, + fullscreen: bool, }; pub const ParameterConfig = struct { @@ -23,6 +26,7 @@ const defaultOutput = OutputConfig{ .type = OutputType.window, .width = 800, .height = 600, + .monitor = "", .fullscreen = false, }; @@ -49,7 +53,7 @@ pub const Config = struct { .width = 1920, .height = 1080, .outputs = ([_]OutputConfig{defaultOutput})[0..], - .fragment = "sphere.frag", + .fragment = "", .parameters = ([0]ParameterConfig{})[0..], .arena = std.heap.ArenaAllocator.init(std.heap.page_allocator), }; @@ -213,6 +217,8 @@ fn parseOutputs(parser: *c.yaml_parser_t, allocator: *std.mem.Allocator) ![]Outp output.*.width = try parseInt(parser, i32); } else if (std.mem.eql(u8, key, "height")) { output.*.height = try parseInt(parser, i32); + } else if (std.mem.eql(u8, key, "monitor")) { + output.*.monitor = try parseString(parser, allocator); } else if (std.mem.eql(u8, key, "fullscreen")) { output.*.fullscreen = try parseBool(parser); } else { @@ -1,12 +1,12 @@ +const std = @import("std"); const c_allocator = @import("std").heap.c_allocator; const panic = @import("std").debug.panic; const c = @import("c.zig"); pub const ShaderProgram = struct { program_id: c.GLuint, - vertex_id: c.GLuint, - fragment_id: c.GLuint, - maybe_geometry_id: ?c.GLuint, + vert_id: c.GLuint, + frag_id: c.GLuint, pub fn bind(self: ShaderProgram) void { c.glUseProgram(self.program_id); @@ -52,26 +52,23 @@ pub const ShaderProgram = struct { c.glUniformMatrix4fv(uniform_id, 1, c.GL_FALSE, &value[0][0]); } - pub fn create( - vertex_source: []const u8, - frag_source: []const u8, - maybe_geometry_source: ?[]u8, - ) !ShaderProgram { + pub fn create(vert_source: []const u8, frag_source: []const u8) !ShaderProgram { var self: ShaderProgram = undefined; - self.vertex_id = try initGlShader(vertex_source, "vertex", c.GL_VERTEX_SHADER); - self.fragment_id = try initGlShader(frag_source, "fragment", c.GL_FRAGMENT_SHADER); - self.maybe_geometry_id = if (maybe_geometry_source) |geo_source| - try initGlShader(geo_source, "geometry", c.GL_GEOMETRY_SHADER) - else - null; + + self.vert_id = try initGlShader(vert_source, "vertex", c.GL_VERTEX_SHADER); + errdefer c.glDeleteShader(self.vert_id); + + self.frag_id = try initGlShader(frag_source, "fragment", c.GL_FRAGMENT_SHADER); + errdefer c.glDeleteShader(self.frag_id); self.program_id = c.glCreateProgram(); - c.glAttachShader(self.program_id, self.vertex_id); - c.glAttachShader(self.program_id, self.fragment_id); - if (self.maybe_geometry_id) |geo_id| { - c.glAttachShader(self.program_id, geo_id); - } + c.glAttachShader(self.program_id, self.vert_id); + c.glAttachShader(self.program_id, self.frag_id); c.glLinkProgram(self.program_id); + + errdefer c.glDeleteProgram(self.program_id); + errdefer c.glDetachShader(self.program_id, self.frag_id); + errdefer c.glDetachShader(self.program_id, self.vert_id); var ok: c.GLint = undefined; c.glGetProgramiv(self.program_id, c.GL_LINK_STATUS, &ok); @@ -81,21 +78,16 @@ pub const ShaderProgram = struct { c.glGetProgramiv(self.program_id, c.GL_INFO_LOG_LENGTH, &error_size); const message = try c_allocator.alloc(u8, @intCast(usize, error_size)); c.glGetProgramInfoLog(self.program_id, error_size, &error_size, message.ptr); - panic("Error linking shader program: {s}\n", .{ @ptrCast([*:0]const u8, message.ptr) }); + std.debug.warn("Error linking shader program: {s}\n", .{ @ptrCast([*:0]const u8, message.ptr) }); + return error.LinkError; } pub fn destroy(self: *ShaderProgram) void { - if (self.maybe_geometry_id) |geo_id| { - c.glDetachShader(self.program_id, geo_id); - } - c.glDetachShader(self.program_id, self.fragment_id); - c.glDetachShader(self.program_id, self.vertex_id); + c.glDetachShader(self.program_id, self.frag_id); + c.glDetachShader(self.program_id, self.vert_id); - if (self.maybe_geometry_id) |geo_id| { - c.glDeleteShader(geo_id); - } - c.glDeleteShader(self.fragment_id); - c.glDeleteShader(self.vertex_id); + c.glDeleteShader(self.frag_id); + c.glDeleteShader(self.vert_id); c.glDeleteProgram(self.program_id); } @@ -103,6 +95,7 @@ pub const ShaderProgram = struct { fn initGlShader(source: []const u8, name: []const u8, kind: c.GLenum) !c.GLuint { const shader_id = c.glCreateShader(kind); + errdefer c.glDeleteShader(shader_id); const source_ptr: ?[*]const u8 = source.ptr; const source_len = @intCast(c.GLint, source.len); c.glShaderSource(shader_id, 1, &source_ptr, &source_len); @@ -117,7 +110,8 @@ fn initGlShader(source: []const u8, name: []const u8, kind: c.GLenum) !c.GLuint const message = try c_allocator.alloc(u8, @intCast(usize, error_size)); c.glGetShaderInfoLog(shader_id, error_size, &error_size, message.ptr); - panic("Error compiling {s} shader:\n{s}\n", .{ name, @ptrCast([*:0]const u8, message.ptr) }); + std.debug.warn("Error compiling {s} shader:\n{s}\n", .{ name, @ptrCast([*:0]const u8, message.ptr) }); + return error.CompileError; } pub const FramebufferObject = struct { @@ -233,8 +227,6 @@ pub const Constants = struct { \\void main(){ \\ color = texture(colorTexture, uv); \\} - , - null ); const vertices = [_]c.GLfloat{ diff --git a/src/main.zig b/src/main.zig index 6d119af..6c2b0c4 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1,14 +1,16 @@ const std = @import("std"); +const fs = @import("std").fs; const panic = std.debug.panic; const c = @import("c.zig"); const debug_gl = @import("debug_gl.zig"); const cfg = @import("config.zig"); const out = @import("output.zig"); const gl = @import("gl.zig"); +const c_allocator = @import("std").heap.c_allocator; var window: *c.GLFWwindow = undefined; -fn errorCallback(err: c_int, description: [*c]const u8) callconv(.C) void { +extern fn errorCallback(err: c_int, description: [*c]const u8) callconv(.C) void { panic("Error: {}\n", .{description}); } @@ -23,6 +25,12 @@ pub fn main() !void { } defer c.glfwTerminate(); + var monitor_count: c_int = 0; + const monitors = c.glfwGetMonitors(&monitor_count); + for (monitors[0..@intCast(usize, monitor_count)]) |monitor, i| { + std.debug.warn("monitor {}: '{s}'\n", .{ i, @ptrCast([*:0]const u8, c.glfwGetMonitorName(monitor))}); + } + c.glfwWindowHint(c.GLFW_CONTEXT_VERSION_MAJOR, 4); c.glfwWindowHint(c.GLFW_CONTEXT_VERSION_MINOR, 2); c.glfwWindowHint(c.GLFW_OPENGL_FORWARD_COMPAT, c.GL_TRUE); @@ -64,7 +72,7 @@ pub fn main() !void { debug_gl.assertNoError(); - var redShader = try gl.ShaderProgram.create( + var main_program = try gl.ShaderProgram.create( \\#version 330 core \\ \\layout(location = 0) in vec2 position; @@ -83,12 +91,14 @@ pub fn main() !void { \\uniform float offset; \\ \\void main() { - \\ color = vec4(mod(uv + offset, vec2(1)), 0, 1); + \\ color = vec4(offset,0,0,1); // mod(uv + offset, vec2(1)), 0, 1); \\} - , - null ); - defer redShader.destroy(); + defer main_program.destroy(); + + const shader_file = try fs.cwd().openFile(config.fragment, .{}); + var last_stat = try shader_file.stat(); + try reloadShader(&main_program, shader_file, last_stat.size); var fbo = try gl.FramebufferObject.create(config.width, config.height); defer fbo.destroy(); @@ -103,12 +113,18 @@ pub fn main() !void { const elapsed = now_time - prev_time; prev_time = now_time; + const stat = try shader_file.stat(); + if (stat.mtime > last_stat.mtime) { + try reloadShader(&main_program, shader_file, stat.size); + last_stat = stat; + } + fbo.bind(); c.glClear(c.GL_COLOR_BUFFER_BIT); - redShader.bind(); + main_program.bind(); offset += @floatCast(f32, elapsed / 4); - redShader.setUniformFloat(redShader.uniformLocation("offset"), offset); + main_program.setUniformFloat(main_program.uniformLocation("offset"), offset); constants.normalizedQuad.draw(); fbo.unbind(); @@ -129,3 +145,29 @@ pub fn main() !void { debug_gl.assertNoError(); } + +fn reloadShader(current: *gl.ShaderProgram, frag_file: fs.File, size: u64) !void { + var frag_source = try c_allocator.alloc(u8, @intCast(usize, size)); + defer c_allocator.free(frag_source); + try frag_file.seekTo(0); + const length = try frag_file.read(frag_source); + + const vert_source = + \\#version 330 core + \\ + \\layout(location = 0) in vec2 position; + \\out vec2 uv; + \\ + \\void main() { + \\ uv = position / 2.0 + 0.5; + \\ gl_Position = vec4(position, 0, 1); + \\} + ; + + if (gl.ShaderProgram.create(vert_source, frag_source[0..length])) |new_program| { + current.destroy(); + current.* = new_program; + } else |err| { + std.debug.warn("Error while reloading shader:{}\n", .{ err }); + } +} diff --git a/src/output.zig b/src/output.zig index 077387c..be3b3dd 100644 --- a/src/output.zig +++ b/src/output.zig @@ -7,7 +7,7 @@ pub const Output = struct { update: fn (*Output, c.GLuint) bool, destroy: fn (*Output) void, - pub fn init(update: fn (*Output, c.GLuint) bool, destroy: fn (*Output) void) Output { + fn init(update: fn (*Output, c.GLuint) bool, destroy: fn (*Output) void) Output { return Output{ .update = update, .destroy = destroy, |
