aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authors-ol <s-ol@users.noreply.github.com>2020-01-24 11:32:48 +0000
committers-ol <s-ol@users.noreply.github.com>2020-01-24 11:32:48 +0000
commit714cc2213950d845f56d8cc8814da5bd2b95c1a6 (patch)
treeb94e073275b2142d1af0ca90bc4006085f26c7cd
parentCode reorganisation (diff)
downloadglsl-view-714cc2213950d845f56d8cc8814da5bd2b95c1a6.tar.gz
glsl-view-714cc2213950d845f56d8cc8814da5bd2b95c1a6.zip
hot reloading
-rw-r--r--src/config.zig10
-rw-r--r--src/gl.zig58
-rw-r--r--src/main.zig58
-rw-r--r--src/output.zig2
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 {
diff --git a/src/gl.zig b/src/gl.zig
index c974cea..bd2c652 100644
--- a/src/gl.zig
+++ b/src/gl.zig
@@ -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,