Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Grass
- -- Use this function to perform your initial setup
- function setup()
- displayMode(FULLSCREEN)
- field = mesh()
- --field.shader = shader("Documents:Grass")
- field.shader = shader(GrassShader.vertexShader, GrassShader.fragmentShader)
- bladeWidth = 0.15
- bladeHeight = 1.5
- midWeight = 0.2
- size = vec2(30,30)
- touchScale = 10
- numBlades = 10000
- field.shader.bladeHeight = bladeHeight
- createField(field, size,numBlades)
- generateTouchMesh(size)
- --pressureZones are x,y then radius and finally type (1 = round pushout)
- field.shader.pressureZone = vec4(-1000,-1000,0,0)
- campos = vec2(0,45)
- imageTouchSurface = image(WIDTH/touchScale,HEIGHT/touchScale)
- currentPressurePoint = 1
- pressurePoints = {}
- pressurePoints[1] = vec4(-1000,-1000,0,0)
- end
- function generateTouchMesh(size)
- --make a square the same footprint as our field to read touch against
- touchMesh = mesh()
- touchMesh:resize(6)
- touchMesh.vertices = {
- vec3(-size.x/2, 0, -size.y/2),
- vec3(-size.x/2, 0, size.y/2),
- vec3(size.x/2, 0, -size.y/2),
- vec3(-size.x/2, 0, size.y/2),
- vec3(size.x/2, 0, size.y/2),
- vec3(size.x/2, 0, -size.y/2)
- }
- touchMesh.texCoords = {
- vec2(0,0),
- vec2(0,1),
- vec2(1,0),
- vec2(0,1),
- vec2(1,1),
- vec2(1,0)
- }
- touchMesh:setColors(color(255,255,255,255))
- --call out for out texture
- touchMesh.texture = generateCoordTexture(vec2(100,100))
- end
- function generateCoordTexture(resolution)
- tex = image(resolution.x, resolution.y)
- for x=1,resolution.x do
- for y=1, resolution.y do
- tex:set(x,y,x/resolution.x*255,y/resolution.y*255,0)
- end
- end
- return tex
- end
- function createField(field, size, blades)
- --data is a vec4 that encode x as weight and y as height from base z and w represent x,y on the field
- dataBuffer = field:buffer("data")
- for i=1,blades do
- pos = vec3(math.random() * size.x - (size.x/2), 0, math.random() * size.y - (size.y/2))
- createBlade(field, pos, pos + vec3(0,bladeHeight,0))
- end
- end
- function createBlade(field, baseLocation, topLocation)
- local firstVertex = field.size + 1
- field:resize(firstVertex+11)
- local bladeRotation = math.random(360)
- --setup our vertex locations
- --2d vertex positions
- v2d = vec2(bladeWidth/2,0):rotate(math.rad(bladeRotation))
- midLocation = (baseLocation + topLocation)/2
- --calculate the vertices
- --base corners
- v1 = vec3(v2d.x+baseLocation.x,baseLocation.y, v2d.y+baseLocation.z)
- v2 = vec3(-v2d.x+baseLocation.x, baseLocation.y, -v2d.y+baseLocation.z)
- --mid corners
- v3 = vec3((v2d.x)+midLocation.x, midLocation.y, (v2d.x)+midLocation.z)
- v4 = vec3(-(v2d.x)+midLocation.x, midLocation.y, -(v2d.x)+midLocation.z)
- --point
- v5 = vec3(v2d.x/2+topLocation.x,topLocation.y, v2d.y/2+topLocation.z)
- v6 = vec3(-v2d.x/2+topLocation.x, topLocation.y, -v2d.y/2+topLocation.z)
- basecol = color(86, 153, 96, 255)
- midcol = color(63, 163, 78, 255)
- topcol = color(12, 229, 8, 255)
- field:vertex(firstVertex, v1)
- field:vertex(firstVertex+1, v2)
- field:vertex(firstVertex+2, v3)
- normal = (v2-v1):normalize():cross((v3-v1):normalize()):normalize()
- field:normal(firstVertex, normal)
- field:normal(firstVertex+1, normal)
- field:normal(firstVertex+2, normal)
- field:normal(firstVertex+3, normal)
- field:normal(firstVertex+4, normal)
- field:normal(firstVertex+5, normal)
- field:normal(firstVertex+6, normal)
- field:normal(firstVertex+7, normal)
- field:normal(firstVertex+8, normal)
- field:normal(firstVertex+9, normal)
- field:normal(firstVertex+10, normal)
- field:normal(firstVertex+11, normal)
- field:vertex(firstVertex+3, v3)
- field:vertex(firstVertex+4, v4)
- field:vertex(firstVertex+5, v2)
- field:vertex(firstVertex+6, v3)
- field:vertex(firstVertex+7, v4)
- field:vertex(firstVertex+8, v5)
- field:vertex(firstVertex+9, v4)
- field:vertex(firstVertex+10, v5)
- field:vertex(firstVertex+11, v6)
- field:color(firstVertex, basecol)
- field:color(firstVertex+1, basecol)
- field:color(firstVertex+2, midcol)
- field:color(firstVertex+3, midcol)
- field:color(firstVertex+4, midcol)
- field:color(firstVertex+5, basecol)
- field:color(firstVertex+6, midcol)
- field:color(firstVertex+7, midcol)
- field:color(firstVertex+8, topcol)
- field:color(firstVertex+9, midcol)
- field:color(firstVertex+10, topcol)
- field:color(firstVertex+11, topcol)
- dataBuffer[firstVertex] = vec4(0, 0, baseLocation.x, baseLocation.z)
- dataBuffer[firstVertex+1] = vec4(0, 0, baseLocation.x, baseLocation.z)
- dataBuffer[firstVertex+2] = vec4(midWeight, midLocation.y - baseLocation.y, baseLocation.x, baseLocation.z)
- dataBuffer[firstVertex+3] = vec4(midWeight, midLocation.y - baseLocation.y, baseLocation.x, baseLocation.z)
- dataBuffer[firstVertex+4] = vec4(midWeight, midLocation.y - baseLocation.y, baseLocation.x, baseLocation.z)
- dataBuffer[firstVertex+5] = vec4(0, 0, baseLocation.x, baseLocation.z)
- dataBuffer[firstVertex+6] = vec4(midWeight, midLocation.y - baseLocation.y, baseLocation.x, baseLocation.z)
- dataBuffer[firstVertex+7] = vec4(midWeight, midLocation.y - baseLocation.y, baseLocation.x, baseLocation.z)
- dataBuffer[firstVertex+8] = vec4(1, topLocation.y - baseLocation.y, baseLocation.x, baseLocation.z)
- dataBuffer[firstVertex+9] = vec4(midWeight, midLocation.y - baseLocation.y, baseLocation.x, baseLocation.z)
- dataBuffer[firstVertex+10] = vec4(1, topLocation.y - baseLocation.y, baseLocation.x, baseLocation.z)
- dataBuffer[firstVertex+11] = vec4(1, topLocation.y - baseLocation.y, baseLocation.x, baseLocation.z)
- end
- function touched(touch)
- if touch.state == BEGAN or touch.state == MOVING then
- r,g,b,a = imageTouchSurface:get(touch.x/touchScale, touch.y/touchScale)
- r = r / 255 * size.x - size.x/2
- g = g / 255 * size.y - size.y/2
- if math.abs(r-pressurePoints[currentPressurePoint].x) + math.abs(g-pressurePoints[currentPressurePoint].y) > 1 then
- currentPressurePoint = (currentPressurePoint + 1)%20
- pressurePoints[currentPressurePoint] = vec4(r,g,3,ElapsedTime)
- if currentPressurePoint == 1 then
- field.shader.pressureZone1 = pressurePoints[currentPressurePoint]
- elseif currentPressurePoint == 2 then
- field.shader.pressureZone2 = pressurePoints[currentPressurePoint]
- elseif currentPressurePoint == 3 then
- field.shader.pressureZone3 = pressurePoints[currentPressurePoint]
- elseif currentPressurePoint == 4 then
- field.shader.pressureZone4 = pressurePoints[currentPressurePoint]
- elseif currentPressurePoint == 5 then
- field.shader.pressureZone5 = pressurePoints[currentPressurePoint]
- elseif currentPressurePoint == 6 then
- field.shader.pressureZone6 = pressurePoints[currentPressurePoint]
- elseif currentPressurePoint == 7 then
- field.shader.pressureZone7 = pressurePoints[currentPressurePoint]
- elseif currentPressurePoint == 8 then
- field.shader.pressureZone8 = pressurePoints[currentPressurePoint]
- elseif currentPressurePoint == 9 then
- field.shader.pressureZone9 = pressurePoints[currentPressurePoint]
- elseif currentPressurePoint == 10 then
- field.shader.pressureZone10 = pressurePoints[currentPressurePoint]
- elseif currentPressurePoint == 11 then
- field.shader.pressureZone11 = pressurePoints[currentPressurePoint]
- elseif currentPressurePoint == 12 then
- field.shader.pressureZone12 = pressurePoints[currentPressurePoint]
- elseif currentPressurePoint == 13 then
- field.shader.pressureZone13 = pressurePoints[currentPressurePoint]
- elseif currentPressurePoint == 14 then
- field.shader.pressureZone14 = pressurePoints[currentPressurePoint]
- elseif currentPressurePoint == 15 then
- field.shader.pressureZone15 = pressurePoints[currentPressurePoint]
- elseif currentPressurePoint == 16 then
- field.shader.pressureZone16 = pressurePoints[currentPressurePoint]
- elseif currentPressurePoint == 17 then
- field.shader.pressureZone17 = pressurePoints[currentPressurePoint]
- elseif currentPressurePoint == 18 then
- field.shader.pressureZone18 = pressurePoints[currentPressurePoint]
- elseif currentPressurePoint == 19 then
- field.shader.pressureZone19 = pressurePoints[currentPressurePoint]
- elseif currentPressurePoint == 20 then
- field.shader.pressureZone20 = pressurePoints[currentPressurePoint]
- end
- end
- end
- end
- -- This function gets called once every frame
- function draw()
- campos = campos:rotate(math.rad(0.2))
- output.clear()
- print(1/DeltaTime)
- field.shader.time = ElapsedTime
- setContext(imageTouchSurface)
- background(40, 40, 50)
- camera(campos.x,30,campos.y, 0,0,0)
- perspective()
- touchMesh:draw()
- setContext()
- background(40,40,50)
- camera(campos.x,30,campos.y, 0,0,0)
- perspective()
- field.shader.vEyePosition = vec3(campos.x, 20, campos.y)
- field.shader.vLightPosition = vec3(10,80,20)
- field.shader.mInvModel = modelMatrix():inverse():transpose()
- field:draw()
- end
- GrassShader = {
- vertexShader = [[
- //
- // A basic vertex shader
- //
- //This is the current model * view * projection matrix
- // Codea sets it automatically
- uniform mat4 modelViewProjection;
- uniform vec4 pressureZone1;
- uniform vec4 pressureZone2;
- uniform vec4 pressureZone3;
- uniform vec4 pressureZone4;
- uniform vec4 pressureZone5;
- uniform vec4 pressureZone6;
- uniform vec4 pressureZone7;
- uniform vec4 pressureZone8;
- uniform vec4 pressureZone9;
- uniform vec4 pressureZone10;
- uniform vec4 pressureZone11;
- uniform vec4 pressureZone12;
- uniform vec4 pressureZone13;
- uniform vec4 pressureZone14;
- uniform vec4 pressureZone15;
- uniform vec4 pressureZone16;
- uniform vec4 pressureZone17;
- uniform vec4 pressureZone18;
- uniform vec4 pressureZone19;
- uniform vec4 pressureZone20;
- uniform float time;
- uniform highp mat4 mInvModel;
- uniform mediump vec3 vEyePosition;
- uniform mediump vec3 vLightPosition;
- //This is the current mesh vertex position, color and tex coord
- // Set automatically
- attribute vec4 position;
- attribute vec4 color;
- attribute vec3 normal;
- attribute vec4 data;
- //This is an output variable that will be passed to the fragment shader
- varying lowp vec4 vColor;
- varying highp vec3 lightDirection;
- varying mediump vec3 eyeDirection;
- varying mediump vec3 vNormal;
- /// 2D Noise by Ian McEwan, Ashima Arts.
- vec3 mod289(vec3 x) {
- return x - floor(x * (1.0 / 289.0)) * 289.0;
- }
- vec2 mod289(vec2 x) {
- return x - floor(x * (1.0 / 289.0)) * 289.0;
- }
- vec3 permute(vec3 x) {
- return mod289(((x*34.0)+1.0)*x);
- }
- float snoise (vec2 v) {
- const vec4 C = vec4(
- 0.211324865405187, // (3.0-sqrt(3.0))/6.0
- 0.366025403784439, // 0.5*(sqrt(3.0)-1.0)
- -0.577350269189626, // -1.0 + 2.0 * C.x
- 0.024390243902439); // 1.0 / 41.0
- // First corner
- vec2 i = floor(v + dot(v, C.yy) );
- vec2 x0 = v - i + dot(i, C.xx);
- // Other corners
- vec2 i1;
- i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);
- vec4 x12 = x0.xyxy + C.xxzz; x12.xy -= i1;
- // Permutations
- i = mod289(i);
- // Avoid truncation effects in permutation
- vec3 p = permute( permute( i.y + vec3(0.0, i1.y, 1.0 )) + i.x + vec3(0.0, i1.x, 1.0 ));
- vec3 m = max(0.5 - vec3(dot(x0,x0), dot(x12.xy,x12.xy), dot(x12.zw,x12.zw)), 0.0);
- m = m*m ;
- m = m*m ;
- // Gradients: 41 points uniformly over a line, mapped onto a diamond.
- // The ring size 17*17 = 289 is close to a multiple of 41 (41*7 = 287)
- vec3 x = 2.0 * fract(p * C.www) - 1.0;
- vec3 h = abs(x) - 0.5;
- vec3 ox = floor(x + 0.5);
- vec3 a0 = x - ox;
- // Normalise gradients implicitly by scaling m
- // Approximation of: m *= inversesqrt( a0*a0 + h*h );
- m *= 1.79284291400159 - 0.85373472095314 * ( a0*a0 + h*h );
- // Compute final noise value at P
- vec3 g;
- g.x = a0.x * x0.x + h.x * x0.y;
- g.yz = a0.yz * x12.xz + h.yz * x12.yw;
- return 60.0 * dot(m, g);
- }
- vec2 applyPressure(vec4 pressureZone)
- {
- float radius = length(pressureZone.xy - data.zw);
- if (radius < pressureZone.z) {
- float factor;
- if (time < pressureZone.w + 2.5) {
- if (time < pressureZone.w + 0.5) {
- factor = 1.0 - (pressureZone.w + 0.5 - time)/0.5;
- }
- else {
- factor = 1.0 - (time - pressureZone.w - 0.5)/2.0;
- }
- return (normalize(data.zw - pressureZone.xy) *
- (1.0 - radius/pressureZone.z)) * factor * 2.0;
- }
- }
- return vec2(0,0);
- }
- void main()
- {
- //convert the positions of the eye and light from world space to object space and then make a vector from position for ADS lighting
- lightDirection = ((vec4(vLightPosition,1) * mInvModel) - position).xyz;
- eyeDirection = ((vec4(vEyePosition,1) * mInvModel) - position).xyz;
- //Pass the mesh color to the fragment shader
- vColor = color;
- //apply force by weight
- vec2 deformation = vec2(snoise(vec2(data.z/15.0+time/2.0,data.w/15.0+time/2.0)),
- snoise(vec2(data.z/15.0+time/2.0+5000.0,data.w/15.0+time/2.0+5000.0)));
- //apply pressureZone
- deformation = deformation + applyPressure(pressureZone1);
- deformation = deformation + applyPressure(pressureZone2);
- deformation = deformation + applyPressure(pressureZone3);
- deformation = deformation + applyPressure(pressureZone4);
- deformation = deformation + applyPressure(pressureZone5);
- deformation = deformation + applyPressure(pressureZone6);
- deformation = deformation + applyPressure(pressureZone7);
- deformation = deformation + applyPressure(pressureZone8);
- deformation = deformation + applyPressure(pressureZone9);
- deformation = deformation + applyPressure(pressureZone10);
- deformation = deformation + applyPressure(pressureZone11);
- deformation = deformation + applyPressure(pressureZone12);
- deformation = deformation + applyPressure(pressureZone13);
- deformation = deformation + applyPressure(pressureZone14);
- deformation = deformation + applyPressure(pressureZone15);
- deformation = deformation + applyPressure(pressureZone16);
- deformation = deformation + applyPressure(pressureZone17);
- deformation = deformation + applyPressure(pressureZone18);
- deformation = deformation + applyPressure(pressureZone19);
- deformation = deformation + applyPressure(pressureZone20);
- deformation = deformation * data.x;
- //limit the force length max to length from root
- if (length(deformation) > (data.y*0.99)) {
- deformation = normalize(deformation)*(data.y*0.99);
- }
- //calculate the vertical adjustment to retain length with deformation
- float heightReduction = -(data.y-sqrt(pow(data.y,2.0) - pow(length(deformation),2.0)));
- vec4 positionModification = vec4(deformation.x,
- heightReduction, deformation.y,0);
- //adjust the normal by the deformation for lighting
- float defHorLength = length(deformation);
- vec2 defHorDirection = normalize(deformation);
- //normal and color to fragment
- //normals should be adjusted for pressure...
- vNormal = normal;
- if (data.y > 0.1) {
- vNormal = normalize(normal + vec3(-defHorDirection.x*heightReduction/data.y,
- defHorLength/data.y,
- -defHorDirection.y*heightReduction/data.y));
- }
- //Multiply the vertex position by our combined transform
- gl_Position = modelViewProjection * (position + positionModification);
- }
- ]],
- fragmentShader = [[
- precision lowp float;
- uniform lowp sampler2D texture;
- //uniform lowp sampler2D bumpMap;
- varying lowp vec4 vColor;
- varying mediump vec3 lightDirection;
- varying mediump vec3 eyeDirection;
- varying mediump vec3 vNormal;
- const float c_zero = 0.0;
- const float c_one = 1.0;
- const float c_two = 2.0;
- void main()
- {
- //if (!gl_FrontFacing) discard;
- vec3 curNormal = normalize(vNormal);
- lowp vec4 curCol = vColor;
- vec3 vLightDirection = normalize(normalize(lightDirection));
- vec3 vCameraDirection = normalize(eyeDirection);
- lowp vec4 vAmbientColor = curCol * 0.2;
- // Calculate Diffuse intensity
- float fDiffuseIntensity = max(max( c_zero, dot( curNormal, vLightDirection )), dot(-curNormal, vLightDirection));
- lowp vec4 vDiffuseColor = curCol * fDiffuseIntensity;
- vAmbientColor.a = c_one;
- vDiffuseColor.a = c_one;
- //Set the output color to the texture color
- gl_FragColor = vAmbientColor + vDiffuseColor;
- //gl_FragColor = curCol;
- }
- ]]
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement