@takram/three-clouds 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/README.md +1130 -0
  3. package/assets/local_weather.png +0 -0
  4. package/assets/shape.bin +1 -0
  5. package/assets/shape_detail.bin +1 -0
  6. package/assets/turbulence.png +0 -0
  7. package/build/index.cjs +583 -0
  8. package/build/index.cjs.map +1 -0
  9. package/build/index.js +728 -0
  10. package/build/index.js.map +1 -0
  11. package/build/r3f.cjs +2 -0
  12. package/build/r3f.cjs.map +1 -0
  13. package/build/r3f.js +205 -0
  14. package/build/r3f.js.map +1 -0
  15. package/build/shared.cjs +2189 -0
  16. package/build/shared.cjs.map +1 -0
  17. package/build/shared.js +3825 -0
  18. package/build/shared.js.map +1 -0
  19. package/package.json +77 -0
  20. package/src/CascadedShadowMaps.ts +288 -0
  21. package/src/CloudLayer.ts +85 -0
  22. package/src/CloudLayers.test.ts +61 -0
  23. package/src/CloudLayers.ts +181 -0
  24. package/src/CloudShape.ts +22 -0
  25. package/src/CloudShapeDetail.ts +22 -0
  26. package/src/CloudsEffect.ts +810 -0
  27. package/src/CloudsMaterial.ts +467 -0
  28. package/src/CloudsPass.ts +285 -0
  29. package/src/CloudsResolveMaterial.ts +108 -0
  30. package/src/DensityProfile.ts +38 -0
  31. package/src/LocalWeather.ts +21 -0
  32. package/src/PassBase.ts +28 -0
  33. package/src/Procedural3DTexture.ts +94 -0
  34. package/src/ProceduralTexture.ts +94 -0
  35. package/src/ShaderArrayPass.ts +32 -0
  36. package/src/ShadowMaterial.ts +141 -0
  37. package/src/ShadowPass.ts +185 -0
  38. package/src/ShadowResolveMaterial.ts +72 -0
  39. package/src/Turbulence.ts +21 -0
  40. package/src/bayer.ts +23 -0
  41. package/src/constants.ts +8 -0
  42. package/src/helpers/FrustumCorners.ts +138 -0
  43. package/src/helpers/setArrayRenderTargetLayers.ts +32 -0
  44. package/src/helpers/splitFrustum.ts +59 -0
  45. package/src/index.ts +14 -0
  46. package/src/qualityPresets.ts +117 -0
  47. package/src/r3f/CloudLayer.tsx +95 -0
  48. package/src/r3f/CloudLayers.tsx +54 -0
  49. package/src/r3f/Clouds.tsx +278 -0
  50. package/src/r3f/index.ts +2 -0
  51. package/src/shaders/catmullRomSampling.glsl +113 -0
  52. package/src/shaders/cloudShape.frag +78 -0
  53. package/src/shaders/cloudShapeDetail.frag +56 -0
  54. package/src/shaders/clouds.frag +996 -0
  55. package/src/shaders/clouds.glsl +190 -0
  56. package/src/shaders/clouds.vert +69 -0
  57. package/src/shaders/cloudsEffect.frag +11 -0
  58. package/src/shaders/cloudsResolve.frag +202 -0
  59. package/src/shaders/cloudsResolve.vert +10 -0
  60. package/src/shaders/localWeather.frag +83 -0
  61. package/src/shaders/parameters.glsl +64 -0
  62. package/src/shaders/perlin.glsl +211 -0
  63. package/src/shaders/shadow.frag +197 -0
  64. package/src/shaders/shadow.vert +16 -0
  65. package/src/shaders/shadowResolve.frag +76 -0
  66. package/src/shaders/shadowResolve.vert +10 -0
  67. package/src/shaders/structuredSampling.glsl +101 -0
  68. package/src/shaders/tileableNoise.glsl +88 -0
  69. package/src/shaders/turbulence.frag +51 -0
  70. package/src/shaders/types.glsl +18 -0
  71. package/src/shaders/varianceClipping.glsl +114 -0
  72. package/src/uniforms.ts +218 -0
  73. package/types/CascadedShadowMaps.d.ts +52 -0
  74. package/types/CloudLayer.d.ts +26 -0
  75. package/types/CloudLayers.d.ts +21 -0
  76. package/types/CloudShape.d.ts +5 -0
  77. package/types/CloudShapeDetail.d.ts +5 -0
  78. package/types/CloudsEffect.d.ts +170 -0
  79. package/types/CloudsMaterial.d.ts +86 -0
  80. package/types/CloudsPass.d.ts +44 -0
  81. package/types/CloudsResolveMaterial.d.ts +30 -0
  82. package/types/DensityProfile.d.ts +12 -0
  83. package/types/LocalWeather.d.ts +5 -0
  84. package/types/PassBase.d.ts +14 -0
  85. package/types/Procedural3DTexture.d.ts +20 -0
  86. package/types/ProceduralTexture.d.ts +24 -0
  87. package/types/ShaderArrayPass.d.ts +7 -0
  88. package/types/ShadowMaterial.d.ts +34 -0
  89. package/types/ShadowPass.d.ts +34 -0
  90. package/types/ShadowResolveMaterial.d.ts +20 -0
  91. package/types/Turbulence.d.ts +5 -0
  92. package/types/bayer.d.ts +4 -0
  93. package/types/constants.d.ts +6 -0
  94. package/types/helpers/FrustumCorners.d.ts +18 -0
  95. package/types/helpers/setArrayRenderTargetLayers.d.ts +3 -0
  96. package/types/helpers/splitFrustum.d.ts +9 -0
  97. package/types/index.d.ts +13 -0
  98. package/types/qualityPresets.d.ts +46 -0
  99. package/types/r3f/CloudLayer.d.ts +7 -0
  100. package/types/r3f/CloudLayers.d.ts +15 -0
  101. package/types/r3f/Clouds.d.ts +16 -0
  102. package/types/r3f/index.d.ts +2 -0
  103. package/types/uniforms.d.ts +66 -0
@@ -0,0 +1,190 @@
1
+ float getSTBN() {
2
+ ivec3 size = textureSize(stbnTexture, 0);
3
+ vec3 scale = 1.0 / vec3(size);
4
+ return texture(stbnTexture, vec3(gl_FragCoord.xy, float(frame % size.z)) * scale).r;
5
+ }
6
+
7
+ // Straightforward spherical mapping
8
+ vec2 getSphericalUv(const vec3 position) {
9
+ vec2 st = normalize(position.yx);
10
+ float phi = atan(st.x, st.y);
11
+ float theta = asin(normalize(position).z);
12
+ return vec2(phi * RECIPROCAL_PI2 + 0.5, theta * RECIPROCAL_PI + 0.5);
13
+ }
14
+
15
+ vec2 getCubeSphereUv(const vec3 position) {
16
+ // Cube-sphere relaxation by: http://mathproofs.blogspot.com/2005/07/mapping-cube-to-sphere.html
17
+ // TODO: Tile and fix seams.
18
+ // Possible improvements:
19
+ // https://iquilezles.org/articles/texturerepetition/
20
+ // https://gamedev.stackexchange.com/questions/184388/fragment-shader-map-dot-texture-repeatedly-over-the-sphere
21
+ // https://github.com/mmikk/hextile-demo
22
+
23
+ vec3 n = normalize(position);
24
+ vec3 f = abs(n);
25
+ vec3 c = n / max(f.x, max(f.y, f.z));
26
+ vec2 m;
27
+ if (all(greaterThan(f.yy, f.xz))) {
28
+ m = c.y > 0.0 ? vec2(-n.x, n.z) : n.xz;
29
+ } else if (all(greaterThan(f.xx, f.yz))) {
30
+ m = c.x > 0.0 ? n.yz : vec2(-n.y, n.z);
31
+ } else {
32
+ m = c.z > 0.0 ? n.xy : vec2(n.x, -n.y);
33
+ }
34
+
35
+ vec2 m2 = m * m;
36
+ float q = dot(m2.xy, vec2(-2.0, 2.0)) - 3.0;
37
+ float q2 = q * q;
38
+ vec2 uv;
39
+ uv.x = sqrt(1.5 + m2.x - m2.y - 0.5 * sqrt(-24.0 * m2.x + q2)) * (m.x > 0.0 ? 1.0 : -1.0);
40
+ uv.y = sqrt(6.0 / (3.0 - uv.x * uv.x)) * m.y;
41
+ return uv * 0.5 + 0.5;
42
+ }
43
+
44
+ vec2 getGlobeUv(const vec3 position) {
45
+ return getCubeSphereUv(position);
46
+ }
47
+
48
+ float getMipLevel(const vec2 uv) {
49
+ const float mipLevelScale = 0.1;
50
+ vec2 coord = uv * resolution;
51
+ vec2 ddx = dFdx(coord);
52
+ vec2 ddy = dFdy(coord);
53
+ float deltaMaxSqr = max(dot(ddx, ddx), dot(ddy, ddy)) * mipLevelScale;
54
+ return max(0.0, 0.5 * log2(max(1.0, deltaMaxSqr)));
55
+ }
56
+
57
+ bool insideLayerIntervals(const float height) {
58
+ bvec3 gt = greaterThan(vec3(height), minIntervalHeights);
59
+ bvec3 lt = lessThan(vec3(height), maxIntervalHeights);
60
+ return any(bvec3(gt.x && lt.x, gt.y && lt.y, gt.z && lt.z));
61
+ }
62
+
63
+ struct WeatherSample {
64
+ vec4 heightFraction; // Normalized height of each layer
65
+ vec4 density;
66
+ };
67
+
68
+ vec4 shapeAlteringFunction(const vec4 heightFraction, const vec4 bias) {
69
+ // Apply a semi-circle transform to round the clouds towards the top.
70
+ vec4 biased = pow(heightFraction, bias);
71
+ vec4 x = clamp(biased * 2.0 - 1.0, -1.0, 1.0);
72
+ return 1.0 - x * x;
73
+ }
74
+
75
+ WeatherSample sampleWeather(const vec2 uv, const float height, const float mipLevel) {
76
+ WeatherSample weather;
77
+ weather.heightFraction = remapClamped(vec4(height), minLayerHeights, maxLayerHeights);
78
+
79
+ vec4 localWeather = pow(
80
+ textureLod(
81
+ localWeatherTexture,
82
+ uv * localWeatherRepeat + localWeatherOffset,
83
+ mipLevel
84
+ ).LOCAL_WEATHER_CHANNELS,
85
+ weatherExponents
86
+ );
87
+ #ifdef SHADOW
88
+ localWeather *= shadowLayerMask;
89
+ #endif // SHADOW
90
+
91
+ vec4 heightScale = shapeAlteringFunction(weather.heightFraction, shapeAlteringBiases);
92
+
93
+ // Modulation to control weather by coverage parameter.
94
+ // Reference: https://github.com/Prograda/Skybolt/blob/master/Assets/Core/Shaders/Clouds.h#L63
95
+ vec4 factor = 1.0 - coverage * heightScale;
96
+ weather.density = remapClamped(
97
+ mix(localWeather, vec4(1.0), coverageFilterWidths),
98
+ factor,
99
+ factor + coverageFilterWidths
100
+ );
101
+
102
+ return weather;
103
+ }
104
+
105
+ vec4 getLayerDensity(const vec4 heightFraction) {
106
+ // prettier-ignore
107
+ return densityProfile.expTerms * exp(densityProfile.exponents * heightFraction) +
108
+ densityProfile.linearTerms * heightFraction +
109
+ densityProfile.constantTerms;
110
+ }
111
+
112
+ struct MediaSample {
113
+ float density;
114
+ vec4 weight;
115
+ float scattering;
116
+ float extinction;
117
+ };
118
+
119
+ MediaSample sampleMedia(
120
+ const WeatherSample weather,
121
+ const vec3 position,
122
+ const vec2 uv,
123
+ const float mipLevel,
124
+ const float jitter,
125
+ out ivec3 sampleCount
126
+ ) {
127
+ vec4 density = weather.density;
128
+
129
+ // TODO: Define in physical length.
130
+ vec3 surfaceNormal = normalize(position);
131
+ float localWeatherSpeed = length(localWeatherOffset);
132
+ vec3 evolution = -surfaceNormal * localWeatherSpeed * 2e4;
133
+
134
+ vec3 turbulence = vec3(0.0);
135
+ #ifdef TURBULENCE
136
+ vec2 turbulenceUv = uv * localWeatherRepeat * turbulenceRepeat;
137
+ turbulence =
138
+ turbulenceDisplacement *
139
+ (texture(turbulenceTexture, turbulenceUv).rgb * 2.0 - 1.0) *
140
+ dot(density, remapClamped(weather.heightFraction, vec4(0.3), vec4(0.0)));
141
+ #endif // TURBULENCE
142
+
143
+ vec3 shapePosition = (position + evolution + turbulence) * shapeRepeat + shapeOffset;
144
+ float shape = texture(shapeTexture, shapePosition).r;
145
+ density = remapClamped(density, vec4(1.0 - shape) * shapeAmounts, vec4(1.0));
146
+
147
+ #ifdef DEBUG_SHOW_SAMPLE_COUNT
148
+ ++sampleCount.y;
149
+ #endif // DEBUG_SHOW_SAMPLE_COUNT
150
+
151
+ #ifdef SHAPE_DETAIL
152
+ if (mipLevel * 0.5 + (jitter - 0.5) * 0.5 < 0.5) {
153
+ vec3 detailPosition = (position + turbulence) * shapeDetailRepeat + shapeDetailOffset;
154
+ float detail = texture(shapeDetailTexture, detailPosition).r;
155
+ // Fluffy at the top and whippy at the bottom.
156
+ vec4 modifier = mix(
157
+ vec4(pow(detail, 6.0)),
158
+ vec4(1.0 - detail),
159
+ remapClamped(weather.heightFraction, vec4(0.2), vec4(0.4))
160
+ );
161
+ modifier = mix(vec4(0.0), modifier, shapeDetailAmounts);
162
+ density = remapClamped(density * 2.0, vec4(modifier * 0.5), vec4(1.0));
163
+
164
+ #ifdef DEBUG_SHOW_SAMPLE_COUNT
165
+ ++sampleCount.z;
166
+ #endif // DEBUG_SHOW_SAMPLE_COUNT
167
+ }
168
+ #endif // SHAPE_DETAIL
169
+
170
+ // Nicely decrease the density at the bottom.
171
+ density = saturate(density * densityScales * getLayerDensity(weather.heightFraction));
172
+
173
+ MediaSample media;
174
+ float densitySum = density.x + density.y + density.z + density.w;
175
+ media.weight = density / densitySum;
176
+ media.scattering = densitySum * scatteringCoefficient;
177
+ media.extinction = densitySum * absorptionCoefficient + media.scattering;
178
+ return media;
179
+ }
180
+
181
+ MediaSample sampleMedia(
182
+ const WeatherSample weather,
183
+ const vec3 position,
184
+ const vec2 uv,
185
+ const float mipLevel,
186
+ const float jitter
187
+ ) {
188
+ ivec3 sampleCount;
189
+ return sampleMedia(weather, position, uv, mipLevel, jitter, sampleCount);
190
+ }
@@ -0,0 +1,69 @@
1
+ precision highp float;
2
+ precision highp sampler3D;
3
+
4
+ #include "atmosphere/parameters"
5
+ #include "atmosphere/functions"
6
+ #include "types"
7
+
8
+ uniform mat4 inverseProjectionMatrix;
9
+ uniform mat4 inverseViewMatrix;
10
+ uniform vec3 cameraPosition;
11
+ uniform vec3 ellipsoidCenter;
12
+ uniform mat4 inverseEllipsoidMatrix;
13
+ uniform vec3 altitudeCorrection;
14
+
15
+ // Atmosphere
16
+ uniform float bottomRadius;
17
+ uniform vec3 sunDirection;
18
+
19
+ // Cloud layers
20
+ uniform float minHeight;
21
+ uniform float maxHeight;
22
+
23
+ layout(location = 0) in vec3 position;
24
+
25
+ out vec2 vUv;
26
+ out vec3 vCameraPosition;
27
+ out vec3 vCameraDirection; // Direction to the center of screen
28
+ out vec3 vRayDirection; // Direction to the texel
29
+ out vec3 vEllipsoidCenter;
30
+
31
+ out GroundIrradiance vGroundIrradiance;
32
+ out CloudsIrradiance vCloudsIrradiance;
33
+
34
+ void sampleSunSkyIrradiance(const vec3 positionECEF) {
35
+ vGroundIrradiance.sun = GetSunAndSkyIrradiance(
36
+ positionECEF * METER_TO_LENGTH_UNIT,
37
+ sunDirection,
38
+ vGroundIrradiance.sky
39
+ );
40
+
41
+ vec3 surfaceNormal = normalize(positionECEF);
42
+ vec2 radii = (bottomRadius + vec2(minHeight, maxHeight)) * METER_TO_LENGTH_UNIT;
43
+ vCloudsIrradiance.minSun = GetSunAndSkyIrradiance(
44
+ surfaceNormal * radii.x,
45
+ sunDirection,
46
+ vCloudsIrradiance.minSky
47
+ );
48
+ vCloudsIrradiance.maxSun = GetSunAndSkyIrradiance(
49
+ surfaceNormal * radii.y,
50
+ sunDirection,
51
+ vCloudsIrradiance.maxSky
52
+ );
53
+ }
54
+
55
+ void main() {
56
+ vUv = position.xy * 0.5 + 0.5;
57
+
58
+ vec4 viewPosition = inverseProjectionMatrix * vec4(position, 1.0);
59
+ vec4 worldDirection = inverseViewMatrix * vec4(viewPosition.xyz, 0.0);
60
+ mat3 rotation = mat3(inverseEllipsoidMatrix);
61
+ vCameraPosition = rotation * cameraPosition;
62
+ vCameraDirection = rotation * normalize((inverseViewMatrix * vec4(0.0, 0.0, -1.0, 0.0)).xyz);
63
+ vRayDirection = rotation * worldDirection.xyz;
64
+ vEllipsoidCenter = ellipsoidCenter + altitudeCorrection;
65
+
66
+ sampleSunSkyIrradiance(vCameraPosition - vEllipsoidCenter);
67
+
68
+ gl_Position = vec4(position.xy, 1.0, 1.0);
69
+ }
@@ -0,0 +1,11 @@
1
+ uniform sampler2D cloudsBuffer;
2
+
3
+ void mainImage(const vec4 inputColor, const vec2 uv, out vec4 outputColor) {
4
+ #ifdef SKIP_RENDERING
5
+ outputColor = inputColor;
6
+ #else // SKIP_RENDERING
7
+ vec4 clouds = texture(cloudsBuffer, uv);
8
+ outputColor.rgb = inputColor.rgb * (1.0 - clouds.a) + clouds.rgb;
9
+ outputColor.a = inputColor.a * (1.0 - clouds.a) + clouds.a;
10
+ #endif // SKIP_RENDERING
11
+ }
@@ -0,0 +1,202 @@
1
+ precision highp float;
2
+ precision highp sampler2DArray;
3
+
4
+ #include "core/turbo"
5
+ #include "catmullRomSampling"
6
+ #include "varianceClipping"
7
+
8
+ uniform sampler2D colorBuffer;
9
+ uniform sampler2D depthVelocityBuffer;
10
+ uniform sampler2D colorHistoryBuffer;
11
+
12
+ #ifdef SHADOW_LENGTH
13
+ uniform sampler2D shadowLengthBuffer;
14
+ uniform sampler2D shadowLengthHistoryBuffer;
15
+ #endif // SHADOW_LENGTH
16
+
17
+ uniform vec2 texelSize;
18
+ uniform int frame;
19
+ uniform float varianceGamma;
20
+ uniform float temporalAlpha;
21
+ uniform vec2 jitterOffset;
22
+
23
+ in vec2 vUv;
24
+
25
+ layout(location = 0) out vec4 outputColor;
26
+ #ifdef SHADOW_LENGTH
27
+ layout(location = 1) out float outputShadowLength;
28
+ #endif // SHADOW_LENGTH
29
+
30
+ const ivec2 neighborOffsets[9] = ivec2[9](
31
+ ivec2(-1, -1),
32
+ ivec2(-1, 0),
33
+ ivec2(-1, 1),
34
+ ivec2(0, -1),
35
+ ivec2(0, 0),
36
+ ivec2(0, 1),
37
+ ivec2(1, -1),
38
+ ivec2(1, 0),
39
+ ivec2(1, 1)
40
+ );
41
+
42
+ const ivec4[4] bayerIndices = ivec4[4](
43
+ ivec4(0, 12, 3, 15),
44
+ ivec4(8, 4, 11, 7),
45
+ ivec4(2, 14, 1, 13),
46
+ ivec4(10, 6, 9, 5)
47
+ );
48
+
49
+ vec2 getUnjitteredUv(ivec2 coord) {
50
+ return (vec2(coord) + 0.5 - jitterOffset) * texelSize;
51
+ }
52
+
53
+ vec4 getClosestFragment(const vec2 uv) {
54
+ vec4 result = vec4(1e7, 0.0, 0.0, 0.0);
55
+ vec4 neighbor;
56
+ #pragma unroll_loop_start
57
+ for (int i = 0; i < 9; ++i) {
58
+ neighbor = textureOffset(depthVelocityBuffer, uv, neighborOffsets[i]);
59
+ if (neighbor.r < result.r) {
60
+ result = neighbor;
61
+ }
62
+ }
63
+ #pragma unroll_loop_end
64
+ return result;
65
+ }
66
+
67
+ vec4 getClosestFragment(const ivec2 coord) {
68
+ vec4 result = vec4(1e7, 0.0, 0.0, 0.0);
69
+ vec4 neighbor;
70
+ #pragma unroll_loop_start
71
+ for (int i = 0; i < 9; ++i) {
72
+ neighbor = texelFetchOffset(depthVelocityBuffer, coord, 0, neighborOffsets[i]);
73
+ if (neighbor.r < result.r) {
74
+ result = neighbor;
75
+ }
76
+ }
77
+ #pragma unroll_loop_end
78
+ return result;
79
+ }
80
+
81
+ void temporalUpscale(
82
+ const ivec2 coord,
83
+ const ivec2 lowResCoord,
84
+ const bool currentFrame,
85
+ out vec4 outputColor,
86
+ out float outputShadowLength
87
+ ) {
88
+ #if !defined(DEBUG_SHOW_VELOCITY)
89
+ if (currentFrame) {
90
+ // Use the texel just rendered without any accumulation.
91
+ outputColor = texelFetch(colorBuffer, lowResCoord, 0);
92
+ #ifdef SHADOW_LENGTH
93
+ outputShadowLength = texelFetch(shadowLengthBuffer, lowResCoord, 0).r;
94
+ #endif // SHADOW_LENGTH
95
+ return;
96
+ }
97
+ #endif // !defined(DEBUG_SHOW_VELOCITY)
98
+
99
+ vec2 unjitteredUv = getUnjitteredUv(coord);
100
+ vec4 currentColor = texture(colorBuffer, unjitteredUv);
101
+ #ifdef SHADOW_LENGTH
102
+ vec4 currentShadowLength = vec4(texture(shadowLengthBuffer, unjitteredUv).rgb, 1.0);
103
+ #endif // SHADOW_LENGTH
104
+
105
+ vec4 depthVelocity = getClosestFragment(unjitteredUv);
106
+ vec2 velocity = depthVelocity.gb * texelSize;
107
+ vec2 prevUv = vUv - velocity;
108
+ if (prevUv.x < 0.0 || prevUv.x > 1.0 || prevUv.y < 0.0 || prevUv.y > 1.0) {
109
+ outputColor = currentColor;
110
+ #ifdef SHADOW_LENGTH
111
+ outputShadowLength = currentShadowLength.r;
112
+ #endif // SHADOW_LENGTH
113
+ return; // Rejection
114
+ }
115
+
116
+ // Variance clipping with a large variance gamma seems to work fine for
117
+ // upsampling. This increases ghosting, of course, but it's hard to notice on
118
+ // clouds.
119
+ // vec4 historyColor = textureCatmullRom(colorHistoryBuffer, prevUv);
120
+ vec4 historyColor = texture(colorHistoryBuffer, prevUv);
121
+ vec4 clippedColor = varianceClipping(colorBuffer, vUv, currentColor, historyColor, varianceGamma);
122
+ outputColor = clippedColor;
123
+
124
+ #ifdef DEBUG_SHOW_VELOCITY
125
+ outputColor.rgb = outputColor.rgb + vec3(abs(velocity), 0.0);
126
+ #endif // DEBUG_SHOW_VELOCITY
127
+
128
+ #ifdef SHADOW_LENGTH
129
+ // Sampling the shadow length history using scene depth doesn't make much
130
+ // sense, but it's too hard to derive it properly. At least this approach
131
+ // resolves the edges of scene objects.
132
+ // vec4 historyShadowLength = vec4(textureCatmullRom(shadowLengthHistoryBuffer, prevUv).rgb, 1.0);
133
+ vec4 historyShadowLength = vec4(texture(shadowLengthHistoryBuffer, prevUv).rgb, 1.0);
134
+ vec4 clippedShadowLength = varianceClipping(
135
+ shadowLengthBuffer,
136
+ vUv,
137
+ currentShadowLength,
138
+ historyShadowLength,
139
+ varianceGamma
140
+ );
141
+ outputShadowLength = clippedShadowLength.r;
142
+ #endif // SHADOW_LENGTH
143
+ }
144
+
145
+ void temporalAntialiasing(const ivec2 coord, out vec4 outputColor, out float outputShadowLength) {
146
+ vec4 currentColor = texelFetch(colorBuffer, coord, 0);
147
+ #ifdef SHADOW_LENGTH
148
+ vec4 currentShadowLength = vec4(texelFetch(shadowLengthBuffer, coord, 0).rgb, 1.0);
149
+ #endif // SHADOW_LENGTH
150
+
151
+ vec4 depthVelocity = getClosestFragment(coord);
152
+ vec2 velocity = depthVelocity.gb * texelSize;
153
+
154
+ vec2 prevUv = vUv - velocity;
155
+ if (prevUv.x < 0.0 || prevUv.x > 1.0 || prevUv.y < 0.0 || prevUv.y > 1.0) {
156
+ outputColor = currentColor;
157
+ #ifdef SHADOW_LENGTH
158
+ outputShadowLength = currentShadowLength.r;
159
+ #endif // SHADOW_LENGTH
160
+ return; // Rejection
161
+ }
162
+
163
+ vec4 historyColor = texture(colorHistoryBuffer, prevUv);
164
+ vec4 clippedColor = varianceClipping(colorBuffer, coord, currentColor, historyColor);
165
+ outputColor = mix(clippedColor, currentColor, temporalAlpha);
166
+
167
+ #ifdef DEBUG_SHOW_VELOCITY
168
+ outputColor.rgb = outputColor.rgb + vec3(abs(velocity), 0.0);
169
+ #endif // DEBUG_SHOW_VELOCITY
170
+
171
+ #ifdef SHADOW_LENGTH
172
+ vec4 historyShadowLength = vec4(texture(shadowLengthHistoryBuffer, prevUv).rgb, 1.0);
173
+ vec4 clippedShadowLength = varianceClipping(
174
+ shadowLengthBuffer,
175
+ coord,
176
+ currentShadowLength,
177
+ historyShadowLength
178
+ );
179
+ outputShadowLength = mix(clippedShadowLength.r, currentShadowLength.r, temporalAlpha);
180
+ #endif // SHADOW_LENGTH
181
+ }
182
+
183
+ void main() {
184
+ ivec2 coord = ivec2(gl_FragCoord.xy);
185
+
186
+ #if !defined(SHADOW_LENGTH)
187
+ float outputShadowLength;
188
+ #endif // !defined(SHADOW_LENGTH)
189
+
190
+ #ifdef TEMPORAL_UPSCALE
191
+ ivec2 lowResCoord = coord / 4;
192
+ int bayerValue = bayerIndices[coord.x % 4][coord.y % 4];
193
+ bool currentFrame = bayerValue == frame % 16;
194
+ temporalUpscale(coord, lowResCoord, currentFrame, outputColor, outputShadowLength);
195
+ #else // TEMPORAL_UPSCALE
196
+ temporalAntialiasing(coord, outputColor, outputShadowLength);
197
+ #endif // TEMPORAL_UPSCALE
198
+
199
+ #if defined(SHADOW_LENGTH) && defined(DEBUG_SHOW_SHADOW_LENGTH)
200
+ outputColor = vec4(turbo(outputShadowLength * 0.05), 1.0);
201
+ #endif // defined(SHADOW_LENGTH) && defined(DEBUG_SHOW_SHADOW_LENGTH)
202
+ }
@@ -0,0 +1,10 @@
1
+ precision highp float;
2
+
3
+ layout(location = 0) in vec3 position;
4
+
5
+ out vec2 vUv;
6
+
7
+ void main() {
8
+ vUv = position.xy * 0.5 + 0.5;
9
+ gl_Position = vec4(position.xy, 1.0, 1.0);
10
+ }
@@ -0,0 +1,83 @@
1
+ precision highp float;
2
+ precision highp int;
3
+
4
+ #include "core/math"
5
+ #include "perlin"
6
+ #include "tileableNoise"
7
+
8
+ in vec2 vUv;
9
+
10
+ layout(location = 0) out vec4 outputColor;
11
+
12
+ float getWorleyFbm(
13
+ const vec3 point,
14
+ float frequency,
15
+ float amplitude,
16
+ const float lacunarity,
17
+ const float gain,
18
+ const int octaveCount
19
+ ) {
20
+ float noise = 0.0;
21
+ for (int i = 0; i < octaveCount; ++i) {
22
+ noise += amplitude * (1.0 - getWorleyNoise(point, frequency));
23
+ frequency *= lacunarity;
24
+ amplitude *= gain;
25
+ }
26
+ return noise;
27
+ }
28
+
29
+ void main() {
30
+ vec3 point = vec3(vUv.x, vUv.y, 0.0);
31
+
32
+ // Mid clouds
33
+ {
34
+ float worley = getWorleyFbm(
35
+ point + vec3(0.5),
36
+ 8.0, // frequency
37
+ 0.4, // amplitude
38
+ 2.0, // lacunarity
39
+ 0.95, // gain
40
+ 4 // octaveCount
41
+ );
42
+ worley = smoothstep(1.0, 1.4, worley);
43
+ outputColor.g = worley;
44
+ }
45
+
46
+ // Low clouds
47
+ {
48
+ float worley = getWorleyFbm(
49
+ point,
50
+ 16.0, // frequency
51
+ 0.4, // amplitude
52
+ 2.0, // lacunarity
53
+ 0.95, // gain
54
+ 4 // octaveCount
55
+ );
56
+ worley = smoothstep(0.8, 1.4, worley);
57
+ outputColor.r = saturate(worley - outputColor.g);
58
+ }
59
+
60
+ // High clouds
61
+ {
62
+ float perlin = getPerlinNoise(
63
+ point,
64
+ vec3(6.0, 12.0, 1.0), // frequency
65
+ 8 // octaveCount
66
+ );
67
+ perlin = smoothstep(-0.5, 0.5, perlin);
68
+ outputColor.b = perlin;
69
+ }
70
+
71
+ // Extra
72
+ {
73
+ float perlin = getPerlinNoise(
74
+ point + vec3(-19.1, 33.4, 47.2),
75
+ 32.0, // frequency
76
+ 4 // octaveCount
77
+ );
78
+ perlin = smoothstep(-0.5, 0.5, perlin);
79
+ outputColor.a = perlin;
80
+ }
81
+
82
+ outputColor.a = 1.0;
83
+ }
@@ -0,0 +1,64 @@
1
+ uniform vec2 resolution;
2
+ uniform int frame;
3
+ uniform sampler3D stbnTexture;
4
+
5
+ // Atmosphere
6
+ uniform float bottomRadius;
7
+ uniform mat4 ellipsoidMatrix;
8
+ uniform mat4 inverseEllipsoidMatrix;
9
+ uniform vec3 sunDirection;
10
+
11
+ // Participating medium
12
+ uniform float scatteringCoefficient;
13
+ uniform float absorptionCoefficient;
14
+ uniform vec3 albedo;
15
+
16
+ // Primary raymarch
17
+ uniform float minDensity;
18
+ uniform float minExtinction;
19
+ uniform float minTransmittance;
20
+
21
+ // Shape and weather
22
+ uniform sampler2D localWeatherTexture;
23
+ uniform vec2 localWeatherRepeat;
24
+ uniform vec2 localWeatherOffset;
25
+ uniform float coverage;
26
+ uniform sampler3D shapeTexture;
27
+ uniform vec3 shapeRepeat;
28
+ uniform vec3 shapeOffset;
29
+
30
+ #ifdef SHAPE_DETAIL
31
+ uniform sampler3D shapeDetailTexture;
32
+ uniform vec3 shapeDetailRepeat;
33
+ uniform vec3 shapeDetailOffset;
34
+ #endif // SHAPE_DETAIL
35
+
36
+ #ifdef TURBULENCE
37
+ uniform sampler2D turbulenceTexture;
38
+ uniform vec2 turbulenceRepeat;
39
+ uniform float turbulenceDisplacement;
40
+ #endif // TURBULENCE
41
+
42
+ // Haze
43
+ #ifdef HAZE
44
+ uniform float hazeDensityScale;
45
+ uniform float hazeExponent;
46
+ #endif // HAZE
47
+
48
+ // Cloud layers
49
+ uniform vec4 minLayerHeights;
50
+ uniform vec4 maxLayerHeights;
51
+ uniform vec3 minIntervalHeights;
52
+ uniform vec3 maxIntervalHeights;
53
+ uniform vec4 densityScales;
54
+ uniform vec4 shapeAmounts;
55
+ uniform vec4 shapeDetailAmounts;
56
+ uniform vec4 weatherExponents;
57
+ uniform vec4 shapeAlteringBiases;
58
+ uniform vec4 coverageFilterWidths;
59
+ uniform float minHeight;
60
+ uniform float maxHeight;
61
+ uniform float shadowTopHeight;
62
+ uniform float shadowBottomHeight;
63
+ uniform vec4 shadowLayerMask;
64
+ uniform DensityProfile densityProfile;