Difference between revisions of "Shader (CMS)"
From The Official Visionaire Studio: Adventure Game Engine Wiki
(→Resources) |
|||
(27 intermediate revisions by 4 users not shown) | |||
Line 1: | Line 1: | ||
{| class="ts" | {| class="ts" | ||
|- | |- | ||
− | ! style="text-align:left" | Name !! style="text-align:left" | Type !! style="text-align:left" | By | + | ! style="text-align:left" | Name !! style="text-align:left;width:10%;" | Version !! style="text-align:left" | Type !! style="text-align:left" | By |
|- | |- | ||
− | | Shader Toolkit || Definition || | + | | Shader Toolkit || 0.96 || Definition || Simon Scheckel, with edits by AFRLme |
|} | |} | ||
− | This script offers some easy functions to use shader power. It ranges from blur, noise, saturation, contrast, lightness, colorize to some simple camera controls. | + | This script offers some easy functions to use shader power. It ranges from blur, noise, saturation, contrast, lightness, colorize to some simple camera controls. ''Visionaire Studio 5.x is required to run this script.'' |
+ | <hr> | ||
+ | {| class="ts" | ||
+ | |- | ||
+ | | ''Quick note: The script on here may be outdated, please download the latest version for 5.x from the [[#resources|resources]] section at the bottom of the page.'' | ||
+ | |} | ||
+ | <hr> | ||
== Instructions == | == Instructions == | ||
− | 1. Add the [[#Main_Script|main script]] to the Visionaire Studio Script Editor & set the script as a definition script.<br/> | + | 1. Add the [[#Main_Script|main script]] to the Visionaire Studio Script Editor & set the script as a definition script.<br /> |
2. Call the functions you need. | 2. Call the functions you need. | ||
+ | |||
+ | === Shader Toolkit Functions === | ||
+ | {| class="ts sortable" | ||
+ | |- | ||
+ | ! style="text-align:left" | Function Name | ||
+ | ! style="text-align:left;width:80%" class="unsortable" | Description | ||
+ | |- | ||
+ | | [[ShaderAddEffect_(CMS)|shaderAddEffect()]] || Add various dynamic pre-made warp effects to the screen. | ||
+ | |- | ||
+ | | [[ShaderBlur_(CMS)|shaderBlur()]] || Blur/Focus the screen over x amount of milliseconds. | ||
+ | |- | ||
+ | | [[ShaderColorize_(CMS)|shaderColorize()]] || Tint all the graphics on the screen a specific color over x amount of milliseconds. | ||
+ | |- | ||
+ | | [[ShaderContrast_(CMS)|shaderContrast()]] || Set the global contrast level of the screen over x amount of milliseconds. | ||
+ | |- | ||
+ | | [[ShaderFollowCharacter_(CMS)|shaderFollowCharacter()]] || Softly follow the linked character around the screen. | ||
+ | |- | ||
+ | | [[ShaderGlow_(CMS)|shaderGlow()]] || Create a glow effect on light/saturated scene objects (automatically selected) over x amount of milliseconds. | ||
+ | |- | ||
+ | | [[ShaderHue_(CMS)|shaderHue()]] || Adjust the hue level of the screen over x amount of milliseconds. | ||
+ | |- | ||
+ | | [[ShaderLightness_(CMS)|shaderLightness()]] || Adjust the lightness of the screen over x amount of milliseconds. | ||
+ | |- | ||
+ | | [[ShaderNoise_(CMS)|shaderNoise()]] || Apply noise effect to the screen over x amount of milliseconds. | ||
+ | |- | ||
+ | | [[ShaderPan_(CMS)|shaderPan()]] || Pan the camera on the x or y axis over x amount of milliseconds. | ||
+ | |- | ||
+ | | [[ShaderRotate_(CMS)|shaderRotate()]] || Rotate the screen over x amount of milliseconds. | ||
+ | |- | ||
+ | | [[ShaderSaturation_(CMS)|shaderSaturation()]] || Adjust saturation value of the screen over x amount of milliseconds. | ||
+ | |- | ||
+ | | [[ShaderViewport_(CMS)|shaderViewport()]] || Pan, zoom & rotate the camera over x amount of milliseconds. | ||
+ | |- | ||
+ | | [[ShaderZoom_(CMS)|shaderZoom()]] || Zoom the camera over x amount of milliseconds. | ||
+ | |- | ||
+ | | [[ShaderZoomCharacter_(CMS)|shaderZoomCharacter()]] || Zoom camera into or out of linked characters position over x amount of milliseconds. | ||
+ | |- | ||
+ | | [[ShaderZoomObject_(CMS)|shaderZoomObject()]] || Zoom camera into or out of linked objects location over x amount of milliseconds. | ||
+ | |} | ||
+ | |||
== Examples == | == Examples == | ||
− | + | <syntaxhighlight lang="lua"> | |
− | <syntaxhighlight> | ||
shaderZoomCharacter("", 1.2, 3000, easeBackOut) -- Zoom 1.2x on current character in 3s with one bounce | shaderZoomCharacter("", 1.2, 3000, easeBackOut) -- Zoom 1.2x on current character in 3s with one bounce | ||
shaderZoomObject(getObject("Objects[pole]"), 1.4, 3000, easeBounceOut) | shaderZoomObject(getObject("Objects[pole]"), 1.4, 3000, easeBounceOut) | ||
Line 28: | Line 73: | ||
shaderColorize(0, 1, 3000) -- colorize with red | shaderColorize(0, 1, 3000) -- colorize with red | ||
</syntaxhighlight> | </syntaxhighlight> | ||
+ | |||
== Reset Values == | == Reset Values == | ||
− | <syntaxhighlight> | + | <syntaxhighlight lang="lua"> |
shaderViewport(1, 0, 0, 0, 1000, easeQuintOut) | shaderViewport(1, 0, 0, 0, 1000, easeQuintOut) | ||
shaderStopFollow(easeQuintOut) -- Stop following character & reset viewport | shaderStopFollow(easeQuintOut) -- Stop following character & reset viewport | ||
Line 42: | Line 88: | ||
shaderColorize(0, 0, 3000) | shaderColorize(0, 0, 3000) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
+ | |||
== Main Script == | == Main Script == | ||
− | <syntaxhighlight> | + | <html><button class="copybtn" onclick="CopyToClipboard('main_script')"></button></html> |
+ | <syntaxhighlight lang="lua" id="main_script"> | ||
+ | --[VISMODULE,id,version,chksum] | ||
-- | -- | ||
-- Shader Toolkit Hue, Saturation, Luminance, Blur, Noise, Camera Control, Bloom, Random Effects | -- Shader Toolkit Hue, Saturation, Luminance, Blur, Noise, Camera Control, Bloom, Random Effects | ||
− | -- (c) | + | -- (c) 2015 Simon Scheckel, Visionaire Studio Engine - with edits by AFRLme |
− | -- Version 0. | + | -- Version 0.96 |
+ | -- updated 29/09/2014 for 4.1 | ||
+ | -- added some save functionality 9/10 | ||
+ | -- bugfix version 16/10 | ||
+ | -- update 10/6/15 radial glow, use per object matrices | ||
+ | -- update 3/2/16 cross platform shaders requires 4.3 | ||
+ | -- update 28/9/18 lua 5.3 | ||
-- | -- | ||
-- Matrix functions from https://github.com/davidm/lua-matrix/blob/master/lua/matrix.lua | -- Matrix functions from https://github.com/davidm/lua-matrix/blob/master/lua/matrix.lua | ||
Line 67: | Line 122: | ||
-- shaderFollowCharacter(name, c_scale, delay) | -- shaderFollowCharacter(name, c_scale, delay) | ||
-- shaderStopFollow() | -- shaderStopFollow() | ||
+ | -- shaderViewportInterpolationPoint(x,y) | ||
-- shaderViewport(zoom, x, y, rotation, delay, easing) rotation in 0-2Pi (full turn) | -- shaderViewport(zoom, x, y, rotation, delay, easing) rotation in 0-2Pi (full turn) | ||
-- shaderPan(offset, delay, easing, axis) | -- shaderPan(offset, delay, easing, axis) | ||
Line 93: | Line 149: | ||
--[[ | --[[ | ||
warp1 | warp1 | ||
− | |||
tv1 | tv1 | ||
− | ripple1 | + | ripple1 |
− | ripple2 | + | ripple2 |
ascii | ascii | ||
edgeglow | edgeglow | ||
chroma | chroma | ||
− | ripple3 | + | ripple3 |
warp2 | warp2 | ||
ripple4 | ripple4 | ||
Line 117: | Line 172: | ||
function matrix:new( rows, columns, value ) | function matrix:new( rows, columns, value ) | ||
− | + | if type( rows ) == "table" then | |
− | + | if type(rows[1]) ~= "table" then | |
− | + | return setmetatable( {{rows[1]},{rows[2]},{rows[3]}},matrix_meta ) | |
− | + | end | |
− | + | return setmetatable( rows,matrix_meta ) | |
− | + | end | |
− | + | local mtx = {} | |
− | + | local value = value or 0 | |
− | + | if columns == "I" then | |
− | + | for i = 1,rows do | |
− | + | mtx[i] = {} | |
− | + | for j = 1,rows do | |
− | + | if i == j then | |
− | + | mtx[i][j] = 1 | |
− | |||
− | |||
− | |||
− | |||
− | |||
else | else | ||
− | + | mtx[i][j] = 0 | |
− | |||
− | |||
− | |||
− | |||
− | |||
end | end | ||
− | return setmetatable( mtx,matrix_meta ) | + | end |
+ | end | ||
+ | else | ||
+ | for i = 1,rows do | ||
+ | mtx[i] = {} | ||
+ | for j = 1,columns do | ||
+ | mtx[i][j] = value | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | return setmetatable( mtx,matrix_meta ) | ||
end | end | ||
function matrix.mul( m1, m2 ) | function matrix.mul( m1, m2 ) | ||
− | + | local mtx = {} | |
− | + | for i = 1,#m1 do | |
− | + | mtx[i] = {} | |
− | + | for j = 1,#m2[1] do | |
− | + | local num = m1[i][1] * m2[1][j] | |
− | + | for n = 2,#m1[1] do | |
− | + | num = num + m1[i][n] * m2[n][j] | |
− | + | end | |
− | + | mtx[i][j] = num | |
− | + | end | |
− | + | end | |
− | + | return setmetatable( mtx, matrix_meta ) | |
end | end | ||
− | function matrix. | + | function matrix.type( mtx ) |
− | + | local e = mtx[1][1] | |
− | + | if type(e) == "table" then | |
− | + | if e.type then | |
− | + | return e:type() | |
− | + | end | |
− | + | return "tensor" | |
− | + | end | |
− | + | return "number" | |
− | |||
end | end | ||
− | + | local num_copy = function( num ) | |
− | + | return num | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | local | ||
− | function | ||
− | |||
− | |||
− | |||
end | end | ||
− | + | local t_copy = function( t ) | |
− | return | + | local newt = setmetatable( {}, getmetatable( t ) ) |
+ | for i,v in ipairs( t ) do | ||
+ | newt[i] = v | ||
+ | end | ||
+ | return newt | ||
end | end | ||
− | + | ||
− | + | function matrix.transpose( m1 ) | |
+ | local docopy = matrix.type( m1 ) == "number" and num_copy or t_copy | ||
+ | local mtx = {} | ||
+ | for i = 1,#m1[1] do | ||
+ | mtx[i] = {} | ||
+ | for j = 1,#m1 do | ||
+ | mtx[i][j] = docopy( m1[j][i] ) | ||
+ | end | ||
+ | end | ||
+ | return setmetatable( mtx, matrix_meta ) | ||
end | end | ||
− | + | ||
− | + | function matrix.tofloat( m1 ) | |
− | + | local mtx = {} | |
+ | local pos = 1 | ||
+ | for i = 1,#m1 do | ||
+ | for j = 1,#m1[1] do | ||
+ | mtx[pos] = m1[i][j] | ||
+ | pos=pos+1 | ||
+ | end | ||
+ | end | ||
+ | return mtx | ||
end | end | ||
+ | matrix_meta.__mul = matrix.mul | ||
+ | matrix_meta.__index = {tofloat = matrix.tofloat, transpose = matrix.transpose} | ||
− | + | setmetatable( matrix, { __call = function( ... ) return matrix.new( ... ) end } ) | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | { | ||
− | |||
− | |||
− | } | ||
− | -- | + | -- End of matrix functions |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | function string.fromhex(str) | |
− | + | return (str:gsub('..', function (cc) | |
− | + | return string.char(tonumber(cc, 16)) | |
− | + | end)) | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | return | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | end | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
end | end | ||
− | function | + | function string.tohex(str) |
− | + | return (str:gsub('.', function (c) | |
− | + | return string.format('%02X', string.byte(c)) | |
− | + | end)) | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
end | end | ||
− | + | -- | |
− | + | -- Source: http://lua-users.org/wiki/DataDumper | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | --[[ DataDumper.lua | |
− | + | Copyright (c) 2007 Olivetti-Engineering SA | |
− | |||
− | |||
− | |||
− | + | Permission is hereby granted, free of charge, to any person | |
− | + | obtaining a copy of this software and associated documentation | |
− | + | files (the "Software"), to deal in the Software without | |
+ | restriction, including without limitation the rights to use, | ||
+ | copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
+ | copies of the Software, and to permit persons to whom the | ||
+ | Software is furnished to do so, subject to the following | ||
+ | conditions: | ||
− | + | The above copyright notice and this permission notice shall be | |
− | + | included in all copies or substantial portions of the Software. | |
− | |||
− | + | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
− | + | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES | |
− | + | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
+ | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | ||
+ | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | ||
+ | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
+ | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
+ | OTHER DEALINGS IN THE SOFTWARE. | ||
+ | ]] | ||
− | function | + | local dumplua_closure = [[ |
− | + | local closures = {} | |
+ | local function closure(t) | ||
+ | closures[#closures+1] = t | ||
+ | t[1] = assert(load(t[1])) | ||
+ | return t[1] | ||
end | end | ||
− | + | for _,t in pairs(closures) do | |
− | + | for i = 2,#t do | |
− | + | debug.setupvalue(t[1], i-1, t[i]) | |
+ | end | ||
end | end | ||
+ | ]] | ||
− | + | local lua_reserved_keywords = { | |
− | + | 'and', 'break', 'do', 'else', 'elseif', 'end', 'false', 'for', | |
− | + | 'function', 'if', 'in', 'local', 'nil', 'not', 'or', 'repeat', | |
− | + | 'return', 'then', 'true', 'until', 'while' } | |
− | |||
− | |||
− | + | local function keys(t) | |
− | function | + | local res = {} |
− | + | local oktypes = { stringstring = true, numbernumber = true } | |
− | + | local function cmpfct(a,b) | |
− | + | if oktypes[type(a)..type(b)] then | |
− | + | return a < b | |
+ | else | ||
+ | return type(a) < type(b) | ||
+ | end | ||
+ | end | ||
+ | for k in pairs(t) do | ||
+ | res[#res+1] = k | ||
+ | end | ||
+ | table.sort(res, cmpfct) | ||
+ | return res | ||
end | end | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | local c_functions = {} | |
− | + | for _,lib in pairs{'_G', 'string', 'table', 'math', | |
− | + | 'io', 'os', 'coroutine', 'package', 'debug'} do | |
− | + | local t = _G[lib] or {} | |
− | + | lib = lib .. "." | |
− | + | if lib == "_G." then lib = "" end | |
− | + | for k,v in pairs(t) do | |
− | + | if type(v) == 'function' and not pcall(string.dump, v) then | |
− | + | c_functions[v] = lib..k | |
− | + | end | |
− | + | end | |
− | + | end | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | # | + | function DataDumper(value, varname, fastmode, ident) |
− | # | + | local defined, dumplua = {} |
− | # | + | -- Local variables for speed optimization |
+ | local string_format, type, string_dump, string_rep = | ||
+ | string.format, type, string.dump, string.rep | ||
+ | -- local tostring, pairs, table_concat = | ||
+ | -- tostring, pairs, table.concat | ||
+ | local pairs, table_concat = | ||
+ | pairs, table.concat | ||
+ | local keycache, strvalcache, out, closure_cnt = {}, {}, {}, 0 | ||
+ | setmetatable(strvalcache, {__index = function(t,value) | ||
+ | local res = string_format('%q', value) | ||
+ | t[value] = res | ||
+ | return res | ||
+ | end}) | ||
+ | local fcts = { | ||
+ | string = function(value) return strvalcache[value] end, | ||
+ | number = function(value) return value end, | ||
+ | boolean = function(value) return tostring(value) end, | ||
+ | ['nil'] = function(value) return 'nil' end, | ||
+ | ['function'] = function(value) | ||
+ | return string_format("load(%q)", string_dump(value)) | ||
+ | end, | ||
+ | userdata = function(value) | ||
+ | --if value.getId ~= nil then | ||
+ | -- return value:getId().id .. " " .. value:getName() | ||
+ | --else | ||
+ | -- return "userdata" | ||
+ | --end | ||
+ | end, | ||
+ | thread = function() error("Cannot dump threads") end, | ||
+ | } | ||
+ | local function test_defined(value, path) | ||
+ | if defined[value] then | ||
+ | if path:match("^getmetatable.*%)$") then | ||
+ | out[#out+1] = string_format("s%s, %s)\n", path:sub(2,-2), defined[value]) | ||
+ | else | ||
+ | out[#out+1] = path .. " = " .. defined[value] .. "\n" | ||
+ | end | ||
+ | return true | ||
+ | end | ||
+ | defined[value] = path | ||
+ | end | ||
+ | local function make_key(t, key) | ||
+ | local s | ||
+ | if type(key) == 'string' and key:match('^[_%a][_%w]*$') then | ||
+ | s = key .. "=" | ||
+ | else | ||
+ | s = "[" .. dumplua(key, 0) .. "]=" | ||
+ | end | ||
+ | t[key] = s | ||
+ | return s | ||
+ | end | ||
+ | for _,k in ipairs(lua_reserved_keywords) do | ||
+ | keycache[k] = '["'..k..'"] = ' | ||
+ | end | ||
+ | if fastmode then | ||
+ | fcts.table = function (value) | ||
+ | -- Table value | ||
+ | local numidx = 1 | ||
+ | out[#out+1] = "{" | ||
+ | for key,val in pairs(value) do | ||
+ | if key == numidx then | ||
+ | numidx = numidx + 1 | ||
+ | else | ||
+ | out[#out+1] = keycache[key] | ||
+ | end | ||
+ | local str = dumplua(val) | ||
+ | out[#out+1] = str.."," | ||
+ | end | ||
+ | if string.sub(out[#out], -1) == "," then | ||
+ | out[#out] = string.sub(out[#out], 1, -2); | ||
+ | end | ||
+ | out[#out+1] = "}" | ||
+ | return "" | ||
+ | end | ||
+ | else | ||
+ | fcts.table = function (value, ident, path) | ||
+ | if test_defined(value, path) then return "nil" end | ||
+ | -- Table value | ||
+ | local sep, str, numidx, totallen = " ", {}, 1, 0 | ||
+ | local meta, metastr = (debug or getfenv()).getmetatable(value) | ||
+ | if meta then | ||
+ | ident = ident + 1 | ||
+ | metastr = dumplua(meta, ident, "getmetatable("..path..")") | ||
+ | totallen = totallen + #metastr + 16 | ||
+ | end | ||
+ | for _,key in pairs(keys(value)) do | ||
+ | local val = value[key] | ||
+ | local s = "" | ||
+ | local subpath = path | ||
+ | if key == numidx then | ||
+ | subpath = subpath .. "[" .. numidx .. "]" | ||
+ | numidx = numidx + 1 | ||
+ | else | ||
+ | s = keycache[key] | ||
+ | if not s:match "^%[" then subpath = subpath .. "." end | ||
+ | subpath = subpath .. s:gsub("%s*=%s*$","") | ||
+ | end | ||
+ | local res = dumplua(val, ident+1, subpath) | ||
+ | if res ~= nil then | ||
+ | s = s .. res | ||
+ | end | ||
+ | str[#str+1] = s | ||
+ | totallen = totallen + #s + 2 | ||
+ | end | ||
+ | if totallen > 80 then | ||
+ | sep = "\n" .. string_rep(" ", ident+1) | ||
+ | end | ||
+ | str = "{"..sep..table_concat(str, ","..sep).." "..sep:sub(1,-3).."}" | ||
+ | if meta then | ||
+ | sep = sep:sub(1,-3) | ||
+ | return "setmetatable("..sep..str..","..sep..metastr..sep:sub(1,-3)..")" | ||
+ | end | ||
+ | return str | ||
+ | end | ||
+ | fcts['function'] = function (value, ident, path) | ||
+ | if test_defined(value, path) then return "nil" end | ||
+ | if c_functions[value] then | ||
+ | return c_functions[value] | ||
+ | elseif debug == nil or debug.getupvalue(value, 1) == nil then | ||
+ | return string_format("load(%q)", string_dump(value)) | ||
+ | end | ||
+ | closure_cnt = closure_cnt + 1 | ||
+ | local res = {string.dump(value)} | ||
+ | for i = 1,math.huge do | ||
+ | local name, v = debug.getupvalue(value,i) | ||
+ | if name == nil then break end | ||
+ | res[i+1] = v | ||
+ | end | ||
+ | print(res) | ||
+ | return "closure " .. dumplua(res, ident, "closures["..closure_cnt.."]") | ||
+ | end | ||
+ | end | ||
+ | function dumplua(value, ident, path) | ||
+ | return fcts[type(value)](value, ident, path) | ||
+ | end | ||
+ | if varname == nil then | ||
+ | varname = "return " | ||
+ | elseif varname:match("^[%a_][%w_]*$") then | ||
+ | varname = varname .. " = " | ||
+ | end | ||
+ | if fastmode then | ||
+ | setmetatable(keycache, {__index = make_key }) | ||
+ | out[1] = varname | ||
+ | table.insert(out,dumplua(value, 0)) | ||
+ | return table.concat(out) | ||
+ | else | ||
+ | setmetatable(keycache, {__index = make_key }) | ||
+ | local items = {} | ||
+ | for i=1,10 do items[i] = '' end | ||
+ | items[3] = dumplua(value, ident or 0, "t") | ||
+ | if closure_cnt > 0 then | ||
+ | items[1], items[6] = dumplua_closure:match("(.*\n)\n(.*)") | ||
+ | out[#out+1] = "" | ||
+ | end | ||
+ | if #out > 0 then | ||
+ | items[2], items[4] = "local t = ", "\n" | ||
+ | items[5] = table.concat(out) | ||
+ | items[7] = varname .. "t" | ||
+ | else | ||
+ | items[2] = varname | ||
+ | end | ||
+ | return table.concat(items) | ||
+ | end | ||
+ | end | ||
− | + | -- End of DataDumper | |
− | + | -- | |
− | + | -- Shader Metatable | |
− | |||
− | |||
− | + | shaders_compiled = {} | |
− | { | + | local shader_meta = {} |
− | return | + | local shader = {} |
− | + | function shader:new (this, id, file) | |
+ | local shader = {} | ||
+ | shader.num = shaderCompile(file) | ||
+ | shader.id = id | ||
+ | if shaders_compiled[id] == nil then | ||
+ | shaders_compiled[id] = {} | ||
+ | end | ||
+ | return setmetatable( shader, shader_meta ) | ||
+ | end | ||
+ | shader_meta.__call = function(this) | ||
+ | return this.num | ||
+ | end | ||
+ | shader_meta.__newindex = function(this, field, value) | ||
+ | shaders_compiled[this.id][field] = value | ||
+ | graphics.shaderUniform(this.num, field, value) | ||
+ | end | ||
+ | setmetatable( shader, { __call = function( ... ) return shader:new( ... ) end } ) | ||
+ | function tween(val,newval,delay,ease) | ||
+ | startTween(val, _G[val], newval, delay,ease) | ||
+ | end | ||
− | + | shaders = { | |
− | { | + | _temporary_=0, c_scene = game.CurrentScene, |
− | + | glownum = shader("glow","sht_glow.bin"), | |
− | + | rglownum = shader("rglow","sht_glowradial.bin"), | |
− | + | bnum = shader("blur","sht_blur.bin"), | |
− | + | num = shader("num","sht_color.bin") | |
− | + | } | |
− | |||
− | |||
− | + | shader_coeff0=0 | |
− | + | shader_coeff1=1 | |
+ | shader_coeff2=1 | ||
+ | shader_coeff3=0 | ||
+ | shader_blur=0 | ||
+ | shader_downsize=1 | ||
+ | shader_colorize=0 | ||
+ | shader_color=0 | ||
+ | shader_iTime = 0 | ||
+ | shader_noise=0 | ||
+ | shader_noiseStrength=0.0 | ||
+ | shader_passes=2 | ||
+ | shader_active = true | ||
+ | shader_glow = 0 | ||
+ | shader_glowradius = 0 | ||
+ | shader_glowexp = 1 | ||
− | + | shader_rotate=0.0 | |
− | + | shader_scale = 1.0 | |
− | + | shader_offsetx = 0.0 | |
− | + | shader_offsety = 0.0 | |
+ | shader_follow = {on=0, name="", c_scale=1, easing = easeQuintOut, delay = 0} | ||
− | + | c_res=game.WindowResolution | |
− | |||
− | + | shaders.num.weights = {shader_colorize,shader_color} | |
− | + | shaders.num.shader_coeff = {shader_coeff0,shader_coeff1,shader_coeff2,shader_coeff3} | |
− | + | shaders.glownum.resolution = {c_res.x,c_res.y} | |
− | + | if graphics.isUpsideDown() then | |
− | + | shaders.bnum.upsideDown = 1.0 | |
+ | shaders.rglownum.upsideDown = 1.0 | ||
+ | shaders.glownum.upsideDown = 1.0 | ||
+ | else | ||
+ | shaders.glownum.upsideDown = 0.0 | ||
+ | shaders.bnum.upsideDown = 0.0 | ||
+ | shaders.rglownum.upsideDown = 0.0 | ||
+ | end | ||
+ | shaders.bnum.resolution = {c_res.x,c_res.y} | ||
− | + | -- * function that stops following specified character & resets camera back to default * -- | |
− | + | function shaderStopFollow(easing) | |
− | + | shader_follow.on = 0 | |
− | + | shaderViewport(1, 0, 0, 0, shader_follow.delay, easing) | |
− | + | unregisterEventHandler("mainLoop", "followCharacter") | |
− | + | end | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | -- * function that smoothly follows specified character * -- | |
− | + | function shaderFollowCharacter(name, c_scale, delay, easing) | |
− | + | if name == "" then name = game.CurrentCharacter:getName() end | |
+ | if shader_follow.on == 0 then registerEventHandler("mainLoop", "followCharacter") end | ||
+ | shader_follow.on = 1 | ||
+ | shader_follow.name = name | ||
+ | shader_follow.c_scale = c_scale | ||
+ | shader_follow.delay = delay | ||
+ | shader_follow.easing = easing or easeQuintOut | ||
+ | end | ||
− | + | function shaderZoomCharacter(name, c_scale, delay, easing) | |
− | + | local c_position={} | |
− | + | if(name=="")then | |
− | + | c_position=game.CurrentCharacter.Position | |
− | + | else | |
− | + | c_position=Characters[name].Position | |
− | + | end | |
− | + | local c_scroll=game.ScrollPosition | |
− | + | c_position.x=c_position.x-c_scroll.x | |
− | + | c_position.y=c_position.y-c_scroll.y | |
− | + | c_position.x=c_position.x-(c_res.x/c_scale/2) | |
− | } | + | c_position.y=c_position.y-(c_res.y/c_scale/1.2) |
− | + | c_position.x = math.min(math.max(0,c_position.x), game.CurrentScene.Sprite:getSize().x - c_res.x/c_scale) | |
− | + | c_position.y = math.min(math.max(0,c_position.y), game.CurrentScene.Sprite:getSize().y - c_res.y/c_scale) | |
− | + | shaderViewport(c_scale, c_position.x, c_position.y, 0, delay, easing) | |
− | + | end | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | / | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | function shaderZoomObject(object, c_scale, delay, easing) | |
− | + | local c_position=object.Position | |
− | + | local c_scroll=game.ScrollPosition | |
− | + | c_position.x=c_position.x-c_scroll.x | |
− | + | c_position.y=c_position.y-c_scroll.y | |
− | + | c_position.x=c_position.x-(c_res.x/c_scale/2) | |
− | + | c_position.y=c_position.y-(c_res.y/c_scale/1.2) | |
− | + | c_position.x = math.min(math.max(0,c_position.x), game.CurrentScene.Sprite:getSize().x - c_res.x/c_scale) | |
− | + | c_position.y = math.min(math.max(0,c_position.y), game.CurrentScene.Sprite:getSize().y - c_res.y/c_scale) | |
− | + | shaderViewport(c_scale, c_position.x, c_position.y, 0, delay, easing) | |
− | + | end | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | function shaderNoise(on, strength,delay) | |
− | + | shaders.num.noise = on | |
− | + | startTween("shader_noiseStrength", shader_noiseStrength, strength, delay,easeLinearInOut) | |
− | + | shader_noise=on | |
+ | end | ||
− | + | function shaderSaturation(factor, delay) | |
− | + | startTween("shader_coeff1",shader_coeff1,factor,delay,easeLinearInOut) | |
− | + | end | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | function shaderLightness(offset, delay) | |
− | + | startTween("shader_coeff3",shader_coeff3,offset,delay,easeLinearInOut) | |
+ | end | ||
− | + | function shaderContrast(contrast, delay) | |
− | + | startTween("shader_coeff2",shader_coeff2,contrast,delay,easeLinearInOut) | |
− | + | end | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | function shaderHue(target, delay) | |
− | + | startTween("shader_coeff0",shader_coeff0,target,delay,easeLinearInOut) | |
− | + | end | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | function shaderColorize(hue, strength, delay) | |
− | + | startTween("shader_colorize",shader_colorize,strength,delay,easeLinearIn) | |
− | + | shader_color=hue | |
− | + | end | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | shader_viewportTransition = 1.0 | |
− | + | shader_oldViewport = { x = 0.0, y=0.0, scale = 1.0, rotate = 0.0} | |
− | + | shader_newViewport = { x = 0.0, y=0.0, scale = 1.0, rotate = 0.0} | |
− | + | shader_interpolationPoint = {x=0.0, y=0.0} | |
− | + | function shaderViewportInterpolationPoint(x,y) | |
− | + | shader_interpolationPoint = {x=x, y=y} | |
− | + | end | |
− | + | function shaderViewport(zoom, x, y, rotation, delay, easing) | |
− | + | shader_viewportTransition = 0.0 | |
− | + | shader_oldViewport.x = shader_offsetx | |
− | + | shader_oldViewport.y = shader_offsety | |
− | + | shader_oldViewport.scale = shader_scale | |
− | + | shader_oldViewport.rotate = shader_rotate | |
− | + | shader_newViewport.x = x | |
− | + | shader_newViewport.y = y | |
− | + | shader_newViewport.scale = zoom | |
− | + | shader_newViewport.rotate = rotation | |
− | + | startTween("shader_viewportTransition", 0.0, 1.0, delay,easing) | |
− | + | currentlyZoomedParameters = { zoomFactor = zoom, x = x, y = y, rotationFactor = rotation } | |
− | + | if delay == 0 then return end | |
− | + | end | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | -- * allows you to pan the camera left or right * -- | |
− | + | function shaderPan(offset, delay, easing, axis) | |
− | + | if axis then | |
+ | startTween("shader_offsety", shader_offsety, offset, delay, easing) | ||
+ | else | ||
+ | startTween("shader_offsetx", shader_offsetx, offset, delay, easing) | ||
+ | end | ||
+ | end | ||
− | + | -- * allows you to zoom the camera in or out * -- | |
− | + | function shaderZoom(zoom, delay, easing) | |
− | + | startTween("shader_scale", shader_scale, zoom, delay, easing) | |
− | + | end | |
− | |||
− | |||
+ | -- * allows you to rotate the screen (w/ degree instead of pi) * -- | ||
+ | function shaderRotate(degree, delay, easing) | ||
+ | degree = (degree / 360 * 2 * 3.14) -- convert degree to pi | ||
+ | startTween("shader_rotate", shader_rotate, degree, delay, easing) | ||
+ | end | ||
− | + | -- * function that follows character; only active when loop enabled * -- | |
− | + | function followCharacter() | |
+ | shaderZoomCharacter(shader_follow.name, shader_follow.c_scale, shader_follow.delay, shader_follow.easing) | ||
+ | end | ||
− | + | shader_effects = {_temporary_=0, | |
− | + | transition={shader= "sht_transition.bin"} , | |
− | + | warp1={shader= "sht_warp1.bin"} , | |
− | + | light1={shader="sht_light.bin"}, | |
− | + | tv1 = {shader = "sht_tv1.bin"}, | |
− | + | ripple1 = {shader = "sht_ripple1.bin", vars={speed=0.2, speed_x=0.3, speed_y=0.3, intensity=0.0, frequency=6.0}}, | |
− | + | ripple2 = {shader = "sht_ripple2.bin"}, | |
− | + | ascii = {shader = "sht_ascii.bin"}, | |
− | + | edgeglow = {shader = "sht_edgeglow.bin"}, | |
− | + | chroma = {shader = "sht_chroma.bin"}, | |
− | + | ripple3 = {shader = "sht_ripple3.bin"}, | |
− | + | warp2 = {shader = "sht_warp2.bin"}, | |
− | + | ripple4 = {shader = "sht_ripple4.bin"}, | |
− | + | pearls={shader="sht_pearls.bin"}, | |
− | + | highlight={shader="sht_hightlight.bin"}, | |
− | + | fourbit={shader="sht_fourbit.bin"}, | |
− | + | tv2={shader="sht_tv2.bin"}, | |
− | + | tv3={shader="sht_tv3.bin"}, | |
− | } | + | tv4={shader="sht_tv4.bin"} |
+ | } | ||
− | + | function clamp(a,b,c) | |
− | |||
− | |||
− | function clamp(a,b,c) | ||
return math.min(math.max(a,b),c) | return math.min(math.max(a,b),c) | ||
− | end | + | end |
− | function modf(a) | + | function modf(a) |
local a,b = math.modf(a) | local a,b = math.modf(a) | ||
return b | return b | ||
− | end | + | end |
− | vector = {add = function(a,b) return {a[1]+b[1],a[2]+b[2],a[3]+b[3]} end, | + | --[[vector = |
− | sub = function(a,b) return {a[1]-b[1],a[2]-b[2],a[3]-b[3]} end, | + | { |
− | mult = function(a,b) return {a*b[1],a*b[2],a*b[3]} end, | + | add = function(a,b) return {a[1]+b[1],a[2]+b[2],a[3]+b[3]} end, |
− | abs = function(a) return {math.abs(a[1]),math.abs(a[2]),math.abs(a[3])} end, | + | sub = function(a,b) return {a[1]-b[1],a[2]-b[2],a[3]-b[3]} end, |
− | modf = function(a) return {modf(a[1]),modf(a[2]),modf(a[3])} end, | + | mult = function(a,b) return {a*b[1],a*b[2],a*b[3]} end, |
− | mix = function(a,b,c) return {a[1]*(1-c)+b[1]*c,a[2]*(1-c)+b[2]*c,a[3]*(1-c)+b[3]*c} end, | + | abs = function(a) return {math.abs(a[1]),math.abs(a[2]),math.abs(a[3])} end, |
− | clamp = function(a,b,c) return {clamp(a[1],b,c),clamp(a[2],b,c),clamp(a[3],b,c)} end } | + | modf = function(a) return {modf(a[1]),modf(a[2]),modf(a[3])} end, |
+ | mix = function(a,b,c) return {a[1]*(1-c)+b[1]*c,a[2]*(1-c)+b[2]*c,a[3]*(1-c)+b[3]*c} end, | ||
+ | clamp = function(a,b,c) return {clamp(a[1],b,c),clamp(a[2],b,c),clamp(a[3],b,c)} end | ||
+ | } | ||
− | function fromHSV(h, s, v) | + | function fromHSV(h, s, v) |
local K = {1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0} | local K = {1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0} | ||
local p = vector.abs(vector.sub(vector.mult(6.0,vector.modf(vector.add({h,h,h},{K[1],K[2],K[3]}))), {K[4],K[4],K[4]})) | local p = vector.abs(vector.sub(vector.mult(6.0,vector.modf(vector.add({h,h,h},{K[1],K[2],K[3]}))), {K[4],K[4],K[4]})) | ||
return vector.mult(v, vector.mix({K[1],K[1],K[1]}, vector.clamp(vector.sub(p,{K[1],K[1],K[1]}), 0.0, 1.0), s)) | return vector.mult(v, vector.mix({K[1],K[1],K[1]}, vector.clamp(vector.sub(p,{K[1],K[1],K[1]}), 0.0, 1.0), s)) | ||
− | end | + | end]] |
− | function standardparam(param, standard) | + | function standardparam(param, standard) |
if param==nil then | if param==nil then | ||
− | + | return standard | |
+ | else | ||
+ | return param | ||
+ | end | ||
+ | end | ||
+ | |||
+ | function shaderGlow(on, blurradius, alpha) | ||
+ | if on == 0 then | ||
+ | passesRemove(5,"glow") | ||
+ | shader_glow = on | ||
+ | shader_glowradius = blurradius | ||
+ | shader_glowexp = alpha | ||
else | else | ||
− | + | passesAdd(5,"glow",{{ shader = shaders.glownum(), source=1, target = 2, clear = 0, variable = "shaders.glownum._i_firstpass" }, | |
+ | { shader = shaders.glownum(), source=2, target = 1, clear = 0 }, | ||
+ | { shader = shaders.glownum(), source=1, target = 2, clear = 0 }, | ||
+ | { shader = shaders.glownum(), source=2, target = 1, clear = 0 }, | ||
+ | { shader = shaders.glownum(), source=1, target = 2, clear = 0 }, | ||
+ | { shader = shaders.glownum(), source=2, target = 1, clear = 0 }, | ||
+ | { shader = shaders.glownum(), source=1, target = 0, clear = 0, comp_dst=1, comp_src=1, variable = "shaders.glownum._i_lastpass" }}) -- 5 4 for cutout | ||
+ | shader_glow = on | ||
+ | shader_glowradius = blurradius | ||
+ | shader_glowexp = alpha | ||
end | end | ||
− | end | + | end |
− | function | + | function shaderRadialGlow(on, blurradius, alpha) |
if on == 0 then | if on == 0 then | ||
− | + | passesRemove(6,"rglow") | |
− | + | shader_rglow = on | |
− | + | shader_rglowradius = blurradius | |
− | + | shader_rglowexp = alpha | |
else | else | ||
− | + | passesAdd(6,"rglow",{{ shader = shaders.rglownum(), source=1, target = 2, clear = 0, variable = "shaders.rglownum._i_firstpass" }, | |
− | + | { shader = shaders.rglownum(), source=2, target = 1, clear = 0 }, | |
− | + | { shader = shaders.rglownum(), source=1, target = 2, clear = 0 }, | |
− | + | { shader = shaders.rglownum(), source=2, target = 0, clear = 0, comp_dst=1, comp_src=1, variable = "shaders.rglownum._i_lastpass" }}) | |
− | + | shader_rglow = on | |
− | + | shader_rglowradius = blurradius | |
− | + | shader_rglowexp = alpha | |
− | |||
− | |||
− | |||
end | end | ||
− | end | + | end |
− | function shaderActivateLighting(lights) | + | function shaderActivateLighting(lights) |
if(shader_effects.light1.num==nil)then | if(shader_effects.light1.num==nil)then | ||
− | + | shader_effects.light1.num = shader("light1", shader_effects.light1.shader) | |
end | end | ||
+ | shader_effects.light1.num.resolution = {game.WindowResolution.x, game.WindowResolution.y} | ||
passesAdd(2,"light1",{ { shader = shader_effects.light1.num(), source=1, target = 2, clear = 0 } }) | passesAdd(2,"light1",{ { shader = shader_effects.light1.num(), source=1, target = 2, clear = 0 } }) | ||
local sh = shader_effects.light1.num | local sh = shader_effects.light1.num | ||
− | sh. | + | sh.lights_count = lights |
− | end | + | end |
− | function shaderDeactivateLighting() | + | function shaderDeactivateLighting() |
passesRemove(2,"light1") | passesRemove(2,"light1") | ||
− | end | + | end |
− | function table.join(t1, t2) | + | function table.join(t1, t2) |
local t3 = {} | local t3 = {} | ||
local offset = #t1 | local offset = #t1 | ||
− | for k,v in pairs(t1) do | + | for k,v in pairs(t1) do |
− | + | t3[k] = v | |
end | end | ||
− | for k,v in pairs(t2) do | + | for k,v in pairs(t2) do |
− | + | if(type(k)=="string")then | |
− | + | t3[k] = v | |
− | + | else | |
− | + | t3[offset + k] = v | |
− | + | end | |
end | end | ||
return t3 | return t3 | ||
− | end | + | end |
− | function shaderLamp(index, type, position, targetpos, falloff, ambient, diffuse, diffusefactor, exponent, cutoff) | + | function shaderLamp(index, type, position, targetpos, falloff, ambient, diffuse, diffusefactor, exponent, cutoff) |
− | |||
− | |||
− | |||
local l = "lights["..index.."]." | local l = "lights["..index.."]." | ||
position[3]=standardparam(position[3],1.0) | position[3]=standardparam(position[3],1.0) | ||
Line 1,311: | Line 861: | ||
sh[l.."diffusefactor"] = standardparam(diffusefactor,1) | sh[l.."diffusefactor"] = standardparam(diffusefactor,1) | ||
if type==0 then --point light | if type==0 then --point light | ||
− | + | sh[l.."exponent"] = standardparam(exponent,90) | |
− | + | sh[l.."cutoff"] = standardparam(cutoff,0) | |
end | end | ||
− | end | + | end |
− | -- * function that blurs the screen * -- | + | -- * function that blurs the screen * -- |
− | function shaderBlur(strength, delay) | + | function shaderBlur(strength, delay) |
− | passesAdd(2, "blur", {{ shader = shaders.bnum(), source=1, target = 2, clear = 0, variable = "shaders.bnum._i_firstpass" }, | + | passesAdd(2, "blur", { |
− | + | { shader = shaders.bnum(), source=1, target = 2, clear = 0, variable = "shaders.bnum._i_firstpass" }, | |
− | + | { shader = shaders.bnum(), source=2, target = 1, clear = 0}, | |
− | + | { shader = shaders.bnum(), source=1, target = 2, clear = 0 }, | |
− | + | { shader = shaders.bnum(), source=2, target = 1, clear = 0 }, | |
− | + | { shader = shaders.bnum(), source=1, target = 2, clear = 0 }, | |
+ | { shader = shaders.bnum(), source=2, target = 0, clear = 0, comp_dst=0, variable = "shaders.bnum._i_lastpass" }}) | ||
startTween("shader_blur",shader_blur,strength, delay,easeBackInOut) | startTween("shader_blur",shader_blur,strength, delay,easeBackInOut) | ||
− | end | + | end |
− | function shaderActivate() | + | function shaderActivate() |
shader_active = true | shader_active = true | ||
passesUpdate() | passesUpdate() | ||
− | end | + | end |
− | function shaderDeactivate() | + | function shaderDeactivate() |
shader_active = false | shader_active = false | ||
passesUpdate() | passesUpdate() | ||
− | end | + | end |
− | -- Passes | + | -- Passes |
− | shader_passes = { | + | shader_passes = { |
{"basic",{renderbuffers = 2, { shader = shaders.num(), source=0, target = 1 }}}, -- basic slot, hue, sat, lightness | {"basic",{renderbuffers = 2, { shader = shaders.num(), source=0, target = 1 }}}, -- basic slot, hue, sat, lightness | ||
{}, -- slot 2 takes many effects | {}, -- slot 2 takes many effects | ||
{}, -- slot 3 takes blur | {}, -- slot 3 takes blur | ||
{"composite", {{source = 1, target = 0 }}}, -- slot 4 takes compositing everything | {"composite", {{source = 1, target = 0 }}}, -- slot 4 takes compositing everything | ||
− | {} -- slot 5 is for glow | + | {}, -- slot 5 is for glow |
− | } | + | {} -- slot 6 is for radial glow |
+ | } | ||
+ | shader_slots = { | ||
+ | {shader = 0, comp_src = 5, comp_dst = 4} | ||
+ | } | ||
− | function passesRemove(position, id) | + | function passesRemove(position, id) |
if position==2 then -- effects slot | if position==2 then -- effects slot | ||
− | + | for k,v in pairs(shader_passes[2]) do | |
− | + | if(v[1]==id)then | |
− | + | table.remove(shader_passes[2], k) | |
− | + | break | |
− | + | end | |
− | + | end | |
else | else | ||
− | + | if shader_passes[position][1]==id then | |
− | + | shader_passes[position]={} | |
− | + | end | |
− | end | + | end |
passesUpdate() | passesUpdate() | ||
− | end | + | end |
− | function passesAdd(position, id, passes) | + | function passesAdd(position, id, passes) |
if position==2 then -- effects slot | if position==2 then -- effects slot | ||
− | + | local found = false | |
− | + | for k,v in pairs(shader_passes[2]) do | |
− | + | if(v[1]==id)then | |
− | + | found = true | |
− | |||
− | |||
− | |||
− | |||
end | end | ||
+ | end | ||
+ | if not found then | ||
+ | table.insert(shader_passes[2], {id, passes}) | ||
+ | end | ||
else | else | ||
− | + | if(shader_passes[position][1]==nil)then | |
− | + | shader_passes[position]={id, passes} | |
− | + | end | |
end | end | ||
passesUpdate() | passesUpdate() | ||
− | end | + | end |
+ | |||
+ | function passesUpdate() | ||
+ | for k,v in pairs(shaders_compiled) do | ||
+ | if(k~="glow" and k~="num" and k~="blur" and k~="rglow" and shader_effects[k].num==nil)then | ||
+ | shader_effects[k].num = shader(k, "", shader_effects[k].shader) | ||
+ | end | ||
+ | end | ||
− | |||
if shader_active == false then | if shader_active == false then | ||
− | + | shaderSetOptions({ { shader = shaders.num(), source=0, target = 0, clear = 0 } }) | |
else | else | ||
− | + | -- composite passes | |
− | + | local worktable = {} | |
− | + | local lastpass = 0 | |
− | + | for k,v in pairs(shader_passes) do | |
− | + | if(k==2)then | |
− | + | for k,v in pairs(shader_passes[2]) do | |
− | + | for i,v in pairs(shader_passes[2][k][2]) do | |
− | + | v.source = lastpass + 1 | |
− | + | lastpass = (lastpass + 1) % 2 | |
− | + | v.target = lastpass + 1 | |
− | + | end | |
− | + | worktable = table.join(worktable,v[2]) | |
+ | end | ||
+ | elseif v[2] ~= nil then | ||
+ | if k~=1 then | ||
+ | if k==5 or k==6 then | ||
+ | lastpass = (lastpass + 1) % 2 | ||
+ | end | ||
+ | for i,v in pairs(shader_passes[k][2]) do | ||
+ | if type(v)=="table" then | ||
+ | v.source = lastpass + 1 | ||
+ | lastpass = (lastpass + 1) % 2 | ||
+ | v.target = lastpass + 1 | ||
+ | if (k==4 or k==5 or k==6) and i==#shader_passes[k][2] then | ||
+ | v.target = 0 | ||
end | end | ||
− | + | end | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
end | end | ||
+ | end | ||
+ | worktable = table.join(worktable,v[2]) | ||
end | end | ||
− | + | end | |
− | + | for k,v in pairs(worktable) do | |
− | + | if type(v) == "table" and v.variable ~= nil then | |
− | + | load(v.variable.."="..(k-1))() | |
end | end | ||
− | + | end | |
+ | shaderSetOptions(worktable) | ||
end | end | ||
− | end | + | end |
− | function shaderAddEffect(name) | + | function shaderAddEffect(name, _table) |
if(shader_effects[name].num==nil)then | if(shader_effects[name].num==nil)then | ||
− | + | shader_effects[name].num = shader(name, shader_effects[name].shader) | |
+ | if shader_effects[name].vars~=nil then | ||
+ | for k,v in pairs(shader_effects[name].vars) do | ||
+ | shader_effects[name].num[k] = v | ||
+ | end | ||
+ | end | ||
end | end | ||
Line 1,435: | Line 1,001: | ||
local sh = shader_effects[name].num | local sh = shader_effects[name].num | ||
− | |||
− | |||
− | |||
sh.resolution = {game.WindowResolution.x, game.WindowResolution.y} | sh.resolution = {game.WindowResolution.x, game.WindowResolution.y} | ||
+ | bind(name, "time", field("shader_iTime")) | ||
+ | sh.strength=1 | ||
− | + | if _table~=nil then | |
− | end | + | for k,v in pairs(_table) do |
+ | sh[k] = v | ||
+ | end | ||
+ | end | ||
+ | end | ||
− | function shaderRemoveEffect(name) | + | function shaderRemoveEffect(name) |
passesRemove(2,name) | passesRemove(2,name) | ||
− | unbind( | + | unbind(name, "time") |
− | end | + | end |
− | function shaderEffectParam(name, param, value) | + | function shaderEffectParam(name, param, value) |
shader_effects[name].num[param] = value | shader_effects[name].num[param] = value | ||
− | end | + | end |
+ | |||
+ | function matrixFastInverse(mat) | ||
+ | local invers = mat * matrix:new({{1,0,0},{0,1,0},{0,0,1}}) | ||
+ | invers[1][3], invers[2][3] = invers[3][1], invers[3][2] | ||
+ | invers[3][1], invers[3][2] = 0,0 | ||
+ | invers[1][1] = 1 / invers[1][1] | ||
+ | invers[2][2] = 1 / invers[2][2] | ||
+ | invers[1][3] = - invers[1][3] * invers[1][1] | ||
+ | invers[2][3] = - invers[2][3] * invers[2][2] | ||
+ | return invers:transpose() | ||
+ | end | ||
− | function shaderMain() | + | function shaderMain() |
+ | if shaders.c_scene:getId().id~=game.CurrentScene:getId().id then | ||
+ | shaders.c_scene = game.CurrentScene | ||
+ | passesUpdate() | ||
+ | for k,v in pairs(shaders_compiled) do | ||
+ | local sh = shader_effects[k] | ||
+ | if sh ~= nil then | ||
+ | sh = sh.num | ||
+ | elseif k=="glow" then | ||
+ | sh = shaders.glownum | ||
+ | elseif k=="rglow" then | ||
+ | sh = shaders.rglownum | ||
+ | elseif k=="num" then | ||
+ | sh = shaders.num | ||
+ | elseif k=="blur" then | ||
+ | sh = shaders.bnum | ||
+ | end | ||
+ | for k,f in pairs(v) do | ||
+ | sh[k] = f | ||
+ | end | ||
+ | end | ||
+ | end | ||
shader_iTime=shader_iTime+0.0166 | shader_iTime=shader_iTime+0.0166 | ||
if(shader_iTime>2000)then | if(shader_iTime>2000)then | ||
− | + | shader_iTime=0 | |
end | end | ||
Line 1,463: | Line 1,064: | ||
shaders.num.shader_coeff={shader_coeff0,shader_coeff1,shader_coeff2,shader_coeff3} | shaders.num.shader_coeff={shader_coeff0,shader_coeff1,shader_coeff2,shader_coeff3} | ||
− | if shader_blur==0 and | + | if shader_blur==0 and #(shader_passes[3])==1 then |
− | + | passesRemove(2, "blur") | |
else | else | ||
− | + | local streng = math.max(shader_blur,0) | |
− | + | shaders.bnum.down = math.max(streng,1) | |
− | + | shaders.bnum.weights={math.min(streng,1)*0.15,1-math.min(streng,1)*(1-0.4)} | |
− | + | shaders.bnum.exposure = 1 | |
end | end | ||
if shader_glow == 1 then | if shader_glow == 1 then | ||
− | + | local streng = math.max(shader_glowradius,0) | |
− | + | shaders.glownum.down = math.max(streng,1) | |
− | + | shaders.glownum.weights={math.min(streng,1)*0.15,1-math.min(streng,1)*(1-0.4)} | |
− | + | shaders.glownum.exposure = shader_glowexp | |
end | end | ||
− | local rot = matrix{{math.cos(shader_rotate),math.sin(shader_rotate) | + | if shader_rglow == 1 then |
− | local scale = matrix{{shader_scale | + | local streng = math.max(shader_rglowradius,0) |
− | local translate = matrix{{ | + | shaders.rglownum.down = math.max(streng,1) |
− | local translate2 = matrix{{ | + | shaders.rglownum.weights={math.min(streng,1)*0.15,1-math.min(streng,1)*(1-0.4)} |
− | local translate3 = matrix{{ | + | shaders.rglownum.exposure = shader_rglowexp |
− | local | + | end |
− | + | ||
+ | if shader_viewportTransition > 0.0 and shader_viewportTransition < 1.0 then | ||
+ | shader_scale = (1.0 -shader_viewportTransition) * shader_oldViewport.scale + shader_viewportTransition * shader_newViewport.scale | ||
+ | shader_rotate = (1.0 -shader_viewportTransition) * shader_oldViewport.rotate + shader_viewportTransition * shader_newViewport.rotate | ||
+ | |||
+ | local startCenter = {x = shader_oldViewport.x + c_res.x / shader_oldViewport.scale * shader_interpolationPoint.x, | ||
+ | y = shader_oldViewport.y + c_res.y / shader_oldViewport.scale * shader_interpolationPoint.y} | ||
+ | local endCenter = {x = shader_newViewport.x + c_res.x / shader_newViewport.scale * shader_interpolationPoint.x, | ||
+ | y = shader_newViewport.y + c_res.y / shader_newViewport.scale * shader_interpolationPoint.y} | ||
+ | local interpolatedCenter = {x = startCenter.x * (1.0 -shader_viewportTransition) + endCenter.x * shader_viewportTransition, | ||
+ | y = startCenter.y * (1.0 -shader_viewportTransition) + endCenter.y * shader_viewportTransition} | ||
+ | |||
+ | shader_offsetx = interpolatedCenter.x - c_res.x / shader_scale * shader_interpolationPoint.x | ||
+ | shader_offsety = interpolatedCenter.y - c_res.y / shader_scale * shader_interpolationPoint.y | ||
+ | |||
+ | elseif shader_viewportTransition == 1.0 then | ||
+ | shader_offsetx = shader_newViewport.x | ||
+ | shader_offsety = shader_newViewport.y | ||
+ | shader_scale = shader_newViewport.scale | ||
+ | shader_rotate = shader_newViewport.rotate | ||
+ | shader_viewportTransition = 0.0 | ||
+ | end | ||
+ | |||
+ | local rot = matrix{{math.cos(shader_rotate),math.sin(shader_rotate),0},{-math.sin(shader_rotate),math.cos(shader_rotate),0},{0,0,1}} | ||
+ | local scale = matrix{{shader_scale,0,0},{0,shader_scale,0},{0,0,1}} | ||
+ | local translate = matrix{{1,0,0},{0,1,0},{-c_res.x/2,-c_res.y/2,1}} | ||
+ | local translate2 = matrix{{1,0,0},{0,1,0},{c_res.x/2,c_res.y/2,1}} | ||
+ | local translate3 = matrix{{1,0,0},{0,1,0},{-shader_offsetx/shader_downsize,-shader_offsety/shader_downsize,1}} | ||
+ | |||
+ | local cam_mat = ((((translate*rot)*translate2)*translate3)*scale) | ||
+ | graphics.matrix1 = cam_mat:tofloat() | ||
+ | graphics.invMatrix1 = matrixFastInverse(cam_mat):tofloat() | ||
+ | graphics.textMatrix = cam_mat:tofloat() | ||
if(binding~=nil)then | if(binding~=nil)then | ||
− | + | for k,v in pairs(binding.binding) do | |
− | + | if(v[3]==nil)then | |
+ | if(v[4]=="")then | ||
+ | binding = {active=false, binding = {}} | ||
+ | break | ||
+ | end | ||
+ | v[3]=load(v[4]:fromhex())() | ||
end | end | ||
+ | shader_effects[v[1]].num[v[2]] = v[3]() | ||
+ | end | ||
end | end | ||
− | end | + | end |
− | registerEventHandler("mainLoop", "shaderMain") | + | registerEventHandler("mainLoop", "shaderMain") |
− | shaderMain() | + | shaderMain() |
− | passesUpdate() | + | passesUpdate() |
− | --- BINDING LIB | + | --- BINDING LIB |
− | binding = {active=false, binding = {}} | + | binding = {active=false, binding = {}} |
− | cursor = function() | + | cursor = function() |
− | + | return getCursorPos() | |
− | end | + | end |
− | function inteval(a) | + | function inteval(a) |
if(type(a)=="function")then | if(type(a)=="function")then | ||
− | + | return a() | |
else | else | ||
− | + | return a | |
end | end | ||
− | end | + | end |
− | function pointeval(a, b, c) | + | function pointeval(a, b, c) |
local a = inteval(a) | local a = inteval(a) | ||
if(type(a)=="table")then | if(type(a)=="table")then | ||
− | + | if(a.x~=nil)then | |
− | + | if(b~=nil)then | |
− | + | return {a.x,a.y,inteval(b)} | |
− | + | else | |
− | + | return {a.x,a.y} | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
end | end | ||
− | + | else if(a[0]~=nil)then | |
− | + | if(c~=nil)then | |
− | + | return {a[0],a[1],inteval(c)} | |
− | |||
− | |||
− | |||
− | |||
− | |||
else | else | ||
− | + | return {a[0],a[1]} | |
− | |||
− | |||
− | |||
− | |||
end | end | ||
+ | end | ||
end | end | ||
+ | else | ||
+ | local b = inteval(b) | ||
+ | if(type(b)=="table")then | ||
+ | if(b.x~=nil)then | ||
+ | return {a,b.x,b.y} | ||
+ | else | ||
+ | return {a,b[0],b[1]} | ||
+ | end | ||
+ | else | ||
+ | if(c~=nil)then | ||
+ | return {a, b, inteval(c)} | ||
+ | else | ||
+ | return {a, b} | ||
+ | end | ||
+ | end | ||
+ | end | ||
end | end | ||
− | function | + | function shaderPoint(a, b, c) |
− | + | return function () | |
− | + | return pointeval(a,b,c) | |
− | + | end | |
end | end | ||
function field(a) | function field(a) | ||
− | + | return load("return function() return "..a.." end")() | |
end | end | ||
function inverty(a) | function inverty(a) | ||
− | + | return function() | |
− | + | local pos = inteval(a) | |
− | + | if not graphics.isUpsideDown() then | |
− | + | pos.y = c_res.y-pos.y | |
− | + | end | |
+ | return pos | ||
+ | end | ||
end | end | ||
function scrollfix(a) | function scrollfix(a) | ||
− | + | return function() | |
− | + | local pos = inteval(a) | |
− | + | local scroll = game.ScrollPosition | |
− | + | pos.x = pos.x - scroll.x | |
− | + | pos.y = pos.y - scroll.y | |
− | + | return pos | |
− | + | end | |
end | end | ||
function bind(shader, name, source) | function bind(shader, name, source) | ||
− | + | local t = string.dump(source) | |
+ | table.insert(binding.binding, {shader, name, source, t:tohex()}) | ||
end | end | ||
function unbind(shader, name) | function unbind(shader, name) | ||
− | + | for k,v in pairs(binding.binding) do | |
− | + | if v[2] == name and v[1] == shader then | |
− | + | table.remove(binding.binding, k) | |
− | + | break | |
− | |||
end | end | ||
+ | end | ||
end | end | ||
function offset(a,b) | function offset(a,b) | ||
− | + | return function() | |
− | + | local pos = inteval(a) | |
− | + | pos.x = pos.x + b[1] | |
− | + | pos.y = pos.y + b[2] | |
− | + | return pos | |
− | + | end | |
end | end | ||
function dist(a,b) | function dist(a,b) | ||
− | + | return function() | |
− | + | local a = inteval(a) | |
− | + | local b = inteval(b) | |
− | + | a.x = a.x - b.x | |
− | + | a.y = a.y - b.y | |
− | + | return math.sqrt(a.x*a.x + a.y*a.y) | |
− | + | end | |
end | end | ||
function factor(a,b) | function factor(a,b) | ||
− | + | return function() | |
− | + | return inteval(a)*b | |
− | + | end | |
end | end | ||
+ | |||
+ | |||
+ | shader_effects["lut"] = {shader="sht_lut.bin"} | ||
+ | |||
+ | --[[shader_effects["fisheye"] = {shader=basic_fsh.. | ||
+ | uniform float amount; | ||
+ | |||
+ | void mainImage( out vec4 fragColor, in vec2 fragCoord ) | ||
+ | { | ||
+ | vec2 p = fragCoord.xy / iResolution.x;//normalized coords with some cheat | ||
+ | //(assume 1:1 prop) | ||
+ | float prop = iResolution.x / iResolution.y;//screen proroption | ||
+ | vec2 m = vec2(0.5, 0.5 / prop);//center coords | ||
+ | vec2 d = p - m;//vector from center to current fragment | ||
+ | float r = sqrt(dot(d, d)); // distance of pixel from center | ||
+ | |||
+ | float power = ( 2.0 * 3.141592 / (2.0 * sqrt(dot(m, m))) ) * | ||
+ | (amount - 0.5);//amount of effect | ||
+ | |||
+ | float bind;//radius of 1:1 effect | ||
+ | if (power > 0.0) bind = sqrt(dot(m, m));//stick to corners | ||
+ | else {if (prop < 1.0) bind = m.x; else bind = m.y;}//stick to borders | ||
+ | |||
+ | //Weird formulas | ||
+ | vec2 uv; | ||
+ | if (power > 0.0)//fisheye | ||
+ | uv = m + normalize(d) * tan(r * power) * bind / tan( bind * power); | ||
+ | else if (power < 0.0)//antifisheye | ||
+ | uv = m + normalize(d) * atan(r * -power * 10.0) * bind / atan(-power * bind * 10.0); | ||
+ | else uv = p;//no effect for power = 1.0 | ||
+ | |||
+ | vec3 col = texture2D(iChannel0, vec2(uv.x, uv.y * prop)).xyz;//Second part of cheat | ||
+ | //for round effect, not elliptical | ||
+ | fragColor = vec4(col, 1.0); | ||
+ | } | ||
+ | |||
+ | void main() | ||
+ | { | ||
+ | vec4 color; | ||
+ | mainImage(color, texcoord.xy*iResolution.xy); | ||
+ | gl_FragColor = color; | ||
+ | } | ||
+ | }]] | ||
</syntaxhighlight> | </syntaxhighlight> | ||
+ | |||
== Resources == | == Resources == | ||
Line 1,608: | Line 1,295: | ||
! style="text-align:left" | Name !! style="text-align:left" | Description | ! style="text-align:left" | Name !! style="text-align:left" | Description | ||
|- | |- | ||
− | | [ | + | | [https://www.visionaire-studio.com/luadocs/#finished-scripts shader toolkit (VS5+)] || ''Visionaire Studio 5.0.8+ is required''. |
− | |} | + | |}{{toc}} |
− | {{toc}} |
Latest revision as of 10:58, 9 August 2023
Name | Version | Type | By |
---|---|---|---|
Shader Toolkit | 0.96 | Definition | Simon Scheckel, with edits by AFRLme |
This script offers some easy functions to use shader power. It ranges from blur, noise, saturation, contrast, lightness, colorize to some simple camera controls. Visionaire Studio 5.x is required to run this script.
Quick note: The script on here may be outdated, please download the latest version for 5.x from the resources section at the bottom of the page. |
Instructions
1. Add the main script to the Visionaire Studio Script Editor & set the script as a definition script.
2. Call the functions you need.
Shader Toolkit Functions
Function Name | Description |
---|---|
shaderAddEffect() | Add various dynamic pre-made warp effects to the screen. |
shaderBlur() | Blur/Focus the screen over x amount of milliseconds. |
shaderColorize() | Tint all the graphics on the screen a specific color over x amount of milliseconds. |
shaderContrast() | Set the global contrast level of the screen over x amount of milliseconds. |
shaderFollowCharacter() | Softly follow the linked character around the screen. |
shaderGlow() | Create a glow effect on light/saturated scene objects (automatically selected) over x amount of milliseconds. |
shaderHue() | Adjust the hue level of the screen over x amount of milliseconds. |
shaderLightness() | Adjust the lightness of the screen over x amount of milliseconds. |
shaderNoise() | Apply noise effect to the screen over x amount of milliseconds. |
shaderPan() | Pan the camera on the x or y axis over x amount of milliseconds. |
shaderRotate() | Rotate the screen over x amount of milliseconds. |
shaderSaturation() | Adjust saturation value of the screen over x amount of milliseconds. |
shaderViewport() | Pan, zoom & rotate the camera over x amount of milliseconds. |
shaderZoom() | Zoom the camera over x amount of milliseconds. |
shaderZoomCharacter() | Zoom camera into or out of linked characters position over x amount of milliseconds. |
shaderZoomObject() | Zoom camera into or out of linked objects location over x amount of milliseconds. |
Examples
shaderZoomCharacter("", 1.2, 3000, easeBackOut) -- Zoom 1.2x on current character in 3s with one bounce
shaderZoomObject(getObject("Objects[pole]"), 1.4, 3000, easeBounceOut)
shaderFollowCharacter("Heinz", 2, 3000, easeQuintOut) -- Follow character Heinz with a slow camera
shaderViewport(2, 300, 200, 1.41, 3000, easeBounceInOut) -- advanced zooming with rotating
shaderNoise(1, -0.1, 3000) -- activate noise in 3s with a soft black grain
shaderBlur(1, 3000) -- activate blur in 3s
shaderSaturation(0, 3000) -- desaturate image in 3s
shaderLightness(-0.5, 3000) -- darken image in 3s
shaderContrast(2, 3000) -- double contrast
shaderHue(0.5, 2000) -- turn hue wheel, red->green
shaderColorize(0, 1, 3000) -- colorize with red
Reset Values
shaderViewport(1, 0, 0, 0, 1000, easeQuintOut)
shaderStopFollow(easeQuintOut) -- Stop following character & reset viewport
shaderNoise(0, 0, 3000)
shaderBlur(0, 3000)
shaderSaturation(1, 3000)
shaderLightness(0, 3000)
shaderContrast(1, 3000)
shaderHue(0, 3000)
shaderColorize(0, 0, 3000)
Main Script
--[VISMODULE,id,version,chksum]
--
-- Shader Toolkit Hue, Saturation, Luminance, Blur, Noise, Camera Control, Bloom, Random Effects
-- (c) 2015 Simon Scheckel, Visionaire Studio Engine - with edits by AFRLme
-- Version 0.96
-- updated 29/09/2014 for 4.1
-- added some save functionality 9/10
-- bugfix version 16/10
-- update 10/6/15 radial glow, use per object matrices
-- update 3/2/16 cross platform shaders requires 4.3
-- update 28/9/18 lua 5.3
--
-- Matrix functions from https://github.com/davidm/lua-matrix/blob/master/lua/matrix.lua
-- Developers: Michael Lutz (chillcode) - original author David Manura http://lua-users.org/wiki/DavidManura
--
-- Usage:
--
-- all factors like zoom, scale are normally 1 to have no change
-- delay in ms
-- hue in 0-1 (0 = red, 0.5 = cyan, 1 = red again)
--
-- easing functions: Back, Bounce, Circ, Cubic, Elastic, Linear, None, Quad, Quint, Sine, all In/Out/InOut
-- examples: easeBackOut, easeLinearIn, easeElasticInOut etc
-- More information about that: http://easings.net
--
-- shaderZoomCharacter(name, c_scale, delay, easing)
-- shaderZoomObject(object, c_scale, delay, easing)
-- shaderFollowCharacter(name, c_scale, delay)
-- shaderStopFollow()
-- shaderViewportInterpolationPoint(x,y)
-- shaderViewport(zoom, x, y, rotation, delay, easing) rotation in 0-2Pi (full turn)
-- shaderPan(offset, delay, easing, axis)
-- shaderRotate(degree, delay, easing) -- degree values 0 to 359 (automatically converts value to Pi)
-- shaderZoom(zoom, delay, easing)
-- on: 1 = on, 0 = off
--
-- shaderNoise(on, strength, delay) -- strength * noise + color, so strength < 0 creates black noise and > 0 white
-- shaderBlur(radius, delay)
-- shaderSaturation(factor, delay)
-- shaderLightness(offset, delay)
-- shaderContrast(contrast, delay)
-- shaderHue(target, delay)
-- shaderColorize(hue, strength, delay)
--
-- shaderActivate()
-- shaderDeactivate()
--
-- shaderGlow(on, radius, exposure)
-- shaderAddEffect(name)
-- shaderRemoveEffect(name)
-- shaderEffectParam(shader, name, value)
-- shaderLamp(index, type, position, targetpos, falloff, ambient, diffuse, diffusefactor, exponent, cutoff)
--
-- Effects at the time:
--[[
warp1
tv1
ripple1
ripple2
ascii
edgeglow
chroma
ripple3
warp2
ripple4
pearls
highlight
fourbit
tv2
tv3
tv4
--
-- Read no further if the word matrix multiplication frightens you
--]]
local matrix = {_TYPE='module', _NAME='matrix', _VERSION='0.2.11.20120416'}
local matrix_meta = { }
function matrix:new( rows, columns, value )
if type( rows ) == "table" then
if type(rows[1]) ~= "table" then
return setmetatable( {{rows[1]},{rows[2]},{rows[3]}},matrix_meta )
end
return setmetatable( rows,matrix_meta )
end
local mtx = {}
local value = value or 0
if columns == "I" then
for i = 1,rows do
mtx[i] = {}
for j = 1,rows do
if i == j then
mtx[i][j] = 1
else
mtx[i][j] = 0
end
end
end
else
for i = 1,rows do
mtx[i] = {}
for j = 1,columns do
mtx[i][j] = value
end
end
end
return setmetatable( mtx,matrix_meta )
end
function matrix.mul( m1, m2 )
local mtx = {}
for i = 1,#m1 do
mtx[i] = {}
for j = 1,#m2[1] do
local num = m1[i][1] * m2[1][j]
for n = 2,#m1[1] do
num = num + m1[i][n] * m2[n][j]
end
mtx[i][j] = num
end
end
return setmetatable( mtx, matrix_meta )
end
function matrix.type( mtx )
local e = mtx[1][1]
if type(e) == "table" then
if e.type then
return e:type()
end
return "tensor"
end
return "number"
end
local num_copy = function( num )
return num
end
local t_copy = function( t )
local newt = setmetatable( {}, getmetatable( t ) )
for i,v in ipairs( t ) do
newt[i] = v
end
return newt
end
function matrix.transpose( m1 )
local docopy = matrix.type( m1 ) == "number" and num_copy or t_copy
local mtx = {}
for i = 1,#m1[1] do
mtx[i] = {}
for j = 1,#m1 do
mtx[i][j] = docopy( m1[j][i] )
end
end
return setmetatable( mtx, matrix_meta )
end
function matrix.tofloat( m1 )
local mtx = {}
local pos = 1
for i = 1,#m1 do
for j = 1,#m1[1] do
mtx[pos] = m1[i][j]
pos=pos+1
end
end
return mtx
end
matrix_meta.__mul = matrix.mul
matrix_meta.__index = {tofloat = matrix.tofloat, transpose = matrix.transpose}
setmetatable( matrix, { __call = function( ... ) return matrix.new( ... ) end } )
-- End of matrix functions
function string.fromhex(str)
return (str:gsub('..', function (cc)
return string.char(tonumber(cc, 16))
end))
end
function string.tohex(str)
return (str:gsub('.', function (c)
return string.format('%02X', string.byte(c))
end))
end
--
-- Source: http://lua-users.org/wiki/DataDumper
--[[ DataDumper.lua
Copyright (c) 2007 Olivetti-Engineering SA
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
]]
local dumplua_closure = [[
local closures = {}
local function closure(t)
closures[#closures+1] = t
t[1] = assert(load(t[1]))
return t[1]
end
for _,t in pairs(closures) do
for i = 2,#t do
debug.setupvalue(t[1], i-1, t[i])
end
end
]]
local lua_reserved_keywords = {
'and', 'break', 'do', 'else', 'elseif', 'end', 'false', 'for',
'function', 'if', 'in', 'local', 'nil', 'not', 'or', 'repeat',
'return', 'then', 'true', 'until', 'while' }
local function keys(t)
local res = {}
local oktypes = { stringstring = true, numbernumber = true }
local function cmpfct(a,b)
if oktypes[type(a)..type(b)] then
return a < b
else
return type(a) < type(b)
end
end
for k in pairs(t) do
res[#res+1] = k
end
table.sort(res, cmpfct)
return res
end
local c_functions = {}
for _,lib in pairs{'_G', 'string', 'table', 'math',
'io', 'os', 'coroutine', 'package', 'debug'} do
local t = _G[lib] or {}
lib = lib .. "."
if lib == "_G." then lib = "" end
for k,v in pairs(t) do
if type(v) == 'function' and not pcall(string.dump, v) then
c_functions[v] = lib..k
end
end
end
function DataDumper(value, varname, fastmode, ident)
local defined, dumplua = {}
-- Local variables for speed optimization
local string_format, type, string_dump, string_rep =
string.format, type, string.dump, string.rep
-- local tostring, pairs, table_concat =
-- tostring, pairs, table.concat
local pairs, table_concat =
pairs, table.concat
local keycache, strvalcache, out, closure_cnt = {}, {}, {}, 0
setmetatable(strvalcache, {__index = function(t,value)
local res = string_format('%q', value)
t[value] = res
return res
end})
local fcts = {
string = function(value) return strvalcache[value] end,
number = function(value) return value end,
boolean = function(value) return tostring(value) end,
['nil'] = function(value) return 'nil' end,
['function'] = function(value)
return string_format("load(%q)", string_dump(value))
end,
userdata = function(value)
--if value.getId ~= nil then
-- return value:getId().id .. " " .. value:getName()
--else
-- return "userdata"
--end
end,
thread = function() error("Cannot dump threads") end,
}
local function test_defined(value, path)
if defined[value] then
if path:match("^getmetatable.*%)$") then
out[#out+1] = string_format("s%s, %s)\n", path:sub(2,-2), defined[value])
else
out[#out+1] = path .. " = " .. defined[value] .. "\n"
end
return true
end
defined[value] = path
end
local function make_key(t, key)
local s
if type(key) == 'string' and key:match('^[_%a][_%w]*$') then
s = key .. "="
else
s = "[" .. dumplua(key, 0) .. "]="
end
t[key] = s
return s
end
for _,k in ipairs(lua_reserved_keywords) do
keycache[k] = '["'..k..'"] = '
end
if fastmode then
fcts.table = function (value)
-- Table value
local numidx = 1
out[#out+1] = "{"
for key,val in pairs(value) do
if key == numidx then
numidx = numidx + 1
else
out[#out+1] = keycache[key]
end
local str = dumplua(val)
out[#out+1] = str..","
end
if string.sub(out[#out], -1) == "," then
out[#out] = string.sub(out[#out], 1, -2);
end
out[#out+1] = "}"
return ""
end
else
fcts.table = function (value, ident, path)
if test_defined(value, path) then return "nil" end
-- Table value
local sep, str, numidx, totallen = " ", {}, 1, 0
local meta, metastr = (debug or getfenv()).getmetatable(value)
if meta then
ident = ident + 1
metastr = dumplua(meta, ident, "getmetatable("..path..")")
totallen = totallen + #metastr + 16
end
for _,key in pairs(keys(value)) do
local val = value[key]
local s = ""
local subpath = path
if key == numidx then
subpath = subpath .. "[" .. numidx .. "]"
numidx = numidx + 1
else
s = keycache[key]
if not s:match "^%[" then subpath = subpath .. "." end
subpath = subpath .. s:gsub("%s*=%s*$","")
end
local res = dumplua(val, ident+1, subpath)
if res ~= nil then
s = s .. res
end
str[#str+1] = s
totallen = totallen + #s + 2
end
if totallen > 80 then
sep = "\n" .. string_rep(" ", ident+1)
end
str = "{"..sep..table_concat(str, ","..sep).." "..sep:sub(1,-3).."}"
if meta then
sep = sep:sub(1,-3)
return "setmetatable("..sep..str..","..sep..metastr..sep:sub(1,-3)..")"
end
return str
end
fcts['function'] = function (value, ident, path)
if test_defined(value, path) then return "nil" end
if c_functions[value] then
return c_functions[value]
elseif debug == nil or debug.getupvalue(value, 1) == nil then
return string_format("load(%q)", string_dump(value))
end
closure_cnt = closure_cnt + 1
local res = {string.dump(value)}
for i = 1,math.huge do
local name, v = debug.getupvalue(value,i)
if name == nil then break end
res[i+1] = v
end
print(res)
return "closure " .. dumplua(res, ident, "closures["..closure_cnt.."]")
end
end
function dumplua(value, ident, path)
return fcts[type(value)](value, ident, path)
end
if varname == nil then
varname = "return "
elseif varname:match("^[%a_][%w_]*$") then
varname = varname .. " = "
end
if fastmode then
setmetatable(keycache, {__index = make_key })
out[1] = varname
table.insert(out,dumplua(value, 0))
return table.concat(out)
else
setmetatable(keycache, {__index = make_key })
local items = {}
for i=1,10 do items[i] = '' end
items[3] = dumplua(value, ident or 0, "t")
if closure_cnt > 0 then
items[1], items[6] = dumplua_closure:match("(.*\n)\n(.*)")
out[#out+1] = ""
end
if #out > 0 then
items[2], items[4] = "local t = ", "\n"
items[5] = table.concat(out)
items[7] = varname .. "t"
else
items[2] = varname
end
return table.concat(items)
end
end
-- End of DataDumper
--
-- Shader Metatable
shaders_compiled = {}
local shader_meta = {}
local shader = {}
function shader:new (this, id, file)
local shader = {}
shader.num = shaderCompile(file)
shader.id = id
if shaders_compiled[id] == nil then
shaders_compiled[id] = {}
end
return setmetatable( shader, shader_meta )
end
shader_meta.__call = function(this)
return this.num
end
shader_meta.__newindex = function(this, field, value)
shaders_compiled[this.id][field] = value
graphics.shaderUniform(this.num, field, value)
end
setmetatable( shader, { __call = function( ... ) return shader:new( ... ) end } )
function tween(val,newval,delay,ease)
startTween(val, _G[val], newval, delay,ease)
end
shaders = {
_temporary_=0, c_scene = game.CurrentScene,
glownum = shader("glow","sht_glow.bin"),
rglownum = shader("rglow","sht_glowradial.bin"),
bnum = shader("blur","sht_blur.bin"),
num = shader("num","sht_color.bin")
}
shader_coeff0=0
shader_coeff1=1
shader_coeff2=1
shader_coeff3=0
shader_blur=0
shader_downsize=1
shader_colorize=0
shader_color=0
shader_iTime = 0
shader_noise=0
shader_noiseStrength=0.0
shader_passes=2
shader_active = true
shader_glow = 0
shader_glowradius = 0
shader_glowexp = 1
shader_rotate=0.0
shader_scale = 1.0
shader_offsetx = 0.0
shader_offsety = 0.0
shader_follow = {on=0, name="", c_scale=1, easing = easeQuintOut, delay = 0}
c_res=game.WindowResolution
shaders.num.weights = {shader_colorize,shader_color}
shaders.num.shader_coeff = {shader_coeff0,shader_coeff1,shader_coeff2,shader_coeff3}
shaders.glownum.resolution = {c_res.x,c_res.y}
if graphics.isUpsideDown() then
shaders.bnum.upsideDown = 1.0
shaders.rglownum.upsideDown = 1.0
shaders.glownum.upsideDown = 1.0
else
shaders.glownum.upsideDown = 0.0
shaders.bnum.upsideDown = 0.0
shaders.rglownum.upsideDown = 0.0
end
shaders.bnum.resolution = {c_res.x,c_res.y}
-- * function that stops following specified character & resets camera back to default * --
function shaderStopFollow(easing)
shader_follow.on = 0
shaderViewport(1, 0, 0, 0, shader_follow.delay, easing)
unregisterEventHandler("mainLoop", "followCharacter")
end
-- * function that smoothly follows specified character * --
function shaderFollowCharacter(name, c_scale, delay, easing)
if name == "" then name = game.CurrentCharacter:getName() end
if shader_follow.on == 0 then registerEventHandler("mainLoop", "followCharacter") end
shader_follow.on = 1
shader_follow.name = name
shader_follow.c_scale = c_scale
shader_follow.delay = delay
shader_follow.easing = easing or easeQuintOut
end
function shaderZoomCharacter(name, c_scale, delay, easing)
local c_position={}
if(name=="")then
c_position=game.CurrentCharacter.Position
else
c_position=Characters[name].Position
end
local c_scroll=game.ScrollPosition
c_position.x=c_position.x-c_scroll.x
c_position.y=c_position.y-c_scroll.y
c_position.x=c_position.x-(c_res.x/c_scale/2)
c_position.y=c_position.y-(c_res.y/c_scale/1.2)
c_position.x = math.min(math.max(0,c_position.x), game.CurrentScene.Sprite:getSize().x - c_res.x/c_scale)
c_position.y = math.min(math.max(0,c_position.y), game.CurrentScene.Sprite:getSize().y - c_res.y/c_scale)
shaderViewport(c_scale, c_position.x, c_position.y, 0, delay, easing)
end
function shaderZoomObject(object, c_scale, delay, easing)
local c_position=object.Position
local c_scroll=game.ScrollPosition
c_position.x=c_position.x-c_scroll.x
c_position.y=c_position.y-c_scroll.y
c_position.x=c_position.x-(c_res.x/c_scale/2)
c_position.y=c_position.y-(c_res.y/c_scale/1.2)
c_position.x = math.min(math.max(0,c_position.x), game.CurrentScene.Sprite:getSize().x - c_res.x/c_scale)
c_position.y = math.min(math.max(0,c_position.y), game.CurrentScene.Sprite:getSize().y - c_res.y/c_scale)
shaderViewport(c_scale, c_position.x, c_position.y, 0, delay, easing)
end
function shaderNoise(on, strength,delay)
shaders.num.noise = on
startTween("shader_noiseStrength", shader_noiseStrength, strength, delay,easeLinearInOut)
shader_noise=on
end
function shaderSaturation(factor, delay)
startTween("shader_coeff1",shader_coeff1,factor,delay,easeLinearInOut)
end
function shaderLightness(offset, delay)
startTween("shader_coeff3",shader_coeff3,offset,delay,easeLinearInOut)
end
function shaderContrast(contrast, delay)
startTween("shader_coeff2",shader_coeff2,contrast,delay,easeLinearInOut)
end
function shaderHue(target, delay)
startTween("shader_coeff0",shader_coeff0,target,delay,easeLinearInOut)
end
function shaderColorize(hue, strength, delay)
startTween("shader_colorize",shader_colorize,strength,delay,easeLinearIn)
shader_color=hue
end
shader_viewportTransition = 1.0
shader_oldViewport = { x = 0.0, y=0.0, scale = 1.0, rotate = 0.0}
shader_newViewport = { x = 0.0, y=0.0, scale = 1.0, rotate = 0.0}
shader_interpolationPoint = {x=0.0, y=0.0}
function shaderViewportInterpolationPoint(x,y)
shader_interpolationPoint = {x=x, y=y}
end
function shaderViewport(zoom, x, y, rotation, delay, easing)
shader_viewportTransition = 0.0
shader_oldViewport.x = shader_offsetx
shader_oldViewport.y = shader_offsety
shader_oldViewport.scale = shader_scale
shader_oldViewport.rotate = shader_rotate
shader_newViewport.x = x
shader_newViewport.y = y
shader_newViewport.scale = zoom
shader_newViewport.rotate = rotation
startTween("shader_viewportTransition", 0.0, 1.0, delay,easing)
currentlyZoomedParameters = { zoomFactor = zoom, x = x, y = y, rotationFactor = rotation }
if delay == 0 then return end
end
-- * allows you to pan the camera left or right * --
function shaderPan(offset, delay, easing, axis)
if axis then
startTween("shader_offsety", shader_offsety, offset, delay, easing)
else
startTween("shader_offsetx", shader_offsetx, offset, delay, easing)
end
end
-- * allows you to zoom the camera in or out * --
function shaderZoom(zoom, delay, easing)
startTween("shader_scale", shader_scale, zoom, delay, easing)
end
-- * allows you to rotate the screen (w/ degree instead of pi) * --
function shaderRotate(degree, delay, easing)
degree = (degree / 360 * 2 * 3.14) -- convert degree to pi
startTween("shader_rotate", shader_rotate, degree, delay, easing)
end
-- * function that follows character; only active when loop enabled * --
function followCharacter()
shaderZoomCharacter(shader_follow.name, shader_follow.c_scale, shader_follow.delay, shader_follow.easing)
end
shader_effects = {_temporary_=0,
transition={shader= "sht_transition.bin"} ,
warp1={shader= "sht_warp1.bin"} ,
light1={shader="sht_light.bin"},
tv1 = {shader = "sht_tv1.bin"},
ripple1 = {shader = "sht_ripple1.bin", vars={speed=0.2, speed_x=0.3, speed_y=0.3, intensity=0.0, frequency=6.0}},
ripple2 = {shader = "sht_ripple2.bin"},
ascii = {shader = "sht_ascii.bin"},
edgeglow = {shader = "sht_edgeglow.bin"},
chroma = {shader = "sht_chroma.bin"},
ripple3 = {shader = "sht_ripple3.bin"},
warp2 = {shader = "sht_warp2.bin"},
ripple4 = {shader = "sht_ripple4.bin"},
pearls={shader="sht_pearls.bin"},
highlight={shader="sht_hightlight.bin"},
fourbit={shader="sht_fourbit.bin"},
tv2={shader="sht_tv2.bin"},
tv3={shader="sht_tv3.bin"},
tv4={shader="sht_tv4.bin"}
}
function clamp(a,b,c)
return math.min(math.max(a,b),c)
end
function modf(a)
local a,b = math.modf(a)
return b
end
--[[vector =
{
add = function(a,b) return {a[1]+b[1],a[2]+b[2],a[3]+b[3]} end,
sub = function(a,b) return {a[1]-b[1],a[2]-b[2],a[3]-b[3]} end,
mult = function(a,b) return {a*b[1],a*b[2],a*b[3]} end,
abs = function(a) return {math.abs(a[1]),math.abs(a[2]),math.abs(a[3])} end,
modf = function(a) return {modf(a[1]),modf(a[2]),modf(a[3])} end,
mix = function(a,b,c) return {a[1]*(1-c)+b[1]*c,a[2]*(1-c)+b[2]*c,a[3]*(1-c)+b[3]*c} end,
clamp = function(a,b,c) return {clamp(a[1],b,c),clamp(a[2],b,c),clamp(a[3],b,c)} end
}
function fromHSV(h, s, v)
local K = {1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0}
local p = vector.abs(vector.sub(vector.mult(6.0,vector.modf(vector.add({h,h,h},{K[1],K[2],K[3]}))), {K[4],K[4],K[4]}))
return vector.mult(v, vector.mix({K[1],K[1],K[1]}, vector.clamp(vector.sub(p,{K[1],K[1],K[1]}), 0.0, 1.0), s))
end]]
function standardparam(param, standard)
if param==nil then
return standard
else
return param
end
end
function shaderGlow(on, blurradius, alpha)
if on == 0 then
passesRemove(5,"glow")
shader_glow = on
shader_glowradius = blurradius
shader_glowexp = alpha
else
passesAdd(5,"glow",{{ shader = shaders.glownum(), source=1, target = 2, clear = 0, variable = "shaders.glownum._i_firstpass" },
{ shader = shaders.glownum(), source=2, target = 1, clear = 0 },
{ shader = shaders.glownum(), source=1, target = 2, clear = 0 },
{ shader = shaders.glownum(), source=2, target = 1, clear = 0 },
{ shader = shaders.glownum(), source=1, target = 2, clear = 0 },
{ shader = shaders.glownum(), source=2, target = 1, clear = 0 },
{ shader = shaders.glownum(), source=1, target = 0, clear = 0, comp_dst=1, comp_src=1, variable = "shaders.glownum._i_lastpass" }}) -- 5 4 for cutout
shader_glow = on
shader_glowradius = blurradius
shader_glowexp = alpha
end
end
function shaderRadialGlow(on, blurradius, alpha)
if on == 0 then
passesRemove(6,"rglow")
shader_rglow = on
shader_rglowradius = blurradius
shader_rglowexp = alpha
else
passesAdd(6,"rglow",{{ shader = shaders.rglownum(), source=1, target = 2, clear = 0, variable = "shaders.rglownum._i_firstpass" },
{ shader = shaders.rglownum(), source=2, target = 1, clear = 0 },
{ shader = shaders.rglownum(), source=1, target = 2, clear = 0 },
{ shader = shaders.rglownum(), source=2, target = 0, clear = 0, comp_dst=1, comp_src=1, variable = "shaders.rglownum._i_lastpass" }})
shader_rglow = on
shader_rglowradius = blurradius
shader_rglowexp = alpha
end
end
function shaderActivateLighting(lights)
if(shader_effects.light1.num==nil)then
shader_effects.light1.num = shader("light1", shader_effects.light1.shader)
end
shader_effects.light1.num.resolution = {game.WindowResolution.x, game.WindowResolution.y}
passesAdd(2,"light1",{ { shader = shader_effects.light1.num(), source=1, target = 2, clear = 0 } })
local sh = shader_effects.light1.num
sh.lights_count = lights
end
function shaderDeactivateLighting()
passesRemove(2,"light1")
end
function table.join(t1, t2)
local t3 = {}
local offset = #t1
for k,v in pairs(t1) do
t3[k] = v
end
for k,v in pairs(t2) do
if(type(k)=="string")then
t3[k] = v
else
t3[offset + k] = v
end
end
return t3
end
function shaderLamp(index, type, position, targetpos, falloff, ambient, diffuse, diffusefactor, exponent, cutoff)
local l = "lights["..index.."]."
position[3]=standardparam(position[3],1.0)
targetpos[3]=standardparam(targetpos[3],10.0)
local sh = shader_effects["light1"].num
sh[l.."position"] = position
sh[l.."targetpos"] = targetpos
sh["_i_"..l.."type"] = type
sh[l.."lightfalloff"] = standardparam(falloff,{0.01,0.0001,0.0})
sh[l.."ambient"] = standardparam(ambient,{0,0,0})
sh[l.."diffuse"] = standardparam(diffuse,{1,1,1})
sh[l.."diffusefactor"] = standardparam(diffusefactor,1)
if type==0 then --point light
sh[l.."exponent"] = standardparam(exponent,90)
sh[l.."cutoff"] = standardparam(cutoff,0)
end
end
-- * function that blurs the screen * --
function shaderBlur(strength, delay)
passesAdd(2, "blur", {
{ shader = shaders.bnum(), source=1, target = 2, clear = 0, variable = "shaders.bnum._i_firstpass" },
{ shader = shaders.bnum(), source=2, target = 1, clear = 0},
{ shader = shaders.bnum(), source=1, target = 2, clear = 0 },
{ shader = shaders.bnum(), source=2, target = 1, clear = 0 },
{ shader = shaders.bnum(), source=1, target = 2, clear = 0 },
{ shader = shaders.bnum(), source=2, target = 0, clear = 0, comp_dst=0, variable = "shaders.bnum._i_lastpass" }})
startTween("shader_blur",shader_blur,strength, delay,easeBackInOut)
end
function shaderActivate()
shader_active = true
passesUpdate()
end
function shaderDeactivate()
shader_active = false
passesUpdate()
end
-- Passes
shader_passes = {
{"basic",{renderbuffers = 2, { shader = shaders.num(), source=0, target = 1 }}}, -- basic slot, hue, sat, lightness
{}, -- slot 2 takes many effects
{}, -- slot 3 takes blur
{"composite", {{source = 1, target = 0 }}}, -- slot 4 takes compositing everything
{}, -- slot 5 is for glow
{} -- slot 6 is for radial glow
}
shader_slots = {
{shader = 0, comp_src = 5, comp_dst = 4}
}
function passesRemove(position, id)
if position==2 then -- effects slot
for k,v in pairs(shader_passes[2]) do
if(v[1]==id)then
table.remove(shader_passes[2], k)
break
end
end
else
if shader_passes[position][1]==id then
shader_passes[position]={}
end
end
passesUpdate()
end
function passesAdd(position, id, passes)
if position==2 then -- effects slot
local found = false
for k,v in pairs(shader_passes[2]) do
if(v[1]==id)then
found = true
end
end
if not found then
table.insert(shader_passes[2], {id, passes})
end
else
if(shader_passes[position][1]==nil)then
shader_passes[position]={id, passes}
end
end
passesUpdate()
end
function passesUpdate()
for k,v in pairs(shaders_compiled) do
if(k~="glow" and k~="num" and k~="blur" and k~="rglow" and shader_effects[k].num==nil)then
shader_effects[k].num = shader(k, "", shader_effects[k].shader)
end
end
if shader_active == false then
shaderSetOptions({ { shader = shaders.num(), source=0, target = 0, clear = 0 } })
else
-- composite passes
local worktable = {}
local lastpass = 0
for k,v in pairs(shader_passes) do
if(k==2)then
for k,v in pairs(shader_passes[2]) do
for i,v in pairs(shader_passes[2][k][2]) do
v.source = lastpass + 1
lastpass = (lastpass + 1) % 2
v.target = lastpass + 1
end
worktable = table.join(worktable,v[2])
end
elseif v[2] ~= nil then
if k~=1 then
if k==5 or k==6 then
lastpass = (lastpass + 1) % 2
end
for i,v in pairs(shader_passes[k][2]) do
if type(v)=="table" then
v.source = lastpass + 1
lastpass = (lastpass + 1) % 2
v.target = lastpass + 1
if (k==4 or k==5 or k==6) and i==#shader_passes[k][2] then
v.target = 0
end
end
end
end
worktable = table.join(worktable,v[2])
end
end
for k,v in pairs(worktable) do
if type(v) == "table" and v.variable ~= nil then
load(v.variable.."="..(k-1))()
end
end
shaderSetOptions(worktable)
end
end
function shaderAddEffect(name, _table)
if(shader_effects[name].num==nil)then
shader_effects[name].num = shader(name, shader_effects[name].shader)
if shader_effects[name].vars~=nil then
for k,v in pairs(shader_effects[name].vars) do
shader_effects[name].num[k] = v
end
end
end
passesAdd(2,name,{ { shader = shader_effects[name].num(), source=0, target = 0, clear = 0 } })
local sh = shader_effects[name].num
sh.resolution = {game.WindowResolution.x, game.WindowResolution.y}
bind(name, "time", field("shader_iTime"))
sh.strength=1
if _table~=nil then
for k,v in pairs(_table) do
sh[k] = v
end
end
end
function shaderRemoveEffect(name)
passesRemove(2,name)
unbind(name, "time")
end
function shaderEffectParam(name, param, value)
shader_effects[name].num[param] = value
end
function matrixFastInverse(mat)
local invers = mat * matrix:new({{1,0,0},{0,1,0},{0,0,1}})
invers[1][3], invers[2][3] = invers[3][1], invers[3][2]
invers[3][1], invers[3][2] = 0,0
invers[1][1] = 1 / invers[1][1]
invers[2][2] = 1 / invers[2][2]
invers[1][3] = - invers[1][3] * invers[1][1]
invers[2][3] = - invers[2][3] * invers[2][2]
return invers:transpose()
end
function shaderMain()
if shaders.c_scene:getId().id~=game.CurrentScene:getId().id then
shaders.c_scene = game.CurrentScene
passesUpdate()
for k,v in pairs(shaders_compiled) do
local sh = shader_effects[k]
if sh ~= nil then
sh = sh.num
elseif k=="glow" then
sh = shaders.glownum
elseif k=="rglow" then
sh = shaders.rglownum
elseif k=="num" then
sh = shaders.num
elseif k=="blur" then
sh = shaders.bnum
end
for k,f in pairs(v) do
sh[k] = f
end
end
end
shader_iTime=shader_iTime+0.0166
if(shader_iTime>2000)then
shader_iTime=0
end
shaders.num.iTime = shader_iTime*0.1
shaders.num.noiseFactor=shader_noiseStrength
shaders.num.weights ={shader_colorize,shader_color}
shaders.num.shader_coeff={shader_coeff0,shader_coeff1,shader_coeff2,shader_coeff3}
if shader_blur==0 and #(shader_passes[3])==1 then
passesRemove(2, "blur")
else
local streng = math.max(shader_blur,0)
shaders.bnum.down = math.max(streng,1)
shaders.bnum.weights={math.min(streng,1)*0.15,1-math.min(streng,1)*(1-0.4)}
shaders.bnum.exposure = 1
end
if shader_glow == 1 then
local streng = math.max(shader_glowradius,0)
shaders.glownum.down = math.max(streng,1)
shaders.glownum.weights={math.min(streng,1)*0.15,1-math.min(streng,1)*(1-0.4)}
shaders.glownum.exposure = shader_glowexp
end
if shader_rglow == 1 then
local streng = math.max(shader_rglowradius,0)
shaders.rglownum.down = math.max(streng,1)
shaders.rglownum.weights={math.min(streng,1)*0.15,1-math.min(streng,1)*(1-0.4)}
shaders.rglownum.exposure = shader_rglowexp
end
if shader_viewportTransition > 0.0 and shader_viewportTransition < 1.0 then
shader_scale = (1.0 -shader_viewportTransition) * shader_oldViewport.scale + shader_viewportTransition * shader_newViewport.scale
shader_rotate = (1.0 -shader_viewportTransition) * shader_oldViewport.rotate + shader_viewportTransition * shader_newViewport.rotate
local startCenter = {x = shader_oldViewport.x + c_res.x / shader_oldViewport.scale * shader_interpolationPoint.x,
y = shader_oldViewport.y + c_res.y / shader_oldViewport.scale * shader_interpolationPoint.y}
local endCenter = {x = shader_newViewport.x + c_res.x / shader_newViewport.scale * shader_interpolationPoint.x,
y = shader_newViewport.y + c_res.y / shader_newViewport.scale * shader_interpolationPoint.y}
local interpolatedCenter = {x = startCenter.x * (1.0 -shader_viewportTransition) + endCenter.x * shader_viewportTransition,
y = startCenter.y * (1.0 -shader_viewportTransition) + endCenter.y * shader_viewportTransition}
shader_offsetx = interpolatedCenter.x - c_res.x / shader_scale * shader_interpolationPoint.x
shader_offsety = interpolatedCenter.y - c_res.y / shader_scale * shader_interpolationPoint.y
elseif shader_viewportTransition == 1.0 then
shader_offsetx = shader_newViewport.x
shader_offsety = shader_newViewport.y
shader_scale = shader_newViewport.scale
shader_rotate = shader_newViewport.rotate
shader_viewportTransition = 0.0
end
local rot = matrix{{math.cos(shader_rotate),math.sin(shader_rotate),0},{-math.sin(shader_rotate),math.cos(shader_rotate),0},{0,0,1}}
local scale = matrix{{shader_scale,0,0},{0,shader_scale,0},{0,0,1}}
local translate = matrix{{1,0,0},{0,1,0},{-c_res.x/2,-c_res.y/2,1}}
local translate2 = matrix{{1,0,0},{0,1,0},{c_res.x/2,c_res.y/2,1}}
local translate3 = matrix{{1,0,0},{0,1,0},{-shader_offsetx/shader_downsize,-shader_offsety/shader_downsize,1}}
local cam_mat = ((((translate*rot)*translate2)*translate3)*scale)
graphics.matrix1 = cam_mat:tofloat()
graphics.invMatrix1 = matrixFastInverse(cam_mat):tofloat()
graphics.textMatrix = cam_mat:tofloat()
if(binding~=nil)then
for k,v in pairs(binding.binding) do
if(v[3]==nil)then
if(v[4]=="")then
binding = {active=false, binding = {}}
break
end
v[3]=load(v[4]:fromhex())()
end
shader_effects[v[1]].num[v[2]] = v[3]()
end
end
end
registerEventHandler("mainLoop", "shaderMain")
shaderMain()
passesUpdate()
--- BINDING LIB
binding = {active=false, binding = {}}
cursor = function()
return getCursorPos()
end
function inteval(a)
if(type(a)=="function")then
return a()
else
return a
end
end
function pointeval(a, b, c)
local a = inteval(a)
if(type(a)=="table")then
if(a.x~=nil)then
if(b~=nil)then
return {a.x,a.y,inteval(b)}
else
return {a.x,a.y}
end
else if(a[0]~=nil)then
if(c~=nil)then
return {a[0],a[1],inteval(c)}
else
return {a[0],a[1]}
end
end
end
else
local b = inteval(b)
if(type(b)=="table")then
if(b.x~=nil)then
return {a,b.x,b.y}
else
return {a,b[0],b[1]}
end
else
if(c~=nil)then
return {a, b, inteval(c)}
else
return {a, b}
end
end
end
end
function shaderPoint(a, b, c)
return function ()
return pointeval(a,b,c)
end
end
function field(a)
return load("return function() return "..a.." end")()
end
function inverty(a)
return function()
local pos = inteval(a)
if not graphics.isUpsideDown() then
pos.y = c_res.y-pos.y
end
return pos
end
end
function scrollfix(a)
return function()
local pos = inteval(a)
local scroll = game.ScrollPosition
pos.x = pos.x - scroll.x
pos.y = pos.y - scroll.y
return pos
end
end
function bind(shader, name, source)
local t = string.dump(source)
table.insert(binding.binding, {shader, name, source, t:tohex()})
end
function unbind(shader, name)
for k,v in pairs(binding.binding) do
if v[2] == name and v[1] == shader then
table.remove(binding.binding, k)
break
end
end
end
function offset(a,b)
return function()
local pos = inteval(a)
pos.x = pos.x + b[1]
pos.y = pos.y + b[2]
return pos
end
end
function dist(a,b)
return function()
local a = inteval(a)
local b = inteval(b)
a.x = a.x - b.x
a.y = a.y - b.y
return math.sqrt(a.x*a.x + a.y*a.y)
end
end
function factor(a,b)
return function()
return inteval(a)*b
end
end
shader_effects["lut"] = {shader="sht_lut.bin"}
--[[shader_effects["fisheye"] = {shader=basic_fsh..
uniform float amount;
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 p = fragCoord.xy / iResolution.x;//normalized coords with some cheat
//(assume 1:1 prop)
float prop = iResolution.x / iResolution.y;//screen proroption
vec2 m = vec2(0.5, 0.5 / prop);//center coords
vec2 d = p - m;//vector from center to current fragment
float r = sqrt(dot(d, d)); // distance of pixel from center
float power = ( 2.0 * 3.141592 / (2.0 * sqrt(dot(m, m))) ) *
(amount - 0.5);//amount of effect
float bind;//radius of 1:1 effect
if (power > 0.0) bind = sqrt(dot(m, m));//stick to corners
else {if (prop < 1.0) bind = m.x; else bind = m.y;}//stick to borders
//Weird formulas
vec2 uv;
if (power > 0.0)//fisheye
uv = m + normalize(d) * tan(r * power) * bind / tan( bind * power);
else if (power < 0.0)//antifisheye
uv = m + normalize(d) * atan(r * -power * 10.0) * bind / atan(-power * bind * 10.0);
else uv = p;//no effect for power = 1.0
vec3 col = texture2D(iChannel0, vec2(uv.x, uv.y * prop)).xyz;//Second part of cheat
//for round effect, not elliptical
fragColor = vec4(col, 1.0);
}
void main()
{
vec4 color;
mainImage(color, texcoord.xy*iResolution.xy);
gl_FragColor = color;
}
}]]
Resources
Name | Description |
---|---|
shader toolkit (VS5+) | Visionaire Studio 5.0.8+ is required. |