diff options
| author | s-ol <s-ol@users.noreply.github.com> | 2020-01-22 16:11:33 +0000 |
|---|---|---|
| committer | s-ol <s-ol@users.noreply.github.com> | 2020-01-22 16:11:33 +0000 |
| commit | 25e9c84b55593da4950b2c9ccac818c606a5321f (patch) | |
| tree | 27f949b82aeeb725025d9099cf7a14767b4a0135 /src/shader.zig | |
| download | glsl-view-25e9c84b55593da4950b2c9ccac818c606a5321f.tar.gz glsl-view-25e9c84b55593da4950b2c9ccac818c606a5321f.zip | |
initial commit
Diffstat (limited to 'src/shader.zig')
| -rw-r--r-- | src/shader.zig | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/src/shader.zig b/src/shader.zig new file mode 100644 index 0000000..ed36035 --- /dev/null +++ b/src/shader.zig @@ -0,0 +1,118 @@ +const std = @import("std"); +const panic = 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, + + pub fn bind(sp: ShaderProgram) void { + c.glUseProgram(sp.program_id); + } + + pub fn attribLocation(sp: ShaderProgram, name: [*]const u8) c.GLint { + const id = c.glGetAttribLocation(sp.program_id, name); + if (id == -1) { + panic("invalid attrib: {}\n", .{name}); + } + return id; + } + + pub fn uniformLocation(sp: ShaderProgram, name: [*]const u8) c.GLint { + const id = c.glGetUniformLocation(sp.program_id, name); + if (id == -1) { + panic("invalid uniform: {}\n", .{name}); + } + return id; + } + + pub fn setUniformInt(sp: ShaderProgram, uniform_id: c.GLint, value: c_int) void { + c.glUniform1i(uniform_id, value); + } + + pub fn setUniformFloat(sp: ShaderProgram, uniform_id: c.GLint, value: f32) void { + c.glUniform1f(uniform_id, value); + } + + pub fn setUniformVec3(sp: ShaderProgram, uniform_id: c.GLint, value: math3d.Vec3) void { + c.glUniform3fv(uniform_id, 1, value.data[0..].ptr); + } + + pub fn setUniformVec4(sp: ShaderProgram, uniform_id: c.GLint, value: Vec4) void { + c.glUniform4fv(uniform_id, 1, value.data[0..].ptr); + } + + pub fn setUniformMat4x4(sp: ShaderProgram, uniform_id: c.GLint, value: Mat4x4) void { + c.glUniformMatrix4fv(uniform_id, 1, c.GL_FALSE, value.data[0][0..].ptr); + } + + pub fn create( + vertex_source: []const u8, + frag_source: []const u8, + maybe_geometry_source: ?[]u8, + ) !ShaderProgram { + var sp: ShaderProgram = undefined; + sp.vertex_id = try initGlShader(vertex_source, "vertex", c.GL_VERTEX_SHADER); + sp.fragment_id = try initGlShader(frag_source, "fragment", c.GL_FRAGMENT_SHADER); + sp.maybe_geometry_id = if (maybe_geometry_source) |geo_source| + try initGlShader(geo_source, "geometry", c.GL_GEOMETRY_SHADER) + else + null; + + sp.program_id = c.glCreateProgram(); + c.glAttachShader(sp.program_id, sp.vertex_id); + c.glAttachShader(sp.program_id, sp.fragment_id); + if (sp.maybe_geometry_id) |geo_id| { + c.glAttachShader(sp.program_id, geo_id); + } + c.glLinkProgram(sp.program_id); + + var ok: c.GLint = undefined; + c.glGetProgramiv(sp.program_id, c.GL_LINK_STATUS, &ok); + if (ok != 0) return sp; + + var error_size: c.GLint = undefined; + c.glGetProgramiv(sp.program_id, c.GL_INFO_LOG_LENGTH, &error_size); + const message = try c_allocator.alloc(u8, @intCast(usize, error_size)); + c.glGetProgramInfoLog(sp.program_id, error_size, &error_size, message.ptr); + panic("Error linking shader program: {}\n", .{message.ptr}); + } + + pub fn destroy(sp: *ShaderProgram) void { + if (sp.maybe_geometry_id) |geo_id| { + c.glDetachShader(sp.program_id, geo_id); + } + c.glDetachShader(sp.program_id, sp.fragment_id); + c.glDetachShader(sp.program_id, sp.vertex_id); + + if (sp.maybe_geometry_id) |geo_id| { + c.glDeleteShader(geo_id); + } + c.glDeleteShader(sp.fragment_id); + c.glDeleteShader(sp.vertex_id); + + c.glDeleteProgram(sp.program_id); + } +}; + +fn initGlShader(source: []const u8, name: [*]const u8, kind: c.GLenum) !c.GLuint { + const shader_id = c.glCreateShader(kind); + const source_ptr: ?[*]const u8 = source.ptr; + const source_len = @intCast(c.GLint, source.len); + c.glShaderSource(shader_id, 1, &source_ptr, &source_len); + c.glCompileShader(shader_id); + + var ok: c.GLint = undefined; + c.glGetShaderiv(shader_id, c.GL_COMPILE_STATUS, &ok); + if (ok != 0) return shader_id; + + var error_size: c.GLint = undefined; + c.glGetShaderiv(shader_id, c.GL_INFO_LOG_LENGTH, &error_size); + + const message = try c_allocator.alloc(u8, @intCast(usize, error_size)); + c.glGetShaderInfoLog(shader_id, error_size, &error_size, message.ptr); + panic("Error compiling {} shader:\n{}\n", .{ name, message.ptr }); +} |
