CloudNoiseFS.glsl 3.0 KB

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