Last active
December 13, 2015 21:28
-
-
Save sp4cemonkey/4977040 to your computer and use it in GitHub Desktop.
3d Sin in a shader
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
-- 3d sin | |
-- todo project touch to y=0 plane... | |
-- Use this function to perform your initial setup | |
function setup() | |
gridSize = 30 | |
--displayMode(FULLSCREEN) | |
parameter.number("speed", 0, 1,0.2) | |
parameter.number("wavelength", -1,-.1,-.2) | |
parameter.number("amp",.5,4,2) | |
parameter.number("ambient", 0, 1, 0.1) | |
parameter.number("diffuse", 0, 1, 1.0) | |
parameter.number("specular", 0, 1, 1) | |
parameter.color("lightColor", color(255,255,255,255)) | |
parameter.color("surfaceColor", color(191,41,85,255)) | |
allTextures = { | |
CAMERA, | |
"Cargo Bot:Codea Icon", | |
"Small World:Store Extra Large", | |
"Small World:Windmill", | |
"Tyrian Remastered:Boss D", | |
} | |
cameraSource(CAMERA_FRONT) | |
g=mesh() | |
g.shader = shader(SinPositioning.vertexShader, SinPositioning.fragmentShaderColor) | |
isoW = 8*math.cos(math.rad(30)) | |
isoH = 8*math.sin(math.rad(30)) | |
cens = {} | |
vert = {} | |
for x = 1,(gridSize-1) do | |
for z = 1,(gridSize-1) do | |
table.insert(vert, vec3(x,0,z)) | |
table.insert(vert, vec3(x+1,0,z)) | |
table.insert(vert, vec3(x+1,0,z+1)) | |
table.insert(vert, vec3(x,0,z)) | |
table.insert(vert, vec3(x,0,z+1)) | |
table.insert(vert, vec3(x+1,0,z+1)) | |
end | |
end | |
g.vertices = vert | |
b = g:buffer("texCoord") | |
b:resize(g.size) | |
offset = 0 | |
parameter.integer("Texture",0,6,1,changeTexture) | |
wireframeTexture = genWireframe(30,2) | |
end | |
function touched(touch) | |
if touch.state == ENDED then | |
else | |
cens[touch.id] = { | |
x = ((touch.x - WIDTH/2)/isoW + (touch.y+200)/isoH)/2, | |
y = ((touch.y+200)/isoH - (touch.x - WIDTH/2)/isoW)/2, | |
t = os.clock() } | |
end | |
for k, touch in pairs(cens) do | |
if os.clock() - touch.t > 1 then | |
cens[k] = nil | |
end | |
end | |
end | |
function changeTexture() | |
if Texture > 1 then | |
g.texture = allTextures[Texture-1] | |
g.shader = shader(SinPositioning.vertexShader, SinPositioning.fragmentShaderTexture) | |
b = g:buffer("texCoord") | |
for i = 1, g.size do | |
local vVec = g:vertex(i) | |
g:texCoord(i,1/gridSize*vVec.x,1/gridSize*vVec.z) | |
end | |
elseif Texture == 1 then | |
g.shader = shader(SinPositioning.vertexShader, SinPositioning.fragmentShaderColor) | |
else | |
--g.shader = shader(SinPositioning.vertexShaderWireFrame, SinPositioning.fragmentShaderWireFrame) | |
g.shader = shader(SinPositioning.vertexShaderWireframe, SinPositioning.fragmentShaderWireframe) | |
b = g:buffer("texCoord") | |
local sq = 1 | |
for x = 1,(gridSize-1) do | |
for z = 1,(gridSize-1) do | |
g:texCoord(sq, 0,0) | |
g:texCoord(sq+1, 1,0) | |
g:texCoord(sq+2, 1,1) | |
g:texCoord(sq+3, 0,0) | |
g:texCoord(sq+4, 0,1) | |
g:texCoord(sq+5, 1,1) | |
sq=sq+6 | |
end | |
end | |
g.texture = wireframeTexture | |
end | |
end | |
-- Wireframe texture | |
function genWireframe(w,l) | |
local t = image(w, w) | |
for y=1, w do | |
for x=1, l do | |
t:set(x, y, 255, 255, 255, 255) | |
t:set(w+1-x,y,255,255,255,255) | |
end | |
end | |
for x=1, w do | |
for y=1, l do | |
t:set(x, y, 255, 255, 255, 255) | |
t:set(x,w+1-y,255,255,255,255) | |
end | |
end | |
for x=2, w-1 do | |
for i=-l/2,l do | |
t:set(x+i, w-x, 255, 255, 255, 255) | |
end | |
end | |
t:set(w, w, 255, 255, 255, 255) | |
t:set(w-1, w, 255, 255, 255, 255) | |
return t | |
end | |
-- This function gets called once every frame | |
function draw() | |
output.clear() | |
g.shader.wavelength = wavelength | |
g.shader.offset = offset | |
g.shader.tp1 = vec2(-100,-100) | |
g.shader.tp2 = vec2(-100,-100) | |
g.shader.tp3 = vec2(-100,-100) | |
g.shader.tp4 = vec2(-100,-100) | |
g.shader.tp5 = vec2(-100,-100) | |
g.shader.amp = amp | |
g.shader.vAmbientMaterial = ambient | |
g.shader.vDiffuseMaterial = diffuse | |
g.shader.vSpecularMaterial = specular | |
g.shader.lightColor = lightColor | |
g:setColors(surfaceColor) | |
i=1 | |
for k, touch in pairs(cens) do | |
if i == 1 then | |
g.shader.tp1 = vec2(touch.x, touch.y) | |
elseif i == 2 then | |
g.shader.tp2 = vec2(touch.x, touch.y) | |
elseif i == 3 then | |
g.shader.tp3 = vec2(touch.x, touch.y) | |
elseif i == 4 then | |
g.shader.tp4 = vec2(touch.x, touch.y) | |
elseif i == 5 then | |
g.shader.tp5 = vec2(touch.x, touch.y) | |
end | |
i=i+1 | |
end | |
--vec2(150,78) | |
offset = offset + speed | |
-- This sets a dark background color | |
background(40, 40, 50) | |
print(math.floor(1/DeltaTime)) | |
-- This sets the line thickness | |
noSmooth() | |
noStroke() | |
camera(-gridSize/4,gridSize/4*3,-gridSize/4,gridSize/2, -gridSize/6, gridSize/2) | |
perspective() | |
--lighting | |
g.shader.mModel = modelMatrix() | |
g.shader.mView = viewMatrix() | |
g.shader.mProjection = projectionMatrix() | |
g.shader.vEyePosition = vec4(-10,30,-10) | |
g.shader.vLightPosition = vec4(20,80,90) | |
g:draw() | |
end | |
--# Shader | |
SinPositioning = { | |
vertexShader = [[ | |
//This is the current model * view * projection matrix | |
// Codea sets it automatically | |
uniform mat4 modelViewProjection; | |
uniform vec2 tp1; | |
uniform vec2 tp2; | |
uniform vec2 tp3; | |
uniform vec2 tp4; | |
uniform vec2 tp5; | |
uniform float amp; | |
uniform float offset; | |
uniform float wavelength; | |
uniform mat4 modelView; | |
// A constant representing the combined model/view matrix. | |
// The position of the light in eye space. | |
//This is the current mesh vertex position, color and tex coord | |
// Set automatically | |
attribute vec4 position; | |
attribute vec4 color; | |
attribute vec2 texCoord; | |
varying lowp vec4 vColor; | |
varying highp vec2 vTexCoord; | |
varying lowp vec4 vSpecularLightColor; | |
varying lowp vec3 vAmbientLightColor; | |
varying lowp vec3 vDiffuseLightColor; | |
//****new attributes | |
// Our Model, View and Projection matrices | |
// we need them to transform the incoming vertices and for lighting | |
// calculation | |
uniform mat4 mModel; | |
uniform mat4 mView; | |
uniform mat4 mProjection; | |
// Position of the "Camera" and the Light | |
// in Model space | |
uniform vec4 vEyePosition; | |
uniform vec4 vLightPosition; | |
// The Colors of the material | |
uniform float vAmbientMaterial; | |
uniform float vDiffuseMaterial; | |
uniform float vSpecularMaterial; | |
uniform vec4 lightColor; | |
float calcHeight(float x, float z) | |
{ | |
float result = 0.0; | |
if (tp1.x > -100.0) { | |
result = result + | |
sin(sqrt( | |
(tp1.x-x)*(tp1.x-x) + | |
(tp1.y-z)*(tp1.y-z)) * | |
wavelength +offset)*amp; | |
} | |
if (tp2.x > -100.0) { | |
result = result + | |
sin(sqrt( | |
(tp2.x-x)*(tp2.x-x) + | |
(tp2.y-z)*(tp2.y-z) | |
) * wavelength + offset | |
)*amp; | |
} | |
if (tp3.x > -100.0) { | |
result = result + | |
sin(sqrt( | |
(tp3.x-x)*(tp3.x-x) + | |
(tp3.y-z)*(tp3.y-z) | |
) * wavelength + offset | |
)*amp; | |
} | |
if (tp4.x > -100.0) { | |
result = result + | |
sin(sqrt( | |
(tp4.x-x)*(tp4.x-x) + | |
(tp4.y-z)*(tp4.y-z) | |
) * wavelength + offset | |
)*amp; | |
} | |
if (tp5.x > -100.0) { | |
result = result + | |
sin(sqrt( | |
(tp5.x-x)*(tp5.x-x) + | |
(tp5.y-z)*(tp5.y-z) | |
) * wavelength + offset | |
)*amp; | |
} | |
return result; | |
} | |
// Returns the specular component of the color | |
vec4 GetSpecularColor(vec3 vVertexNormal, vec4 vVertexPosition) | |
{ | |
// Transform the Vertex and corresponding Normal into Model space | |
vec4 vTransformedNormal = mModel * vec4( vVertexNormal, 1 ); | |
vec4 vTransformedVertex = mModel * vVertexPosition; | |
// Get the directional vector to the light and to the camera | |
// originating from the vertex position | |
vec4 vLightDirection = normalize( vLightPosition - vTransformedVertex ); | |
vec4 vCameraDirection = normalize( vEyePosition - vTransformedVertex ); | |
// Calculate the reflection vector between the incoming light and the | |
// normal (incoming angle = outgoing angle) | |
// We have to use the invert of the light direction because "reflect" | |
// expects the incident vector as its first parameter | |
vec4 vReflection = reflect( -vLightDirection, vTransformedNormal ); | |
// Calculate specular component | |
// Based on the dot product between the reflection vector and the camera | |
// direction. | |
// | |
// hint: The Dot Product corresponds to the angle between the two vectors | |
// hint: if the angle is out of range (0 ... 180 degrees) we use 0.0 | |
float spec = pow( max( 0.0, dot( vCameraDirection, vReflection )), 32.0 ); | |
return vec4( lightColor.r * spec, lightColor.g * spec, lightColor.b * spec, 1.0 ) * vSpecularMaterial; | |
} | |
// Ambient color component of vertex | |
vec4 GetAmbientColor() | |
{ | |
vec4 vAmbientColor; | |
vAmbientColor.xyz = color.rgb * lightColor.rgb * vAmbientMaterial; | |
vAmbientColor.a = 1.0; | |
vAmbientLightColor.xyz = lightColor.rgb * vAmbientMaterial; | |
return vAmbientColor; | |
} | |
// Diffuse Color component of vertex | |
vec4 GetDiffuseColor(vec3 vVertexNormal) | |
{ | |
// Transform the normal from Object to Model space | |
// we also normalize the vector just to be sure ... | |
vec4 vTransformedNormal = normalize( mModel * vec4( vVertexNormal, 1 )); | |
// Get direction of light in Model space | |
vec4 vLightDirection = normalize( vLightPosition - vTransformedNormal ); | |
// Calculate Diffuse intensity | |
float fDiffuseIntensity = max( 0.0, dot( vTransformedNormal, vLightDirection )); | |
// Calculate resulting Color | |
vec4 vDiffuseColor; | |
vDiffuseColor.xyz = color.rgb * lightColor.rgb * fDiffuseIntensity * vDiffuseMaterial; | |
vDiffuseColor.a = 1.0; | |
vDiffuseLightColor.xyz = lightColor.rgb * | |
fDiffuseIntensity * vDiffuseMaterial; | |
return vDiffuseColor; | |
} | |
void main() | |
{ | |
//Pass the mesh color to the fragment shader | |
vColor = color; | |
vTexCoord = vec2(texCoord.x, 1.0 - texCoord.y); | |
//Generate the height of the current vertex | |
vec4 calcpos = position; | |
calcpos.y = calcpos.y + calcHeight(position.x, position.z); | |
//Generate the vertex normal by looking at vectors to adjacent vertexes, this is a bit of a fudge as I don't consider the true triangles. | |
vec3 wPoint = | |
normalize( | |
vec3(1,calcHeight(position.x+1.0, position.z) | |
-calcpos.y,0)); | |
vec3 ePoint = | |
normalize( | |
vec3(-1,calcHeight(position.x-1.0, position.z) | |
-calcpos.y,0)); | |
vec3 nPoint = | |
normalize( | |
vec3(0,calcHeight(position.x, position.z+1.0) | |
-calcpos.y,1)); | |
vec3 sPoint = | |
normalize( | |
vec3(0,calcHeight(position.x, position.z-1.0) | |
-calcpos.y,-1)); | |
vec3 vNormal = normalize(cross(nPoint, wPoint) + | |
cross(wPoint, sPoint) + | |
cross(ePoint, nPoint) + | |
cross(sPoint, ePoint)); | |
vec4 ambientColor = GetAmbientColor(); | |
vec4 diffuseColor = GetDiffuseColor(vNormal); | |
vec4 specularColor = GetSpecularColor(vNormal, calcpos); | |
vSpecularLightColor = specularColor; | |
// Combine into final color | |
vColor = ambientColor + diffuseColor + specularColor; | |
//Multiply the vertex position by our combined transform | |
gl_Position = modelViewProjection * calcpos; | |
} | |
]], | |
fragmentShaderColor = [[ | |
//Default precision qualifier | |
precision highp float; | |
//The interpolated vertex color for this fragment | |
varying lowp vec4 vColor; | |
void main() | |
{ | |
//Set the output color to the texture color | |
gl_FragColor = vColor; | |
} | |
]], | |
fragmentShaderTexture = [[ | |
// | |
// A basic fragment shader | |
// | |
//Default precision qualifier | |
precision highp float; | |
//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; | |
varying lowp vec4 vSpecularLightColor; | |
varying lowp vec3 vAmbientLightColor; | |
varying lowp vec3 vDiffuseLightColor; | |
void main() | |
{ | |
//Sample the texture at the interpolated coordinate | |
lowp vec4 col = texture2D( texture, vTexCoord ); | |
vec4 aColor; | |
aColor.xyz = col.rgb * vAmbientLightColor; | |
aColor.a = 1.0; | |
vec4 dColor; | |
dColor.xyz = col.rgb * vDiffuseLightColor; | |
dColor.a = 1.0; | |
col = aColor + dColor + vSpecularLightColor; | |
//Set the output color to the texture color | |
gl_FragColor = col; | |
} | |
]], | |
vertexShaderWireframe = [[ | |
//This is the current model * view * projection matrix | |
// Codea sets it automatically | |
uniform mat4 modelViewProjection; | |
uniform vec2 tp1; | |
uniform vec2 tp2; | |
uniform vec2 tp3; | |
uniform vec2 tp4; | |
uniform vec2 tp5; | |
uniform float amp; | |
uniform float offset; | |
uniform float wavelength; | |
uniform mat4 modelView; | |
// A constant representing the combined model/view matrix. | |
// The position of the light in eye space. | |
//This is the current mesh vertex position, color and tex coord | |
// Set automatically | |
attribute vec4 position; | |
attribute vec4 color; | |
attribute vec2 texCoord; | |
varying lowp vec4 vColor; | |
varying highp vec2 vTexCoord; | |
varying lowp vec4 vSpecularLightColor; | |
varying lowp vec3 vAmbientLightColor; | |
varying lowp vec3 vDiffuseLightColor; | |
//****new attributes | |
// Our Model, View and Projection matrices | |
// we need them to transform the incoming vertices and for lighting | |
// calculation | |
uniform mat4 mModel; | |
uniform mat4 mView; | |
uniform mat4 mProjection; | |
// Position of the "Camera" and the Light | |
// in Model space | |
uniform vec4 vEyePosition; | |
uniform vec4 vLightPosition; | |
// The Colors of the material | |
uniform float vAmbientMaterial; | |
uniform float vDiffuseMaterial; | |
uniform float vSpecularMaterial; | |
uniform vec4 lightColor; | |
float calcHeight(float x, float z) | |
{ | |
float result = 0.0; | |
if (tp1.x > -100.0) { | |
result = result + | |
sin(sqrt( | |
(tp1.x-x)*(tp1.x-x) + | |
(tp1.y-z)*(tp1.y-z)) * | |
wavelength +offset)*amp; | |
} | |
if (tp2.x > -100.0) { | |
result = result + | |
sin(sqrt( | |
(tp2.x-x)*(tp2.x-x) + | |
(tp2.y-z)*(tp2.y-z) | |
) * wavelength + offset | |
)*amp; | |
} | |
if (tp3.x > -100.0) { | |
result = result + | |
sin(sqrt( | |
(tp3.x-x)*(tp3.x-x) + | |
(tp3.y-z)*(tp3.y-z) | |
) * wavelength + offset | |
)*amp; | |
} | |
if (tp4.x > -100.0) { | |
result = result + | |
sin(sqrt( | |
(tp4.x-x)*(tp4.x-x) + | |
(tp4.y-z)*(tp4.y-z) | |
) * wavelength + offset | |
)*amp; | |
} | |
if (tp5.x > -100.0) { | |
result = result + | |
sin(sqrt( | |
(tp5.x-x)*(tp5.x-x) + | |
(tp5.y-z)*(tp5.y-z) | |
) * wavelength + offset | |
)*amp; | |
} | |
return result; | |
} | |
void main() | |
{ | |
//Pass the mesh color to the fragment shader | |
vColor = color; | |
vTexCoord = vec2(texCoord.x, 1.0 - texCoord.y); | |
//Generate the height of the current vertex | |
vec4 calcpos = position; | |
calcpos.y = calcpos.y + calcHeight(position.x, position.z); | |
//Multiply the vertex position by our combined transform | |
gl_Position = modelViewProjection * calcpos; | |
} | |
]], | |
fragmentShaderWireframe = [[ | |
// | |
// A basic fragment shader | |
// | |
//Default precision qualifier | |
precision highp float; | |
//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; | |
varying lowp vec4 vSpecularLightColor; | |
varying lowp vec3 vAmbientLightColor; | |
varying lowp vec3 vDiffuseLightColor; | |
void main() | |
{ | |
//Sample the texture at the interpolated coordinate | |
lowp vec4 col = texture2D( texture, vTexCoord ); | |
if (col.x == 0.0) discard; | |
//Set the output color to the texture color | |
gl_FragColor = col; | |
} | |
]] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment