summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsanine <sanine.not@pm.me>2023-03-29 00:01:54 -0500
committersanine <sanine.not@pm.me>2023-03-29 00:01:54 -0500
commit5a93fb6f6a8fb6f1dad821b407b4f4531bc23783 (patch)
treed7b7fb60868e2381bdd14efa357188ba3a27b804
parent45dbe47d17303050cbea7c2c51e838acfe21c2fb (diff)
add image caching
-rw-r--r--fragment.glsl6
-rw-r--r--honey/ecs.lua.bak228
-rw-r--r--honey/image.lua50
-rw-r--r--honey/ode.lua55
-rw-r--r--honey/shader.lua20
-rw-r--r--honey/std.lua9
-rw-r--r--main.lua59
7 files changed, 400 insertions, 27 deletions
diff --git a/fragment.glsl b/fragment.glsl
index 27dbbfa..c6ef691 100644
--- a/fragment.glsl
+++ b/fragment.glsl
@@ -5,11 +5,13 @@ in vec3 position;
in vec3 normal;
in vec2 tex;
+uniform float time;
uniform sampler2D ourTexture;
void main()
{
- FragColor = vec4(normal, 1.0f);
+ //FragColor = vec4(sin(time), cos(time), -sin(time), 1.0f);
+ //FragColor = vec4(normal, 1.0f);
//FragColor = vec4(tex, 1.0f, 1.0f);
- //FragColor = texture(ourTexture, TexCoord);
+ FragColor = texture(ourTexture, tex);
}
diff --git a/honey/ecs.lua.bak b/honey/ecs.lua.bak
new file mode 100644
index 0000000..3632f34
--- /dev/null
+++ b/honey/ecs.lua.bak
@@ -0,0 +1,228 @@
+local module = {}
+setmetatable(module, {__index=_G})
+setfenv(1, module)
+
+
+--===== filters =====--
+
+
+Filter = {}
+
+-- base filter creation
+function Filter.new(_, operation, tbl)
+ local self = {}
+ self.keys = {}
+ self.filters = {}
+ self.op = operation
+
+ for _, v in ipairs(tbl) do
+ if type(v) == "function" then
+ table.insert(self.filters, v)
+ elseif type(v) == "string" then
+ table.insert(self.keys, v)
+ end
+ end
+
+ return function(entity, _self)
+ local entity = _self or entity -- able to call as . or :
+ return Filter.check(self, entity)
+ end
+end
+setmetatable(Filter, {__call=Filter.new})
+
+
+-- base filter checking
+function Filter.check(self, entity)
+ local funcname = "check" .. self.op
+ return Filter[funcname](self, entity)
+end
+
+
+-- AND filter (all keys and subfilters must match)
+function Filter.AND(tbl)
+ return Filter("AND", tbl)
+end
+function Filter.checkAND(self, entity)
+ for _, subfilter in ipairs(self.filters) do
+ if not subfilter(entity) then return false end
+ end
+ for _, key in ipairs(self.keys) do
+ if entity[key] == nil then return false end
+ end
+ return true
+end
+
+
+-- OR filter (at least one key or subfilter must match)
+function Filter.OR(tbl)
+ return Filter("OR", tbl)
+end
+function Filter.checkOR(self, entity)
+ for _, subfilter in ipairs(self.filters) do
+ if subfilter(entity) then return true end
+ end
+ for _, key in ipairs(self.keys) do
+ if entity[key] ~= nil then return true end
+ end
+ return false
+end
+
+
+-- NAND filter (at least one key or subfilter must NOT match)
+function Filter.NAND(tbl)
+ return Filter("NAND", tbl)
+end
+function Filter.checkNAND(self, entity)
+ for _, subfilter in ipairs(self.filters) do
+ if not subfilter(entity) then return true end
+ end
+ for _, key in ipairs(self.keys) do
+ if entity[key] == nil then return true end
+ end
+ return false
+end
+
+
+-- NOR filter (no keys or subfilters may match)
+function Filter.NOR(tbl)
+ return Filter("NOR", tbl)
+end
+function Filter.checkNOR(self, entity)
+ for _, subfilter in ipairs(self.filters) do
+ if subfilter(entity) then return false end
+ end
+ for _, key in ipairs(self.keys) do
+ if entity[key] ~= nil then return false end
+ end
+ return true
+end
+
+
+--===== levels =====--
+
+Level = {}
+Level.__index = Level
+
+function Level.new(_)
+ local self = {}
+ self.systems = {}
+ self.entities = {}
+ self.nextId = 1
+ setmetatable(self, Level)
+ return self
+end
+setmetatable(Level, {__call=Level.new})
+
+
+local function systemLt(a, b)
+ return (a.priority or 50) < (b.priority or 50)
+end
+function Level.addSystem(self, system)
+ assert(system.update, "systems must have an 'update' key")
+ assert(system.filter, "systems must have a 'filter' key")
+ system.entities = {}
+ table.insert(self.systems, system)
+ table.sort(self.systems, systemLt)
+ if system.setup then
+ system.setup(system)
+ end
+end
+
+
+local function addEntityToSystem(system, id, entity)
+ -- check if entity is already present
+ if system.entities[id] then return end
+
+ if system.onAddEntity then
+ system:onAddEntity(id, entity)
+ end
+ system.entities[id] = true
+end
+
+
+local function removeEntityFromSystem(system, id, entity)
+ -- check if entity is already absent
+ if not system.entities[id] then return end
+
+ if system.onRemoveEntity then
+ system:onRemoveEntity(id, entity)
+ end
+ system.entities[id] = nil
+end
+
+
+function Level.addEntity(self, entity)
+ local id = self.nextId
+ self.entities[id] = entity
+ self.nextId = id + 1
+
+ for _, system in ipairs(self.systems) do
+ if system.filter(entity) then
+ addEntityToSystem(system, id, entity)
+ end
+ end
+
+ return id
+end
+
+
+function Level.reconfigureEntity(self, id)
+ local entity = self.entities[id]
+
+ for _, system in ipairs(self.systems) do
+ if system.filter(entity) then
+ addEntityToSystem(system, id, entity)
+ else
+ removeEntityFromSystem(system, id, entity)
+ end
+ end
+end
+
+
+function Level.removeEntity(self, id)
+ local entity = self.entities[id]
+ if not entity then error("bad id: "..tostring(id)) end
+ for _, system in ipairs(self.systems) do
+ removeEntityFromSystem(system, id, entity)
+ end
+ self.entities[id] = nil
+end
+
+
+function Level.reconfigureAllEntities(self)
+ for id in ipairs(self.entities) do
+ self:reconfigureEntity(id)
+ end
+end
+
+
+function Level.update(self, dt, paused)
+ local paused = paused or false
+ for _, system in ipairs(self.systems) do
+ if (not paused) or (paused and system.nopause) then
+ if system.preUpdate then
+ system:preUpdate()
+ end
+ if system.prepareEntity then
+ for id in pairs(system.entities) do
+ local entity = self.entities[id]
+ if entity then
+ system:prepareEntity(entity)
+ end
+ end
+ end
+ for id in pairs(system.entities) do
+ local entity = self.entities[id]
+ if entity then
+ system:update(entity, dt)
+ end
+ end
+ if system.postUpdate then
+ system:postUpdate()
+ end
+ end
+ end
+end
+
+
+return module
diff --git a/honey/image.lua b/honey/image.lua
new file mode 100644
index 0000000..f074272
--- /dev/null
+++ b/honey/image.lua
@@ -0,0 +1,50 @@
+local gl = honey.gl
+
+local module = {}
+setmetatable(module, {__index=_G})
+setfenv(1, module)
+
+function Image(filename, params)
+ local params = params or {}
+ local data, width, height = honey.image.load(filename, 4)
+ local self = {}
+ self.width = width
+ self.height = height
+
+ self.texture = gl.GenTextures()
+ gl.BindTexture(gl.TEXTURE_2D, self.texture)
+ for param, value in pairs(params) do
+ gl.TexParameteri(gl.TEXTURE_2D, gl[param], value)
+ end
+ gl.TexImage2D(
+ gl.TEXTURE_2D, 0,
+ gl.RGBA, width, height,
+ gl.RGBA, gl.UNSIGNED_BYTE, data
+ )
+ gl.GenerateMipmap(gl.TEXTURE_2D)
+ honey.image.destroy(data)
+
+ self.__gc = honey.util.gc_canary(function()
+ gl.DeleteTextures(self.texture)
+ end)
+
+ return self
+end
+
+
+local cache = {}
+function loadImage(filename, params)
+ if not cache[filename] then
+ local img = Image(filename, params)
+ cache[filename] = img
+ return img
+ end
+
+ return cache[filename]
+end
+
+function clearImageCache()
+ cache = {}
+end
+
+return module
diff --git a/honey/ode.lua b/honey/ode.lua
new file mode 100644
index 0000000..4cd2e54
--- /dev/null
+++ b/honey/ode.lua
@@ -0,0 +1,55 @@
+local module = {}
+setmetatable(module, {__index=_G}
+setfenv(1, module)
+
+
+--===== collision =====--
+
+Geom = {}
+Geom.__index = Geom
+
+
+function Geom.new(_, type, params)
+ local self = {}
+ self.type = type
+ self.params = params
+ setmetatable(self, Geom)
+ return self
+end
+setmetatable(Geom, {__call=Geom.new})
+
+
+function Geom.renew(geom)
+ return ode.GeomGetData(geom)
+end
+
+
+local function instantiateSphere(space, params)
+ local geom = ode.CreateSphere(space, params.radius)
+ return geom
+end
+
+
+local function instantiatePlane(space, params)
+ local geom = ode.CreatePlane(space, params.a, params.b, params.c, params.d)
+ return geom
+end
+
+
+function Geom.instantiate(self, space)
+ if self.type == "sphere" then
+ self.geom = instantiateSphere(space, self.params)
+ elseif self.type == "plane" then
+ self.geom = instantiatePlane(space, self.params)
+ else
+ error(string.format("bad geom type: %s", self.type))
+ end
+ ode.GeomSetData(self.geom, self)
+ return self
+end
+
+
+function Geom.setBody(self, body)
+ ode.GeomSetBody(self.geom, body.body)
+ return self
+end
diff --git a/honey/shader.lua b/honey/shader.lua
index 083b260..6b281f7 100644
--- a/honey/shader.lua
+++ b/honey/shader.lua
@@ -52,6 +52,10 @@ function Shader.new(_, sources)
gl.DeleteShader(shader)
end
+ self.__gc = honey.util.gc_canary(function()
+ gl.DeleteProgram(self.program)
+ end)
+
setmetatable(self, Shader)
return self
end
@@ -115,4 +119,18 @@ function Shader.configure(self, tbl)
processKey("matrix", "setMatrix")
end
-return module.Shader
+
+local shaderCache = {}
+function loadShader(vertex, fragment)
+ local id = vertex .. "+" .. fragment
+ if not shaderCache[id] then
+ local shader = Shader{vertexFile=vertex, fragmentFile=fragment}
+ shaderCache[id] = shader
+ end
+ return shaderCache[id]
+end
+function clearShaderCache()
+ shaderCache = {}
+end
+
+return module
diff --git a/honey/std.lua b/honey/std.lua
index 2a5d2c2..98e942d 100644
--- a/honey/std.lua
+++ b/honey/std.lua
@@ -7,10 +7,17 @@ honey.terminate = init.terminate
honey.ecs = require 'honey.ecs'
--honey.standardSystems = require 'honey.ecs-systems'
honey.mesh = require 'honey.mesh'
-honey.Shader = require 'honey.shader'
+honey.shader = require 'honey.shader'
honey.Window = require 'honey.window'
+-- image
+local image = require 'honey.image'
+for k, v in pairs(image) do
+ honey.image[k] = v
+end
+
+
local glm = require 'honey.glm'
honey.Vec3 = glm.Vec3
honey.Mat4 = glm.Mat4
diff --git a/main.lua b/main.lua
index 098a65b..f13a1a6 100644
--- a/main.lua
+++ b/main.lua
@@ -22,27 +22,12 @@ local vw, vh = 640, 480
-- create camera matrices
local camera = {
- view=Mat4():identity():translate(Vec3{0, 0, -30}),
+ view=Mat4():identity():translate(Vec3{0, 0, -3}),
projection=Mat4():perspective(math.rad(45), 640/480, 0.1, 100),
}
--- create shader
-local shader = honey.Shader{
- vertexFile = "vertex.glsl",
- fragmentFile = "fragment.glsl",
-}
-
--- load models
-local plane = honey.mesh.loadFile("assets/plane.obj")[1]
-local tetra = honey.mesh.loadFile("assets/tetrahedron.obj")[1]
-local cube = honey.mesh.loadFile("assets/cube.obj")[1]
-local octa = honey.mesh.loadFile("assets/octahedron.obj")[1]
-local dodeca = honey.mesh.loadFile("assets/dodecahedron.obj")[1]
-local icosa = honey.mesh.loadFile("assets/icosahedron.obj")[1]
-
-
-- close window on ESCAPE key
window:setKeyCallback(function(_, key, scancode, action)
if action == glfw.PRESS then
@@ -82,14 +67,39 @@ sdb:addSystem{
update = function(self, dt)
local entities = self.db:queryComponent("renderMesh")
for entity, tbl in pairs(entities) do
- tbl.shader:use()
- tbl.shader:configure{matrix={
- view=camera.view,
- projection=camera.projection,
- model=Mat4():identity(),
- }}
+ -- get shader
+ local shader = honey.shader.loadShader(tbl.shader.vertex, tbl.shader.fragment)
+ shader:use()
+
+ -- bind textures
+ local texOffset = 0
+ for name, texTbl in pairs(tbl.textures) do
+ local texture = honey.image.loadImage(texTbl.filename, texTbl.params)
+ gl.BindTexture(gl.TEXTURE_2D + texOffset, texture.texture)
+ shader:setInt(name, texOffset)
+ texOffset = texOffset + 1
+ end
+
+ -- configure default uniforms
+ shader:configure{
+ float={
+ time=glfw.GetTime(),
+ },
+ matrix={
+ view=camera.view,
+ projection=camera.projection,
+ model=Mat4():identity(),
+ },
+ }
+
+ -- draw mesh
local mesh = honey.mesh.loadMesh(tbl.mesh.filename, tbl.mesh.index)
mesh:drawElements()
+
+ -- unbind textures
+ for i=0,texOffset-1 do
+ gl.BindTexture(gl.TEXTURE_2D + i, 0)
+ end
end
end,
db = edb,
@@ -99,7 +109,10 @@ sdb:addSystem{
local id = edb:createEntity()
edb:addComponent(id, "renderMesh", {
- shader = shader,
+ textures = {
+ ourTexture={ filename="77155.png" },
+ },
+ shader = { vertex="vertex.glsl", fragment="fragment.glsl" },
mesh = { filename="assets/icosahedron.obj", index=1 },
})