Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --# Main
- -- 3D Snow
- function setup()
- displayMode(OVERLAY)
- displayMode(FULLSCREEN)
- parameter.watch("FPS")
- parameter.boolean("camOrtho", false)
- parameter.number("timeSpeed", 0, 8, 1)
- parameter.number("hspread", 0, 50, 50)
- parameter.number("vspread", 0, 50, 0)
- parameter.number("stretch", 0, 16, 0)
- parameter.boolean("vortex", false)
- parameter.boolean("night", false)
- instances = 300
- snowMesh = mesh() -- Generate a mesh with 100 triangles randomly positioned and rotated in it, with texture coordinates
- local v = {}
- local tc = {}
- local size = 0.5 -- Lower this to make each individual triangle smaller
- local hspread = 25 -- The horizontal spread of triangles within the mesh
- local vspread = 5 -- The vertical spread of triangles within the mesh
- for i = 1, 100 do
- local rel = {vec3(-0.5, -0.5, 0), vec3(0.5, -0.5, 0.0), vec3(0.5, 0.5, 0.0)}
- for k, vec in ipairs(rel) do
- math.randomseed(i * math.pi * 10000 * 123456789)
- vec = matrix()
- :translate((math.random() * 2 - 1) * hspread, (math.random() * 2 - 1) * vspread, (math.random() * 2 - 1) * hspread)
- :rotate(math.random(0, 359), 1, 0, 0):rotate(math.random(0, 359), 0, 1, 0):rotate(math.random(0, 359), 0, 0, 1)
- *vec3(vec.x * size, vec.y * size, vec.z * size)
- table.insert(v, vec)
- end
- table.insert(tc, vec2(0, 0))
- table.insert(tc, vec2(1, 0))
- table.insert(tc, vec2(1, 1))
- end
- snowMesh.vertices = v
- snowMesh.texCoords = tc
- snowMesh.shader = shader("Snow") -- The shader transforms and textures the vertices
- snowMesh.shader.stretch = 0
- transform = snowMesh:buffer("transform")
- transform.instanced = true
- transform:resize(instances)
- instTint = snowMesh:buffer("tint")
- instTint.instanced = true
- instTint:resize(instances)
- instAlpha = snowMesh:buffer("alpha")
- instAlpha.instanced = true
- instAlpha:resize(instances)
- for i = 1, instances do
- math.randomseed(i)
- transform[i] = matrix()
- instTint[i] = color(255)
- end
- time = 0
- ts = timeSpeed
- pos = vec3(0, -50, 0) -- Variables to handle camera movement and direction
- ang = vec2(1, 1):normalize()
- ang2 = vec2(1, 1):normalize()
- tpos = vec3(pos.x, pos.y, pos.z)
- tang = vec2(ang.x, ang.y)
- tang2 = vec2(ang2.x, ang2.y)
- mId = 0
- lId = 0
- zoom = 20
- tzoom = zoom
- end
- function draw()
- if night then
- background(0)
- else
- background(191, 220, 255)
- end
- local pmix = 0.0375 -- Smoothes the camera movement
- pos.x = pos.x * (1 - pmix) + tpos.x * pmix
- pos.y = pos.y * (1 - pmix) + tpos.y * pmix
- pos.z = pos.z * (1 - pmix) + tpos.z * pmix
- local amix = 0.1
- ang.x = ang.x * (1 - amix) + tang.x * amix
- ang.y = ang.y * (1 - amix) + tang.y * amix
- ang2.x = ang2.x * (1 - amix) + tang2.x * amix
- ang2.y = ang2.y * (1 - amix) + tang2.y * amix
- local zmix = 0.1
- zoom = zoom * (1 - zmix) + tzoom * zmix
- local smix = 0.05
- ts = ts * (1 - smix) + timeSpeed * smix
- time = time + DeltaTime * ts
- if camOrtho then
- camera(ang.x * ang2.x * -100, ang2.y * -100, ang.y * ang2.x * -100, ang.x * ang2.x, ang2.y, ang.y * ang2.x, 0, 1, 0)
- local aspect = WIDTH / HEIGHT
- ortho(-zoom * aspect, zoom * aspect, -zoom, zoom, 0.001, 65536)
- else
- camera(pos.x, pos.y, pos.z, pos.x + ang.x * ang2.x, pos.y + ang2.y, pos.z + ang.y * ang2.x, 0, 1, 0)
- perspective(70, WIDTH / HEIGHT, 0.001, 65536)
- end
- --local hspread = 0
- --local vspread = 0
- local step = 1
- local height = 20
- local pOffset = 1
- local lOffset = 0
- for i = 1, instances do
- math.randomseed(i * math.pi * 10000)
- local max = (instances * height * step * lOffset + height * step * (1 - lOffset))
- local offset = (time + i * step * pOffset) % (instances * height * step * lOffset + height * step * (1 - lOffset))
- transform[i] = matrix()
- if vortex then
- transform[i] = transform[i]:rotate(time * 45, 0, 1, 0)
- end
- transform[i] = transform[i]:translate(0.0, -offset * 3.0, 0.0)
- :translate((math.random() * 2 - 1) * hspread, (math.random() * 2 - 1) * vspread, (math.random() * 2 - 1) * hspread)
- :rotate(math.random(0, 359), 0, 1, 0)
- instAlpha[i] = math.min(1, (offset / max) * height) * math.min(1, (1 - offset / max) * height)
- end
- snowMesh.shader.stretch = stretch
- snowMesh:draw(instances)
- collectgarbage()
- collectgarbage()
- collectgarbage()
- end
- function touched(touch) -- Handles camera movement and direction
- if touch.state == BEGAN then
- if touch.x < WIDTH / 2 and mId == 0 then
- mId = touch.id
- elseif touch.x >= WIDTH / 2 and lId == 0 then
- lId = touch.id
- end
- end
- if touch.id == mId then
- if camOrtho then
- tzoom = tzoom - touch.deltaY / 20 * (tzoom / 40 + 0.5)
- else
- local speed = 1 / 32
- tpos.x = tpos.x + tang:rotate(math.pi / 2).x * touch.deltaX * speed
- tpos.z = tpos.z + tang:rotate(math.pi / 2).y * touch.deltaX * speed
- tpos.x = tpos.x + tang.x * tang2.x * touch.deltaY * speed
- tpos.z = tpos.z + tang.y * tang2.x * touch.deltaY * speed
- tpos.y = tpos.y + tang2.y * touch.deltaY * speed
- end
- elseif touch.id == lId then
- local speed = zoom / 40 + 0.5
- tang = tang:rotate(math.rad(touch.deltaX / 2 * speed))
- tang2 = tang2:rotate(math.rad(touch.deltaY / 2 * speed))
- if tang2.x < 0.01 then
- if tang2.y < 0 then
- tang2 = vec2(0.01, -1):normalize()
- else
- tang2 = vec2(0.01, 1):normalize()
- end
- end
- end
- if touch.state == ENDED or touch.state == CANCELLED then
- if touch.id == mId then
- mId = 0
- elseif touch.id == lId then
- lId = 0
- end
- end
- end
- vert=[[
- uniform mat4 modelViewProjection;
- attribute mat4 transform;
- attribute vec4 position;
- attribute vec4 color;
- attribute mediump vec2 texCoord;
- varying lowp vec4 vColor;
- varying mediump vec2 vTexCoord;
- void main()
- {
- vColor = color;
- vTexCoord = texCoord;
- gl_Position = modelViewProjection * (transform * position);
- }
- ]]
- frag=[[
- uniform sampler2D texture;
- varying lowp vec4 vColor;
- varying mediump vec2 vTexCoord;
- void main()
- {
- gl_FragColor = vec4(1.0);//texture2D(texture, vTexCoord) * vColor;
- }
- ]]
- --# Primitive
- Primitive = class()
- -- Primitive class originally by @spacemonkey
- -- Edited by @SkyTheCoder to add options for width, height, length, and position, also to generate texture coordinates for the cube
- --primitves gives basic mesh building for cubes and isospheres
- --triangles are wound consistently to avoid gl_facing issues
- function Primitive:Cube(w, h, l, x, y, z)
- local s = 1
- w = w or 1
- h = h or w
- l = l or h
- x = x or 0
- y = y or 0
- z = z or 0
- local vertices = {
- vec3(-0.5*s, -0.5*s, 0.5*s), -- Left bottom front
- vec3( 0.5*s, -0.5*s, 0.5*s), -- Right bottom front
- vec3( 0.5*s, 0.5*s, 0.5*s), -- Right top front
- vec3(-0.5*s, 0.5*s, 0.5*s), -- Left top front
- vec3(-0.5*s, -0.5*s, -0.5*s), -- Left bottom back
- vec3( 0.5*s, -0.5*s, -0.5*s), -- Right bottom back
- vec3( 0.5*s, 0.5*s, -0.5*s), -- Right top back
- vec3(-0.5*s, 0.5*s, -0.5*s), -- Left top back
- }
- -- now construct a cube out of the vertices above
- v = {
- -- Front
- vertices[1], vertices[2], vertices[3],
- vertices[1], vertices[3], vertices[4],
- -- Right
- vertices[2], vertices[6], vertices[7],
- vertices[2], vertices[7], vertices[3],
- -- Back
- vertices[6], vertices[5], vertices[8],
- vertices[6], vertices[8], vertices[7],
- -- Left
- vertices[5], vertices[1], vertices[4],
- vertices[5], vertices[4], vertices[8],
- -- Top
- vertices[4], vertices[3], vertices[7],
- vertices[4], vertices[7], vertices[8],
- -- Bottom
- vertices[5], vertices[6], vertices[2],
- vertices[5], vertices[2], vertices[1],
- }
- for i, j in ipairs(v) do
- v[i] = vec3(j.x * w + x, j.y * h + y, j.z * l + z)
- end
- return v
- end
- function Primitive:CubeTexCoords(w, h, x)
- w = w or 1
- h = h or w
- x = x or Primitive:Cube(1)
- local ret = {}
- for i = 1, #x / 3 do
- table.insert(ret, vec2(0.0, 0.0))
- table.insert(ret, vec2(w, 0.0))
- table.insert(ret, vec2(w, h))
- table.insert(ret, vec2(0.0, 0.0))
- table.insert(ret, vec2(w, h))
- table.insert(ret, vec2(0.0, h))
- end
- return ret
- end
- function Primitive:Sphere(w, h, l, x, y, z, depth)
- local s = 1
- w = w or 1
- h = h or w
- l = l or h
- x = x or 0
- y = y or 0
- z = z or 0
- depth = depth or 1
- local t = (1 + math.sqrt(5)) / 2
- --all the vertices of an icosohedron
- local vertices = {
- vec3(-1 , t, 0):normalize(),
- vec3(1 , t, 0):normalize(),
- vec3(-1 , -t, 0):normalize(),
- vec3(1 , -t, 0):normalize(),
- vec3(0 , -1, t):normalize(),
- vec3(0 , 1, t):normalize(),
- vec3(0 , -1, -t):normalize(),
- vec3(0 , 1, -t):normalize(),
- vec3(t , 0, -1):normalize(),
- vec3(t , 0, 1):normalize(),
- vec3(-t , 0, -1):normalize(),
- vec3(-t , 0, 1):normalize()
- }
- --20 faces
- icovertices = {
- -- 5 faces around point 0
- vertices[1], vertices[12], vertices[6],
- vertices[1], vertices[6], vertices[2],
- vertices[1], vertices[2], vertices[8],
- vertices[1], vertices[8], vertices[11],
- vertices[1], vertices[11], vertices[12],
- -- 5 adjacent faces
- vertices[2], vertices[6], vertices[10],
- vertices[6], vertices[12], vertices[5],
- vertices[12], vertices[11], vertices[3],
- vertices[11], vertices[8], vertices[7],
- vertices[8], vertices[2], vertices[9],
- -- 5 faces around point 3
- vertices[4], vertices[10], vertices[5],
- vertices[4], vertices[5], vertices[3],
- vertices[4], vertices[3], vertices[7],
- vertices[4], vertices[7], vertices[9],
- vertices[4], vertices[9], vertices[10],
- --5 adjacent faces
- vertices[5], vertices[10], vertices[6],
- vertices[3], vertices[5], vertices[12],
- vertices[7], vertices[3], vertices[11],
- vertices[9], vertices[7], vertices[8],
- vertices[10], vertices[9], vertices[2]
- }
- local finalVertices = {}
- --divide each triangle into 4 sub triangles to make an isosphere
- --this can be repeated (based on depth) for higher res spheres
- for j=1,depth do
- for i=1,#icovertices/3 do
- midpoint1 = ((icovertices[i*3-2] + icovertices[i*3-1])/2):normalize()
- midpoint2 = ((icovertices[i*3-1] + icovertices[i*3])/2):normalize()
- midpoint3 = ((icovertices[i*3] + icovertices[i*3-2])/2):normalize()
- --triangle 1
- table.insert(finalVertices,icovertices[i*3-2])
- table.insert(finalVertices,midpoint1)
- table.insert(finalVertices,midpoint3)
- --triangle 2
- table.insert(finalVertices,midpoint1)
- table.insert(finalVertices,icovertices[i*3-1])
- table.insert(finalVertices,midpoint2)
- --triangle 3
- table.insert(finalVertices,midpoint2)
- table.insert(finalVertices,icovertices[i*3])
- table.insert(finalVertices,midpoint3)
- --triangle 4
- table.insert(finalVertices,midpoint1)
- table.insert(finalVertices,midpoint2)
- table.insert(finalVertices,midpoint3)
- end
- icovertices = finalVertices
- finalVertices = {}
- end
- for i, j in ipairs(icovertices) do
- icovertices[i] = vec3(j.x * w + x, j.y * h + y, j.z * l + z)
- end
- return icovertices
- end
- --# FPS
- FPS = 0 -- Code to calculate accurate frames per secoond
- local frames = 0
- local time = 0
- tween.delay(0.001, function()
- local d = draw
- draw = function()
- frames = frames + 1
- if math.floor(ElapsedTime) ~= math.floor(time) then
- FPS = frames - 1
- frames = 1
- end
- time = ElapsedTime
- d()
- end
- end)
- --# Shaders
- Shaders = {
- --shaderstart:Snow
- Snow = {
- vS = [[
- //
- // A basic vertex shader
- //
- //This is the current model * view * projection matrix
- // Codea sets it automatically
- uniform mat4 modelViewProjection;
- uniform highp float stretch;
- //This is the current mesh vertex position, color and tex coord
- // Set automatically
- attribute vec4 position;
- attribute vec4 color;
- attribute vec2 texCoord;
- attribute mat4 transform;
- attribute vec4 tint;
- attribute lowp float alpha;
- //This is an output variable that will be passed to the fragment shader
- varying lowp vec4 vColor;
- varying highp vec2 vTexCoord;
- varying lowp vec4 vTint;
- varying lowp float vAlpha;
- void main()
- {
- //Pass the mesh color to the fragment shader
- vColor = color;
- vTexCoord = texCoord;
- vTint = tint;
- vAlpha = alpha;
- vec4 offset = vec4(0.0);
- if (vTexCoord.xy == vec2(1.0, 1.0)) offset = vec4(0.0, stretch, 0.0, 0.0);
- //Multiply the vertex position by our combined transform
- gl_Position = modelViewProjection * (transform * (position + offset));
- }
- ]],
- fS = [[
- //
- // 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 vTint;
- varying lowp float vAlpha;
- void main()
- {
- //Sample the texture at the interpolated coordinate
- //lowp vec4 col = texture2D( texture, vTexCoord ) * vColor;
- float dist = (1.0 - pow(min(1.0, distance(vTexCoord, vec2(0.75, 0.25)) * 4.0), 3.0));
- if (dist <= 0.1) discard;
- //Set the output color to the texture color
- gl_FragColor = vec4(vTint.rgb, vAlpha) * dist;//col;
- }
- ]],
- },
- --shaderend:Snow
- }
- --# Utility
- function math.dec(x)
- return x - math.floor(x)
- end
- function math.mix(a, b, x)
- return a * x + b * (1 - x)
- end
- -- Function tweak to make shaders easier, so I can call shader("X") instead of shader(Shaders.X.vS, Shaders.X.fS)
- local _shader = shader
- function shader(...)
- if select("#", ...) == 1 then
- local data = Shaders[select(1, ...)]
- if data ~= nil then
- return _shader(data.vS, data.fS)
- else
- return _shader(...)
- end
- else
- return _shader(...)
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement