SHARE
TWEET

3DSnow.lua

SkyTheCoder Dec 26th, 2015 (edited) 122 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. --# Main
  2. -- 3D Snow
  3.  
  4. function setup()
  5.     displayMode(OVERLAY)
  6.     displayMode(FULLSCREEN)
  7.    
  8.     parameter.watch("FPS")
  9.     parameter.boolean("camOrtho", false)
  10.     parameter.number("timeSpeed", 0, 8, 1)
  11.     parameter.number("hspread", 0, 50, 50)
  12.     parameter.number("vspread", 0, 50, 0)
  13.     parameter.number("stretch", 0, 16, 0)
  14.     parameter.boolean("vortex", false)
  15.     parameter.boolean("night", false)
  16.    
  17.     instances = 300
  18.     snowMesh = mesh() -- Generate a mesh with 100 triangles randomly positioned and rotated in it, with texture coordinates
  19.     local v = {}
  20.     local tc = {}
  21.     local size = 0.5 -- Lower this to make each individual triangle smaller
  22.     local hspread = 25 -- The horizontal spread of triangles within the mesh
  23.     local vspread = 5 -- The vertical spread of triangles within the mesh
  24.     for i = 1, 100 do
  25.         local rel = {vec3(-0.5, -0.5, 0), vec3(0.5, -0.5, 0.0), vec3(0.5, 0.5, 0.0)}
  26.         for k, vec in ipairs(rel) do
  27.             math.randomseed(i * math.pi * 10000 * 123456789)
  28.             vec = matrix()
  29.             :translate((math.random() * 2 - 1) * hspread, (math.random() * 2 - 1) * vspread, (math.random() * 2 - 1) * hspread)
  30.             :rotate(math.random(0, 359), 1, 0, 0):rotate(math.random(0, 359), 0, 1, 0):rotate(math.random(0, 359), 0, 0, 1)
  31.             *vec3(vec.x * size, vec.y * size, vec.z * size)
  32.             table.insert(v, vec)
  33.         end
  34.         table.insert(tc, vec2(0, 0))
  35.         table.insert(tc, vec2(1, 0))
  36.         table.insert(tc, vec2(1, 1))
  37.     end
  38.    
  39.     snowMesh.vertices = v
  40.     snowMesh.texCoords = tc
  41.     snowMesh.shader = shader("Snow") -- The shader transforms and textures the vertices
  42.     snowMesh.shader.stretch = 0
  43.     transform = snowMesh:buffer("transform")
  44.     transform.instanced = true
  45.     transform:resize(instances)
  46.     instTint = snowMesh:buffer("tint")
  47.     instTint.instanced = true
  48.     instTint:resize(instances)
  49.     instAlpha = snowMesh:buffer("alpha")
  50.     instAlpha.instanced = true
  51.     instAlpha:resize(instances)
  52.    
  53.     for i = 1, instances do
  54.         math.randomseed(i)
  55.         transform[i] = matrix()
  56.         instTint[i] = color(255)
  57.     end
  58.    
  59.     time = 0
  60.     ts = timeSpeed
  61.    
  62.     pos = vec3(0, -50, 0) -- Variables to handle camera movement and direction
  63.     ang = vec2(1, 1):normalize()
  64.     ang2 = vec2(1, 1):normalize()
  65.     tpos = vec3(pos.x, pos.y, pos.z)
  66.     tang = vec2(ang.x, ang.y)
  67.     tang2 = vec2(ang2.x, ang2.y)
  68.    
  69.     mId = 0
  70.     lId = 0
  71.    
  72.     zoom = 20
  73.     tzoom = zoom
  74. end
  75.  
  76. function draw()
  77.     if night then
  78.         background(0)
  79.     else
  80.         background(191, 220, 255)
  81.     end
  82.  
  83.     local pmix = 0.0375 -- Smoothes the camera movement
  84.     pos.x = pos.x * (1 - pmix) + tpos.x * pmix
  85.     pos.y = pos.y * (1 - pmix) + tpos.y * pmix
  86.     pos.z = pos.z * (1 - pmix) + tpos.z * pmix
  87.     local amix = 0.1
  88.     ang.x = ang.x * (1 - amix) + tang.x * amix
  89.     ang.y = ang.y * (1 - amix) + tang.y * amix
  90.     ang2.x = ang2.x * (1 - amix) + tang2.x * amix
  91.     ang2.y = ang2.y * (1 - amix) + tang2.y * amix
  92.     local zmix = 0.1
  93.     zoom = zoom * (1 - zmix) + tzoom * zmix
  94.     local smix = 0.05
  95.     ts = ts * (1 - smix) + timeSpeed * smix
  96.     time = time + DeltaTime * ts
  97.    
  98.     if camOrtho then
  99.         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)
  100.         local aspect = WIDTH / HEIGHT
  101.         ortho(-zoom * aspect, zoom * aspect, -zoom, zoom, 0.001, 65536)
  102.     else
  103.         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)
  104.         perspective(70, WIDTH / HEIGHT, 0.001, 65536)
  105.     end
  106.    
  107.     --local hspread = 0
  108.     --local vspread = 0
  109.     local step = 1
  110.     local height = 20
  111.     local pOffset = 1
  112.     local lOffset = 0
  113.     for i = 1, instances do
  114.         math.randomseed(i * math.pi * 10000)
  115.         local max = (instances * height * step * lOffset + height * step * (1 - lOffset))
  116.         local offset = (time + i * step * pOffset) % (instances * height * step * lOffset + height * step * (1 - lOffset))
  117.         transform[i] = matrix()
  118.         if vortex then
  119.             transform[i] = transform[i]:rotate(time * 45, 0, 1, 0)
  120.         end
  121.         transform[i] = transform[i]:translate(0.0, -offset * 3.0, 0.0)
  122.         :translate((math.random() * 2 - 1) * hspread, (math.random() * 2 - 1) * vspread, (math.random() * 2 - 1) * hspread)
  123.         :rotate(math.random(0, 359), 0, 1, 0)
  124.         instAlpha[i] = math.min(1, (offset / max) * height) * math.min(1, (1 - offset / max) * height)
  125.     end
  126.    
  127.     snowMesh.shader.stretch = stretch
  128.    
  129.     snowMesh:draw(instances)
  130.    
  131.     collectgarbage()
  132.     collectgarbage()
  133.     collectgarbage()
  134. end
  135.  
  136. function touched(touch) -- Handles camera movement and direction
  137.     if touch.state == BEGAN then
  138.         if touch.x < WIDTH / 2 and mId == 0 then
  139.             mId = touch.id
  140.         elseif touch.x >= WIDTH / 2 and lId == 0 then
  141.             lId = touch.id
  142.         end
  143.     end
  144.    
  145.     if touch.id == mId then
  146.         if camOrtho then
  147.             tzoom = tzoom - touch.deltaY / 20 * (tzoom / 40 + 0.5)
  148.         else
  149.             local speed = 1 / 32
  150.             tpos.x = tpos.x + tang:rotate(math.pi / 2).x * touch.deltaX * speed
  151.             tpos.z = tpos.z + tang:rotate(math.pi / 2).y * touch.deltaX * speed
  152.             tpos.x = tpos.x + tang.x * tang2.x * touch.deltaY * speed
  153.             tpos.z = tpos.z + tang.y * tang2.x * touch.deltaY * speed
  154.             tpos.y = tpos.y + tang2.y * touch.deltaY * speed
  155.         end
  156.     elseif touch.id == lId then
  157.         local speed = zoom / 40 + 0.5
  158.         tang = tang:rotate(math.rad(touch.deltaX / 2 * speed))
  159.         tang2 = tang2:rotate(math.rad(touch.deltaY / 2 * speed))
  160.         if tang2.x < 0.01 then
  161.             if tang2.y < 0 then
  162.                 tang2 = vec2(0.01, -1):normalize()
  163.             else
  164.                 tang2 = vec2(0.01, 1):normalize()
  165.             end
  166.         end
  167.     end
  168.    
  169.     if touch.state == ENDED or touch.state == CANCELLED then
  170.         if touch.id == mId then
  171.             mId = 0
  172.         elseif touch.id == lId then
  173.             lId = 0
  174.         end
  175.     end
  176. end
  177.  
  178. vert=[[
  179. uniform mat4 modelViewProjection;
  180.  
  181. attribute mat4 transform;
  182. attribute vec4 position;
  183. attribute vec4 color;
  184. attribute mediump vec2 texCoord;
  185.  
  186. varying lowp vec4 vColor;
  187. varying mediump vec2 vTexCoord;
  188.  
  189. void main()
  190. {
  191.     vColor = color;
  192.     vTexCoord = texCoord;
  193.     gl_Position = modelViewProjection * (transform * position);
  194. }
  195. ]]
  196.  
  197. frag=[[
  198. uniform sampler2D texture;
  199. varying lowp vec4 vColor;
  200. varying mediump vec2 vTexCoord;
  201. void main()
  202. {
  203.     gl_FragColor = vec4(1.0);//texture2D(texture, vTexCoord) * vColor;
  204. }
  205. ]]
  206.  
  207.  
  208. --# Primitive
  209. Primitive = class()
  210. -- Primitive class originally by @spacemonkey
  211. -- Edited by @SkyTheCoder to add options for width, height, length, and position, also to generate texture coordinates for the cube
  212.  
  213. --primitves gives basic mesh building for cubes and isospheres
  214. --triangles are wound consistently to avoid gl_facing issues
  215.  
  216. function Primitive:Cube(w, h, l, x, y, z)
  217.     local s = 1
  218.     w = w or 1
  219.     h = h or w
  220.     l = l or h
  221.     x = x or 0
  222.     y = y or 0
  223.     z = z or 0
  224.     local vertices = {
  225.       vec3(-0.5*s, -0.5*s,  0.5*s), -- Left  bottom front
  226.       vec3( 0.5*s, -0.5*s,  0.5*s), -- Right bottom front
  227.       vec3( 0.5*s,  0.5*s,  0.5*s), -- Right top    front
  228.       vec3(-0.5*s,  0.5*s,  0.5*s), -- Left  top    front
  229.       vec3(-0.5*s, -0.5*s, -0.5*s), -- Left  bottom back
  230.       vec3( 0.5*s, -0.5*s, -0.5*s), -- Right bottom back
  231.       vec3( 0.5*s,  0.5*s, -0.5*s), -- Right top    back
  232.       vec3(-0.5*s,  0.5*s, -0.5*s), -- Left  top    back
  233.     }
  234.  
  235.     -- now construct a cube out of the vertices above
  236.     v = {
  237.       -- Front
  238.       vertices[1], vertices[2], vertices[3],
  239.       vertices[1], vertices[3], vertices[4],
  240.       -- Right
  241.       vertices[2], vertices[6], vertices[7],
  242.       vertices[2], vertices[7], vertices[3],
  243.       -- Back
  244.       vertices[6], vertices[5], vertices[8],
  245.       vertices[6], vertices[8], vertices[7],
  246.       -- Left
  247.       vertices[5], vertices[1], vertices[4],
  248.       vertices[5], vertices[4], vertices[8],
  249.       -- Top
  250.       vertices[4], vertices[3], vertices[7],
  251.       vertices[4], vertices[7], vertices[8],
  252.       -- Bottom
  253.       vertices[5], vertices[6], vertices[2],
  254.       vertices[5], vertices[2], vertices[1],
  255.     }
  256.     for i, j in ipairs(v) do
  257.         v[i] = vec3(j.x * w + x, j.y * h + y, j.z * l + z)
  258.     end
  259.     return v
  260. end
  261.  
  262. function Primitive:CubeTexCoords(w, h, x)
  263.     w = w or 1
  264.     h = h or w
  265.     x = x or Primitive:Cube(1)
  266.     local ret = {}
  267.     for i = 1, #x / 3 do
  268.         table.insert(ret, vec2(0.0, 0.0))
  269.         table.insert(ret, vec2(w, 0.0))
  270.         table.insert(ret, vec2(w, h))
  271.         table.insert(ret, vec2(0.0, 0.0))
  272.         table.insert(ret, vec2(w, h))
  273.         table.insert(ret, vec2(0.0, h))
  274.     end
  275.     return ret
  276. end
  277.  
  278. function Primitive:Sphere(w, h, l, x, y, z, depth)
  279.     local s = 1
  280.     w = w or 1
  281.     h = h or w
  282.     l = l or h
  283.     x = x or 0
  284.     y = y or 0
  285.     z = z or 0
  286.     depth = depth or 1
  287.     local t = (1 + math.sqrt(5)) / 2
  288.     --all the vertices of an icosohedron
  289.     local vertices = {
  290.             vec3(-1 , t, 0):normalize(),
  291.             vec3(1 , t, 0):normalize(),
  292.             vec3(-1 , -t, 0):normalize(),
  293.             vec3(1 , -t, 0):normalize(),
  294.            
  295.             vec3(0 , -1, t):normalize(),
  296.             vec3(0 , 1, t):normalize(),
  297.             vec3(0 , -1, -t):normalize(),
  298.             vec3(0 , 1, -t):normalize(),
  299.            
  300.             vec3(t , 0, -1):normalize(),
  301.             vec3(t , 0, 1):normalize(),
  302.             vec3(-t , 0, -1):normalize(),
  303.             vec3(-t , 0, 1):normalize()
  304.         }
  305.     --20 faces
  306.     icovertices = {
  307.             -- 5 faces around point 0
  308.             vertices[1], vertices[12], vertices[6],
  309.             vertices[1], vertices[6], vertices[2],
  310.             vertices[1], vertices[2], vertices[8],
  311.             vertices[1], vertices[8], vertices[11],
  312.             vertices[1], vertices[11], vertices[12],
  313.            
  314.             -- 5 adjacent faces
  315.             vertices[2], vertices[6], vertices[10],
  316.             vertices[6], vertices[12], vertices[5],
  317.             vertices[12], vertices[11], vertices[3],
  318.             vertices[11], vertices[8], vertices[7],
  319.             vertices[8], vertices[2], vertices[9],
  320.            
  321.             -- 5 faces around point 3
  322.             vertices[4], vertices[10], vertices[5],
  323.             vertices[4], vertices[5], vertices[3],
  324.             vertices[4], vertices[3], vertices[7],
  325.             vertices[4], vertices[7], vertices[9],
  326.             vertices[4], vertices[9], vertices[10],
  327.            
  328.             --5 adjacent faces
  329.             vertices[5], vertices[10], vertices[6],
  330.             vertices[3], vertices[5], vertices[12],
  331.             vertices[7], vertices[3], vertices[11],
  332.             vertices[9], vertices[7], vertices[8],
  333.             vertices[10], vertices[9], vertices[2]
  334.         }
  335.    
  336.     local finalVertices = {}
  337.     --divide each triangle into 4 sub triangles to make an isosphere    
  338.     --this can be repeated (based on depth) for higher res spheres  
  339.     for j=1,depth do
  340.         for i=1,#icovertices/3 do
  341.             midpoint1 = ((icovertices[i*3-2] + icovertices[i*3-1])/2):normalize()
  342.             midpoint2 = ((icovertices[i*3-1] + icovertices[i*3])/2):normalize()
  343.             midpoint3 = ((icovertices[i*3] + icovertices[i*3-2])/2):normalize()
  344.             --triangle 1
  345.             table.insert(finalVertices,icovertices[i*3-2])
  346.             table.insert(finalVertices,midpoint1)
  347.             table.insert(finalVertices,midpoint3)
  348.             --triangle 2
  349.             table.insert(finalVertices,midpoint1)
  350.             table.insert(finalVertices,icovertices[i*3-1])
  351.             table.insert(finalVertices,midpoint2)
  352.             --triangle 3
  353.             table.insert(finalVertices,midpoint2)
  354.             table.insert(finalVertices,icovertices[i*3])
  355.             table.insert(finalVertices,midpoint3)
  356.             --triangle 4
  357.             table.insert(finalVertices,midpoint1)
  358.             table.insert(finalVertices,midpoint2)
  359.             table.insert(finalVertices,midpoint3)
  360.         end
  361.         icovertices = finalVertices
  362.         finalVertices = {}
  363.     end
  364.     for i, j in ipairs(icovertices) do
  365.         icovertices[i] = vec3(j.x * w + x, j.y * h + y, j.z * l + z)
  366.     end
  367.     return icovertices
  368. end
  369.  
  370.  
  371. --# FPS
  372. FPS = 0 -- Code to calculate accurate frames per secoond
  373. local frames = 0
  374. local time = 0
  375. tween.delay(0.001, function()
  376.     local d = draw
  377.     draw = function()
  378.         frames = frames + 1
  379.         if math.floor(ElapsedTime) ~= math.floor(time) then
  380.             FPS = frames - 1
  381.             frames = 1
  382.         end
  383.         time = ElapsedTime
  384.         d()
  385.     end
  386. end)
  387. --# Shaders
  388. Shaders = {
  389. --shaderstart:Snow
  390. Snow = {
  391. vS = [[
  392. //
  393. // A basic vertex shader
  394. //
  395.  
  396. //This is the current model * view * projection matrix
  397. // Codea sets it automatically
  398. uniform mat4 modelViewProjection;
  399.  
  400. uniform highp float stretch;
  401.  
  402. //This is the current mesh vertex position, color and tex coord
  403. // Set automatically
  404. attribute vec4 position;
  405. attribute vec4 color;
  406. attribute vec2 texCoord;
  407. attribute mat4 transform;
  408. attribute vec4 tint;
  409. attribute lowp float alpha;
  410.  
  411. //This is an output variable that will be passed to the fragment shader
  412. varying lowp vec4 vColor;
  413. varying highp vec2 vTexCoord;
  414. varying lowp vec4 vTint;
  415. varying lowp float vAlpha;
  416.  
  417. void main()
  418. {
  419.     //Pass the mesh color to the fragment shader
  420.     vColor = color;
  421.     vTexCoord = texCoord;
  422.     vTint = tint;
  423.     vAlpha = alpha;
  424.    
  425.     vec4 offset = vec4(0.0);
  426.     if (vTexCoord.xy == vec2(1.0, 1.0)) offset = vec4(0.0, stretch, 0.0, 0.0);
  427.    
  428.     //Multiply the vertex position by our combined transform
  429.     gl_Position = modelViewProjection * (transform * (position + offset));
  430. }
  431. ]],
  432. fS = [[
  433. //
  434. // A basic fragment shader
  435. //
  436.  
  437. //Default precision qualifier
  438. precision highp float;
  439.  
  440. //This represents the current texture on the mesh
  441. uniform lowp sampler2D texture;
  442.  
  443. //The interpolated vertex color for this fragment
  444. varying lowp vec4 vColor;
  445.  
  446. //The interpolated texture coordinate for this fragment
  447. varying highp vec2 vTexCoord;
  448.  
  449. varying lowp vec4 vTint;
  450.  
  451. varying lowp float vAlpha;
  452.  
  453. void main()
  454. {
  455.     //Sample the texture at the interpolated coordinate
  456.     //lowp vec4 col = texture2D( texture, vTexCoord ) * vColor;
  457.    
  458.     float dist = (1.0 - pow(min(1.0, distance(vTexCoord, vec2(0.75, 0.25)) * 4.0), 3.0));
  459.     if (dist <= 0.1) discard;
  460.  
  461.     //Set the output color to the texture color
  462.     gl_FragColor = vec4(vTint.rgb, vAlpha) * dist;//col;
  463. }
  464. ]],
  465. },
  466. --shaderend:Snow
  467. }
  468. --# Utility
  469. function math.dec(x)
  470.     return x - math.floor(x)
  471. end
  472.  
  473. function math.mix(a, b, x)
  474.     return a * x + b * (1 - x)
  475. end
  476.  
  477. -- Function tweak to make shaders easier, so I can call shader("X") instead of shader(Shaders.X.vS, Shaders.X.fS)
  478. local _shader = shader
  479. function shader(...)
  480.     if select("#", ...) == 1 then
  481.         local data = Shaders[select(1, ...)]
  482.         if data ~= nil then
  483.             return _shader(data.vS, data.fS)
  484.         else
  485.             return _shader(...)
  486.         end
  487.     else
  488.         return _shader(...)
  489.     end
  490. end
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Top