diff options
Diffstat (limited to 'honey/asset/shader.lua')
-rw-r--r-- | honey/asset/shader.lua | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/honey/asset/shader.lua b/honey/asset/shader.lua new file mode 100644 index 0000000..0e8c93a --- /dev/null +++ b/honey/asset/shader.lua @@ -0,0 +1,143 @@ +local gl = honey.gl + +local module = {} +setmetatable(module, {__index=_G}) +setfenv(1, module) + +-- compile glsl source code +local function compileShader(source, type) + local shader = gl.CreateShader(type) + gl.ShaderSource(shader, source) + gl.CompileShader(shader) + return shader +end + +-- helper function +local builtin = {} +local function readFile(filename) + -- support built-in shaders + if builtin[filename] then return builtin[filename] end + + local f, err = io.open(filename) + if not f then error(err) end + local str = f:read("*a") + f:close() + return str +end + + +-- build a shader program from provided source files +local function buildProgram(sources) + local shaders = {} + + -- load & compile shaders + if sources.vertex then + local shader = compileShader(readFile(sources.vertex), gl.VERTEX_SHADER) + table.insert(shaders, shader) + end + if sources.vertex then + local shader = compileShader(readFile(sources.vertex), gl.VERTEX_SHADER) + table.insert(shaders, shader) + end + + -- link shaders + local program = gl.CreateProgram() + for _, shader in ipairs(shaders) do + gl.AttachShader(program, shader) + end + gl.LinkProgram(program) + + -- clean up + for _, shader in ipairs(shaders) do + gl.DeleteShader(shader) + end + + return program +end + + +-- public uniform setters +function setInt(program, name, value) + local location = gl.GetUniformLocation(program, name) + gl.Uniform1i(location, value) +end +function setFloat(program, name, value) + local location = gl.GetUniformLocation(program, name) + gl.Uniform1f(location, value) +end +function setVec3(program, name, value) + local location = gl.GetUniformLocation(program, name) + gl.Uniform3f(location, value[1], value[2], value[3]) +end +function setVec4(program, name, value) + local location = gl.GetUniformLocation(program, name) + gl.Uniform3f(location, value[1], value[2], value[3], value[4]) +end +function setMatrix(program, name, matrix) + local location = gl.GetUniformLocation(program, name) + gl.UniformMatrix4fv(location, false, matrix.data) +end + + +function configure(program, tbl) + local processKey = function(key, set) + local subtbl = tbl[key] + if subtbl then + for name, value in pairs(subtbl) do + set(program, name, value) + end + end + end + + processKey("int", setInt) + processKey("float", setFloat) + processKey("vec3", setVec3) + processKey("vec4", setVec4) + processKey("matrix", setMatrix) +end + + +--===== public asset cache functions =====-- + +local cache = {} + + +-- generate id string based on shader sources +local function shaderId(sources) + return string.format( + "%s;%s", + sources.vertex or "nil", + sources.fragment or "nil" + ) +end + +-- get a cached shader program +get = function(sources) + local id = shaderId(sources) + if not cache[id] then + cache[id] = buildProgram(sources) + end + return cache[id] +end + + +-- remove a cached shader program +forget = function(sources) + local id = shaderId(sources) + if cache[id] then + gl.DeleteProgram(cache[id]) + cache[id] = nil + end +end + + +-- clear the cache +clearCache = function() + for key, program in pairs(cache) do + gl.DeleteProgram(program) + cache[key] = nil + end +end + + +return module |