Difference between revisions of "Shader (CMS)"

From The Official Visionaire Studio: Adventure Game Engine Wiki
m
 
(18 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 || SimonS
+
| 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 ==
Please see [[Compiled_Index_of_Lua_Scripts_for_Visionaire_Studio#Shader_Toolkit_Functions|here]] for a list of working 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) 2014 Simon Scheckel, Visionaire Studio Engine - with edits by AFRLme
+
-- (c) 2015 Simon Scheckel, Visionaire Studio Engine - with edits by AFRLme
-- Version 0.8.7 [updated 29/09/2014 for 4.1, added some save functionality 9/10, bugfix version 24/10/2014]
+
-- 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 94: Line 150:
 
warp1
 
warp1
 
tv1
 
tv1
ripple1  
+
ripple1
ripple2  
+
ripple2
 
ascii
 
ascii
 
edgeglow
 
edgeglow
 
chroma
 
chroma
ripple3  
+
ripple3
 
warp2
 
warp2
 
ripple4
 
ripple4
Line 116: Line 172:
  
 
function matrix:new( rows, columns, value )
 
function matrix:new( rows, columns, value )
        if type( rows ) == "table" then
+
  if type( rows ) == "table" then
                if type(rows[1]) ~= "table" then
+
    if type(rows[1]) ~= "table" then
                        return setmetatable( {{rows[1]},{rows[2]},{rows[3]}},matrix_meta )
+
      return setmetatable( {{rows[1]},{rows[2]},{rows[3]}},matrix_meta )
                end
+
    end
                return setmetatable( rows,matrix_meta )
+
    return setmetatable( rows,matrix_meta )
        end
+
  end
        local mtx = {}
+
  local mtx = {}
        local value = value or 0
+
  local value = value or 0
        if columns == "I" then
+
  if columns == "I" then
                for i = 1,rows do
+
    for i = 1,rows do
                        mtx[i] = {}
+
      mtx[i] = {}
                        for j = 1,rows do
+
      for j = 1,rows do
                                if i == j then
+
        if i == j then
                                        mtx[i][j] = 1
+
          mtx[i][j] = 1
                                else
 
                                        mtx[i][j] = 0
 
                                end
 
                        end
 
                end
 
 
         else
 
         else
                for i = 1,rows do
+
          mtx[i][j] = 0
                        mtx[i] = {}
 
                        for j = 1,columns do
 
                                mtx[i][j] = value
 
                        end
 
                end
 
 
         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 = {}
+
  local mtx = {}
        for i = 1,#m1 do
+
  for i = 1,#m1 do
                mtx[i] = {}
+
    mtx[i] = {}
                for j = 1,#m2[1] do
+
    for j = 1,#m2[1] do
                        local num = m1[i][1] * m2[1][j]
+
      local num = m1[i][1] * m2[1][j]
                        for n  = 2,#m1[1] do
+
      for n  = 2,#m1[1] do
                                num = num + m1[i][n] * m2[n][j]
+
        num = num + m1[i][n] * m2[n][j]
                        end
+
      end
                        mtx[i][j] = num
+
      mtx[i][j] = num
                end
+
    end
        end
+
  end
        return setmetatable( mtx, matrix_meta )
+
  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
 
end
  
 
function matrix.tofloat( m1 )
 
function matrix.tofloat( m1 )
        local mtx = {}
+
  local mtx = {}
        local pos = 1
+
  local pos = 1
        for i = 1,#m1 do
+
  for i = 1,#m1 do
                for j = 1,#m1[1] do
+
    for j = 1,#m1[1] do
                        mtx[pos] = m1[i][j]
+
      mtx[pos] = m1[i][j]
                        pos=pos+1
+
      pos=pos+1
                end
+
    end
        end
+
  end
        return mtx
+
  return mtx
 
end
 
end
  
 
matrix_meta.__mul = matrix.mul
 
matrix_meta.__mul = matrix.mul
matrix_meta.__index = {tofloat = matrix.tofloat}
+
matrix_meta.__index = {tofloat = matrix.tofloat, transpose = matrix.transpose}
  
 
setmetatable( matrix, { __call = function( ... ) return matrix.new( ... ) end } )
 
setmetatable( matrix, { __call = function( ... ) return matrix.new( ... ) end } )
Line 182: Line 272:
  
 
function string.fromhex(str)
 
function string.fromhex(str)
    return (str:gsub('..', function (cc)
+
  return (str:gsub('..', function (cc)
        return string.char(tonumber(cc, 16))
+
    return string.char(tonumber(cc, 16))
    end))
+
  end))
 
end
 
end
  
 
function string.tohex(str)
 
function string.tohex(str)
    return (str:gsub('.', function (c)
+
  return (str:gsub('.', function (c)
        return string.format('%02X', string.byte(c))
+
    return string.format('%02X', string.byte(c))
    end))
+
  end))
 
end
 
end
  
Line 223: Line 313:
 
local dumplua_closure = [[
 
local dumplua_closure = [[
 
local closures = {}
 
local closures = {}
local function closure(t)  
+
local function closure(t)
 
   closures[#closures+1] = t
 
   closures[#closures+1] = t
   t[1] = assert(loadstring(t[1]))
+
   t[1] = assert(load(t[1]))
 
   return t[1]
 
   return t[1]
 
end
 
end
  
 
for _,t in pairs(closures) do
 
for _,t in pairs(closures) do
   for i = 2,#t do  
+
   for i = 2,#t do
     debug.setupvalue(t[1], i-1, t[i])  
+
     debug.setupvalue(t[1], i-1, t[i])
   end  
+
   end
 
end
 
end
 
]]
 
]]
  
 
local lua_reserved_keywords = {
 
local lua_reserved_keywords = {
   'and', 'break', 'do', 'else', 'elseif', 'end', 'false', 'for',  
+
   'and', 'break', 'do', 'else', 'elseif', 'end', 'false', 'for',
   'function', 'if', 'in', 'local', 'nil', 'not', 'or', 'repeat',  
+
   'function', 'if', 'in', 'local', 'nil', 'not', 'or', 'repeat',
  'return', 'then', 'true', 'until', 'while' }
+
    'return', 'then', 'true', 'until', 'while' }
  
local function keys(t)
+
    local function keys(t)
  local res = {}
+
      local res = {}
  local oktypes = { stringstring = true, numbernumber = true }
+
      local oktypes = { stringstring = true, numbernumber = true }
  local function cmpfct(a,b)
+
      local function cmpfct(a,b)
    if oktypes[type(a)..type(b)] then
+
        if oktypes[type(a)..type(b)] then
      return a < b
+
          return a < b
    else
+
        else
      return type(a) < type(b)
+
          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
  end
 
  for k in pairs(t) do
 
    res[#res+1] = k
 
  end
 
  table.sort(res, cmpfct)
 
  return res
 
end
 
  
local c_functions = {}
+
    local c_functions = {}
for _,lib in pairs{'_G', 'string', 'table', 'math',  
+
    for _,lib in pairs{'_G', 'string', 'table', 'math',
 
     'io', 'os', 'coroutine', 'package', 'debug'} do
 
     'io', 'os', 'coroutine', 'package', 'debug'} do
  local t = _G[lib] or {}
+
      local t = _G[lib] or {}
  lib = lib .. "."
+
      lib = lib .. "."
  if lib == "_G." then lib = "" end
+
      if lib == "_G." then lib = "" end
  for k,v in pairs(t) do
+
      for k,v in pairs(t) do
    if type(v) == 'function' and not pcall(string.dump, v) then
+
        if type(v) == 'function' and not pcall(string.dump, v) then
      c_functions[v] = lib..k
+
          c_functions[v] = lib..k
 +
        end
 +
      end
 
     end
 
     end
  end
 
end
 
  
function DataDumper(value, varname, fastmode, ident)
+
    function DataDumper(value, varname, fastmode, ident)
  local defined, dumplua = {}
+
      local defined, dumplua = {}
  -- Local variables for speed optimization
+
      -- Local variables for speed optimization
  local string_format, type, string_dump, string_rep =  
+
      local string_format, type, string_dump, string_rep =
        string.format, type, string.dump, string.rep
+
      string.format, type, string.dump, string.rep
  local tostring, pairs, table_concat =  
+
      -- local tostring, pairs, table_concat =
        tostring, pairs, table.concat
+
      -- tostring, pairs, table.concat
  local keycache, strvalcache, out, closure_cnt = {}, {}, {}, 0
+
      local pairs, table_concat =
  setmetatable(strvalcache, {__index = function(t,value)
+
      pairs, table.concat
    local res = string_format('%q', value)
+
      local keycache, strvalcache, out, closure_cnt = {}, {}, {}, 0
    t[value] = res
+
      setmetatable(strvalcache, {__index = function(t,value)
    return res
+
        local res = string_format('%q', value)
  end})
+
        t[value] = res
  local fcts = {
+
        return res
    string = function(value) return strvalcache[value] end,
+
      end})
    number = function(value) return value end,
+
      local fcts = {
    boolean = function(value) return tostring(value) end,
+
        string = function(value) return strvalcache[value] end,
    ['nil'] = function(value) return 'nil' end,
+
        number = function(value) return value end,
    ['function'] = function(value)  
+
        boolean = function(value) return tostring(value) end,
      return string_format("loadstring(%q)", string_dump(value))  
+
        ['nil'] = function(value) return 'nil' end,
    end,
+
        ['function'] = function(value)
    userdata = function(value)
+
          return string_format("load(%q)", string_dump(value))
if value.getId ~= nil then
+
        end,
    return value:getId().id .. " " .. value:getName()
+
        userdata = function(value)
else
+
          --if value.getId ~= nil then
    return "userdata"
+
          --    return value:getId().id .. " " .. value:getName()
end
+
          --else
end,
+
          --    return "userdata"
    thread = function() error("Cannot dump threads") end,
+
          --end
  }
+
        end,
  local function test_defined(value, path)
+
        thread = function() error("Cannot dump threads") end,
    if defined[value] then
+
      }
      if path:match("^getmetatable.*%)$") then
+
      local function test_defined(value, path)
        out[#out+1] = string_format("s%s, %s)\n", path:sub(2,-2), defined[value])
+
        if defined[value] then
      else
+
          if path:match("^getmetatable.*%)$") then
        out[#out+1] = path .. " = " .. defined[value] .. "\n"
+
            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
 
       end
       return true
+
       local function make_key(t, key)
    end
+
        local s
    defined[value] = path
+
        if type(key) == 'string' and key:match('^[_%a][_%w]*$') then
  end
+
          s = key .. "="
  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
 
         else
           out[#out+1] = keycache[key]
+
           s = "[" .. dumplua(key, 0) .. "]="
 
         end
 
         end
         local str = dumplua(val)
+
         t[key] = s
         out[#out+1] = str..","
+
         return s
 
       end
 
       end
       if string.sub(out[#out], -1) == "," then
+
       for _,k in ipairs(lua_reserved_keywords) do
         out[#out] = string.sub(out[#out], 1, -2);
+
         keycache[k] = '["'..k..'"] = '
 
       end
 
       end
       out[#out+1] = "}"
+
       if fastmode then
      return ""  
+
        fcts.table = function (value)
    end
+
          -- Table value
  else  
+
          local numidx = 1
    fcts.table = function (value, ident, path)
+
          out[#out+1] = "{"
      if test_defined(value, path) then return "nil" end
+
          for key,val in pairs(value) do
      -- Table value
+
            if key == numidx then
      local sep, str, numidx, totallen = " ", {}, 1, 0
+
              numidx = numidx + 1
      local meta, metastr = (debug or getfenv()).getmetatable(value)
+
            else
      if meta then
+
              out[#out+1] = keycache[key]
        ident = ident + 1
+
            end
        metastr = dumplua(meta, ident, "getmetatable("..path..")")
+
            local str = dumplua(val)
        totallen = totallen + #metastr + 16
+
            out[#out+1] = str..","
      end
+
          end
      for _,key in pairs(keys(value)) do
+
          if string.sub(out[#out], -1) == "," then
        local val = value[key]
+
            out[#out] = string.sub(out[#out], 1, -2);
        local s = ""
+
          end
        local subpath = path
+
          out[#out+1] = "}"
        if key == numidx then
+
          return ""
          subpath = subpath .. "[" .. numidx .. "]"
+
        end
          numidx = numidx + 1
+
      else
        else
+
        fcts.table = function (value, ident, path)
          s = keycache[key]
+
          if test_defined(value, path) then return "nil" end
          if not s:match "^%[" then subpath = subpath .. "." end
+
          -- Table value
          subpath = subpath .. s:gsub("%s*=%s*$","")
+
          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
        s = s .. dumplua(val, ident+1, subpath)
 
        str[#str+1] = s
 
        totallen = totallen + #s + 2
 
 
       end
 
       end
       if totallen > 80 then
+
       function dumplua(value, ident, path)
         sep = "\n" .. string_rep("  ", ident+1)
+
         return fcts[type(value)](value, ident, path)
 
       end
 
       end
       str = "{"..sep..table_concat(str, ","..sep).." "..sep:sub(1,-3).."}"
+
       if varname == nil then
      if meta then
+
        varname = "return "
         sep = sep:sub(1,-3)
+
      elseif varname:match("^[%a_][%w_]*$") then
        return "setmetatable("..sep..str..","..sep..metastr..sep:sub(1,-3)..")"
+
         varname = varname .. " = "
 
       end
 
       end
       return str
+
       if fastmode then
    end
+
        setmetatable(keycache, {__index = make_key })
    fcts['function'] = function (value, ident, path)
+
        out[1] = varname
      if test_defined(value, path) then return "nil" end
+
        table.insert(out,dumplua(value, 0))
      if c_functions[value] then
+
        return table.concat(out)
        return c_functions[value]
+
      else
      elseif debug == nil or debug.getupvalue(value, 1) == nil then
+
        setmetatable(keycache, {__index = make_key })
         return string_format("loadstring(%q)", string_dump(value))
+
        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
      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
 
      return "closure " .. dumplua(res, ident, "closures["..closure_cnt.."]")
 
 
     end
 
     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
+
    -- End of DataDumper
--
+
    --
-- Shader Metatable
+
    -- Shader Metatable
  
shaders_compiled = {}
+
    shaders_compiled = {}
local shader_meta = {}
+
    local shader_meta = {}
local shader = {}
 
function shader:new (this, id, fsh, vsh)
 
 
     local shader = {}
 
     local shader = {}
     shader.num = shaderCompile(fsh,vsh)
+
     function shader:new (this, id, file)
    shader.id = id
+
      local shader = {}
    if shaders_compiled[id] == nil then
+
      shader.num = shaderCompile(file)
 +
      shader.id = id
 +
      if shaders_compiled[id] == nil then
 
         shaders_compiled[id] = {}
 
         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
 
     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
 
    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")
 +
}
  
basic_vsh=[[#ifdef GL_ES
+
    shader_coeff0=0
precision lowp float;
+
    shader_coeff1=1
precision lowp int;
+
    shader_coeff2=1
#endif
+
    shader_coeff3=0
varying vec2 texcoord;
+
    shader_blur=0
uniform mat4 mvp_mat;
+
    shader_downsize=1
attribute vec2 position;
+
    shader_colorize=0
attribute vec2 uv;
+
    shader_color=0
uniform int pass;
+
    shader_iTime = 0
void main ()
+
    shader_noise=0
{
+
    shader_noiseStrength=0.0
  gl_Position = mvp_mat * vec4(position.x,position.y,0.0,1.0);
+
    shader_passes=2
  texcoord = uv;
+
    shader_active = true
}]]
+
    shader_glow = 0
 +
    shader_glowradius = 0
 +
    shader_glowexp = 1
  
----------------------------
+
    shader_rotate=0.0
basic_fsh=[[#ifdef GL_ES
+
    shader_scale = 1.0
precision highp float;
+
    shader_offsetx = 0.0
precision lowp  int;
+
    shader_offsety = 0.0
#endif
+
    shader_follow = {on=0, name="", c_scale=1, easing = easeQuintOut, delay = 0}
#define iChannel0 composite
 
#define iResolution resolution
 
#define iGlobalTime time
 
#define iMouse mouse
 
uniform float time;
 
uniform sampler2D composite;
 
uniform int pass;
 
uniform vec2 mouse;
 
uniform vec2 resolution;
 
varying vec2 texcoord;]]
 
  
----------------------------
+
    c_res=game.WindowResolution
shaders = {_temporary_=0, c_scene = game.CurrentScene,
 
---------------------------
 
glownum = shader("glow",[[#ifdef GL_ES
 
precision lowp float;
 
precision lowp int;
 
#endif
 
varying vec2 texcoord;
 
uniform mat4 mvp_mat;
 
attribute vec2 position;
 
attribute vec2 uv;
 
uniform int pass;
 
uniform int firstpass;
 
uniform int lastpass;
 
uniform float down;
 
  
mat4 scale4 = mat4(1.0/down,0,0,0,
+
    shaders.num.weights = {shader_colorize,shader_color}
  0,1.0/down,0,0,
+
    shaders.num.shader_coeff = {shader_coeff0,shader_coeff1,shader_coeff2,shader_coeff3}
  0,0,1,0,
+
    shaders.glownum.resolution = {c_res.x,c_res.y}
  0,0,0,1);
+
     if graphics.isUpsideDown() then
mat3 scale = mat3(1,0,0, 0,1,0, 0,0,1);
+
      shaders.bnum.upsideDown = 1.0
void main ()
+
      shaders.rglownum.upsideDown = 1.0
{
+
      shaders.glownum.upsideDown = 1.0
     if(pass==lastpass)
 
        gl_Position = mvp_mat * vec4(position.x,position.y,0.0,1.0);
 
 
     else
 
     else
        gl_Position = mvp_mat * (scale4 * vec4(position.x,position.y,0.0,1.0));
+
      shaders.glownum.upsideDown = 0.0
    if(pass > firstpass)
+
      shaders.bnum.upsideDown = 0.0
        scale=mat3(1.0/down,0,0,0,1.0/down,0,0,1.0-1.0/down,1);
+
      shaders.rglownum.upsideDown = 0.0
     texcoord = (scale*vec3(uv,1.0)).xy;
+
     end
}]], [[#ifdef GL_ES
+
    shaders.bnum.resolution = {c_res.x,c_res.y}
precision highp float;
 
precision lowp  int;
 
#endif
 
uniform sampler2D composite;
 
uniform int pass;
 
uniform float exposure;
 
varying vec2 texcoord;
 
uniform vec2 weights;
 
uniform int firstpass;
 
uniform int lastpass;
 
uniform vec2 resolution;
 
  
void identity() {
+
    -- * function that stops following specified character & resets camera back to default * --
    vec4 col = exposure*texture2D(composite, texcoord.st);
+
    function shaderStopFollow(easing)
    col.a=1.0;
+
      shader_follow.on = 0
     gl_FragColor = col;
+
      shaderViewport(1, 0, 0, 0, shader_follow.delay, easing)
}
+
      unregisterEventHandler("mainLoop", "followCharacter")
 +
     end
  
void blurFast(){
+
     -- * function that smoothly follows specified character * --
     vec4 sum = vec4(0.0);
+
     function shaderFollowCharacter(name, c_scale, delay, easing)
    float blurSize=1.0/resolution.x*(5.0-float(pass-firstpass+1));
+
      if name == "" then name = game.CurrentCharacter:getName() end
     sum += texture2D(composite, vec2(texcoord.x - blurSize, texcoord.y - blurSize)) * weights[0];
+
      if shader_follow.on == 0 then registerEventHandler("mainLoop", "followCharacter") end
    sum += texture2D(composite, vec2(texcoord.x - blurSize, texcoord.y + blurSize)) * weights[0];
+
      shader_follow.on = 1
    sum += texture2D(composite, vec2(texcoord.x, texcoord.y)) * weights[1];
+
      shader_follow.name = name
    sum += texture2D(composite, vec2(texcoord.x + blurSize, texcoord.y - blurSize)) * weights[0];
+
      shader_follow.c_scale = c_scale
    sum += texture2D(composite, vec2(texcoord.x + blurSize, texcoord.y + blurSize)) * weights[0];
+
      shader_follow.delay = delay
     gl_FragColor = sum;
+
      shader_follow.easing = easing or easeQuintOut
}
+
     end
  
void main()
+
     function shaderZoomCharacter(name, c_scale, delay, easing)
+
      local c_position={}
    if(pass==lastpass)
+
      if(name=="")then
        identity();
 
    else if(pass==firstpass)
 
        gl_FragColor = 2.0*max(vec4(0.0),texture2D(composite, texcoord).rgba-0.5);
 
    else
 
        blurFast();
 
}]]),
 
----------------------------
 
bnum = shader("blur",[[#ifdef GL_ES
 
precision lowp float;
 
precision lowp int;
 
#endif
 
varying vec2 texcoord;
 
uniform mat4 mvp_mat;
 
attribute vec2 position;
 
attribute vec2 uv;
 
uniform int pass;
 
uniform int firstpass;
 
uniform int lastpass;
 
uniform float down;
 
 
 
mat4 scale4 = mat4(1.0/down,0,0,0,
 
  0,1.0/down,0,0,
 
  0,0,1,0,
 
  0,0,0,1);
 
mat3 scale = mat3(1,0,0, 0,1,0, 0,0,1);
 
void main ()
 
{
 
  if(pass==lastpass)
 
    gl_Position = mvp_mat * vec4(position.x,position.y,0.0,1.0);
 
  else
 
  gl_Position = mvp_mat * (scale4 * vec4(position.x,position.y,0.0,1.0));
 
  if(pass>firstpass)
 
    scale=mat3(1.0/down,0,0,0,1.0/down,0,0,1.0-1.0/down,1);
 
  texcoord = (scale*vec3(uv,1.0)).xy;
 
}]], [[#ifdef GL_ES
 
precision highp float;
 
precision lowp  int;
 
#endif
 
 
 
uniform sampler2D composite;
 
uniform int pass;
 
uniform float exposure;
 
varying vec2 texcoord;
 
uniform vec2 weights;
 
uniform int firstpass;
 
uniform int lastpass;
 
uniform vec2 resolution;
 
 
 
void identity() {
 
    vec4 col = exposure*texture2D(composite, texcoord.st);
 
    col.a=1.0;
 
    gl_FragColor = col;
 
}
 
 
 
void blurFast(){
 
    vec4 sum = vec4(0.0);
 
    float blurSize=1.0/resolution.x*(5.0-float(pass-firstpass));
 
    sum += texture2D(composite, vec2(texcoord.x - blurSize, texcoord.y - blurSize)) * weights[0];
 
    sum += texture2D(composite, vec2(texcoord.x - blurSize, texcoord.y + blurSize)) * weights[0];
 
    sum += texture2D(composite, vec2(texcoord.x, texcoord.y)) * weights[1];
 
    sum += texture2D(composite, vec2(texcoord.x + blurSize, texcoord.y - blurSize)) * weights[0];
 
    sum += texture2D(composite, vec2(texcoord.x + blurSize, texcoord.y + blurSize)) * weights[0];
 
    gl_FragColor = sum;
 
}
 
 
 
void main()
 
 
    if(pass==lastpass)
 
        identity();
 
    else
 
        blurFast();
 
}]]),
 
----------------------------
 
num = shader("num",[[#ifdef GL_ES
 
precision lowp float;
 
precision lowp int;
 
#endif
 
varying vec2 texcoord;
 
uniform mat4 mvp_mat;
 
uniform mat4 cam_mat;
 
attribute vec2 position;
 
attribute vec2 uv;
 
uniform int pass;
 
void main ()
 
{
 
  gl_Position = mvp_mat * (cam_mat * vec4(position.x,position.y,0.0,1.0));
 
  texcoord = uv;
 
}]],[[#ifdef GL_ES
 
precision highp float;
 
precision lowp  int;
 
#endif
 
 
 
uniform sampler2D composite;
 
uniform int pass;
 
uniform int noise;
 
uniform float noiseFactor;
 
uniform float iTime;
 
uniform vec2 weights;
 
uniform vec4 shader_coeff;
 
varying vec2 texcoord;
 
 
 
void identity() {
 
    gl_FragColor = texture2D(composite, texcoord.st);
 
}
 
 
 
float rand(vec2 co){
 
    return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
 
}
 
 
 
vec3 rgb2hsv(vec3 c)
 
{
 
    vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
 
    vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
 
    vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
 
 
    float d = q.x - min(q.w, q.y);
 
    float e = 1.0e-10;
 
    return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
 
}
 
 
 
vec3 hsv2rgb(vec3 c)
 
{
 
    vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
 
    vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
 
    return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
 
}
 
void sat()
 
{
 
    vec4 textureColor = texture2D(composite, texcoord.st);
 
   
 
    vec3 fragRGB = textureColor.rgb;
 
    vec3 fragHSV = rgb2hsv(fragRGB);
 
    fragHSV.x += shader_coeff[0];
 
    fragHSV.y *= shader_coeff[1];
 
    fragHSV.z = (fragHSV.z - 0.5)*shader_coeff[2]+0.5+shader_coeff[3];
 
    fragRGB = hsv2rgb(fragHSV);
 
    fragHSV.x = weights[1];
 
    vec3 fragRGBC = hsv2rgb(fragHSV);
 
    vec4 color = vec4(mix(fragRGB, fragRGBC, weights[0]), textureColor.w);
 
    if(noise==1)
 
        color+= noiseFactor*rand(texcoord.xy+vec2(iTime*2.0,0.0));
 
     gl_FragColor=color;
 
}
 
void main()
 
 
        sat();
 
}]])}
 
 
 
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}
 
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
 
end
 
 
 
function shaderZoomCharacter(name, c_scale, delay, easing)
 
    local c_position={}
 
    if(name=="")then
 
 
         c_position=game.CurrentCharacter.Position
 
         c_position=game.CurrentCharacter.Position
    else
+
      else
 
         c_position=Characters[name].Position
 
         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
 
     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)
 
    shaderViewport(c_scale, c_position.x, c_position.y, 0, delay, easing)
 
end
 
  
function shaderZoomObject(object, c_scale, delay, easing)
+
    function shaderZoomObject(object, c_scale, delay, easing)
    local c_position=object.Position
+
      local c_position=object.Position
    local c_scroll=game.ScrollPosition
+
      local c_scroll=game.ScrollPosition
    c_position.x=c_position.x-c_scroll.x
+
      c_position.x=c_position.x-c_scroll.x
    c_position.y=c_position.y-c_scroll.y
+
      c_position.y=c_position.y-c_scroll.y
    c_position.x=c_position.x-(c_res.x/c_scale/2)
+
      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.y=c_position.y-(c_res.y/c_scale/1.2)
    shaderViewport(c_scale, c_position.x, c_position.y, 0, delay, easing)
+
      c_position.x = math.min(math.max(0,c_position.x), game.CurrentScene.Sprite:getSize().x - c_res.x/c_scale)
end
+
      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)
+
    function shaderNoise(on, strength,delay)
    shaders.num._i_noise = on
+
      shaders.num.noise = on
    startTween("shader_noiseStrength", shader_noiseStrength, strength, delay,easeLinearInOut)
+
      startTween("shader_noiseStrength", shader_noiseStrength, strength, delay,easeLinearInOut)
    shader_noise=on
+
      shader_noise=on
end
+
    end
  
function shaderSaturation(factor, delay)
+
    function shaderSaturation(factor, delay)
    startTween("shader_coeff1",shader_coeff1,factor,delay,easeLinearInOut)
+
      startTween("shader_coeff1",shader_coeff1,factor,delay,easeLinearInOut)
end
+
    end
  
function shaderLightness(offset, delay)
+
    function shaderLightness(offset, delay)
    startTween("shader_coeff3",shader_coeff3,offset,delay,easeLinearInOut)
+
      startTween("shader_coeff3",shader_coeff3,offset,delay,easeLinearInOut)
end
+
    end
  
function shaderContrast(contrast, delay)
+
    function shaderContrast(contrast, delay)
    startTween("shader_coeff2",shader_coeff2,contrast,delay,easeLinearInOut)
+
      startTween("shader_coeff2",shader_coeff2,contrast,delay,easeLinearInOut)
end
+
    end
  
function shaderHue(target, delay)
+
    function shaderHue(target, delay)
    startTween("shader_coeff0",shader_coeff0,target,delay,easeLinearInOut)
+
      startTween("shader_coeff0",shader_coeff0,target,delay,easeLinearInOut)
end
+
    end
  
function shaderColorize(hue, strength, delay)
+
    function shaderColorize(hue, strength, delay)
    startTween("shader_colorize",shader_colorize,strength,delay,easeLinearIn)
+
      startTween("shader_colorize",shader_colorize,strength,delay,easeLinearIn)
    shader_color=hue
+
      shader_color=hue
end
+
    end
  
function shaderViewport(zoom, x, y, rotation, delay, easing)
+
    shader_viewportTransition = 1.0
     startTween("shader_offsetx", shader_offsetx, x, delay,easing)
+
    shader_oldViewport = { x = 0.0, y=0.0, scale = 1.0, rotate = 0.0}
     startTween("shader_offsety", shader_offsety, y, delay,easing)
+
    shader_newViewport = { x = 0.0, y=0.0, scale = 1.0, rotate = 0.0}
    startTween("shader_scale", shader_scale, zoom, delay,easing)  
+
    shader_interpolationPoint = {x=0.0, y=0.0}
    startTween("shader_rotate", shader_rotate, rotation, delay,easing)     
+
     function shaderViewportInterpolationPoint(x,y)
end
+
      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 * --
+
    -- * allows you to pan the camera left or right * --
function shaderPan(offset, delay, easing, axis)
+
    function shaderPan(offset, delay, easing, axis)
    if axis then  
+
      if axis then
         startTween("shader_offsety", shader_offsety, offset, delay, easing)  
+
         startTween("shader_offsety", shader_offsety, offset, delay, easing)
    else  
+
      else
         startTween("shader_offsetx", shader_offsetx, offset, delay, easing)  
+
         startTween("shader_offsetx", shader_offsetx, offset, delay, easing)
 +
      end
 
     end
 
     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,
+
     -- * allows you to zoom the camera in or out * --
warp1={shader=basic_fsh..[[uniform float strength;
+
     function shaderZoom(zoom, delay, easing)
void main(void)
+
      startTween("shader_scale", shader_scale, zoom, delay, easing)
{
+
     end
     float t = iGlobalTime * 0.5;
 
    vec2 uv = texcoord;
 
    float aspect = iResolution.x / iResolution.y;
 
   
 
    mat3 xform = mat3(cos(sin(t)), sin(t  *0.25), 0.0,
 
                      -sin(t * 0.25), cos(cos(t)), 0.0,
 
                      cos(t / 2.0) * 0.2, sin(t) * 0.2, 1.0);
 
   
 
     uv = (xform * vec3(uv, 1.0)).xy * vec2(aspect, 1.0);
 
   
 
    uv.x -= sin(t) + cos(t * 2.0 + cos(uv.x) * sin(t * 2.0) * 2.0) / 2.0;
 
    uv.y += cos(t + uv.y * 0.5) + sin(uv.y * cos(t)) + sin(cos(t * 0.5) * length(uv));
 
    uv= mix(texcoord,uv,strength);
 
    uv = mod(uv, 1.0);
 
   
 
    vec3 color = texture2D(iChannel0, uv).xyz;
 
      
 
    gl_FragColor.xyz = color;
 
    gl_FragColor.w = 1.0;
 
}]] } ,
 
light1={shader=basic_fsh..[[
 
uniform vec3 lightpos, targetpos;
 
uniform int lights_count;
 
struct light {
 
    int type;
 
    vec3 position;
 
    vec3 targetpos;
 
    vec3 lightfalloff;
 
    vec3 ambient;
 
    vec3 diffuse;
 
    float diffusefactor;
 
    float exponent;
 
    float cutoff;
 
};
 
uniform light lights[6];
 
  
#define OFFSET_X 1
+
    -- * allows you to rotate the screen (w/ degree instead of pi) * --
#define OFFSET_Y 1
+
    function shaderRotate(degree, delay, easing)
#define DEPTH    10.
+
      degree = (degree / 360 * 2 * 3.14) -- convert degree to pi
 +
      startTween("shader_rotate", shader_rotate, degree, delay, easing)
 +
    end
  
vec3 sample(const int x, const int y)
+
    -- * function that follows character; only active when loop enabled * --
{
+
    function followCharacter()
    vec2 uv = (gl_FragCoord.xy + vec2(x, y)) / iResolution.xy;
+
      shaderZoomCharacter(shader_follow.name, shader_follow.c_scale, shader_follow.delay, shader_follow.easing)
    return texture2D(iChannel0, uv).xyz;
+
    end
}
 
  
float luminance(vec3 c)
+
     shader_effects = {_temporary_=0,
{
+
     transition={shader= "sht_transition.bin"} ,
     return dot(c, vec3(.2126, .7152, .0722));
+
     warp1={shader= "sht_warp1.bin"} ,
}
+
    light1={shader="sht_light.bin"},
 
+
     tv1 = {shader = "sht_tv1.bin"},
vec3 normal(void)
+
     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"},
    float R = abs(luminance(sample( OFFSET_X,0)));
+
     ascii = {shader = "sht_ascii.bin"},
    float L = abs(luminance(sample(-OFFSET_X,0)));
+
     edgeglow = {shader = "sht_edgeglow.bin"},
     float D = abs(luminance(sample(0, OFFSET_Y)));
+
     chroma = {shader = "sht_chroma.bin"},
    float U = abs(luminance(sample(0,-OFFSET_Y)));
+
     ripple3 = {shader = "sht_ripple3.bin"},
               
+
     warp2 = {shader = "sht_warp2.bin"},
    float X = (L-R) * .5;
+
     ripple4 = {shader = "sht_ripple4.bin"},
    float Y = (U-D) * .5;
+
    pearls={shader="sht_pearls.bin"},
 
+
    highlight={shader="sht_hightlight.bin"},
    return normalize(vec3(X, Y, 1. / DEPTH));
+
     fourbit={shader="sht_fourbit.bin"},
}
+
    tv2={shader="sht_tv2.bin"},
 
+
     tv3={shader="sht_tv3.bin"},
void main(void)
+
     tv4={shader="sht_tv4.bin"}
{
+
   }
    vec3 n=vec3(0.0,0.0,1.0);
 
     vec3 diffuse = texture2D(composite, texcoord).rgb;
 
 
 
    float att = 0.0;
 
    vec3 color=vec3(0.0);
 
 
 
    for(int i = 0; i < lights_count; i++)
 
    {
 
        vec3 lightDir = vec3(lights[i].position-vec3(gl_FragCoord.xy,0.0));
 
        float NdotL = max(dot(n,normalize(lightDir)),0.0);
 
        float dist = length(lightDir);
 
 
 
        if (lights[i].type == 0)
 
        {
 
            if (NdotL > 0.0)
 
            {
 
                float spotEffect = dot(normalize(lights[i].targetpos-lights[i].position), normalize(-lightDir));
 
                if (spotEffect > lights[i].cutoff)
 
                {
 
                    spotEffect = pow(spotEffect,lights[i].exponent);
 
                    att = spotEffect / (lights[i].lightfalloff[0] + lights[i].lightfalloff[1] * dist + lights[i].lightfalloff[2] * dist * dist);
 
                    color += att * (diffuse * lights[i].diffuse * (NdotL * lights[i].diffusefactor) + lights[i].ambient);
 
                }
 
            }
 
        }
 
        else
 
        {
 
            att = 1.0 / (lights[i].lightfalloff[0] + lights[i].lightfalloff[1] * dist + lights[i].lightfalloff[2] * dist * dist);
 
            color += att * (diffuse * lights[i].diffuse * (NdotL * lights[i].diffusefactor) + lights[i].ambient);
 
            //color = vec3(NdotL);
 
        }
 
     }
 
 
 
    gl_FragColor = vec4(color, 1.); 
 
}]]},
 
tv1 = {shader = basic_fsh..[[
 
 
 
#define BLACK_AND_WHITE
 
#define LINES_AND_FLICKER
 
#define BLOTCHES
 
#define GRAIN
 
#define FREQUENCY 15.0
 
vec2 uv;
 
float rand(vec2 co){
 
    return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
 
}
 
float rand(float c){
 
    return rand(vec2(c,1.0));
 
}
 
float randomLine(float seed)
 
{
 
     float b = 0.01 * rand(seed);
 
    float a = rand(seed+1.0);
 
    float c = rand(seed+2.0) - 0.5;
 
    float mu = rand(seed+3.0);
 
    float l = 1.0;
 
    if ( mu > 0.2)
 
        l = pow(  abs(a * uv.x + b * uv.y + c ), 1.0/8.0 );
 
    else
 
        l = 2.0 - pow( abs(a * uv.x + b * uv.y + c), 1.0/8.0 );           
 
    return mix(0.5, 1.0, l);
 
}
 
float randomBlotch(float seed)
 
{
 
    float x = rand(seed);
 
    float y = rand(seed+1.0);
 
    float s = 0.01 * rand(seed+2.0);
 
    vec2 p = vec2(x,y) - uv;
 
    p.x *= iResolution.x / iResolution.y;
 
    float a = atan(p.y,p.x);
 
    float v = 1.0;
 
    float ss = s*s * (sin(6.2831*a*x)*0.1 + 1.0);
 
    if ( dot(p,p) < ss ) v = 0.2;
 
     else
 
        v = pow(dot(p,p) - ss, 1.0/16.0);
 
    return mix(0.3 + 0.2 * (1.0 - (s / 0.02)), 1.0, v);
 
}
 
void main(void)
 
{
 
    uv = gl_FragCoord.xy / iResolution.xy;
 
     float t = float(int(iGlobalTime * FREQUENCY));
 
    vec2 suv = uv + 0.002 * vec2( rand(t), rand(t + 23.0));
 
     vec3 image = texture2D( iChannel0, vec2(suv.x, suv.y) ).xyz;
 
#ifdef BLACK_AND_WHITE
 
    // Pass it to B/W
 
    float luma = dot( vec3(0.2126, 0.7152, 0.0722), image );
 
     vec3 oldImage = luma * vec3(0.7, 0.7, 0.7);
 
#else
 
    vec3 oldImage = image;
 
#endif
 
    float vI = 16.0 * (uv.x * (1.0-uv.x) * uv.y * (1.0-uv.y));
 
    vI *= mix( 0.7, 1.0, rand(t + 0.5));
 
     vI += 1.0 + 0.4 * rand(t+8.);
 
    vI *= pow(16.0 * uv.x * (1.0-uv.x) * uv.y * (1.0-uv.y), 0.4);
 
#ifdef LINES_AND_FLICKER
 
     int l = int(8.0 * rand(t+7.0));
 
    if ( 0 < l ) vI *= randomLine( t+6.0+17.* float(0));
 
    if ( 1 < l ) vI *= randomLine( t+6.0+17.* float(1));
 
    if ( 2 < l ) vI *= randomLine( t+6.0+17.* float(2));       
 
    if ( 3 < l ) vI *= randomLine( t+6.0+17.* float(3));
 
    if ( 4 < l ) vI *= randomLine( t+6.0+17.* float(4));
 
    if ( 5 < l ) vI *= randomLine( t+6.0+17.* float(5));
 
    if ( 6 < l ) vI *= randomLine( t+6.0+17.* float(6));
 
    if ( 7 < l ) vI *= randomLine( t+6.0+17.* float(7));
 
#endif
 
#ifdef BLOTCHES
 
    int s = int( max(8.0 * rand(t+18.0) -2.0, 0.0 ));
 
     if ( 0 < s ) vI *= randomBlotch( t+6.0+19.* float(0));
 
    if ( 1 < s ) vI *= randomBlotch( t+6.0+19.* float(1));
 
    if ( 2 < s ) vI *= randomBlotch( t+6.0+19.* float(2));
 
    if ( 3 < s ) vI *= randomBlotch( t+6.0+19.* float(3));
 
    if ( 4 < s ) vI *= randomBlotch( t+6.0+19.* float(4));
 
    if ( 5 < s ) vI *= randomBlotch( t+6.0+19.* float(5));
 
#endif
 
    gl_FragColor.xyz = oldImage * vI;
 
#ifdef GRAIN
 
    gl_FragColor.xyz *= (1.0+(rand(uv+t*.01)-.2)*.15);     
 
#endif     
 
}]]},
 
ripple1 = {shader = basic_fsh..[[
 
// Simple Water shader. (c) Victor Korsun, bitekas@gmail.com; 2012.
 
// Attribution-ShareAlike CC License.
 
const float PI = 3.1415926535897932;
 
const float speed = 0.2;
 
const float speed_x = 0.3;
 
const float speed_y = 0.3;
 
const float emboss = 0.50;
 
const float intensity = 2.4;
 
const int steps = 8;
 
const float frequency = 6.0;
 
const int angle = 7; // better when a prime
 
const float delta = 60.;
 
const float intence = 700.;
 
const float reflectionCutOff = 0.012;
 
const float reflectionIntence = 200000.;
 
float col(vec2 coord)
 
{
 
float delta_theta = 2.0 * PI / float(angle);
 
float col = 0.0;
 
float theta = 0.0;
 
for (int i = 0; i < steps; i++)
 
{
 
  vec2 adjc = coord;
 
  theta = delta_theta*float(i);
 
  adjc.x += cos(theta)*time*speed + time * speed_x;
 
  adjc.y -= sin(theta)*time*speed - time * speed_y;
 
  col = col + cos( (adjc.x*cos(theta) - adjc.y*sin(theta))*frequency)*intensity;
 
}
 
return cos(col);
 
}
 
void main(void)
 
{
 
vec2 p = texcoord, c1 = p, c2 = p;
 
float cc1 = col(c1);
 
c2.x += iResolution.x/delta;
 
float dx = emboss*(cc1-col(c2))/delta;
 
c2.x = p.x;
 
c2.y += iResolution.y/delta;
 
float dy = emboss*(cc1-col(c2))/delta;
 
c1.x += dx*2.;
 
c1.y = (c1.y+dy*2.);
 
float alpha = 1.+dot(dx,dy)*intence;
 
float ddx = dx - reflectionCutOff;
 
float ddy = dy - reflectionCutOff;
 
if (ddx > 0. && ddy > 0.)
 
     alpha = pow(alpha, ddx*ddy*reflectionIntence);
 
c1=mod(c1,1.0);
 
vec4 col = texture2D(iChannel0,c1)*(alpha);
 
gl_FragColor = col;
 
}
 
]]},
 
ripple2 = {shader = basic_fsh..[[
 
float count = 10.0;
 
float strength = 0.9;
 
void main(void)
 
{
 
    vec2 uv = texcoord;
 
    float w = (0.5 - (uv.x)) * (iResolution.x / iResolution.y);
 
    float h = 0.5 - uv.y;
 
    float distanceFromCenter = sqrt(w * w + h * h);
 
    float sinArg = distanceFromCenter * count - iGlobalTime * 10.0;
 
    float slope = cos(sinArg) ;
 
    vec4 color = texture2D(iChannel0, uv + strength * normalize(vec2(w, h)) * slope * 0.05);
 
     gl_FragColor = color;
 
}
 
]]},
 
ascii = {shader = basic_fsh..[[
 
// Bitmap to ASCII (not really) fragment shader by movAX13h, September 2013
 
// If you change the input channel texture, disable this:
 
float character(float n, vec2 p) // some compilers have the word "char" reserved
 
{
 
    p = floor(p*vec2(4.0, -4.0) + 2.5);
 
     if (clamp(p.x, 0.0, 4.0) == p.x && clamp(p.y, 0.0, 4.0) == p.y)
 
    {
 
        if (int(mod(n/exp2(p.x + 5.0*p.y), 2.0)) == 1) return 1.0;
 
    }    
 
    return 0.0;
 
}
 
  
void main()
+
   function clamp(a,b,c)
{
 
    vec3 col = texture2D(iChannel0, floor(gl_FragCoord.xy/8.0)*8.0/iResolution.xy).rgb; 
 
    float gray = (col.r + col.g + col.b)/3.0;
 
    float n =  65536.0;            // .
 
    if (gray > 0.2) n = 65600.0;    // :
 
    if (gray > 0.3) n = 332772.0;   // *
 
    if (gray > 0.4) n = 15255086.0; // o
 
    if (gray > 0.5) n = 23385164.0; // &
 
    if (gray > 0.6) n = 15252014.0; // 8
 
    if (gray > 0.7) n = 13199452.0; // @
 
    if (gray > 0.8) n = 11512810.0; // #
 
    vec2 p = mod(gl_FragCoord.xy/4.0, 2.0) - vec2(1.0);
 
    col = col*character(n, p);
 
    gl_FragColor = vec4(col, 1.0);
 
}
 
]]},
 
edgeglow = {shader = basic_fsh..[[
 
float d = sin(iGlobalTime * 5.0)*0.5 + 1.5;
 
float lookup(vec2 p, float dx, float dy)
 
{
 
    vec2 uv = (p.xy + vec2(dx * d, dy * d)) / iResolution.xy;
 
    vec4 c = texture2D(iChannel0, uv.xy);
 
    return 0.2126*c.r + 0.7152*c.g + 0.0722*c.b;
 
}
 
void main(void)
 
{
 
    vec2 p = gl_FragCoord.xy;
 
    float gx = 0.0;
 
    gx += -1.0 * lookup(p, -1.0, -1.0);
 
    gx += -2.0 * lookup(p, -1.0,  0.0);
 
    gx += -1.0 * lookup(p, -1.0,  1.0);
 
    gx +=  1.0 * lookup(p,  1.0, -1.0);
 
    gx +=  2.0 * lookup(p,  1.0,  0.0);
 
    gx +=  1.0 * lookup(p,  1.0,  1.0);
 
    float gy = 0.0;
 
    gy += -1.0 * lookup(p, -1.0, -1.0);
 
    gy += -2.0 * lookup(p,  0.0, -1.0);
 
    gy += -1.0 * lookup(p,  1.0, -1.0);
 
    gy +=  1.0 * lookup(p, -1.0,  1.0);
 
    gy +=  2.0 * lookup(p,  0.0,  1.0);
 
    gy +=  1.0 * lookup(p,  1.0,  1.0);
 
    float g = gx*gx + gy*gy;
 
    float g2 = g * (sin(iGlobalTime) / 2.0 + 0.5);
 
    vec4 col = texture2D(iChannel0, p / iResolution.xy);
 
    col += vec4(0.0, g, g2, 1.0);
 
    gl_FragColor = col;
 
}
 
]]},
 
chroma = {shader = basic_fsh..[[
 
// MIT License (MIT)
 
// Copyright (c) 2014 Justin Saunders
 
void main(void)
 
{
 
    vec2 uv = texcoord;
 
    float d = length(uv - vec2(0.5,0.5));
 
    float blur = 0.0; 
 
    blur = (1.0 + sin(iGlobalTime*6.0)) * 0.5;
 
    blur *= 1.0 + sin(iGlobalTime*16.0) * 0.5;
 
    blur = pow(blur, 3.0);
 
    blur *= 0.05;
 
    blur *= d;
 
    vec3 col;
 
    col.r = texture2D( iChannel0, vec2(uv.x+blur,uv.y) ).r;
 
    col.g = texture2D( iChannel0, uv ).g;
 
    col.b = texture2D( iChannel0, vec2(uv.x-blur,uv.y) ).b;
 
    float scanline = sin(uv.y*800.0)*0.04;
 
    col -= scanline;
 
    col *= 1.0 - d * 0.5;
 
    gl_FragColor = vec4(col,1.0);
 
}
 
]]},
 
ripple3 = {shader = basic_fsh..[[
 
void main(void)
 
{
 
    vec2 uv = texcoord;
 
    uv.x += (sin((uv.y + (iGlobalTime * 0.07)) * 45.0) * 0.009) +
 
        (sin((uv.y + (iGlobalTime * 0.1)) * 35.0) * 0.005);
 
    vec4 texColor = texture2D(iChannel0,uv);
 
    gl_FragColor = texColor;
 
}
 
]]},
 
warp2 = {shader = basic_fsh..[[
 
uniform float strength;
 
void main(void)
 
 
    vec2 uv = texcoord;
 
    float y =
 
        0.7*sin((uv.y + iGlobalTime) * 4.0) * 0.038 +
 
        0.3*sin((uv.y + iGlobalTime) * 8.0) * 0.010 +
 
        0.05*sin((uv.y + iGlobalTime) * 40.0) * 0.05;
 
 
 
    float x =
 
        0.5*sin((uv.y + iGlobalTime) * 5.0) * 0.1 +
 
        0.2*sin((uv.x + iGlobalTime) * 10.0) * 0.05 +
 
        0.2*sin((uv.x + iGlobalTime) * 30.0) * 0.02;
 
 
 
    gl_FragColor = texture2D(iChannel0, mix(uv, 0.79*(uv + vec2(y+0.11, x+0.11)), strength));
 
}
 
]]},
 
ripple4 = {shader = basic_fsh..[[
 
void main(void)
 
{
 
    vec2 uv = texcoord;
 
   
 
    float w = (0.5 - (uv.x)) * (iResolution.x / iResolution.y);
 
    float h = 0.5 - uv.y;
 
    vec2 dv = vec2(w,h);
 
    float distanceFromCenter = sqrt(dot(dv,dv));
 
   
 
    float sinArg = distanceFromCenter * 10.0 - iGlobalTime * 10.0;
 
    float slope = cos(sinArg) ;
 
    vec4 color = texture2D(iChannel0, uv + normalize(vec2(w, h)) * slope * 0.01);
 
   
 
    gl_FragColor = color;
 
}
 
]]},
 
pearls={shader=basic_fsh..[[
 
// Size of the quad in pixels
 
const float size = 7.0;
 
 
 
// Radius of the circle
 
const float radius = size * 0.5 * 0.75;
 
 
 
void main(void)
 
 
    // Current quad in pixels
 
    vec2 quadPos = floor(gl_FragCoord.xy / size) * size;
 
    // Normalized quad position
 
    vec2 quad = quadPos/iResolution.xy;
 
    // Center of the quad
 
    vec2 quadCenter = (quadPos + size/2.0);
 
    // Distance to quad center 
 
    float dist = length(quadCenter - gl_FragCoord.xy);
 
   
 
    vec4 texel = texture2D(iChannel0, quad);
 
    if (dist > radius)
 
    {
 
        gl_FragColor = vec4(0.25);
 
    }
 
    else
 
    {
 
        gl_FragColor = texel;
 
    }
 
}
 
]]},
 
highlight={shader=basic_fsh..[[
 
uniform float strength;
 
const bool leftToRight = false;
 
float slopeSign = (leftToRight ? -1.0 : 1.0);
 
float slope1 = 5.0 * slopeSign;
 
float slope2 = 7.0 * slopeSign;
 
void main(void)
 
{
 
   
 
   
 
    vec2 uv = gl_FragCoord.xy / iResolution.xy;
 
    float bright =
 
    - sin(uv.y * slope1 + uv.x * 30.0+ iGlobalTime *3.10) *.2
 
    - sin(uv.y * slope2 + uv.x * 37.0 + iGlobalTime *3.10) *.1
 
    - cos(              + uv.x * 2.0 * slopeSign + iGlobalTime *2.10) *.1
 
    - sin(              - uv.x * 5.0 * slopeSign + iGlobalTime * 2.0) * .3;
 
   
 
    float modulate = abs(cos(iGlobalTime*.1) *.5 + sin(iGlobalTime * .7)) *.5;
 
    bright *= modulate;
 
    vec4 pix = texture2D(iChannel0,uv);
 
    pix.rgb += 1.0*clamp(bright / 1.0,0.0,1.0);
 
    gl_FragColor = pix;
 
}
 
]]},
 
fourbit={shader=basic_fsh..[[
 
// 4BIT COLOR
 
// Maps into DawnBringer's 4-bit (16 color) palette http://www.pixeljoint.com/forum/forum_posts.asp?TID=12795
 
// Also see the amazing ASCII shadertoy: https://www.shadertoy.com/view/lssGDj
 
float hash(vec2 p) { return fract(1e4 * sin(17.0 * p.x + p.y * 0.1) * (0.1 + abs(sin(p.y * 13.0 + p.x)))); }
 
float compare(vec3 a, vec3 b) {
 
    // Increase saturation
 
    a = max(vec3(0.0), a - min(a.r, min(a.g, a.b)) * 0.25);
 
    b = max(vec3(0.0), b - min(b.r, min(b.g, b.b)) * 0.25);
 
    a*=a*a;
 
    b*=b*b;
 
    vec3 diff = (a - b);
 
    return dot(diff, diff);
 
}
 
void main(void) {
 
    const float pixelSize = 4.0;
 
    vec2 c = floor(gl_FragCoord.xy / pixelSize);
 
    vec2 coord = c * pixelSize;
 
    vec3 src = texture2D(iChannel0, coord / iResolution.xy).rgb;
 
    // Track the two best colors
 
    vec3 dst0 = vec3(0), dst1 = vec3(0);
 
    float best0 = 1e3, best1 = 1e3;
 
#  define TRY(R, G, B) { const vec3 tst = vec3(R, G, B); float err = compare(src, tst); if (err < best0) { best1 = best0; dst1 = dst0; best0 = err; dst0 = tst; } }
 
    TRY(0.078431, 0.047059, 0.109804);
 
    TRY(0.266667, 0.141176, 0.203922);
 
    TRY(0.188235, 0.203922, 0.427451);
 
    TRY(0.305882, 0.290196, 0.305882);
 
    TRY(0.521569, 0.298039, 0.188235);
 
    TRY(0.203922, 0.396078, 0.141176);
 
    TRY(0.815686, 0.274510, 0.282353);
 
    TRY(0.458824, 0.443137, 0.380392);
 
    TRY(0.349020, 0.490196, 0.807843);
 
    TRY(0.823529, 0.490196, 0.172549);
 
    TRY(0.521569, 0.584314, 0.631373);
 
    TRY(0.427451, 0.666667, 0.172549);
 
    TRY(0.823529, 0.666667, 0.600000);
 
    TRY(0.427451, 0.760784, 0.792157);
 
    TRY(0.854902, 0.831373, 0.368627);
 
    TRY(0.870588, 0.933333, 0.839216);
 
#  undef TRY 
 
    best0 = sqrt(best0); best1 = sqrt(best1);
 
    gl_FragColor = vec4(mod(c.x + c.y, 2.0) >  (hash(c * 2.0 + fract(sin(vec2(floor(iGlobalTime), floor(iGlobalTime * 1.7))))) * 0.75) + (best1 / (best0 + best1)) ? dst1 : dst0, 1.0);
 
}
 
]]},
 
tv2={shader=basic_fsh..[[
 
float rand(vec2 co){
 
    return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
 
}
 
 
 
void main(void)
 
{
 
    vec2 uv = texcoord;
 
    float screenRatio = iResolution.x / iResolution.y;
 
   
 
    vec3 texture = texture2D(iChannel0, uv).rgb;
 
   
 
    float barHeight = 6.;
 
    float barSpeed = 5.6;
 
    float barOverflow = 1.2;
 
    float blurBar = clamp(sin(uv.y * barHeight + iGlobalTime * barSpeed) + 1.25, 0., 1.);
 
    float bar = clamp(floor(sin(uv.y * barHeight + iGlobalTime * barSpeed) + 1.95), 0., barOverflow);
 
   
 
    float noiseIntensity = .75;
 
    float pixelDensity = 250.;
 
    vec3 color = vec3(clamp(rand(
 
        vec2(floor(uv.x * pixelDensity * screenRatio), floor(uv.y * pixelDensity)) *
 
        iGlobalTime / 1000.
 
    ) + 1. - noiseIntensity, 0., 1.));
 
   
 
    color = mix(color - noiseIntensity * vec3(.25), color, blurBar);
 
    color = mix(color - noiseIntensity * vec3(.08), color, bar);
 
    color = mix(vec3(0.), texture, color);
 
    color.b += .042;
 
   
 
    color *= vec3(1.0 - pow(distance(uv, vec2(0.5, 0.5)), 2.1) * 2.8);
 
   
 
    gl_FragColor = vec4(color, 1.);
 
}
 
]]},
 
tv3={shader=basic_fsh..[[
 
// SOFT TV
 
 
 
float rand(vec2 co)
 
{
 
    float a = 12.9898;
 
    float b = 78.233;
 
    float c = 43758.5453;
 
    float dt= dot(co.xy ,vec2(a,b));
 
    float sn= mod(dt,3.14);
 
    return fract(sin(sn) * c);
 
}
 
 
 
void main(void)
 
{
 
    vec2 uv = texcoord;
 
   
 
    float magnitude = 0.0009;
 
   
 
   
 
    // Set up offset
 
    vec2 offsetRedUV = uv;
 
    offsetRedUV.x = uv.x + rand(vec2(iGlobalTime*0.03,uv.y*0.42)) * 0.001;
 
    offsetRedUV.x += sin(rand(vec2(iGlobalTime*0.2, uv.y)))*magnitude;
 
   
 
    vec2 offsetGreenUV = uv;
 
    offsetGreenUV.x = uv.x + rand(vec2(iGlobalTime*0.004,uv.y*0.002)) * 0.004;
 
    offsetGreenUV.x += sin(iGlobalTime*9.0)*magnitude;
 
   
 
    vec2 offsetBlueUV = uv;
 
    offsetBlueUV.x = uv.y;
 
    offsetBlueUV.x += rand(vec2(cos(iGlobalTime*0.01),sin(uv.y)));
 
   
 
    // Load Texture
 
    float r = texture2D(iChannel0, offsetRedUV).r;
 
    float g = texture2D(iChannel0, offsetGreenUV).g;
 
    float b = texture2D(iChannel0, uv).b;
 
   
 
    gl_FragColor = vec4(r,g,b,0);
 
   
 
}]]},
 
tv4={shader=basic_fsh..[[
 
// Noise generation functions borrowed from:
 
// https://github.com/ashima/webgl-noise/blob/master/src/noise2D.glsl
 
vec3 mod289(vec3 x) {
 
  return x - floor(x * (1.0 / 289.0)) * 289.0;
 
}
 
vec2 mod289(vec2 x) {
 
  return x - floor(x * (1.0 / 289.0)) * 289.0;
 
}
 
vec3 permute(vec3 x) {
 
  return mod289(((x*34.0)+1.0)*x);
 
}
 
float snoise(vec2 v)
 
  {
 
  const vec4 C = vec4(0.211324865405187,  // (3.0-sqrt(3.0))/6.0
 
                      0.366025403784439,  // 0.5*(sqrt(3.0)-1.0)
 
                    -0.577350269189626,  // -1.0 + 2.0 * C.x
 
                      0.024390243902439); // 1.0 / 41.0
 
  vec2 i  = floor(v + dot(v, C.yy) );
 
  vec2 x0 = v -  i + dot(i, C.xx);
 
  vec2 i1;
 
  //i1.x = step( x0.y, x0.x ); // x0.x > x0.y ? 1.0 : 0.0
 
  //i1.y = 1.0 - i1.x;
 
  i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);
 
  // x0 = x0 - 0.0 + 0.0 * C.xx ;
 
  // x1 = x0 - i1 + 1.0 * C.xx ;
 
  // x2 = x0 - 1.0 + 2.0 * C.xx ;
 
  vec4 x12 = x0.xyxy + C.xxzz;
 
  x12.xy -= i1;
 
  i = mod289(i); // Avoid truncation effects in permutation
 
  vec3 p = permute( permute( i.y + vec3(0.0, i1.y, 1.0 ))
 
        + i.x + vec3(0.0, i1.x, 1.0 ));
 
  vec3 m = max(0.5 - vec3(dot(x0,x0), dot(x12.xy,x12.xy), dot(x12.zw,x12.zw)), 0.0);
 
  m = m*m ;
 
  m = m*m ;
 
// Gradients: 41 points uniformly over a line, mapped onto a diamond.
 
// The ring size 17*17 = 289 is close to a multiple of 41 (41*7 = 287)
 
  vec3 x = 2.0 * fract(p * C.www) - 1.0;
 
  vec3 h = abs(x) - 0.5;
 
  vec3 ox = floor(x + 0.5);
 
  vec3 a0 = x - ox;
 
 
 
// Normalise gradients implicitly by scaling m
 
// Approximation of: m *= inversesqrt( a0*a0 + h*h );
 
  m *= 1.79284291400159 - 0.85373472095314 * ( a0*a0 + h*h );
 
 
 
// Compute final noise value at P
 
  vec3 g;
 
  g.x  = a0.x  * x0.x  + h.x  * x0.y;
 
  g.yz = a0.yz * x12.xz + h.yz * x12.yw;
 
  return 130.0 * dot(m, g);
 
}
 
 
 
 
 
void main(void)
 
{
 
 
 
    vec2 uv =  gl_FragCoord.xy/iResolution.xy;
 
   
 
    float jerkOffset = (1.0-step(snoise(vec2(iGlobalTime*1.3,5.0)),0.8))*0.05;
 
   
 
    float wiggleOffset = snoise(vec2(iGlobalTime*15.0,uv.y*80.0))*0.003;
 
    float largeWiggleOffset = snoise(vec2(iGlobalTime*1.0,uv.y*25.0))*0.004;
 
   
 
    float xOffset = wiggleOffset + largeWiggleOffset + jerkOffset;
 
   
 
    float red  =  texture2D(  iChannel0,  vec2(uv.x + xOffset -0.01,uv.y)).r;
 
    float green =  texture2D(  iChannel0,  vec2(uv.x + xOffset,      uv.y)).g;
 
    float blue  =  texture2D(  iChannel0,  vec2(uv.x + xOffset +0.01,uv.y)).b;
 
   
 
    vec3 color = vec3(red,green,blue);
 
    float scanline = sin(uv.y*800.0)*0.04;
 
    color -= scanline;
 
   
 
    gl_FragColor = vec4(color,1.0);
 
}
 
 
 
]]}
 
}
 
 
 
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
+
      return standard
 
     else
 
     else
        return param
+
      return param
 
     end
 
     end
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 shaderGlow(on, blurradius, alpha)
+
  function shaderRadialGlow(on, blurradius, alpha)
 
     if on == 0 then
 
     if on == 0 then
        passesRemove(5,"glow")
+
      passesRemove(6,"rglow")
        shader_glow = on
+
      shader_rglow = on
        shader_glowradius = blurradius
+
      shader_rglowradius = blurradius
        shader_glowexp = alpha
+
      shader_rglowexp = alpha
 
     else
 
     else
        passesAdd(5,"glow",{{ shader = shaders.glownum(), source=1, target = 2, clear = 0, variable = "shaders.glownum._i_firstpass" },
+
      passesAdd(6,"rglow",{{ shader = shaders.rglownum(), source=1, target = 2, clear = 0, variable = "shaders.rglownum._i_firstpass" },
            { shader = shaders.glownum(), source=2, target = 1, clear = 0 },
+
      { shader = shaders.rglownum(), source=2, target = 1, clear = 0 },
            { shader = shaders.glownum(), source=1, target = 2, clear = 0 },
+
      { shader = shaders.rglownum(), source=1, target = 2, clear = 0 },
            { shader = shaders.glownum(), source=2, target = 1, clear = 0 },
+
      { shader = shaders.rglownum(), source=2, target = 0, clear = 0, comp_dst=1, comp_src=1, variable = "shaders.rglownum._i_lastpass" }})
            { shader = shaders.glownum(), source=1, target = 2, clear = 0 },
+
      shader_rglow = on
            { shader = shaders.glownum(), source=2, target = 1, clear = 0 },
+
      shader_rglowradius = blurradius
            { shader = shaders.glownum(), source=1, target = 0, clear = 0, comp_dst=1, variable = "shaders.glownum._i_lastpass" }})
+
      shader_rglowexp = alpha
        shader_glow = on
 
        shader_glowradius = blurradius
 
        shader_glowexp = 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", basic_vsh, shader_effects.light1.shader)
+
      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._i_lights_count = lights
+
     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  
+
      t3[k] = v
 
     end
 
     end
     for k,v in pairs(t2) do  
+
     for k,v in pairs(t2) do
        if(type(k)=="string")then
+
      if(type(k)=="string")then
            t3[k] = v  
+
        t3[k] = v
        else
+
      else
            t3[offset + k] = v  
+
        t3[offset + k] = v
        end
+
      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)
    if(shader_effects.light1.num==nil)then
 
        shader_effects.light1.num = shader("light1", basic_vsh, shader_effects.light1.shader)
 
    end
 
 
     local l = "lights["..index.."]."
 
     local l = "lights["..index.."]."
 
     position[3]=standardparam(position[3],1.0)
 
     position[3]=standardparam(position[3],1.0)
Line 1,572: 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.."exponent"] = standardparam(exponent,90)
        sh[l.."cutoff"] = standardparam(cutoff,0)
+
      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=2, target = 1, clear = 0},
+
{ shader = shaders.bnum(), source=1, target = 2, clear = 0, variable = "shaders.bnum._i_firstpass" },
        { shader = shaders.bnum(), source=1, target = 2, clear = 0 },
+
{ shader = shaders.bnum(), source=2, target = 1, clear = 0},
        { shader = shaders.bnum(), source=2, target = 1, clear = 0 },
+
{ shader = shaders.bnum(), source=1, target = 2, clear = 0 },
        { shader = shaders.bnum(), source=1, target = 2, clear = 0 },
+
{ shader = shaders.bnum(), source=2, target = 1, clear = 0 },
        { shader = shaders.bnum(), source=2, target = 0, clear = 0, comp_dst=0, variable = "shaders.bnum._i_lastpass" }})
+
{ 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
+
      for k,v in pairs(shader_passes[2]) do
            if(v[1]==id)then
+
        if(v[1]==id)then
                table.remove(shader_passes[2], k)
+
          table.remove(shader_passes[2], k)
                break
+
          break
            end
+
        end
        end  
+
      end
 
     else
 
     else
        if shader_passes[position][1]==id then
+
      if shader_passes[position][1]==id then
            shader_passes[position]={}
+
        shader_passes[position]={}
        end
+
      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
+
      local found = false
        for k,v in pairs(shader_passes[2]) do
+
      for k,v in pairs(shader_passes[2]) do
            if(v[1]==id)then
+
        if(v[1]==id)then
                found = true
+
          found = true
            end
 
        end
 
        if not found then
 
            table.insert(shader_passes[2], {id, passes})
 
 
         end
 
         end
 +
      end
 +
      if not found then
 +
        table.insert(shader_passes[2], {id, passes})
 +
      end
 
     else
 
     else
        if(shader_passes[position][1]==nil)then
+
      if(shader_passes[position][1]==nil)then
            shader_passes[position]={id, passes}
+
        shader_passes[position]={id, passes}
        end
+
      end
 
     end
 
     end
 
     passesUpdate()
 
     passesUpdate()
end
+
  end
  
function passesUpdate()
+
  function passesUpdate()
 
     for k,v in pairs(shaders_compiled) do
 
     for k,v in pairs(shaders_compiled) do
        if(k~="glow" and k~="num" and k~="blur" and shader_effects[k].num==nil)then
+
      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, basic_vsh, shader_effects[k].shader)
+
        shader_effects[k].num = shader(k, "", shader_effects[k].shader)
        end
+
      end
 
     end
 
     end
  
 
     if shader_active == false then
 
     if shader_active == false then
        shaderSetOptions({ { shader = shaders.num(), source=0, target = 0, clear = 0 } })
+
      shaderSetOptions({ { shader = shaders.num(), source=0, target = 0, clear = 0 } })
 
     else
 
     else
        -- composite passes
+
      -- composite passes
        local worktable = {}
+
      local worktable = {}
        local lastpass = 0
+
      local lastpass = 0
        for k,v in pairs(shader_passes) do
+
      for k,v in pairs(shader_passes) do
            if(k==2)then
+
        if(k==2)then
                for k,v in pairs(shader_passes[2]) do
+
          for k,v in pairs(shader_passes[2]) do
                    for i,v in pairs(shader_passes[2][k][2]) do
+
            for i,v in pairs(shader_passes[2][k][2]) do
                        v.source = lastpass + 1
+
              v.source = lastpass + 1
                        lastpass = (lastpass + 1) % 2
+
              lastpass = (lastpass + 1) % 2
                        v.target = lastpass + 1
+
              v.target = lastpass + 1
                    end
+
            end
                    worktable = table.join(worktable,v[2])
+
            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
            elseif v[2] ~= nil then
+
              end
                if k~=1 then
 
                    if k==5 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) and i==#shader_passes[k][2] then
 
                                v.target = 0
 
                            end
 
                        end
 
                    end
 
                end
 
                worktable = table.join(worktable,v[2])
 
 
             end
 
             end
 +
          end
 +
          worktable = table.join(worktable,v[2])
 
         end
 
         end
        for k,v in pairs(worktable) do  
+
      end
            if type(v) == "table" and v.variable ~= nil then
+
      for k,v in pairs(worktable) do
                loadstring(v.variable.."="..(k-1))()
+
        if type(v) == "table" and v.variable ~= nil then
            end
+
          load(v.variable.."="..(k-1))()
 
         end
 
         end
        shaderSetOptions(worktable)
+
      end
 +
      shaderSetOptions(worktable)
 
     end
 
     end
end
+
  end
  
function shaderAddEffect(name, _table)
+
  function shaderAddEffect(name, _table)
 
     if(shader_effects[name].num==nil)then
 
     if(shader_effects[name].num==nil)then
        shader_effects[name].num = shader(name, basic_vsh, shader_effects[name].shader)
+
      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,704: Line 1,003:
 
     sh.resolution = {game.WindowResolution.x, game.WindowResolution.y}
 
     sh.resolution = {game.WindowResolution.x, game.WindowResolution.y}
 
     bind(name, "time", field("shader_iTime"))
 
     bind(name, "time", field("shader_iTime"))
     sh.strength=0
+
     sh.strength=1
  
 
     if _table~=nil then
 
     if _table~=nil then
        for k,v in pairs(_table) do
+
      for k,v in pairs(_table) do
            sh[k] = v
+
        sh[k] = v
        end
+
      end
 
     end
 
     end
end
+
  end
  
function shaderRemoveEffect(name)
+
  function shaderRemoveEffect(name)
 
     passesRemove(2,name)
 
     passesRemove(2,name)
 
     unbind(name, "time")
 
     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
 
     if shaders.c_scene:getId().id~=game.CurrentScene:getId().id then
        shaders.c_scene = game.CurrentScene
+
      shaders.c_scene = game.CurrentScene
        passesUpdate()
+
      passesUpdate()
        for k,v in pairs(shaders_compiled) do
+
      for k,v in pairs(shaders_compiled) do
            local sh = shader_effects[k]
+
        local sh = shader_effects[k]
            if sh ~= nil then
+
        if sh ~= nil then
                sh = sh.num
+
          sh = sh.num
            elseif k=="glow" then
+
        elseif k=="glow" then
                sh = shaders.glownum
+
          sh = shaders.glownum
            elseif k=="num" then
+
        elseif k=="rglow" then
                sh = shaders.num
+
          sh = shaders.rglownum
            elseif k=="blur" then
+
        elseif k=="num" then
                sh = shaders.bnum
+
          sh = shaders.num
            end
+
        elseif k=="blur" then
            for k,f in pairs(v) do
+
          sh = shaders.bnum
                sh[k] = f
+
        end
            end
+
        for k,f in pairs(v) do
 +
          sh[k] = f
 
         end
 
         end
 +
      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
+
      shader_iTime=0
 
     end
 
     end
  
Line 1,752: 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 table.getn(shader_passes[3])==1 then
+
     if shader_blur==0 and #(shader_passes[3])==1 then
        passesRemove(2, "blur")
+
      passesRemove(2, "blur")
 
     else
 
     else
        local streng = math.max(shader_blur,0)
+
      local streng = math.max(shader_blur,0)
        shaders.bnum.down = math.max(streng,1)
+
      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.weights={math.min(streng,1)*0.15,1-math.min(streng,1)*(1-0.4)}
        shaders.bnum.exposure = 1
+
      shaders.bnum.exposure = 1
 
     end
 
     end
 
     if shader_glow == 1 then
 
     if shader_glow == 1 then
        local streng = math.max(shader_glowradius,0)
+
      local streng = math.max(shader_glowradius,0)
        shaders.glownum.down = math.max(streng,1)
+
      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.weights={math.min(streng,1)*0.15,1-math.min(streng,1)*(1-0.4)}
        shaders.glownum.exposure = shader_glowexp
+
      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
 
     end
  
     local rot = matrix{{math.cos(shader_rotate),math.sin(shader_rotate),0,0},{-math.sin(shader_rotate),math.cos(shader_rotate),0,0},{0,0,1,0},{0,0,0,1}}
+
     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},{0,shader_scale,0,0},{0,0,1,0},{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},{0,1,0,0},{0,0,1,0},{-c_res.x/2,-c_res.y/2,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},{0,1,0,0},{0,0,1,0},{c_res.x/2,c_res.y/2,0,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},{0,1,0,0},{0,0,1,0},{-shader_offsetx/shader_downsize,-shader_offsety/shader_downsize,0,1}}
+
     local translate3 = matrix{{1,0,0},{0,1,0},{-shader_offsetx/shader_downsize,-shader_offsety/shader_downsize,1}}
     local identity = matrix{{1,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1}}
+
 
    shaders.num.cam_mat = ((((translate*rot)*translate2)*translate3)*scale):tofloat()
+
     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
+
      for k,v in pairs(binding.binding) do
            if(v[3]==nil)then
+
        if(v[3]==nil)then
                if(v[4]=="")then
+
          if(v[4]=="")then
                    binding = {active=false, binding = {}}
+
            binding = {active=false, binding = {}}
                    break
+
            break
                end
+
          end
                v[3]=loadstring(v[4]:fromhex())()
+
          v[3]=load(v[4]:fromhex())()
            end
 
            shader_effects[v[1]].num[v[2]] = v[3]()
 
 
         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()
 
     return getCursorPos()
end
+
  end
function inteval(a)
+
  function inteval(a)
 
     if(type(a)=="function")then
 
     if(type(a)=="function")then
        return a()
+
      return a()
 
     else
 
     else
        return a
+
      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(a.x~=nil)then
            if(b~=nil)then
+
        if(b~=nil)then
                return {a.x,a.y,inteval(b)}
+
          return {a.x,a.y,inteval(b)}
            else
+
        else
                return {a.x,a.y}
+
          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
 
         end
    else
+
      else if(a[0]~=nil)then
        local b = inteval(b)
+
        if(c~=nil)then
        if(type(b)=="table")then
+
          return {a[0],a[1],inteval(c)}
            if(b.x~=nil)then
 
                  return {a,b.x,b.y}
 
            else
 
                  return {a,b[0],b[1]}
 
            end
 
 
         else
 
         else
            if(c~=nil)then
+
          return {a[0],a[1]}
                return {a, b, inteval(c)}
 
            else
 
                return {a, b}
 
            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
 
end
function point(a, b, c)
+
function shaderPoint(a, b, c)
    return function ()
+
  return function ()
        return pointeval(a,b,c)
+
    return pointeval(a,b,c)
    end
+
  end
 
end
 
end
 
function field(a)
 
function field(a)
    return loadstring("return function() return "..a.." end")()
+
  return load("return function() return "..a.." end")()
 
end
 
end
 
function inverty(a)
 
function inverty(a)
    return function()  
+
  return function()
        local pos = inteval(a)
+
    local pos = inteval(a)
        pos.y = c_res.y-pos.y
+
if not graphics.isUpsideDown() then
        return pos
+
pos.y = c_res.y-pos.y
    end
+
end
 +
    return pos
 +
  end
 
end
 
end
 
function scrollfix(a)
 
function scrollfix(a)
    return function()  
+
  return function()
        local pos = inteval(a)
+
    local pos = inteval(a)
        local scroll = game.ScrollPosition
+
    local scroll = game.ScrollPosition
        pos.x = pos.x - scroll.x
+
    pos.x = pos.x - scroll.x
        pos.y = pos.y - scroll.y
+
    pos.y = pos.y - scroll.y
        return pos
+
    return pos
    end
+
  end
 
end
 
end
 
function bind(shader, name, source)
 
function bind(shader, name, source)
    local t = DataDumper(source)
+
  local t = string.dump(source)
    table.insert(binding.binding, {shader, name, source, t:tohex()})
+
  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
+
  for k,v in pairs(binding.binding) do
        if v[2] == name and v[1] == shader then
+
    if v[2] == name and v[1] == shader then
            table.remove(binding.binding, k)
+
      table.remove(binding.binding, k)
            break
+
      break
        end
 
 
     end
 
     end
 +
  end
 
end
 
end
 
function offset(a,b)
 
function offset(a,b)
    return function()  
+
  return function()
        local pos = inteval(a)
+
    local pos = inteval(a)
        pos.x = pos.x + b[1]
+
    pos.x = pos.x + b[1]
        pos.y = pos.y + b[2]
+
    pos.y = pos.y + b[2]
        return pos
+
    return pos
    end
+
  end
 
end
 
end
 
function dist(a,b)
 
function dist(a,b)
    return function()  
+
  return function()
        local a = inteval(a)
+
    local a = inteval(a)
        local b = inteval(b)
+
    local b = inteval(b)
        a.x = a.x - b.x
+
    a.x = a.x - b.x
        a.y = a.y - b.y
+
    a.y = a.y - b.y
        return math.sqrt(a.x*a.x + a.y*a.y)
+
    return math.sqrt(a.x*a.x + a.y*a.y)
    end
+
  end
 
end
 
end
 
function factor(a,b)
 
function factor(a,b)
    return function()  
+
  return function()
        return inteval(a)*b
+
    return inteval(a)*b
    end
+
  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,905: Line 1,295:
 
! style="text-align:left" | Name !! style="text-align:left" | Description
 
! style="text-align:left" | Name !! style="text-align:left" | Description
 
|-
 
|-
| [[media:shader_toolkit_0.8.7.lua|shader_toolkit_0.8.7.lua]] || The main script in .lua format. ''Visionaire Studio 4.1+ is required for this script''.
+
| [https://www.visionaire-studio.com/luadocs/#finished-scripts shader toolkit (VS5+)] || ''Visionaire Studio 5.0.8+ is required''.
|}
+
|}{{toc}}
{{toc}}
 

Latest revision as of 11: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.