Precipitation.glsl.js 4.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. /*
  2. All material copyright ESRI, All Rights Reserved, unless otherwise specified.
  3. See https://js.arcgis.com/4.24/esri/copyright.txt for details.
  4. */
  5. import{PrecipitationType as e}from"../views/3d/environment/PrecipitationTechniqueConfiguration.js";import{Float3Uniform as t}from"../views/3d/webgl-engine/core/shaderModules/Float3Uniform.js";import{FloatUniform as o}from"../views/3d/webgl-engine/core/shaderModules/FloatUniform.js";import{glsl as i}from"../views/3d/webgl-engine/core/shaderModules/interfaces.js";import{Matrix4PassUniform as r}from"../views/3d/webgl-engine/core/shaderModules/Matrix4PassUniform.js";import{Matrix4Uniform as a}from"../views/3d/webgl-engine/core/shaderModules/Matrix4Uniform.js";import{ShaderBuilder as n}from"../views/3d/webgl-engine/core/shaderModules/ShaderBuilder.js";import{VertexAttribute as s}from"../views/3d/webgl-engine/lib/VertexAttribute.js";function d(d){const c=new n;return c.attributes.add(s.POSITION,"vec3"),c.attributes.add(s.INSTANCEFEATUREATTRIBUTE,"float"),c.vertex.uniforms.add(new t("cameraPosition")),c.vertex.uniforms.add(new t("offset")),c.vertex.uniforms.add(new o("width")),c.vertex.uniforms.add(new r("proj",((e,t)=>t.camera.projectionMatrix))),c.vertex.uniforms.add(new a("view")),c.vertex.uniforms.add(new o("time")),c.varyings.add("vUv","vec2"),c.vertex.code.add(i`
  6. vec3 hash31(float p){
  7. vec3 p3 = fract(vec3(p) * vec3(0.1031, 0.1030, 0.0973));
  8. p3 += dot(p3, p3.yzx + 33.33);
  9. return fract((p3.xxy + p3.yzz) * p3.zyx);
  10. }
  11. float hash11(float p){
  12. p = fract(p * 0.1031);
  13. p *= p + 33.33;
  14. p *= p + p;
  15. return fract(p);
  16. }
  17. //https://www.geeks3d.com/20141201/how-to-rotate-a-vertex-by-a-quaternion-in-glsl/
  18. vec3 rotateVectorByQuaternion(vec3 v, vec4 q){
  19. return 2.0 * cross(q.xyz, v * q.w + cross(q.xyz, v)) + v;
  20. }
  21. void main(void) {
  22. vUv = position.xz;
  23. vec3 rand = hash31(instanceFeatureAttribute);
  24. // Set random position for all particles
  25. // The hash function space is not high resolution so offset particles by an additional random value
  26. // This creates grids of 1000 particles which are shifted by random hundreths of the tile width
  27. // overlaying multiple identical but offset grids
  28. vec3 randomPosition = 2.0 * (rand + (0.01 + 0.01 * rand) * floor(0.001 * instanceFeatureAttribute)) - 1.0;
  29. // Random orientation of rain drops
  30. float angle = 3.1415 * hash11(instanceFeatureAttribute);
  31. vec3 up = vec3(0, 0, 1);
  32. // Gravity and wind direction
  33. vec3 direction = normalize(cameraPosition);
  34. vec3 tangent = normalize(cross(direction, up));
  35. // Gravity
  36. vec3 animatedPos = randomPosition + direction * -time;
  37. // Rain particles fall straight down and are randomly oriented
  38. // Snow particles have random sinusoid trajectories and are rotated to face the camera
  39. ${d.type===e.Rain?i`
  40. // Random rotation for particle
  41. vec3 rotationAxis = up;
  42. vec4 quat = vec4(rotationAxis * sin(angle), cos(angle));
  43. vec3 transformedPos = rotateVectorByQuaternion(vec3(0.2, 0.2, 4.0) * (position - vec3(0.5, 0.0, 0.5)), quat);
  44. // Rotate particle to planetary position
  45. rotationAxis = tangent;
  46. angle = 0.5 * -acos(dot(direction, up));
  47. quat = vec4(rotationAxis * sin(angle), cos(angle));
  48. transformedPos = rotateVectorByQuaternion(transformedPos, quat);
  49. vec4 pos = mat4(mat3(view)) * vec4(transformedPos + (mod(width * animatedPos - offset, width) - 0.5 * width), 1.0);
  50. gl_Position = proj * pos;
  51. `:i`
  52. vec3 rotationAxis = direction;
  53. vec4 quat = vec4(rotationAxis * sin(angle), cos(angle));
  54. tangent = rotateVectorByQuaternion(tangent, quat);
  55. // Random sinusoid from friction
  56. animatedPos += tangent * 0.25 * sin(dot(animatedPos, direction));
  57. vec4 pos = mat4(mat3(view)) * vec4((mod(width * animatedPos - offset, width) - 0.5 * width), 1.0);
  58. gl_Position = proj * (0.5 * vec4(position.xzy, 0.0) + pos);
  59. `}
  60. }
  61. `),c.fragment.uniforms.add(new o("opacity")),c.fragment.uniforms.add(new t("particleColor")),c.fragment.code.add(i`
  62. void main() {
  63. // Cut off corners of the triangle
  64. if(vUv.x < 0.0 || vUv.y < 0.0){
  65. discard;
  66. }
  67. float d = length(vUv - vec2(0.5));
  68. ${d.type===e.Rain?i`d = 0.35 * smoothstep(0.5, 0.0, d);`:i`d = smoothstep(0.5, 0.1, d);`}
  69. gl_FragColor = opacity * vec4(particleColor * d, d);
  70. }
  71. `),c}const c=Object.freeze(Object.defineProperty({__proto__:null,build:d},Symbol.toStringTag,{value:"Module"}));export{c as P,d as b};