CloudNoiseFS.glsl 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. uniform vec3 u_noiseTextureDimensions;
  2. uniform float u_noiseDetail;
  3. uniform vec3 u_noiseOffset;
  4. varying vec2 v_position;
  5. float textureSliceWidth = u_noiseTextureDimensions.x;
  6. float inverseNoiseTextureRows = u_noiseTextureDimensions.z;
  7. float wrap(float value, float rangeLength) {
  8. if(value < 0.0) {
  9. float absValue = abs(value);
  10. float modValue = mod(absValue, rangeLength);
  11. return mod(rangeLength - modValue, rangeLength);
  12. }
  13. return mod(value, rangeLength);
  14. }
  15. vec3 wrapVec(vec3 value, float rangeLength) {
  16. return vec3(wrap(value.x, rangeLength),
  17. wrap(value.y, rangeLength),
  18. wrap(value.z, rangeLength));
  19. }
  20. vec3 random3(vec3 p) {
  21. float dot1 = dot(p, vec3(127.1, 311.7, 932.8));
  22. float dot2 = dot(p, vec3(269.5, 183.3, 421.4));
  23. return fract(vec3(sin(dot1 - dot2), cos(dot1 * dot2), dot1 * dot2));
  24. }
  25. // Frequency corresponds to cell size.
  26. // The higher the frequency, the smaller the cell size.
  27. vec3 getWorleyCellPoint(vec3 centerCell, vec3 offset, float freq) {
  28. vec3 cell = centerCell + offset;
  29. cell = wrapVec(cell, textureSliceWidth / u_noiseDetail);
  30. cell += floor(u_noiseOffset / u_noiseDetail);
  31. vec3 p = offset + random3(cell);
  32. return p;
  33. }
  34. float worleyNoise(vec3 p, float freq) {
  35. vec3 centerCell = floor(p * freq);
  36. vec3 pointInCell = fract(p * freq);
  37. float shortestDistance = 1000.0;
  38. for(float z = -1.0; z <= 1.0; z++) {
  39. for(float y = -1.0; y <= 1.0; y++) {
  40. for(float x = -1.0; x <= 1.0; x++) {
  41. vec3 offset = vec3(x, y, z);
  42. vec3 point = getWorleyCellPoint(centerCell, offset, freq);
  43. float distance = length(pointInCell - point);
  44. if(distance < shortestDistance) {
  45. shortestDistance = distance;
  46. }
  47. }
  48. }
  49. }
  50. return shortestDistance;
  51. }
  52. const float MAX_FBM_ITERATIONS = 10.0;
  53. float worleyFBMNoise(vec3 p, float octaves, float scale) {
  54. float noise = 0.0;
  55. float freq = 1.0;
  56. float persistence = 0.625;
  57. for(float i = 0.0; i < MAX_FBM_ITERATIONS; i++) {
  58. if(i >= octaves) {
  59. break;
  60. }
  61. noise += worleyNoise(p * scale, freq * scale) * persistence;
  62. persistence *= 0.5;
  63. freq *= 2.0;
  64. }
  65. return noise;
  66. }
  67. void main() {
  68. float x = mod(v_position.x, textureSliceWidth);
  69. float y = mod(v_position.y, textureSliceWidth);
  70. float sliceRow = floor(v_position.y / textureSliceWidth);
  71. float z = floor(v_position.x / textureSliceWidth) + sliceRow * inverseNoiseTextureRows * textureSliceWidth;
  72. vec3 position = vec3(x, y, z);
  73. position /= u_noiseDetail;
  74. float worley0 = clamp(worleyFBMNoise(position, 3.0, 1.0), 0.0, 1.0);
  75. float worley1 = clamp(worleyFBMNoise(position, 3.0, 2.0), 0.0, 1.0);
  76. float worley2 = clamp(worleyFBMNoise(position, 3.0, 3.0), 0.0, 1.0);
  77. gl_FragColor = vec4(worley0, worley1, worley2, 1.0);
  78. }