Last active
September 10, 2015 20:55
-
-
Save GlueBalloon/67fd3f00b927257861e2 to your computer and use it in GitHub Desktop.
Complex Shader Life
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--# Main | |
displayMode(FULLSCREEN) | |
function setup() | |
showBuffer = true | |
readPixelCode = true | |
local w,h = WIDTH,HEIGHT | |
local w,h = 20,20 | |
source = image(w,h) | |
target = image(w,h) | |
worldEngine = mesh() | |
local s = shader() | |
s.vertexProgram, s.fragmentProgram = worldEngineShader() | |
worldEngine.shader = s | |
worldEngine.texture = source | |
worldEngine:addRect(w/2,h/2,w,h) | |
-- Factor of 2 is for retina displays | |
worldEngine.shader.width = 2*w | |
worldEngine.shader.height = 2*h | |
worldEngine.shader.markerTurnA = true | |
local leftOfVisible = color(0, 0, 25, 255) | |
local belowLeftOfVisible = color(0,0,100,255) | |
local belowVisible = color(0,0,150,255) | |
local markerA = color(0, 0, 255, 255) | |
local markerB = color(0, 255,255, 255) | |
worldEngine.shader.leftOfVisible = leftOfVisible | |
worldEngine.shader.belowLeftOfVisible = belowLeftOfVisible | |
worldEngine.shader.belowVisible = belowVisible | |
worldEngine.shader.markerA = markerA | |
worldEngine.shader.markerB = markerB | |
local nf = 50 + 5*math.random() | |
local xd = math.random() | |
local yd = math.random() | |
for x = 1,w do | |
for y = 1,h do | |
if math.fmod(y,2) == 0 and math.fmod(x,2) == 1 then | |
source:set(x,y,color(10,255,0,255)) -- color for ground | |
elseif math.fmod(y,2) == 0 and math.fmod(x,2) == 0 then | |
source:set(x,y,leftOfVisible) | |
elseif math.fmod(y,2) == 1 and math.fmod(x,2) == 1 then | |
source:set(x,y,belowVisible) | |
elseif math.fmod(y,2) == 1 and math.fmod(x,2) == 0 then | |
source:set(x,y,belowLeftOfVisible) | |
end | |
if math.fmod(y,8) == 0 and math.fmod(x,12) == 0 then | |
source:set(x,y,markerA) -- color for initial creatures | |
elseif (y == 2 or y == 18) and math.fmod(x,16) == 0 then | |
source:set(x,y,markerB) -- color for initial creatures | |
end | |
end | |
end | |
visibleWorld = mesh() | |
visibleWorld:addRect(WIDTH/2,HEIGHT/2,WIDTH,HEIGHT) | |
s = shader() | |
s.vertexProgram, s.fragmentProgram = displayShader() | |
visibleWorld.shader = s | |
visibleWorld.texture = source | |
visibleWorld.shader.colour = color(36, 45, 69, 255) | |
visibleWorld.shader.alive = color(30, 164, 23, 255) | |
visibleWorld:setColors(255,255,255,255) | |
visibleWorld.shader.width = worldEngine.shader.width | |
visibleWorld.shader.height = worldEngine.shader.height | |
end | |
function draw() | |
background(56, 62, 61, 255) | |
noSmooth() | |
setContext(target) | |
worldEngine:draw() | |
setContext() | |
source, target = target, source | |
worldEngine.texture = source | |
visibleWorld.texture = source | |
visibleWorld:draw() | |
if showBuffer then | |
ortho() | |
viewMatrix(matrix()) | |
sprite(target,170,170,320,320) | |
end | |
if worldEngine.shader.markerTurnA == true then | |
worldEngine.shader.markerTurnA = false | |
else | |
worldEngine.shader.markerTurnA = true | |
end | |
end | |
function touched(touch) | |
end | |
--# golShader | |
function worldEngineShader() | |
return [[ | |
// | |
// A Game of Life shader, vertex section does almost nothing. | |
// | |
//This is the current model * view * projection matrix | |
// Codea sets it automatically | |
uniform mat4 modelViewProjection; | |
//This is the current mesh vertex position, color and tex coord | |
// Set automatically | |
attribute vec4 position; | |
attribute vec4 color; | |
attribute vec2 texCoord; | |
//This is an output variable that will be passed to the fragment shader | |
varying lowp vec4 vColor; | |
varying highp vec2 vTexCoord; | |
void main() | |
{ | |
//Pass the everything to the fragment shader | |
vColor = color; | |
vTexCoord = texCoord; | |
gl_Position = modelViewProjection * position; | |
} | |
]], | |
[[ | |
// fragment shader, does the work. | |
//boilerplate: | |
//This represents the current texture on the mesh | |
uniform lowp sampler2D texture; | |
//The interpolated vertex color for this fragment | |
varying lowp vec4 vColor; | |
//The interpolated texture coordinate for this fragment | |
varying highp vec2 vTexCoord; | |
//custom code: | |
// width and height of the texture for finding neighbours | |
uniform highp float width; | |
uniform highp float height; | |
lowp float colstep = .05; | |
highp float w = 1./width; | |
highp float h = 1./height; | |
uniform bool markerTurnA; | |
uniform highp vec4 leftOfVisible; | |
uniform highp vec4 belowLeftOfVisible; | |
uniform highp vec4 belowVisible; | |
uniform highp vec4 markerA; | |
uniform highp vec4 markerB; | |
highp vec2 above2 = vec2(0.,-4.); | |
highp vec2 aboveright2 = vec2(4.,-4.); | |
highp vec2 right2 = vec2(4.,0.); | |
highp vec2 belowright2 = vec2(4.,4.); | |
highp vec2 below2 = vec2(0.,4.); | |
highp vec2 belowleft2 = vec2(-4.,4.); | |
highp vec2 left2 = vec2(-4.,0.); | |
highp vec2 aboveleft2 = vec2(-4.,-4.); | |
//something mathy by Andrew Stacey, not sure what it does: | |
highp vec2 vfract(highp vec2 v) { | |
return vec2(fract(v.x),fract(v.y)); //fract(whatever) returns just the decimal part? | |
} | |
// get the color in vector direction | |
lowp vec4 colorAt(highp vec2 direction) { | |
lowp vec4 found = texture2D(texture,vfract(vTexCoord + vec2(w*direction.x,h*direction.y))); | |
return found; | |
} | |
//check for markers | |
lowp vec2 markerInRadius () { | |
highp vec4 thisColor = colorAt(above2); | |
if (thisColor == markerB || thisColor == markerA) { | |
return above2; | |
} | |
thisColor = colorAt(aboveright2); | |
if (thisColor == markerB || thisColor == markerA) { | |
return aboveright2; | |
} | |
thisColor = colorAt(right2); | |
if (thisColor == markerB || thisColor == markerA) { | |
return right2; | |
} | |
thisColor = colorAt(belowright2); | |
if (thisColor == markerB || thisColor == markerA) { | |
return belowright2; | |
} | |
thisColor = colorAt(below2); | |
if (thisColor == markerB || thisColor == markerA) { | |
return below2; | |
} | |
thisColor = colorAt(belowleft2); | |
if (thisColor == markerB || thisColor == markerA) { | |
return belowleft2; | |
} | |
thisColor = colorAt(left2); | |
if (thisColor == markerB || thisColor == markerA) { | |
return left2; | |
} | |
thisColor = colorAt(aboveleft2); | |
if (thisColor == markerB || thisColor == markerA) { | |
//return aboveleft2; | |
} | |
return vec2(0.,0.); | |
} | |
void main() | |
{ | |
lowp vec4 col; | |
col = texture2D(texture,vTexCoord); | |
//colors defined | |
lowp vec4 ground = vec4(0.04,1.,0.,1.); | |
lowp vec4 livingThing = vec4(1.,0.,0.,1.); | |
lowp vec4 colorToLeft = colorAt(vec2(-2.,0.)); | |
lowp vec4 colorTwoToLeft = colorAt(vec2(-4.,0.)); | |
//check if there is a marker around | |
lowp vec2 markerAt = markerInRadius(); | |
if (markerAt != vec2(0.,0.)) { | |
//get the color | |
lowp vec4 colorThere = colorAt(markerAt); | |
//if the position is to the left | |
if (markerAt == left2) { | |
//if it is a markerA on markerTurnA | |
if (colorThere == markerA && markerTurnA == true) { | |
//make this a markerB | |
col = markerB; | |
} | |
//else if the position is up and left | |
} else if (markerAt == belowleft2){ | |
//if it is a markerB NOT on markerTurnA | |
if (colorThere == markerB && markerTurnA == false) { | |
//make this a markerA | |
col = markerA; | |
} | |
} | |
} | |
if (markerTurnA == true && col == markerA){ | |
col = leftOfVisible; | |
} else if (markerTurnA == false && col == markerB){ | |
col = leftOfVisible; | |
} else if (colorAt(vec2(-2.,0.)) == markerB || colorAt(vec2(-2.,0.)) == markerA){ | |
col = livingThing; | |
} else if (col == livingThing){ | |
col = ground; | |
} | |
//if this is markerTurnA... | |
if (true ==false){ | |
if (markerTurnA == true){ | |
//if the color two to the left is markerA... | |
if (colorTwoToLeft == markerA) { | |
//make this markerB | |
col = markerB; | |
//but if the color one to the left is markerA... | |
} else if (colorToLeft == markerA) { | |
//this should be alive | |
col = livingThing; | |
//but if it is already alive.. | |
} else if (col == livingThing){ | |
//un-alive it | |
col = ground; | |
//but if this itself is markerA... | |
} else if (col == markerA){ | |
//code it as the leftOfVisible | |
col = leftOfVisible; | |
} | |
} else { | |
//if the color two to the left is markerB... | |
if (colorTwoToLeft == markerB) { | |
//make this markerA | |
col = markerA; | |
//but if the color one to the left is markerB... | |
} else if (colorToLeft == markerB) { | |
//this should be alive | |
col = livingThing; | |
//but if it is already alive.. | |
} else if (col == livingThing){ | |
//un-alive it | |
col = ground; | |
//but if this itself is markerB... | |
} else if (col == markerB){ | |
//code it as the leftOfVisible | |
col = leftOfVisible; | |
} | |
} | |
} | |
//Set the output color to the texture color | |
gl_FragColor = col; | |
} | |
]] | |
end | |
--# golrShader | |
function displayShader() | |
return [[ | |
// | |
// Rendering vertex shader, does almost nothing. | |
// | |
//This is the current model * view * projection matrix | |
// Codea sets it automatically | |
uniform mat4 modelViewProjection; | |
//This is the current mesh vertex position, color and tex coord | |
// Set automatically | |
attribute vec4 position; | |
attribute vec4 color; | |
attribute vec2 texCoord; | |
//This is an output variable that will be passed to the fragment shader | |
varying lowp vec4 vColor; | |
varying highp vec2 vTexCoord; | |
void main() | |
{ | |
//Pass the everything to the fragment shader | |
vColor = color; | |
vTexCoord = texCoord; | |
gl_Position = modelViewProjection * position; | |
} | |
]],[[ | |
// | |
// Rendering fragment shader, interprets the raw GoL data. | |
// | |
//This is the raw data | |
uniform lowp sampler2D texture; | |
//Colours for rendering | |
uniform lowp vec4 colour; | |
uniform lowp vec4 alive; | |
//The interpolated vertex color for this fragment | |
varying lowp vec4 vColor; | |
//The interpolated texture coordinate for this fragment | |
varying highp vec2 vTexCoord; | |
// width and height of the texture for finding neighbours | |
uniform highp float width; | |
uniform highp float height; | |
lowp float colstep = .05; | |
highp float w = 1./width; | |
highp float h = 1./height; | |
highp vec2 vfract(highp vec2 v) | |
{ | |
return vec2(fract(v.x),fract(v.y)); //fract(whatever) returns just the decimal part? | |
} | |
// get the color in vector direction | |
lowp vec4 colorAt(highp vec2 direction) | |
{ | |
lowp vec4 found = texture2D(texture,vfract(vTexCoord + vec2(w*direction.x,h*direction.y))); | |
return found; | |
} | |
void main() | |
{ | |
//Sample the data at the interpolated coordinate | |
lowp vec4 col; | |
col = texture2D( texture, vTexCoord ); | |
lowp float multiple = 80.; | |
lowp vec4 rightColor = colorAt(vec2(multiple*w,0.)); | |
lowp vec4 upColor = colorAt(vec2(0.,multiple*h)); | |
lowp vec4 upAndRightColor = colorAt(vec2(multiple*w,multiple*h)); | |
if (col.r > 0.02) { | |
//leave as is | |
} else if (rightColor.r > 0.02 ){ | |
col = rightColor; | |
} else if (upColor.r > 0.02) { | |
col = upColor; | |
} else if (upAndRightColor.r > 0.02) { | |
col = upAndRightColor; | |
} | |
//Set the output color | |
gl_FragColor = col; | |
} | |
]] | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment