@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.
- package/CHANGELOG.md +5 -0
- package/README.md +1130 -0
- package/assets/local_weather.png +0 -0
- package/assets/shape.bin +1 -0
- package/assets/shape_detail.bin +1 -0
- package/assets/turbulence.png +0 -0
- package/build/index.cjs +583 -0
- package/build/index.cjs.map +1 -0
- package/build/index.js +728 -0
- package/build/index.js.map +1 -0
- package/build/r3f.cjs +2 -0
- package/build/r3f.cjs.map +1 -0
- package/build/r3f.js +205 -0
- package/build/r3f.js.map +1 -0
- package/build/shared.cjs +2189 -0
- package/build/shared.cjs.map +1 -0
- package/build/shared.js +3825 -0
- package/build/shared.js.map +1 -0
- package/package.json +77 -0
- package/src/CascadedShadowMaps.ts +288 -0
- package/src/CloudLayer.ts +85 -0
- package/src/CloudLayers.test.ts +61 -0
- package/src/CloudLayers.ts +181 -0
- package/src/CloudShape.ts +22 -0
- package/src/CloudShapeDetail.ts +22 -0
- package/src/CloudsEffect.ts +810 -0
- package/src/CloudsMaterial.ts +467 -0
- package/src/CloudsPass.ts +285 -0
- package/src/CloudsResolveMaterial.ts +108 -0
- package/src/DensityProfile.ts +38 -0
- package/src/LocalWeather.ts +21 -0
- package/src/PassBase.ts +28 -0
- package/src/Procedural3DTexture.ts +94 -0
- package/src/ProceduralTexture.ts +94 -0
- package/src/ShaderArrayPass.ts +32 -0
- package/src/ShadowMaterial.ts +141 -0
- package/src/ShadowPass.ts +185 -0
- package/src/ShadowResolveMaterial.ts +72 -0
- package/src/Turbulence.ts +21 -0
- package/src/bayer.ts +23 -0
- package/src/constants.ts +8 -0
- package/src/helpers/FrustumCorners.ts +138 -0
- package/src/helpers/setArrayRenderTargetLayers.ts +32 -0
- package/src/helpers/splitFrustum.ts +59 -0
- package/src/index.ts +14 -0
- package/src/qualityPresets.ts +117 -0
- package/src/r3f/CloudLayer.tsx +95 -0
- package/src/r3f/CloudLayers.tsx +54 -0
- package/src/r3f/Clouds.tsx +278 -0
- package/src/r3f/index.ts +2 -0
- package/src/shaders/catmullRomSampling.glsl +113 -0
- package/src/shaders/cloudShape.frag +78 -0
- package/src/shaders/cloudShapeDetail.frag +56 -0
- package/src/shaders/clouds.frag +996 -0
- package/src/shaders/clouds.glsl +190 -0
- package/src/shaders/clouds.vert +69 -0
- package/src/shaders/cloudsEffect.frag +11 -0
- package/src/shaders/cloudsResolve.frag +202 -0
- package/src/shaders/cloudsResolve.vert +10 -0
- package/src/shaders/localWeather.frag +83 -0
- package/src/shaders/parameters.glsl +64 -0
- package/src/shaders/perlin.glsl +211 -0
- package/src/shaders/shadow.frag +197 -0
- package/src/shaders/shadow.vert +16 -0
- package/src/shaders/shadowResolve.frag +76 -0
- package/src/shaders/shadowResolve.vert +10 -0
- package/src/shaders/structuredSampling.glsl +101 -0
- package/src/shaders/tileableNoise.glsl +88 -0
- package/src/shaders/turbulence.frag +51 -0
- package/src/shaders/types.glsl +18 -0
- package/src/shaders/varianceClipping.glsl +114 -0
- package/src/uniforms.ts +218 -0
- package/types/CascadedShadowMaps.d.ts +52 -0
- package/types/CloudLayer.d.ts +26 -0
- package/types/CloudLayers.d.ts +21 -0
- package/types/CloudShape.d.ts +5 -0
- package/types/CloudShapeDetail.d.ts +5 -0
- package/types/CloudsEffect.d.ts +170 -0
- package/types/CloudsMaterial.d.ts +86 -0
- package/types/CloudsPass.d.ts +44 -0
- package/types/CloudsResolveMaterial.d.ts +30 -0
- package/types/DensityProfile.d.ts +12 -0
- package/types/LocalWeather.d.ts +5 -0
- package/types/PassBase.d.ts +14 -0
- package/types/Procedural3DTexture.d.ts +20 -0
- package/types/ProceduralTexture.d.ts +24 -0
- package/types/ShaderArrayPass.d.ts +7 -0
- package/types/ShadowMaterial.d.ts +34 -0
- package/types/ShadowPass.d.ts +34 -0
- package/types/ShadowResolveMaterial.d.ts +20 -0
- package/types/Turbulence.d.ts +5 -0
- package/types/bayer.d.ts +4 -0
- package/types/constants.d.ts +6 -0
- package/types/helpers/FrustumCorners.d.ts +18 -0
- package/types/helpers/setArrayRenderTargetLayers.d.ts +3 -0
- package/types/helpers/splitFrustum.d.ts +9 -0
- package/types/index.d.ts +13 -0
- package/types/qualityPresets.d.ts +46 -0
- package/types/r3f/CloudLayer.d.ts +7 -0
- package/types/r3f/CloudLayers.d.ts +15 -0
- package/types/r3f/Clouds.d.ts +16 -0
- package/types/r3f/index.d.ts +2 -0
- 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,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;
|