Difference between revisions of "Custom Shader Examples"
(Created page with "__NOTOC__ '''Parent:''' Writing Custom Shaders<br/> === A Grey Shader === The code below defines a Grey shader consisting of: * mycshaders/vShaderGrey.glsl vertex shader...") |
|||
(6 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
− | |||
'''Parent:''' [[Writing Custom Shaders]]<br/> | '''Parent:''' [[Writing Custom Shaders]]<br/> | ||
+ | |||
+ | |||
+ | __TOC__ | ||
+ | |||
+ | '''Note: not all shaders will display correctly in html5''' | ||
=== A Grey Shader === | === A Grey Shader === | ||
Line 76: | Line 80: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | {{ | + | === A Wave Shader === |
+ | {{#widget:GApp|app=Playground_Shaders_Wave.GApp|width=480|height=320|auto=1}} | ||
+ | |||
+ | The code below defines a Wave shader consisting of: | ||
+ | * mycshaders/vShaderWave.glsl vertex shader | ||
+ | * mycshaders/fShaderWave.glsl fragment shader | ||
+ | |||
+ | Here the shader files are in the '''assets/mycshaders''' directory. | ||
+ | |||
+ | '''GLSL Vertex Shader:''' ''mycshaders/vShaderWave.glsl'' | ||
+ | <syntaxhighlight lang="c"> | ||
+ | attribute vec4 POSITION0; | ||
+ | attribute vec2 TEXCOORD0; | ||
+ | uniform mat4 g_MVPMatrix; | ||
+ | varying vec2 texCoord; | ||
+ | |||
+ | void main() | ||
+ | { | ||
+ | gl_Position = g_MVPMatrix * POSITION0; | ||
+ | texCoord = TEXCOORD0; | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | '''GLSL Fragment Shader:''' ''mycshaders/fShaderWave.glsl'' | ||
+ | <syntaxhighlight lang="c"> | ||
+ | uniform lowp sampler2D g_Texture; | ||
+ | uniform lowp vec4 g_Color; | ||
+ | uniform highp float time; | ||
+ | varying highp vec2 texCoord; | ||
+ | |||
+ | void main() | ||
+ | { | ||
+ | highp vec2 tc = texCoord.xy; | ||
+ | // highp float dist = cos(tc.x * 24.0 - time * 4.0) * 0.02; | ||
+ | highp float dist = cos(tc.x * 2.0 - time * 8.0) * 0.02; | ||
+ | highp vec2 uv = tc + dist; | ||
+ | gl_FragColor = g_Color * texture2D(g_Texture, uv); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | '''Lua Code''' | ||
+ | <syntaxhighlight lang="lua"> | ||
+ | -- open gl shader | ||
+ | local shaderwave = Shader.new("mycshaders/vShaderWave", "mycshaders/fShaderWave", 0, | ||
+ | { | ||
+ | {name="g_MVPMatrix", type=Shader.CMATRIX, sys=Shader.SYS_WVP, vertex=true}, | ||
+ | {name="g_Color", type=Shader.CFLOAT4, mult=1, sys=Shader.SYS_COLOR}, | ||
+ | {name="g_Texture", type=Shader.CTEXTURE, mult=1, vertex=false}, | ||
+ | {name="time", type=Shader.CFLOAT, mult=1, vertex=false} | ||
+ | }, | ||
+ | { | ||
+ | {name="POSITION0", type=Shader.DFLOAT, mult=3, slot=0, offset=0}, | ||
+ | {name="vColor", type=Shader.DUBYTE, mult=0, slot=1, offset=0}, | ||
+ | {name="TEXCOORD0", type=Shader.DFLOAT, mult=2, slot=2, offset=0} | ||
+ | } | ||
+ | ) | ||
+ | |||
+ | application:setBackgroundColor(0x333333) | ||
+ | |||
+ | local bitmap = Bitmap.new(Texture.new("gfx/test.png")) | ||
+ | local bitmap2 = bitmap:clone() | ||
+ | -- position | ||
+ | bitmap:setPosition(32*1, 32*4) | ||
+ | bitmap2:setPosition(32*6, 32*1) | ||
+ | -- shaders | ||
+ | bitmap:setShader(shaderwave) | ||
+ | bitmap2:setShader(shaderwave) | ||
+ | -- order | ||
+ | stage:addChild(bitmap) | ||
+ | stage:addChild(bitmap2) | ||
+ | |||
+ | -- loop | ||
+ | local timer = 0 | ||
+ | stage:addEventListener(Event.ENTER_FRAME, function(e) | ||
+ | timer += 0.018 | ||
+ | shaderwave:setConstant("time", Shader.CFLOAT, 1, timer) | ||
+ | bitmap:setX(bitmap:getX() + 1) | ||
+ | if bitmap:getX() > 400 then bitmap:setX(-80) end | ||
+ | end) | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | === An Outline Shader ''FLAG_FROM_CODE'' === | ||
+ | <syntaxhighlight lang="lua"> | ||
+ | spriteOutline = {} | ||
+ | |||
+ | spriteOutline.VS_GL = [[ | ||
+ | |||
+ | uniform highp mat4 vMatrix; | ||
+ | |||
+ | attribute highp vec3 vVertex; | ||
+ | attribute mediump vec2 vTexCoord; | ||
+ | |||
+ | varying mediump vec2 fTexCoord; | ||
+ | |||
+ | void main() { | ||
+ | vec4 vertex = vec4(vVertex, 1.0); | ||
+ | gl_Position = vMatrix*vertex; | ||
+ | fTexCoord = vTexCoord; | ||
+ | } | ||
+ | ]] | ||
+ | |||
+ | spriteOutline.FS_GL = [[ | ||
+ | |||
+ | #ifdef GL_ES | ||
+ | precision highp float; | ||
+ | #endif | ||
+ | |||
+ | const float offseta = 0.010; | ||
+ | |||
+ | uniform lowp vec4 fColor; | ||
+ | uniform mediump vec4 fTexSize; | ||
+ | uniform lowp sampler2D fTexture; | ||
+ | |||
+ | uniform lowp int fSwitch; | ||
+ | |||
+ | varying mediump vec2 fTexCoord; | ||
+ | |||
+ | vec4 getSample(float x, float y, float offset, float num) | ||
+ | { | ||
+ | vec4 result = vec4(0); | ||
+ | float size = 360.0 / num; | ||
+ | |||
+ | for (float a; a <= 360.0; a += size) | ||
+ | { | ||
+ | vec2 coord = vec2(cos(a) * offset + x, sin(a) * offset + y); | ||
+ | |||
+ | result += texture2D(fTexture, coord); | ||
+ | } | ||
+ | |||
+ | return result; | ||
+ | } | ||
+ | |||
+ | void main() | ||
+ | { | ||
+ | vec4 col = texture2D(fTexture, fTexCoord); | ||
+ | |||
+ | float nums = 32.0; | ||
+ | |||
+ | if (fSwitch == 44) // fSwitch can be changed in code, 44 is some random value for documentation purposes | ||
+ | { | ||
+ | vec4 nb = getSample(fTexCoord.x, fTexCoord.y, 0.020, nums); | ||
+ | |||
+ | if (col.a > 0. && nb.a < nums) | ||
+ | { | ||
+ | col.a = nb.a / nums; | ||
+ | col.r = nb.a / nums; | ||
+ | col.g = 0.0; | ||
+ | col.b = 0.0; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | gl_FragColor = col; | ||
+ | } | ||
+ | ]] | ||
+ | |||
+ | spriteOutline.Shader=Shader.new(spriteOutline.VS_GL, spriteOutline.FS_GL, Shader.FLAG_FROM_CODE, | ||
+ | { | ||
+ | {name="vMatrix",type=Shader.CMATRIX,sys=Shader.SYS_WVP,vertex=true}, | ||
+ | {name="fColor",type=Shader.CFLOAT4,sys=Shader.SYS_COLOR,vertex=false}, | ||
+ | {name="fTexture",type=Shader.CTEXTURE,vertex=false}, | ||
+ | {name="fSwitch",type=Shader.CINT,vertex=false}, | ||
+ | }, | ||
+ | { | ||
+ | {name="vVertex",type=Shader.DFLOAT,mult=3,slot=0,offset=0}, | ||
+ | {name="vColor",type=Shader.DUBYTE,mult=4,slot=1,offset=0}, | ||
+ | {name="vTexCoord",type=Shader.DFLOAT,mult=2,slot=2,offset=0}, | ||
+ | } | ||
+ | ) | ||
+ | |||
+ | local sprite = Bitmap.new(Texture.new("gfx/test.png")) | ||
+ | --spriteOutline.Shader:setConstant("fSwitch", Shader.CINT, 1, 44) -- set fSwitch value to be 44 | ||
+ | sprite:setShader(spriteOutline.Shader) | ||
+ | sprite:setShaderConstant("fSwitch", Shader.CINT, 1, 44) -- set fSwitch value to be 44 | ||
+ | stage:addChild(sprite) | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | === A Pulsing Effect Shader ''FLAG_FROM_CODE'' - by Hgy29 === | ||
+ | {{#widget:GApp|app=Playground_ShaderPulsingEffect.GApp|width=480|height=320|auto=1}} | ||
+ | <syntaxhighlight lang="lua"> | ||
+ | local shaderV=[[ | ||
+ | attribute highp vec3 vVertex; | ||
+ | attribute mediump vec2 vTexCoord; | ||
+ | uniform highp mat4 vMatrix; | ||
+ | varying mediump vec2 fTexCoord; | ||
+ | |||
+ | void main() { | ||
+ | vec4 vertex = vec4(vVertex,1.0); | ||
+ | gl_Position = vMatrix*vertex; | ||
+ | fTexCoord=vTexCoord; | ||
+ | } | ||
+ | ]] | ||
+ | |||
+ | local scanlinesF=[[ | ||
+ | uniform lowp sampler2D fTexture; | ||
+ | varying mediump vec2 fTexCoord; | ||
+ | uniform mediump vec4 fTextureSize; | ||
+ | uniform mediump float fTime; | ||
+ | |||
+ | lowp vec3 hsv2rgb(vec3 c) { | ||
+ | lowp vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); | ||
+ | lowp 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 main() { | ||
+ | mediump vec4 pixel=texture2D(fTexture, fTexCoord); | ||
+ | mediump vec4 frag=pixel; | ||
+ | mediump vec2 centerDir=normalize((fTextureSize.xy/2.0-fTexCoord)/fTextureSize.xy)*fTextureSize.zw; | ||
+ | for (int k=-5;k<=5;k++) | ||
+ | frag=frag+texture2D(fTexture, fTexCoord-centerDir*float(k)); | ||
+ | frag=frag/12.0; | ||
+ | if (frag.a<=0.0) discard; | ||
+ | if (pixel.a>=1.0) | ||
+ | gl_FragColor = pixel; | ||
+ | else | ||
+ | gl_FragColor = vec4(hsv2rgb(vec3(frag.a/2.0+fTime*2.0,0.7,1.0)),frag.a); | ||
+ | } | ||
+ | ]] | ||
+ | |||
+ | local result,reply=pcall(Shader.new,shaderV,scanlinesF,Shader.FLAG_FROM_CODE,{ | ||
+ | {name="vMatrix",type=Shader.CMATRIX,sys=Shader.SYS_WVP,vertex=true}, | ||
+ | {name="fColor",type=Shader.CFLOAT4,sys=Shader.SYS_COLOR,vertex=false}, | ||
+ | {name="fTexture",type=Shader.CTEXTURE,vertex=false}, | ||
+ | {name="fTextureSize",type=Shader.CFLOAT4,sys=Shader.SYS_TEXTUREINFO,vertex=false}, | ||
+ | {name="fTime",type=Shader.CFLOAT,sys=Shader.SYS_TIMER,vertex=false}, | ||
+ | }, | ||
+ | {{name="vVertex",type=Shader.DFLOAT,mult=3,slot=0,offset=0}, | ||
+ | {name="vColor",type=Shader.DUBYTE,mult=4,slot=1,offset=0}, | ||
+ | {name="vTexCoord",type=Shader.DFLOAT,mult=2,slot=2,offset=0}, }) | ||
+ | |||
+ | PulsingEffect=reply | ||
+ | |||
+ | application:setBackgroundColor(0x442200) | ||
+ | local mysprite = Bitmap.new(Texture.new("gfx/checkbox.png")) | ||
+ | local mysprite2 = Bitmap.new(Texture.new("gfx/clock_hand_h.png")) | ||
+ | local mysprite3 = Bitmap.new(Texture.new("gfx/clock_hand_m.png")) | ||
+ | local mysprite4 = Bitmap.new(Texture.new("gfx/test.png")) | ||
+ | -- position | ||
+ | mysprite:setPosition(32*6, 32*3.35) | ||
+ | mysprite2:setPosition(32*10, 32*2) | ||
+ | mysprite3:setPosition(32*14, 32*2) | ||
+ | mysprite4:setPosition(32*10, 32*8) | ||
+ | -- order | ||
+ | stage:addChild(mysprite) | ||
+ | stage:addChild(mysprite2) | ||
+ | stage:addChild(mysprite3) | ||
+ | stage:addChild(mysprite4) | ||
+ | |||
+ | if not result then | ||
+ | print("Shader Compilation error:"..reply) | ||
+ | else | ||
+ | mysprite:setShader(PulsingEffect) | ||
+ | mysprite2:setShader(PulsingEffect) | ||
+ | mysprite3:setShader(PulsingEffect) | ||
+ | mysprite4:setShader(PulsingEffect) | ||
+ | end | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | === Shadertoy Code Viewer (glsl) === | ||
+ | '''This code reads Shadertoy shaders (no texture, no mouse). Simply replace the code in the local shadertoycode variable'''</br> | ||
+ | '''https://www.shadertoy.com/view/MsjSW3'''</br> | ||
+ | '''https://www.shadertoy.com/view/Xt2SDc'''</br> | ||
+ | '''...'''</br> | ||
+ | Full Shadertoy Gideros Viewer: '''https://forum.gideros.rocks/discussion/comment/66639#Comment_66639'''</br> | ||
+ | '''Note''': '''Shadertoy shaders are copyrighted'''</br> | ||
+ | {{#widget:GApp|app=ShadertoyViewer_text.GApp|width=480|height=320|auto=1}} | ||
+ | <syntaxhighlight lang="lua"> | ||
+ | local function loadShader(xshader) | ||
+ | local vs = [[ | ||
+ | attribute vec4 POSITION0; | ||
+ | attribute vec2 TEXCOORD0; | ||
+ | |||
+ | uniform mat4 g_MVPMatrix; | ||
+ | |||
+ | varying vec2 fragCoord; | ||
+ | varying vec2 texCoord; | ||
+ | |||
+ | void main() | ||
+ | { | ||
+ | texCoord = TEXCOORD0; | ||
+ | gl_Position = g_MVPMatrix * POSITION0; | ||
+ | } | ||
+ | ]] | ||
+ | |||
+ | local ps = [[ | ||
+ | #extension GL_OES_standard_derivatives : enable | ||
+ | #extension GL_EXT_shader_texture_lod : enable | ||
+ | |||
+ | vec4 texture2DGrad(sampler2D s, in vec2 uv, vec2 gx, vec2 gy) { | ||
+ | return texture2D(s, uv); | ||
+ | } | ||
+ | |||
+ | vec4 texture2DLod(sampler2D s, in vec2 uv, in float lod) { | ||
+ | return texture2D(s, uv); | ||
+ | } | ||
+ | |||
+ | uniform vec4 iResolution; // viewport resolution (in pixels) | ||
+ | uniform float iGlobalTime; // shader playback time (in seconds) | ||
+ | uniform float iTime; // shader playback time (in seconds) | ||
+ | uniform float iTimeDelta; // render time (in seconds) | ||
+ | uniform int iFrame; // shader playback frame | ||
+ | uniform float iChannelTime[4]; // channel playback time (in seconds) | ||
+ | uniform vec4 iMouse; // mouse pixel coords. xy: current (if MLB down), zw: click | ||
+ | uniform sampler2D iChannel0; // input channel #0. XX = 2D/Cube | ||
+ | uniform sampler2D iChannel1; // input channel #1. XX = 2D/Cube | ||
+ | uniform sampler2D iChannel2; // input channel #2. XX = 2D/Cube | ||
+ | uniform sampler2D iChannel3; // input channel #3. XX = 2D/Cube | ||
+ | uniform vec4 iDate; // (year, month, day, time in seconds) | ||
+ | uniform float iSampleRate; // sound sample rate (i.e., 44100) | ||
+ | |||
+ | varying vec2 texCoord; | ||
+ | varying vec2 fragCoord; | ||
+ | |||
+ | #ifdef GL_ES | ||
+ | precision mediump float; | ||
+ | #endif | ||
+ | |||
+ | ]] .. xshader[1] .. [[ | ||
+ | |||
+ | void main() { | ||
+ | vec4 color = vec4(0.0,0.0,0.0,1.0); | ||
+ | mainImage(color, gl_FragCoord.xy); | ||
+ | color.w = 1.0; | ||
+ | gl_FragColor = color; | ||
+ | } | ||
+ | ]] | ||
+ | |||
+ | return Shader.new(vs, ps, Shader.FLAG_FROM_CODE, | ||
+ | { | ||
+ | {name="g_MVPMatrix",type=Shader.CMATRIX,sys=Shader.SYS_WVP, vertex=true}, | ||
+ | {name="g_Color",type=Shader.CFLOAT4,mult=1,sys=Shader.SYS_COLOR}, | ||
+ | |||
+ | {name="iResolution",type=Shader.CFLOAT4,mult=1,vertex=false}, | ||
+ | {name="iGlobalTime",type=Shader.CFLOAT,mult=1,vertex=false}, | ||
+ | {name="iTime",type=Shader.CFLOAT,mult=1,vertex=false}, | ||
+ | {name="iTimeDelta",type=Shader.CFLOAT,mult=1,vertex=false}, | ||
+ | {name="iFrame",type=Shader.CINT,mult=1,vertex=false}, | ||
+ | {name="iChannelTime",type=Shader.CFLOAT,mult=1,vertex=false}, | ||
+ | {name="iMouse",type=Shader.CFLOAT4,mult=1,vertex=false}, | ||
+ | {name="iDate",type=Shader.CFLOAT4,mult=1,vertex=false}, | ||
+ | {name="iSampleRate",type=Shader.CFLOAT,mult=1,vertex=false}, | ||
+ | {name="iChannel0",type=Shader.CTEXTURE,mult=1,vertex=false}, | ||
+ | {name="iChannel1",type=Shader.CTEXTURE,mult=1,vertex=false}, | ||
+ | {name="iChannel2",type=Shader.CTEXTURE,mult=1,vertex=false}, | ||
+ | {name="iChannel3",type=Shader.CTEXTURE,mult=1,vertex=false}, | ||
+ | }, | ||
+ | { | ||
+ | {name="POSITION0",type=Shader.DFLOAT,mult=3,slot=0,offset=0}, | ||
+ | {name="vColor",type=Shader.DUBYTE,mult=0,slot=1,offset=0}, | ||
+ | {name="TEXCOORD0",type=Shader.DFLOAT,mult=2,slot=2,offset=0}, | ||
+ | } | ||
+ | ) | ||
+ | end | ||
+ | |||
+ | function Shadertoy(xcode, width, height) | ||
+ | local effect = assert(loadShader(xcode)) | ||
+ | |||
+ | local sprite | ||
+ | if application:getDeviceOrientation() == "Portrait" then | ||
+ | sprite = Pixel.new(nil, width, height) | ||
+ | else -- landscape | ||
+ | sprite = Pixel.new(nil, height, width) | ||
+ | end | ||
+ | sprite:setShader(effect) | ||
+ | |||
+ | local frame, time = 0, 0 | ||
+ | stage:addEventListener(Event.ENTER_FRAME, function(event) | ||
+ | if xcapture then return end | ||
+ | frame = frame + 1 | ||
+ | local t = time | ||
+ | local d = os.date("*t") | ||
+ | local s = d.hour * 3600 + d.min * 60 + d.sec | ||
+ | effect:setConstant("iResolution", Shader.CFLOAT4, 1, width, height, 0, 0) | ||
+ | effect:setConstant("iSampleRate", Shader.CFLOAT, 1, 44100) | ||
+ | effect:setConstant("iGlobalTime", Shader.CFLOAT, 1, t) | ||
+ | effect:setConstant("iTime", Shader.CFLOAT, 1, t) | ||
+ | effect:setConstant("iTimeDelta", Shader.CFLOAT, 1, event.deltaTime) | ||
+ | effect:setConstant("iFrame", Shader.CINT, 1, frame) | ||
+ | effect:setConstant("iChannelTime", Shader.CFLOAT, 4, t, t, t, t) | ||
+ | effect:setConstant("iDate", Shader.CFLOAT4, 1, d.year, d.month, d.day, s) | ||
+ | time = time + event.deltaTime | ||
+ | end) | ||
+ | |||
+ | return sprite | ||
+ | end | ||
+ | |||
+ | local w, h = application:getDeviceWidth(), application:getDeviceHeight() | ||
+ | local shadertoycode = [[ | ||
+ | // Ether by nimitz 2014 (twitter: @stormoid) | ||
+ | // https://www.shadertoy.com/view/MsjSW3 | ||
+ | // License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License | ||
+ | // Contact the author for other licensing options | ||
+ | |||
+ | #define t iTime | ||
+ | mat2 m(float a){float c=cos(a), s=sin(a);return mat2(c,-s,s,c);} | ||
+ | float map(vec3 p){ | ||
+ | p.xz*= m(t*0.4);p.xy*= m(t*0.3); | ||
+ | vec3 q = p*2.+t; | ||
+ | return length(p+vec3(sin(t*0.7)))*log(length(p)+1.) + sin(q.x+sin(q.z+sin(q.y)))*0.5 - 1.; | ||
+ | } | ||
+ | |||
+ | void mainImage( out vec4 fragColor, in vec2 fragCoord ){ | ||
+ | vec2 p = fragCoord.xy/iResolution.y - vec2(.9,.5); | ||
+ | vec3 cl = vec3(0.); | ||
+ | float d = 2.5; | ||
+ | for(int i=0; i<=5; i++) { | ||
+ | vec3 p = vec3(0,0,5.) + normalize(vec3(p, -1.))*d; | ||
+ | float rz = map(p); | ||
+ | float f = clamp((rz - map(p+.1))*0.5, -.1, 1. ); | ||
+ | vec3 l = vec3(0.1,0.3,.4) + vec3(5., 2.5, 3.)*f; | ||
+ | cl = cl*l + smoothstep(2.5, .0, rz)*.7*l; | ||
+ | d += min(rz, 1.); | ||
+ | } | ||
+ | fragColor = vec4(cl, 1.); | ||
+ | } | ||
+ | ]] | ||
+ | local ok, image | ||
+ | if application:getDeviceOrientation() == "Portrait" then | ||
+ | ok, image = pcall(Shadertoy, {shadertoycode}, w, h) | ||
+ | else | ||
+ | ok, image = pcall(Shadertoy, {shadertoycode}, h, w) -- landscape | ||
+ | end | ||
+ | if ok then stage:addChild(image) else image = nil print("shader error") end | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | {{SHADERS}} |
Latest revision as of 19:41, 10 November 2023
Parent: Writing Custom Shaders
Note: not all shaders will display correctly in html5
A Grey Shader
The code below defines a Grey shader consisting of:
- mycshaders/vShaderGrey.glsl vertex shader
- mycshaders/fShaderGrey.glsl fragment shader
Here the shader files are in the assets/mycshaders directory.
GLSL Vertex Shader: mycshaders/vShaderGrey.glsl
uniform highp mat4 vMatrix;
attribute highp vec3 vVertex;
attribute mediump vec2 vTexCoord;
varying mediump vec2 fTexCoord;
void main() {
vec4 vertex = vec4(vVertex, 0.8); // vertex coords, scale
gl_Position = vMatrix*vertex;
fTexCoord = vTexCoord;
}
GLSL Fragment Shader: mycshaders/fShaderGrey.glsl
//precision highp float;
#ifdef GLES2
precision highp float;
#endif
uniform lowp vec4 fColor;
uniform lowp sampler2D fTexture;
varying mediump vec2 fTexCoord;
void main() {
lowp vec4 frag = fColor*texture2D(fTexture, fTexCoord);
float color;
if (frag.a == 0.0) {
gl_FragColor = vec4(1.0, 0.5, 1.0, 1.0); // purple
} else {
color = dot(frag.rgb, vec3(0.299, 0.587, 0.114));
gl_FragColor = vec4(color, color, color, frag.a); // gray
}
}
Lua Code
-- open gl shader
local shadergrey = Shader.new("mycshaders/vShaderGrey", "mycshaders/fShaderGrey", 0,
{
{name="vMatrix", type=Shader.CMATRIX, sys=Shader.SYS_WVP, vertex=true},
{name="fColor", type=Shader.CFLOAT4, sys=Shader.SYS_COLOR, vertex=false},
{name="fTexture", type=Shader.CTEXTURE, vertex=false},
},
{
{name="vVertex", type=Shader.DFLOAT, mult=3, slot=0, offset=0},
{name="vColor", type=Shader.DUBYTE, mult=4, slot=1, offset=0},
{name="vTexCoord", type=Shader.DFLOAT, mult=2, slot=2, offset=0},
}
)
application:setBackgroundColor(0x333333)
local bitmap = Bitmap.new(Texture.new("gfx/test.png"))
local bitmap2 = Bitmap.new(Texture.new("gfx/arrow_0001.png"))
-- position
bitmap:setPosition(32*1, 32*4)
bitmap2:setPosition(32*6, 32*1)
-- shaders
bitmap:setShader(shadergrey)
bitmap2:setShader(shadergrey)
-- order
stage:addChild(bitmap)
stage:addChild(bitmap2)
A Wave Shader
The code below defines a Wave shader consisting of:
- mycshaders/vShaderWave.glsl vertex shader
- mycshaders/fShaderWave.glsl fragment shader
Here the shader files are in the assets/mycshaders directory.
GLSL Vertex Shader: mycshaders/vShaderWave.glsl
attribute vec4 POSITION0;
attribute vec2 TEXCOORD0;
uniform mat4 g_MVPMatrix;
varying vec2 texCoord;
void main()
{
gl_Position = g_MVPMatrix * POSITION0;
texCoord = TEXCOORD0;
}
GLSL Fragment Shader: mycshaders/fShaderWave.glsl
uniform lowp sampler2D g_Texture;
uniform lowp vec4 g_Color;
uniform highp float time;
varying highp vec2 texCoord;
void main()
{
highp vec2 tc = texCoord.xy;
// highp float dist = cos(tc.x * 24.0 - time * 4.0) * 0.02;
highp float dist = cos(tc.x * 2.0 - time * 8.0) * 0.02;
highp vec2 uv = tc + dist;
gl_FragColor = g_Color * texture2D(g_Texture, uv);
}
Lua Code
-- open gl shader
local shaderwave = Shader.new("mycshaders/vShaderWave", "mycshaders/fShaderWave", 0,
{
{name="g_MVPMatrix", type=Shader.CMATRIX, sys=Shader.SYS_WVP, vertex=true},
{name="g_Color", type=Shader.CFLOAT4, mult=1, sys=Shader.SYS_COLOR},
{name="g_Texture", type=Shader.CTEXTURE, mult=1, vertex=false},
{name="time", type=Shader.CFLOAT, mult=1, vertex=false}
},
{
{name="POSITION0", type=Shader.DFLOAT, mult=3, slot=0, offset=0},
{name="vColor", type=Shader.DUBYTE, mult=0, slot=1, offset=0},
{name="TEXCOORD0", type=Shader.DFLOAT, mult=2, slot=2, offset=0}
}
)
application:setBackgroundColor(0x333333)
local bitmap = Bitmap.new(Texture.new("gfx/test.png"))
local bitmap2 = bitmap:clone()
-- position
bitmap:setPosition(32*1, 32*4)
bitmap2:setPosition(32*6, 32*1)
-- shaders
bitmap:setShader(shaderwave)
bitmap2:setShader(shaderwave)
-- order
stage:addChild(bitmap)
stage:addChild(bitmap2)
-- loop
local timer = 0
stage:addEventListener(Event.ENTER_FRAME, function(e)
timer += 0.018
shaderwave:setConstant("time", Shader.CFLOAT, 1, timer)
bitmap:setX(bitmap:getX() + 1)
if bitmap:getX() > 400 then bitmap:setX(-80) end
end)
An Outline Shader FLAG_FROM_CODE
spriteOutline = {}
spriteOutline.VS_GL = [[
uniform highp mat4 vMatrix;
attribute highp vec3 vVertex;
attribute mediump vec2 vTexCoord;
varying mediump vec2 fTexCoord;
void main() {
vec4 vertex = vec4(vVertex, 1.0);
gl_Position = vMatrix*vertex;
fTexCoord = vTexCoord;
}
]]
spriteOutline.FS_GL = [[
#ifdef GL_ES
precision highp float;
#endif
const float offseta = 0.010;
uniform lowp vec4 fColor;
uniform mediump vec4 fTexSize;
uniform lowp sampler2D fTexture;
uniform lowp int fSwitch;
varying mediump vec2 fTexCoord;
vec4 getSample(float x, float y, float offset, float num)
{
vec4 result = vec4(0);
float size = 360.0 / num;
for (float a; a <= 360.0; a += size)
{
vec2 coord = vec2(cos(a) * offset + x, sin(a) * offset + y);
result += texture2D(fTexture, coord);
}
return result;
}
void main()
{
vec4 col = texture2D(fTexture, fTexCoord);
float nums = 32.0;
if (fSwitch == 44) // fSwitch can be changed in code, 44 is some random value for documentation purposes
{
vec4 nb = getSample(fTexCoord.x, fTexCoord.y, 0.020, nums);
if (col.a > 0. && nb.a < nums)
{
col.a = nb.a / nums;
col.r = nb.a / nums;
col.g = 0.0;
col.b = 0.0;
}
}
gl_FragColor = col;
}
]]
spriteOutline.Shader=Shader.new(spriteOutline.VS_GL, spriteOutline.FS_GL, Shader.FLAG_FROM_CODE,
{
{name="vMatrix",type=Shader.CMATRIX,sys=Shader.SYS_WVP,vertex=true},
{name="fColor",type=Shader.CFLOAT4,sys=Shader.SYS_COLOR,vertex=false},
{name="fTexture",type=Shader.CTEXTURE,vertex=false},
{name="fSwitch",type=Shader.CINT,vertex=false},
},
{
{name="vVertex",type=Shader.DFLOAT,mult=3,slot=0,offset=0},
{name="vColor",type=Shader.DUBYTE,mult=4,slot=1,offset=0},
{name="vTexCoord",type=Shader.DFLOAT,mult=2,slot=2,offset=0},
}
)
local sprite = Bitmap.new(Texture.new("gfx/test.png"))
--spriteOutline.Shader:setConstant("fSwitch", Shader.CINT, 1, 44) -- set fSwitch value to be 44
sprite:setShader(spriteOutline.Shader)
sprite:setShaderConstant("fSwitch", Shader.CINT, 1, 44) -- set fSwitch value to be 44
stage:addChild(sprite)
A Pulsing Effect Shader FLAG_FROM_CODE - by Hgy29
local shaderV=[[
attribute highp vec3 vVertex;
attribute mediump vec2 vTexCoord;
uniform highp mat4 vMatrix;
varying mediump vec2 fTexCoord;
void main() {
vec4 vertex = vec4(vVertex,1.0);
gl_Position = vMatrix*vertex;
fTexCoord=vTexCoord;
}
]]
local scanlinesF=[[
uniform lowp sampler2D fTexture;
varying mediump vec2 fTexCoord;
uniform mediump vec4 fTextureSize;
uniform mediump float fTime;
lowp vec3 hsv2rgb(vec3 c) {
lowp vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
lowp 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 main() {
mediump vec4 pixel=texture2D(fTexture, fTexCoord);
mediump vec4 frag=pixel;
mediump vec2 centerDir=normalize((fTextureSize.xy/2.0-fTexCoord)/fTextureSize.xy)*fTextureSize.zw;
for (int k=-5;k<=5;k++)
frag=frag+texture2D(fTexture, fTexCoord-centerDir*float(k));
frag=frag/12.0;
if (frag.a<=0.0) discard;
if (pixel.a>=1.0)
gl_FragColor = pixel;
else
gl_FragColor = vec4(hsv2rgb(vec3(frag.a/2.0+fTime*2.0,0.7,1.0)),frag.a);
}
]]
local result,reply=pcall(Shader.new,shaderV,scanlinesF,Shader.FLAG_FROM_CODE,{
{name="vMatrix",type=Shader.CMATRIX,sys=Shader.SYS_WVP,vertex=true},
{name="fColor",type=Shader.CFLOAT4,sys=Shader.SYS_COLOR,vertex=false},
{name="fTexture",type=Shader.CTEXTURE,vertex=false},
{name="fTextureSize",type=Shader.CFLOAT4,sys=Shader.SYS_TEXTUREINFO,vertex=false},
{name="fTime",type=Shader.CFLOAT,sys=Shader.SYS_TIMER,vertex=false},
},
{{name="vVertex",type=Shader.DFLOAT,mult=3,slot=0,offset=0},
{name="vColor",type=Shader.DUBYTE,mult=4,slot=1,offset=0},
{name="vTexCoord",type=Shader.DFLOAT,mult=2,slot=2,offset=0}, })
PulsingEffect=reply
application:setBackgroundColor(0x442200)
local mysprite = Bitmap.new(Texture.new("gfx/checkbox.png"))
local mysprite2 = Bitmap.new(Texture.new("gfx/clock_hand_h.png"))
local mysprite3 = Bitmap.new(Texture.new("gfx/clock_hand_m.png"))
local mysprite4 = Bitmap.new(Texture.new("gfx/test.png"))
-- position
mysprite:setPosition(32*6, 32*3.35)
mysprite2:setPosition(32*10, 32*2)
mysprite3:setPosition(32*14, 32*2)
mysprite4:setPosition(32*10, 32*8)
-- order
stage:addChild(mysprite)
stage:addChild(mysprite2)
stage:addChild(mysprite3)
stage:addChild(mysprite4)
if not result then
print("Shader Compilation error:"..reply)
else
mysprite:setShader(PulsingEffect)
mysprite2:setShader(PulsingEffect)
mysprite3:setShader(PulsingEffect)
mysprite4:setShader(PulsingEffect)
end
Shadertoy Code Viewer (glsl)
This code reads Shadertoy shaders (no texture, no mouse). Simply replace the code in the local shadertoycode variable
https://www.shadertoy.com/view/MsjSW3
https://www.shadertoy.com/view/Xt2SDc
...
Full Shadertoy Gideros Viewer: https://forum.gideros.rocks/discussion/comment/66639#Comment_66639
Note: Shadertoy shaders are copyrighted
local function loadShader(xshader)
local vs = [[
attribute vec4 POSITION0;
attribute vec2 TEXCOORD0;
uniform mat4 g_MVPMatrix;
varying vec2 fragCoord;
varying vec2 texCoord;
void main()
{
texCoord = TEXCOORD0;
gl_Position = g_MVPMatrix * POSITION0;
}
]]
local ps = [[
#extension GL_OES_standard_derivatives : enable
#extension GL_EXT_shader_texture_lod : enable
vec4 texture2DGrad(sampler2D s, in vec2 uv, vec2 gx, vec2 gy) {
return texture2D(s, uv);
}
vec4 texture2DLod(sampler2D s, in vec2 uv, in float lod) {
return texture2D(s, uv);
}
uniform vec4 iResolution; // viewport resolution (in pixels)
uniform float iGlobalTime; // shader playback time (in seconds)
uniform float iTime; // shader playback time (in seconds)
uniform float iTimeDelta; // render time (in seconds)
uniform int iFrame; // shader playback frame
uniform float iChannelTime[4]; // channel playback time (in seconds)
uniform vec4 iMouse; // mouse pixel coords. xy: current (if MLB down), zw: click
uniform sampler2D iChannel0; // input channel #0. XX = 2D/Cube
uniform sampler2D iChannel1; // input channel #1. XX = 2D/Cube
uniform sampler2D iChannel2; // input channel #2. XX = 2D/Cube
uniform sampler2D iChannel3; // input channel #3. XX = 2D/Cube
uniform vec4 iDate; // (year, month, day, time in seconds)
uniform float iSampleRate; // sound sample rate (i.e., 44100)
varying vec2 texCoord;
varying vec2 fragCoord;
#ifdef GL_ES
precision mediump float;
#endif
]] .. xshader[1] .. [[
void main() {
vec4 color = vec4(0.0,0.0,0.0,1.0);
mainImage(color, gl_FragCoord.xy);
color.w = 1.0;
gl_FragColor = color;
}
]]
return Shader.new(vs, ps, Shader.FLAG_FROM_CODE,
{
{name="g_MVPMatrix",type=Shader.CMATRIX,sys=Shader.SYS_WVP, vertex=true},
{name="g_Color",type=Shader.CFLOAT4,mult=1,sys=Shader.SYS_COLOR},
{name="iResolution",type=Shader.CFLOAT4,mult=1,vertex=false},
{name="iGlobalTime",type=Shader.CFLOAT,mult=1,vertex=false},
{name="iTime",type=Shader.CFLOAT,mult=1,vertex=false},
{name="iTimeDelta",type=Shader.CFLOAT,mult=1,vertex=false},
{name="iFrame",type=Shader.CINT,mult=1,vertex=false},
{name="iChannelTime",type=Shader.CFLOAT,mult=1,vertex=false},
{name="iMouse",type=Shader.CFLOAT4,mult=1,vertex=false},
{name="iDate",type=Shader.CFLOAT4,mult=1,vertex=false},
{name="iSampleRate",type=Shader.CFLOAT,mult=1,vertex=false},
{name="iChannel0",type=Shader.CTEXTURE,mult=1,vertex=false},
{name="iChannel1",type=Shader.CTEXTURE,mult=1,vertex=false},
{name="iChannel2",type=Shader.CTEXTURE,mult=1,vertex=false},
{name="iChannel3",type=Shader.CTEXTURE,mult=1,vertex=false},
},
{
{name="POSITION0",type=Shader.DFLOAT,mult=3,slot=0,offset=0},
{name="vColor",type=Shader.DUBYTE,mult=0,slot=1,offset=0},
{name="TEXCOORD0",type=Shader.DFLOAT,mult=2,slot=2,offset=0},
}
)
end
function Shadertoy(xcode, width, height)
local effect = assert(loadShader(xcode))
local sprite
if application:getDeviceOrientation() == "Portrait" then
sprite = Pixel.new(nil, width, height)
else -- landscape
sprite = Pixel.new(nil, height, width)
end
sprite:setShader(effect)
local frame, time = 0, 0
stage:addEventListener(Event.ENTER_FRAME, function(event)
if xcapture then return end
frame = frame + 1
local t = time
local d = os.date("*t")
local s = d.hour * 3600 + d.min * 60 + d.sec
effect:setConstant("iResolution", Shader.CFLOAT4, 1, width, height, 0, 0)
effect:setConstant("iSampleRate", Shader.CFLOAT, 1, 44100)
effect:setConstant("iGlobalTime", Shader.CFLOAT, 1, t)
effect:setConstant("iTime", Shader.CFLOAT, 1, t)
effect:setConstant("iTimeDelta", Shader.CFLOAT, 1, event.deltaTime)
effect:setConstant("iFrame", Shader.CINT, 1, frame)
effect:setConstant("iChannelTime", Shader.CFLOAT, 4, t, t, t, t)
effect:setConstant("iDate", Shader.CFLOAT4, 1, d.year, d.month, d.day, s)
time = time + event.deltaTime
end)
return sprite
end
local w, h = application:getDeviceWidth(), application:getDeviceHeight()
local shadertoycode = [[
// Ether by nimitz 2014 (twitter: @stormoid)
// https://www.shadertoy.com/view/MsjSW3
// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// Contact the author for other licensing options
#define t iTime
mat2 m(float a){float c=cos(a), s=sin(a);return mat2(c,-s,s,c);}
float map(vec3 p){
p.xz*= m(t*0.4);p.xy*= m(t*0.3);
vec3 q = p*2.+t;
return length(p+vec3(sin(t*0.7)))*log(length(p)+1.) + sin(q.x+sin(q.z+sin(q.y)))*0.5 - 1.;
}
void mainImage( out vec4 fragColor, in vec2 fragCoord ){
vec2 p = fragCoord.xy/iResolution.y - vec2(.9,.5);
vec3 cl = vec3(0.);
float d = 2.5;
for(int i=0; i<=5; i++) {
vec3 p = vec3(0,0,5.) + normalize(vec3(p, -1.))*d;
float rz = map(p);
float f = clamp((rz - map(p+.1))*0.5, -.1, 1. );
vec3 l = vec3(0.1,0.3,.4) + vec3(5., 2.5, 3.)*f;
cl = cl*l + smoothstep(2.5, .0, rz)*.7*l;
d += min(rz, 1.);
}
fragColor = vec4(cl, 1.);
}
]]
local ok, image
if application:getDeviceOrientation() == "Portrait" then
ok, image = pcall(Shadertoy, {shadertoycode}, w, h)
else
ok, image = pcall(Shadertoy, {shadertoycode}, h, w) -- landscape
end
if ok then stage:addChild(image) else image = nil print("shader error") end