Skip to content

Instantly share code, notes, and snippets.

@sp4cemonkey
Last active December 13, 2015 21:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sp4cemonkey/4977040 to your computer and use it in GitHub Desktop.
Save sp4cemonkey/4977040 to your computer and use it in GitHub Desktop.
3d Sin in a shader
-- 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