Difference between revisions of "Shader (CMS)"

From The Official Visionaire Studio: Adventure Game Engine Wiki
(Created page with "{| class="wikitable" style="width:100%" |- ! style="text-align:left" | Name !! style="text-align:left" | Type !! style="text-align:left" | By |- | Shader Toolkit || Definition...")
 
Line 37: Line 37:
 
shaderBlur(0, 0, 3000)
 
shaderBlur(0, 0, 3000)
 
shaderSaturation(1, 3000)
 
shaderSaturation(1, 3000)
shaderLightness(1, 3000)
+
shaderLightness(0, 3000)
 
shaderContrast(1, 3000)
 
shaderContrast(1, 3000)
shaderHue(0, 2000)
+
shaderHue(0, 3000)
 
shaderColorize(0, 0, 3000)
 
shaderColorize(0, 0, 3000)
 
</syntaxhighlight>
 
</syntaxhighlight>
Line 45: Line 45:
 
== Main Script ==
 
== Main Script ==
 
<syntaxhighlight>
 
<syntaxhighlight>
--[[
+
--
Dynamic action names for dragged items [v2] (20/02/2014)
+
-- Shader Toolkit Hue, Saturation, Luminance, Blur, Noise, Camera Control
Written by AFRLme [Lee Clarke]
+
-- (c) 2014 Simon Scheckel, Visionaire Studio Engine - with edits by AFRLme
-- + --
+
-- Version 0.71
alternatingfrequencies@hotmail.com | skype @ AFRLme
+
--
-- + --
+
-- Matrix functions from https://github.com/davidm/lua-matrix/blob/master/lua/matrix.lua
This script is donation optional. In game credit is non-negotiable.
+
-- Developers:    Michael Lutz (chillcode) - original author    David Manura http://lua-users.org/wiki/DavidManura
You are free to: ¹ use it in your game(s). ² modify the script.
+
--
Do not remove - or edit - this comment block.
+
-- 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()
 +
-- 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(on, strength, delay) -- strength 0.8 to 1.4 recommended, programmed for 1
 +
-- shaderSaturation(factor, delay)
 +
-- shaderLightness(offset, delay)
 +
-- shaderContrast(contrast, delay)
 +
-- shaderHue(target, delay)
 +
-- shaderColorize(hue, strength, delay)
 +
--
 +
-- shaderActivate()
 +
-- shaderDeactivate()
 +
--
 +
-- Read no further if the word matrix multiplication frightens you
 +
--
  
-- * local variables * --
+
local matrix = {_TYPE='module', _NAME='matrix', _VERSION='0.2.11.20120416'}
local item, txt, current, lang, old, new, iw, cj, val  -- empty variables
+
local matrix_meta = {}
  
-- * tables * --
+
function matrix:new( rows, columns, value )
old = {} -- table which will contain original item names
+
        if type( rows ) == "table" then
new = {} -- table which will contain updated names
+
                if type(rows[1]) ~= "table" then
iw = {} -- initial word table
+
                        return setmetatable( {{rows[1]},{rows[2]},{rows[3]}},matrix_meta )
iw["English"] = {"Use ", "Give ", "Show ", "Combine "}
+
                end
iw["French"] = {"Usage ", "Donner ", "Montrer ", "Combiner "}
+
                return setmetatable( rows,matrix_meta )
iw["German"] = {"Benutzen ", "Geben ", "Zeigen ", "Kombinieren "}
+
        end
iw["Spanish"] = {"Usar ", "Dar ", "Mostrar ", "Combinar "}
+
        local mtx = {}
cj = {} -- conjunction word table
+
        local value = value or 0
cj["English"] = {" on ", " to ", " to ", " with "}
+
        if columns == "I" then
cj["French"] = {" en ", " à ", " à ", " avec "}
+
                for i = 1,rows do
cj["German"] = {" auf ", " zu ", " zu ", " mit "}
+
                        mtx[i] = {}
cj["Spanish"] = {" en ", " a ", " a ", " con "}
+
                        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
 +
 
 +
setmetatable( matrix, { __call = function( ... ) return matrix.new( ... ) end } )
 +
 
 +
-- End of matrix functions
 +
 
 +
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
 +
 
 +
shader = {_temporary_=0, num = shaderCompile([[#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 ()
 +
{
 +
  if(pass==0)
 +
  gl_Position = mvp_mat * (cam_mat * vec4(position.x,position.y,0.0,1.0));
 +
else
 +
gl_Position = mvp_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 float noise;
 +
uniform float noiseFactor;
 +
uniform float iTime;
 +
uniform vec4 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);
 +
}
 +
 
 +
void blurFast(){
 +
        vec4 sum = vec4(0.0);
 +
        float blurSize=1.0/2048.0*(4.0-float(pass));
 +
        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;
 +
}
 +
 
 +
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.x = mix(fragHSV.x, weights[3], weights[2]);
 +
        fragHSV.y *= shader_coeff[1];
 +
        fragHSV.z = (fragHSV.z - 0.5)*shader_coeff[2]+0.5+shader_coeff[3];
 +
    fragRGB = hsv2rgb(fragHSV);
 +
    vec4 color = vec4(fragRGB, textureColor.w);
 +
    if(noise==1.0)
 +
                color+= noiseFactor*rand(texcoord.xy+vec2(iTime*2.0,0.0));
 +
    gl_FragColor=color;
 +
}
 +
void main()
 +
{   
 +
if(pass==0) 
 +
        sat();
 +
else if(pass!=5)
 +
        blurFast();
 +
else
 +
        identity();
 +
}]])}
 +
shader_coeff0=0
 +
shader_coeff1=1
 +
shader_coeff2=1
 +
shader_coeff3=0
 +
shader_mweight=1
 +
shader_weight=0
 +
shader_downsize=1
 +
shader_colorize=0
 +
shader_color=0
 +
shader_iTime = 0
 +
shader_noise=0
 +
shader_noiseStrength=0
 +
shader_passes=2
 +
 
 +
shader_rotate=0.0
 +
shader_scale = 1.0
 +
shader_offsetx = 0.0
 +
shader_offsety = 0.0
 +
shader_noise = 0.0
 +
shader_follow = {on=0, name="", c_scale=1, easing = easeQuintOut, delay = 0}
 +
 
 +
c_res=game:getPoint(VGameWindowResolution)
 +
 
 +
shaderSetOptions("active",shader.num)
 +
shaderSetOptions("downsize",1)
 +
shaderSetOptions("passes",2)
 +
shaderUniform("weights",{shader_weight,shader_mweight,shader_colorize,shader_color})
 +
shaderUniform("shader_coeff",{shader_coeff0,shader_coeff1,shader_coeff2,shader_coeff3})
 +
 
 +
function shaderStopFollow()
 +
        shader_follow.on = 0
 +
end
 +
 
 +
function shaderFollowCharacter(name, c_scale, delay)
 +
        shader_follow.on = 1
 +
        shader_follow.name = name
 +
        shader_follow.c_scale = c_scale
 +
        shader_follow.delay = delay
 +
end
 +
 
 +
function shaderZoomCharacter(name, c_scale, delay, easing)
 +
        local c_position={}
 +
        if(name=="")then
 +
                c_position=game:getLink(VGameCurrentCharacter):getPoint(VCharacterPosition)
 +
        else
 +
                c_position=getObject("Characters["..name.."]"):getPoint(VCharacterPosition)
 +
        end
 +
        local c_scroll=game:getPoint(VGameScrollPosition)
 +
        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)
 +
        local c_position={}
 +
        c_position=object:getPoint(VObjectPosition)
 +
        local c_scroll=game:getPoint(VGameScrollPosition)
 +
        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 shaderNoise(on, strength,delay)
 +
        shaderUniform("noise",on)
 +
        startTween("shader_noiseStrength", shader_noiseStrength, strength, delay,easeLinearInOut)
 +
        shader_noise=on
 +
end
 +
 
 +
function shaderBlur(on, strength, delay)
 +
        if(on==1)then
 +
                startTween("shader_mweight",shader_mweight,0.4/strength/strength, delay,easeBackInOut)
 +
                startTween("shader_weight", shader_weight, 0.15*strength, delay,easeBackInOut)
 +
                startTween("shader_downsize", shader_downsize, 4*strength, delay, easeLinearInOut)
 +
                shader_passes=6
 +
        else
 +
                startTween("shader_mweight",shader_mweight,1, delay,easeBackInOut)
 +
                startTween("shader_weight", shader_weight, 0, delay,easeBackInOut)
 +
                startTween("shader_downsize", shader_downsize, 1, delay, easeLinearInOut)
 +
                startTween("shader_passes", shader_passes, 2, delay, easeNoneInOut)
 +
        end
 +
end
  
-- * function for udating object name with action text * --
+
function shaderSaturation(factor, delay)
function itemActionName()
+
        startTween("shader_coeff1",shader_coeff1,factor,delay,easeLinearInOut)
item = game:getLink(VGameUsedItem) -- get currently held item
 
current = game:getLink(VGameCurrentObject) -- get current object (under cursor)
 
lang = game:getLink(VGameStandardLanguage):getName() -- get current game language
 
val = getObject("Values[conjunction_class]"):getInt(VValueInt) -- get conjunction class value
 
-- + --
 
if not item:isEmpty() then -- if held item exists then...
 
  txt = item:getLink(VObjectName):getLinks(VTextAll) -- get all texts for the held item
 
  for i = 1, table.maxn(txt) do if txt[i]:getLink(VTextLanguageLanguage):getName() == lang then item = txt[i]:getStr(VTextLanguageText) end end -- store item name
 
  -- + --
 
  new = current:getLink(VObjectName):getLinks(VTextAll) -- get all texts for the object under cursor
 
  for i = 1, table.maxn(new) do table.insert(old, new[i]:getStr(VTextLanguageText))  end -- insert string names of table above
 
  -- + --
 
  for i = 1, table.maxn(new) do if new[i]:getLink(VTextLanguageLanguage):getName() == lang then new[i]:setValue(VTextLanguageText, iw[lang][val] .. item .. cj[lang][val] .. old[i]) end end -- update object name with action text (initial word, item, conjunction word, target)
 
end 
 
 
end
 
end
  
-- * function for resetting object name back to original name * --
+
function shaderLightness(offset, delay)
function resetItemActionName()
+
        startTween("shader_coeff3",shader_coeff3,offset,delay,easeLinearInOut)
  for i = 1, table.maxn(new) do new[i]:setValue(VTextLanguageText, old[i]) end -- reset all text (for each language) back to original text...
+
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
 +
 
 +
function shaderViewport(zoom, x, y, rotation, delay, easing)
 +
        startTween("shader_offsetx", shader_offsetx, x, delay,easing)
 +
        startTween("shader_offsety", shader_offsety, y, delay,easing)
 +
        startTween("shader_scale", shader_scale, zoom, delay,easing)   
 +
        startTween("shader_rotate", shader_rotate, rotation, delay,easing)     
 +
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 shaderActivate()
 +
        shaderSetOptions("active",shader.num)
 +
end
 +
 
 +
function shaderDeactivate()
 +
        shaderSetOptions("active",0)
 +
end
 +
 
 +
function shaderMain()
 +
    shader_iTime=shader_iTime+0.0166
 +
    if(shader_iTime>1)then
 +
                shader_iTime=0
 +
    end
 +
        shaderUniform("iTime",shader_iTime*0.1)
 +
        shaderUniform("noiseFactor",shader_noiseStrength)
 +
        shaderUniform("weights",{shader_weight,shader_mweight,shader_colorize,shader_color})
 +
        shaderUniform("shader_coeff",{shader_coeff0,shader_coeff1,shader_coeff2,shader_coeff3})
 +
        shaderSetOptions("downsize",shader_downsize)
 +
        shaderSetOptions("passes",shader_passes)
 +
     
 +
        if(shader_follow.on==1)then
 +
                shaderZoomCharacter(shader_follow.name, shader_follow.c_scale, shader_follow.delay, shader_follow.easing)
 +
        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 scale = matrix{{shader_scale,0,0,0},{0,shader_scale,0,0},{0,0,1,0},{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 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 translate3 = matrix{{1,0,0,0},{0,1,0,0},{0,0,1,0},{-shader_offsetx/shader_downsize,-shader_offsety/shader_downsize,0,1}}
 +
        shaderUniform("cam_mat",matrix.tofloat(matrix.mul(matrix.mul(matrix.mul(matrix.mul(translate,rot),translate2),translate3),scale)))
 
end
 
end
 +
registerEventHandler("mainLoop", "shaderMain")
 +
shaderMain()
 
</syntaxhighlight>
 
</syntaxhighlight>

Revision as of 15:49, 14 August 2014

Name Type By
Shader Toolkit Definition SimonS

This script offers some easy functions to use shader power. It ranges from blur, noise, saturation, contrast, lightness, colorize to some simple camera controls.

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.

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) -- Follow character Heinz with a slow camera
shaderStopFollow() -- Stop following
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, 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() -- Stop following

shaderNoise(0, 0, 3000)
shaderBlur(0, 0, 3000)
shaderSaturation(1, 3000)
shaderLightness(0, 3000)
shaderContrast(1, 3000)
shaderHue(0, 3000)
shaderColorize(0, 0, 3000)

Main Script

--
-- Shader Toolkit Hue, Saturation, Luminance, Blur, Noise, Camera Control
-- (c) 2014 Simon Scheckel, Visionaire Studio Engine - with edits by AFRLme
-- Version 0.71
--
-- 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()
-- 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(on, strength, delay) -- strength 0.8 to 1.4 recommended, programmed for 1
-- shaderSaturation(factor, delay)
-- shaderLightness(offset, delay)
-- shaderContrast(contrast, delay)
-- shaderHue(target, delay)
-- shaderColorize(hue, strength, delay)
--
-- shaderActivate()
-- shaderDeactivate()
--
-- 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

setmetatable( matrix, { __call = function( ... ) return matrix.new( ... ) end } )

-- End of matrix functions

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

shader = {_temporary_=0, num = shaderCompile([[#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 ()
{
  if(pass==0)
  gl_Position = mvp_mat * (cam_mat * vec4(position.x,position.y,0.0,1.0));
else
gl_Position = mvp_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 float noise;
uniform float noiseFactor;
uniform float iTime;
uniform vec4 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);
}

void blurFast(){
        vec4 sum = vec4(0.0);
        float blurSize=1.0/2048.0*(4.0-float(pass));
        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;
}

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.x = mix(fragHSV.x, weights[3], weights[2]);
        fragHSV.y *= shader_coeff[1];
        fragHSV.z = (fragHSV.z - 0.5)*shader_coeff[2]+0.5+shader_coeff[3];
    fragRGB = hsv2rgb(fragHSV);
    vec4 color = vec4(fragRGB, textureColor.w);
    if(noise==1.0)
                color+= noiseFactor*rand(texcoord.xy+vec2(iTime*2.0,0.0));
    gl_FragColor=color;
}
void main()
{    
if(pass==0)  
        sat();
else if(pass!=5)
        blurFast();
else
        identity();
}]])}
shader_coeff0=0
shader_coeff1=1
shader_coeff2=1
shader_coeff3=0
shader_mweight=1
shader_weight=0
shader_downsize=1
shader_colorize=0
shader_color=0
shader_iTime = 0
shader_noise=0
shader_noiseStrength=0
shader_passes=2

shader_rotate=0.0
shader_scale = 1.0
shader_offsetx = 0.0
shader_offsety = 0.0
shader_noise = 0.0
shader_follow = {on=0, name="", c_scale=1, easing = easeQuintOut, delay = 0}

c_res=game:getPoint(VGameWindowResolution)

shaderSetOptions("active",shader.num)
shaderSetOptions("downsize",1)
shaderSetOptions("passes",2)
shaderUniform("weights",{shader_weight,shader_mweight,shader_colorize,shader_color})
shaderUniform("shader_coeff",{shader_coeff0,shader_coeff1,shader_coeff2,shader_coeff3})

function shaderStopFollow()
        shader_follow.on = 0
end

function shaderFollowCharacter(name, c_scale, delay)
        shader_follow.on = 1
        shader_follow.name = name
        shader_follow.c_scale = c_scale
        shader_follow.delay = delay
end

function shaderZoomCharacter(name, c_scale, delay, easing)
        local c_position={}
        if(name=="")then
                c_position=game:getLink(VGameCurrentCharacter):getPoint(VCharacterPosition)
        else
                c_position=getObject("Characters["..name.."]"):getPoint(VCharacterPosition)
        end
        local c_scroll=game:getPoint(VGameScrollPosition)
        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)
        local c_position={}
        c_position=object:getPoint(VObjectPosition)
        local c_scroll=game:getPoint(VGameScrollPosition)
        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 shaderNoise(on, strength,delay)
        shaderUniform("noise",on)
        startTween("shader_noiseStrength", shader_noiseStrength, strength, delay,easeLinearInOut)
        shader_noise=on
end

function shaderBlur(on, strength, delay)
        if(on==1)then
                startTween("shader_mweight",shader_mweight,0.4/strength/strength, delay,easeBackInOut)
                startTween("shader_weight", shader_weight, 0.15*strength, delay,easeBackInOut)
                startTween("shader_downsize", shader_downsize, 4*strength, delay, easeLinearInOut)
                shader_passes=6
        else
                startTween("shader_mweight",shader_mweight,1, delay,easeBackInOut)
                startTween("shader_weight", shader_weight, 0, delay,easeBackInOut)
                startTween("shader_downsize", shader_downsize, 1, delay, easeLinearInOut)
                startTween("shader_passes", shader_passes, 2, delay, easeNoneInOut)
        end
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

function shaderViewport(zoom, x, y, rotation, delay, easing)
        startTween("shader_offsetx", shader_offsetx, x, delay,easing)
        startTween("shader_offsety", shader_offsety, y, delay,easing)
        startTween("shader_scale", shader_scale, zoom, delay,easing)    
        startTween("shader_rotate", shader_rotate, rotation, delay,easing)      
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 shaderActivate()
        shaderSetOptions("active",shader.num)
end

function shaderDeactivate()
        shaderSetOptions("active",0)
end

function shaderMain()
    shader_iTime=shader_iTime+0.0166
    if(shader_iTime>1)then
                shader_iTime=0
    end
        shaderUniform("iTime",shader_iTime*0.1)
        shaderUniform("noiseFactor",shader_noiseStrength)
        shaderUniform("weights",{shader_weight,shader_mweight,shader_colorize,shader_color})
        shaderUniform("shader_coeff",{shader_coeff0,shader_coeff1,shader_coeff2,shader_coeff3})
        shaderSetOptions("downsize",shader_downsize)
        shaderSetOptions("passes",shader_passes)
       
        if(shader_follow.on==1)then
                shaderZoomCharacter(shader_follow.name, shader_follow.c_scale, shader_follow.delay, shader_follow.easing)
        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 scale = matrix{{shader_scale,0,0,0},{0,shader_scale,0,0},{0,0,1,0},{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 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 translate3 = matrix{{1,0,0,0},{0,1,0,0},{0,0,1,0},{-shader_offsetx/shader_downsize,-shader_offsety/shader_downsize,0,1}}
        shaderUniform("cam_mat",matrix.tofloat(matrix.mul(matrix.mul(matrix.mul(matrix.mul(translate,rot),translate2),translate3),scale)))
end
registerEventHandler("mainLoop", "shaderMain")
shaderMain()