summaryrefslogtreecommitdiff
path: root/honey/asset/shader.lua
diff options
context:
space:
mode:
authorsanine <sanine.not@pm.me>2023-05-12 01:16:46 -0500
committersanine <sanine.not@pm.me>2023-05-12 01:16:46 -0500
commit3275ae4948fd2c1bb8da780214cbb741dc3178be (patch)
tree69dbf1d5b56896e1212454e5f79daaec1d201ec1 /honey/asset/shader.lua
parent14195dac1eda9140192ca07003258715b8b0abd3 (diff)
begin refactor
Diffstat (limited to 'honey/asset/shader.lua')
-rw-r--r--honey/asset/shader.lua143
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