diff --git a/game/engines/default/engine/Particles.lua b/game/engines/default/engine/Particles.lua index e89212a8efee70d372c43f17a5d60f1b4eb8f223..36a805d3b6a90161840f56a413423107da293d40 100644 --- a/game/engines/default/engine/Particles.lua +++ b/game/engines/default/engine/Particles.lua @@ -41,6 +41,7 @@ function _M:save() return class.save(self, { ps = true, gl_texture = true, + _shader = true, }) end diff --git a/game/engines/default/engine/Shader.lua b/game/engines/default/engine/Shader.lua index 3d9ff0499a8a14146846d68b64413272e1f8389e..bfe449b1eb54cfa5527e0ea62a31364e2aaab3bb 100644 --- a/game/engines/default/engine/Shader.lua +++ b/game/engines/default/engine/Shader.lua @@ -41,7 +41,11 @@ function _M:cleanup() for name, s in pairs(self.progs) do if s.dieat < time then todel[name] = true end end - for name, _ in pairs(todel) do self.progs[name] = nil end + for name, _ in pairs(todel) do + self.progs[name] = nil + self.progsreset[name] = nil + print("Deleting temp shader", name) + end end --- Make a shader @@ -152,10 +156,13 @@ function _M:loaded() if _M.progsperm[self.totalname] then -- print("[SHADER] using permcached shader "..self.totalname) self.shad = _M.progsperm[self.totalname] - elseif _M.progs[self.totalname] and not _M.progsreset[self.totalname] then + elseif _M.progs[self.totalname] then -- print("[SHADER] using cached shader "..self.totalname) self.shad = _M.progs[self.totalname].shad - _M.progs[self.totalname].dieat = os.time() + 60 + _M.progs[self.totalname].dieat = os.time() + 60*4 + if _M.progsreset[self.totalname] then + self.shad = self.shad:clone() + end else print("[SHADER] Loading from /data/gfx/shaders/"..self.name..".lua") local f, err = loadfile("/data/gfx/shaders/"..self.name..".lua") @@ -170,18 +177,17 @@ function _M:loaded() if not core.shader.allow(def.require_kind) then return end end - if def.resetargs then - self.totalname = self:makeTotalName(def.resetargs) - end print("[SHADER] Loaded shader with totalname", self.totalname) if not _M.progs[self.totalname] then - _M.progs[self.totalname] = {shad=self:createProgram(def), dieat=def.resetargs and (os.time() + 3) or (os.time() + 60)} - _M.progsreset[self.totalname] = def.resetargs + _M.progs[self.totalname] = {shad=self:createProgram(def), dieat=(os.time() + 60*4)} else - _M.progs[self.totalname].dieat = def.resetargs and (os.time() + 3) or (os.time() + 60) + _M.progs[self.totalname].dieat = (os.time() + 60*4) end + if def.resetargs then + _M.progsreset[self.totalname] = def.resetargs + end self.shad = _M.progs[self.totalname].shad if self.shad then @@ -194,8 +200,9 @@ function _M:loaded() end if self.shad and _M.progsreset[self.totalname] then + self.shad:resetClean() for k, v in pairs(_M.progsreset[self.totalname]) do - self:setUniform(k, v(self)) + self:setResetUniform(k, v(self)) end end end @@ -221,6 +228,27 @@ function _M:setUniform(k, v) end end +function _M:setResetUniform(k, v) + if type(v) == "number" then + print("[SHADER] setting reset param", k, v) + self.shad:resetParamNumber(k, v) + elseif type(v) == "table" then + if v.texture then +-- print("[SHADER] setting texture param", k, v.texture) + self.shad:resetParamTexture(k, v.texture, v.is3d) + elseif #v == 2 then +-- print("[SHADER] setting vec2 param", k, v[1], v[2]) + self.shad:resetParamNumber2(k, v[1], v[2]) + elseif #v == 3 then +-- print("[SHADER] setting vec3 param", k, v[1], v[2], v[3]) + self.shad:resetParamNumber3(k, v[1], v[2], v[3]) + elseif #v == 4 then +-- print("[SHADER] setting vec4 param", k, v[1], v[2], v[3], v[4]) + self.shad:resetParamNumber4(k, v[1], v[2], v[3], v[4]) + end + end +end + ---------------------------------------------------------------------------- -- Default shaders ---------------------------------------------------------------------------- diff --git a/game/modules/tome/data/gfx/shaders/boneshield.lua b/game/modules/tome/data/gfx/shaders/boneshield.lua index 16ccacd4e3b8e2663e43a3790f1b933c424615a7..8193f99de2da69f5900d79f066058b92566df38a 100644 --- a/game/modules/tome/data/gfx/shaders/boneshield.lua +++ b/game/modules/tome/data/gfx/shaders/boneshield.lua @@ -26,10 +26,9 @@ return { side = noup or 0, verticalIntensityAdjust = 0, scrollingSpeed = scrollingSpeed or 0.004, - chargesCount = chargesCount or 6, }, resetargs = { - unused = function() return rng.range(1, 99999) end, + chargesCount = function(self) return self.args.chargesCount or 0 end, }, clone = true, } diff --git a/game/modules/tome/data/talents/corruptions/bone.lua b/game/modules/tome/data/talents/corruptions/bone.lua index 0ee56b08b5f95e005a5851f2bbcabee34888bcfd..32d425f5319911d8e1a287775d82a537bebddeff 100644 --- a/game/modules/tome/data/talents/corruptions/bone.lua +++ b/game/modules/tome/data/talents/corruptions/bone.lua @@ -144,7 +144,8 @@ newTalent{ p.nb = p.nb + 1 if p.adv_gfx then if p.particles[1] and p.particles[1]._shader and p.particles[1]._shader.shad then - p.particles[1]._shader:setUniform("chargesCount", util.bound(p.nb, 0, 10)) + p.particles[1]._shader.shad:resetClean() + p.particles[1]._shader:setResetUniform("chargesCount", util.bound(p.nb, 0, 10)) p.particles[1].shader.chargesCount = util.bound(p.nb, 0, 10) end else @@ -160,7 +161,8 @@ newTalent{ p.nb = p.nb - 1 if p.adv_gfx then if p.particles[1] and p.particles[1]._shader and p.particles[1]._shader.shad then - p.particles[1]._shader:setUniform("chargesCount", util.bound(p.nb, 0, 10)) + p.particles[1]._shader.shad:resetClean() + p.particles[1]._shader:setResetUniform("chargesCount", util.bound(p.nb, 0, 10)) p.particles[1].shader.chargesCount = util.bound(p.nb, 0, 10) end else @@ -177,7 +179,10 @@ newTalent{ local adv_gfx = core.shader.allow("adv") and true or false local ps = {} if adv_gfx then - ps[1] = self:addParticles(Particles.new("shader_ring_rotating", 1, {toback=true, a=0.5, rotation=0, radius=1.5, img="bone_shield"}, {type="boneshield", chargesCount=util.bound(nb, 0, 10)})) + ps[1] = self:addParticles(Particles.new("shader_ring_rotating", 1, {toback=true, a=0.5, rotation=0, radius=1.5, img="bone_shield"}, {type="boneshield"})) + ps[1]._shader.shad:resetClean() + ps[1]._shader:setResetUniform("chargesCount", util.bound(nb, 0, 10)) + ps[1].shader.chargesCount = util.bound(nb, 0, 10) else for i = 1, nb do ps[#ps+1] = self:addParticles(Particles.new("bone_shield", 1)) end end diff --git a/src/shaders.c b/src/shaders.c index 83a6623e5ce4051949a29d5383d0516d45c4962c..afa73a087ecd41d5348719c2c7009a4ef97165fa 100644 --- a/src/shaders.c +++ b/src/shaders.c @@ -52,6 +52,25 @@ void useShader(shader_type *p, int x, int y, int w, int h, float r, float g, flo c[0] = w; c[1] = h; glUniform2fvARB(p->p_texsize, 1, c); + + shader_reset_uniform *ru = p->reset_uniforms; + while (ru) { + switch (ru->kind) { + case UNIFORM_NUMBER: + glUniform1fvARB(ru->p, 1, &ru->data.number); + break; + case UNIFORM_VEC2: + glUniform2fvARB(ru->p, 1, ru->data.vec2); + break; + case UNIFORM_VEC3: + glUniform3fvARB(ru->p, 1, ru->data.vec3); + break; + case UNIFORM_VEC4: + glUniform4fvARB(ru->p, 1, ru->data.vec4); + break; + } + ru = ru->next; + } } static GLuint loadShader(const char* code, GLuint type) @@ -96,6 +115,8 @@ static int program_new(lua_State *L) auxiliar_setclass(L, "gl{program}", -1); p->shader = glCreateProgramObjectARB(); + p->reset_uniforms = NULL; + p->clone = FALSE; printf("New GL Shader program %d\n", p->shader); @@ -106,12 +127,32 @@ static int program_free(lua_State *L) { shader_type *p = (shader_type*)lua_touserdata(L, 1); - glDeleteObjectARB(p->shader); + printf("Deleting shader %d (is clone %d)\n", p->shader, p->clone); + if (!p->clone) glDeleteObjectARB(p->shader); + + while (p->reset_uniforms) { + shader_reset_uniform *ru = p->reset_uniforms; + free(ru); + p->reset_uniforms = p->reset_uniforms->next; + } lua_pushnumber(L, 1); return 1; } +static int program_remove_resets(lua_State *L) +{ + shader_type *p = (shader_type*)lua_touserdata(L, 1); + + while (p->reset_uniforms) { + shader_reset_uniform *ru = p->reset_uniforms; + free(ru); + p->reset_uniforms = p->reset_uniforms->next; + } + + return 0; +} + static int program_attach(lua_State *L) { shader_type *p = (shader_type*)lua_touserdata(L, 1); @@ -132,6 +173,46 @@ static int program_detach(lua_State *L) return 0; } +static int program_clone(lua_State *L) +{ + shader_type *p = (shader_type*)lua_touserdata(L, 1); + + shader_type *np = (shader_type*)lua_newuserdata(L, sizeof(shader_type)); // 2 + auxiliar_setclass(L, "gl{program}", -1); + + np->clone = TRUE; + np->shader = p->shader; + np->p_tick = p->p_tick; + np->p_color = p->p_color; + np->p_mapcoord = p->p_mapcoord; + np->p_texsize = p->p_texsize; + np->reset_uniforms = NULL; + + lua_getmetatable(L, 1); // 3 + lua_newtable(L); // 4 + + // Iterate old table and copy to new table + lua_pushnil(L); + while (lua_next(L, 3) != 0) { + lua_pushvalue(L, -2); + lua_pushvalue(L, -2); + lua_rawset(L, 4); + lua_pop(L, 1); + } + + // Capture a reference to the parent so it is not GC'ed before us + lua_pushstring(L, "_parent_clone"); + lua_pushvalue(L, 1); + lua_rawset(L, 4); + + lua_setmetatable(L, 2); + lua_pop(L, 1); + + printf("Cloned shader %d\n", p->shader); + + return 1; +} + static int program_set_uniform_number(lua_State *L) { shader_type *p = (shader_type*)lua_touserdata(L, 1); @@ -196,6 +277,68 @@ static int program_set_uniform_number4(lua_State *L) return 0; } +static int program_reset_uniform_number(lua_State *L) +{ + shader_type *p = (shader_type*)lua_touserdata(L, 1); + const char *var = luaL_checkstring(L, 2); + + shader_reset_uniform *ru = malloc(sizeof(shader_reset_uniform)); + ru->next = p->reset_uniforms; + p->reset_uniforms = ru; + ru->p = glGetUniformLocationARB(p->shader, var); + ru->kind = UNIFORM_NUMBER; + ru->data.number = luaL_checknumber(L, 3); + return 0; +} + +static int program_reset_uniform_number2(lua_State *L) +{ + shader_type *p = (shader_type*)lua_touserdata(L, 1); + const char *var = luaL_checkstring(L, 2); + + shader_reset_uniform *ru = malloc(sizeof(shader_reset_uniform)); + ru->next = p->reset_uniforms; + p->reset_uniforms = ru; + ru->p = glGetUniformLocationARB(p->shader, var); + ru->kind = UNIFORM_VEC2; + ru->data.vec2[0] = luaL_checknumber(L, 3); + ru->data.vec2[1] = luaL_checknumber(L, 4); + return 0; +} + +static int program_reset_uniform_number3(lua_State *L) +{ + shader_type *p = (shader_type*)lua_touserdata(L, 1); + const char *var = luaL_checkstring(L, 2); + + shader_reset_uniform *ru = malloc(sizeof(shader_reset_uniform)); + ru->next = p->reset_uniforms; + p->reset_uniforms = ru; + ru->p = glGetUniformLocationARB(p->shader, var); + ru->kind = UNIFORM_VEC3; + ru->data.vec3[0] = luaL_checknumber(L, 3); + ru->data.vec3[1] = luaL_checknumber(L, 4); + ru->data.vec3[2] = luaL_checknumber(L, 5); + return 0; +} + +static int program_reset_uniform_number4(lua_State *L) +{ + shader_type *p = (shader_type*)lua_touserdata(L, 1); + const char *var = luaL_checkstring(L, 2); + + shader_reset_uniform *ru = malloc(sizeof(shader_reset_uniform)); + ru->next = p->reset_uniforms; + p->reset_uniforms = ru; + ru->p = glGetUniformLocationARB(p->shader, var); + ru->kind = UNIFORM_VEC4; + ru->data.vec4[0] = luaL_checknumber(L, 3); + ru->data.vec4[1] = luaL_checknumber(L, 4); + ru->data.vec4[2] = luaL_checknumber(L, 5); + ru->data.vec4[3] = luaL_checknumber(L, 6); + return 0; +} + static int program_set_uniform_texture(lua_State *L) { shader_type *p = (shader_type*)lua_touserdata(L, 1); @@ -471,6 +614,7 @@ static const struct luaL_Reg shaderlib[] = static const struct luaL_Reg program_reg[] = { {"__gc", program_free}, + {"clone", program_clone}, {"compile", program_compile}, {"attach", program_attach}, {"detach", program_detach}, @@ -479,6 +623,11 @@ static const struct luaL_Reg program_reg[] = {"paramNumber3", program_set_uniform_number3}, {"paramNumber4", program_set_uniform_number4}, {"paramTexture", program_set_uniform_texture}, + {"resetClean", program_remove_resets}, + {"resetParamNumber", program_reset_uniform_number}, + {"resetParamNumber2", program_reset_uniform_number2}, + {"resetParamNumber3", program_reset_uniform_number3}, + {"resetParamNumber4", program_reset_uniform_number4}, {"use", program_use}, {NULL, NULL}, }; diff --git a/src/useshader.h b/src/useshader.h index af77810665c589e3e658caa9db09742f8fbee67f..9eb5b8a04ae68b08902df1fdf082c621ae163b5b 100644 --- a/src/useshader.h +++ b/src/useshader.h @@ -1,10 +1,24 @@ #ifndef __USESHADER_H__ #define __USESHADER_H__ +struct s_shader_reset_uniform { + enum{UNIFORM_NUMBER, UNIFORM_VEC2, UNIFORM_VEC3, UNIFORM_VEC4} kind; + GLint p; + union { + GLfloat number; + GLfloat vec2[2]; + GLfloat vec3[3]; + GLfloat vec4[4]; + } data; + struct s_shader_reset_uniform *next; +}; +typedef struct s_shader_reset_uniform shader_reset_uniform; + typedef struct { + bool clone; GLuint shader; GLint p_tick, p_color, p_mapcoord, p_texsize; - int params_ref; + struct s_shader_reset_uniform *reset_uniforms; } shader_type; extern bool shaders_active;