Shader (CMS)
From The Official Visionaire Studio: Adventure Game Engine Wiki
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
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(easeQuintOut) -- Stop following character & reset viewport
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 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)
if name == "" then name = game:getLink(VGameCurrentCharacter):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
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 that follows character; only active when loop enabled * --
function followCharacter()
if shader_follow.on == 1 then
shaderZoomCharacter(shader_follow.name, shader_follow.c_scale, shader_follow.delay, shader_follow.easing)
end
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)
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()