@takram/three-geospatial-effects 0.0.1-alpha.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 (60) hide show
  1. package/README.md +15 -0
  2. package/build/index.cjs +1 -0
  3. package/build/index.js +25 -0
  4. package/build/r3f.cjs +748 -0
  5. package/build/r3f.js +1645 -0
  6. package/build/shared.cjs +315 -0
  7. package/build/shared.js +741 -0
  8. package/package.json +52 -0
  9. package/src/DepthEffect.ts +81 -0
  10. package/src/DitheringEffect.ts +28 -0
  11. package/src/DownsampleThresholdMaterial.ts +83 -0
  12. package/src/GeometryEffect.ts +79 -0
  13. package/src/GeometryPass.ts +53 -0
  14. package/src/LensFlareEffect.ts +185 -0
  15. package/src/LensFlareFeaturesMaterial.ts +96 -0
  16. package/src/NormalEffect.ts +135 -0
  17. package/src/createHaldLookupTexture.ts +20 -0
  18. package/src/index.ts +7 -0
  19. package/src/r3f/Depth.tsx +8 -0
  20. package/src/r3f/Dithering.tsx +5 -0
  21. package/src/r3f/EffectComposer.tsx +189 -0
  22. package/src/r3f/Geometry.tsx +45 -0
  23. package/src/r3f/LensFlare.tsx +30 -0
  24. package/src/r3f/Normal.tsx +49 -0
  25. package/src/r3f/SSAO.tsx +123 -0
  26. package/src/r3f/index.ts +8 -0
  27. package/src/r3f/types.ts +12 -0
  28. package/src/setupMaterialsForGeometryPass.ts +131 -0
  29. package/src/shaders/depthEffect.frag +26 -0
  30. package/src/shaders/ditheringEffect.frag +7 -0
  31. package/src/shaders/downsampleThreshold.frag +73 -0
  32. package/src/shaders/downsampleThreshold.vert +34 -0
  33. package/src/shaders/geometryEffect.frag +17 -0
  34. package/src/shaders/lensFlareEffect.frag +12 -0
  35. package/src/shaders/lensFlareFeatures.frag +73 -0
  36. package/src/shaders/lensFlareFeatures.vert +10 -0
  37. package/src/shaders/normalEffect.frag +37 -0
  38. package/src/shaders/ssr.frag +381 -0
  39. package/src/shaders/ssr.vert +6 -0
  40. package/src/shaders/ssrEffect.frag +6 -0
  41. package/types/DepthEffect.d.ts +23 -0
  42. package/types/DitheringEffect.d.ts +11 -0
  43. package/types/DownsampleThresholdMaterial.d.ts +21 -0
  44. package/types/GeometryEffect.d.ts +20 -0
  45. package/types/GeometryPass.d.ts +9 -0
  46. package/types/LensFlareEffect.d.ts +43 -0
  47. package/types/LensFlareFeaturesMaterial.d.ts +26 -0
  48. package/types/NormalEffect.d.ts +27 -0
  49. package/types/createHaldLookupTexture.d.ts +4 -0
  50. package/types/index.d.ts +7 -0
  51. package/types/r3f/Depth.d.ts +8 -0
  52. package/types/r3f/Dithering.d.ts +6 -0
  53. package/types/r3f/EffectComposer.d.ts +25 -0
  54. package/types/r3f/Geometry.d.ts +6 -0
  55. package/types/r3f/LensFlare.d.ts +6 -0
  56. package/types/r3f/Normal.d.ts +6 -0
  57. package/types/r3f/SSAO.d.ts +26 -0
  58. package/types/r3f/index.d.ts +8 -0
  59. package/types/r3f/types.d.ts +8 -0
  60. package/types/setupMaterialsForGeometryPass.d.ts +8 -0
@@ -0,0 +1,131 @@
1
+ // cSpell:words defaultnormal specularmap envmap
2
+
3
+ /// <reference types="vite-plugin-glsl/ext" />
4
+
5
+ import { ShaderLib, type ShaderLibShader } from 'three'
6
+
7
+ import { packingShader } from '@takram/three-geospatial'
8
+
9
+ const SETUP = Symbol('SETUP')
10
+
11
+ declare module 'three' {
12
+ interface ShaderLibShader {
13
+ [SETUP]?: boolean
14
+ }
15
+ }
16
+
17
+ function injectNormal(shader: ShaderLibShader): ShaderLibShader {
18
+ const vertexShader = shader.vertexShader
19
+ .replace(
20
+ /* glsl */ `#include <fog_pars_vertex>`,
21
+ /* glsl */ `
22
+ #include <fog_pars_vertex>
23
+ #include <normal_pars_vertex>
24
+ `
25
+ )
26
+ .replace(
27
+ /* glsl */ `#include <defaultnormal_vertex>`,
28
+ /* glsl */ `
29
+ #include <defaultnormal_vertex>
30
+ #include <normal_vertex>
31
+ `
32
+ )
33
+ .replace(
34
+ /* glsl */ `#if defined ( USE_ENVMAP ) || defined ( USE_SKINNING )`,
35
+ /* glsl */ `#if 1`
36
+ )
37
+ .replace(
38
+ /* glsl */ `#include <clipping_planes_vertex>`,
39
+ /* glsl */ `
40
+ #include <clipping_planes_vertex>
41
+ vViewPosition = - mvPosition.xyz;
42
+ `
43
+ )
44
+ shader.vertexShader = /* glsl */ `
45
+ #undef FLAT_SHADED
46
+ varying vec3 vViewPosition;
47
+ ${vertexShader}
48
+ `
49
+
50
+ const fragmentShader = shader.fragmentShader
51
+ .replace(
52
+ /#ifndef FLAT_SHADED\s+varying vec3 vNormal;\s+#endif/m,
53
+ /* glsl */ `#include <normal_pars_fragment>`
54
+ )
55
+ .replace(
56
+ /* glsl */ `#include <common>`,
57
+ /* glsl */ `
58
+ #include <common>
59
+ #include <packing>
60
+ `
61
+ )
62
+ .replace(
63
+ /* glsl */ `#include <specularmap_fragment>`,
64
+ /* glsl */ `
65
+ #include <specularmap_fragment>
66
+ #include <normal_fragment_begin>
67
+ #include <normal_fragment_maps>
68
+ `
69
+ )
70
+ shader.fragmentShader = /* glsl */ `
71
+ #undef FLAT_SHADED
72
+ varying vec3 vViewPosition;
73
+ ${fragmentShader}
74
+ `
75
+
76
+ return shader
77
+ }
78
+
79
+ function injectGBuffer(
80
+ shader: ShaderLibShader,
81
+ { type }: { type?: 'basic' | 'physical' } = {}
82
+ ): ShaderLibShader {
83
+ if (shader[SETUP] === true) {
84
+ return shader
85
+ }
86
+ if (type === 'basic') {
87
+ injectNormal(shader)
88
+ }
89
+ const outputBuffer1 =
90
+ type === 'physical'
91
+ ? /* glsl */ `
92
+ vec4(
93
+ packNormalToVec2(normal),
94
+ metalnessFactor,
95
+ roughnessFactor
96
+ )
97
+ `
98
+ : /* glsl */ `
99
+ vec4(
100
+ packNormalToVec2(normal),
101
+ reflectivity,
102
+ 0.0
103
+ );
104
+ `
105
+ shader.fragmentShader = /* glsl */ `
106
+ layout(location = 1) out vec4 outputBuffer1;
107
+
108
+ #ifndef USE_ENVMAP
109
+ uniform float reflectivity;
110
+ #endif
111
+
112
+ ${packingShader}
113
+ ${shader.fragmentShader.replace(
114
+ /}\s*$/m, // Assume the last curly brace is of main()
115
+ /* glsl */ `
116
+ outputBuffer1 = ${outputBuffer1};
117
+ }
118
+ `
119
+ )}
120
+ `
121
+ shader[SETUP] = true
122
+ return shader
123
+ }
124
+
125
+ export function setupMaterialsForGeometryPass(): void {
126
+ injectGBuffer(ShaderLib.lambert)
127
+ injectGBuffer(ShaderLib.phong)
128
+ injectGBuffer(ShaderLib.basic, { type: 'basic' })
129
+ injectGBuffer(ShaderLib.standard, { type: 'physical' })
130
+ injectGBuffer(ShaderLib.physical, { type: 'physical' })
131
+ }
@@ -0,0 +1,26 @@
1
+ uniform float near;
2
+ uniform float far;
3
+
4
+ // A fifth-order polynomial approximation of Turbo colormap.
5
+ // See: https://observablehq.com/@mbostock/turbo
6
+ // prettier-ignore
7
+ vec3 turbo(const float x) {
8
+ float r = 0.1357 + x * (4.5974 - x * (42.3277 - x * (130.5887 - x * (150.5666 - x * 58.1375))));
9
+ float g = 0.0914 + x * (2.1856 + x * (4.8052 - x * (14.0195 - x * (4.2109 + x * 2.7747))));
10
+ float b = 0.1067 + x * (12.5925 - x * (60.1097 - x * (109.0745 - x * (88.5066 - x * 26.8183))));
11
+ return vec3(r, g, b);
12
+ }
13
+
14
+ void mainImage(const vec4 inputColor, const vec2 uv, out vec4 outputColor) {
15
+ float depth = readDepth(uv);
16
+ depth = reverseLogDepth(depth, cameraNear, cameraFar);
17
+ depth = linearizeDepth(depth, near, far) / far;
18
+
19
+ #ifdef USE_TURBO
20
+ vec3 color = turbo(1.0 - depth);
21
+ #else
22
+ vec3 color = vec3(depth);
23
+ #endif // USE_TURBO
24
+
25
+ outputColor = vec4(color, inputColor.a);
26
+ }
@@ -0,0 +1,7 @@
1
+ #define DITHERING
2
+
3
+ #include <dithering_pars_fragment>
4
+
5
+ void mainImage(const vec4 inputColor, const vec2 uv, out vec4 outputColor) {
6
+ outputColor = vec4(dithering(inputColor.rgb), inputColor.a);
7
+ }
@@ -0,0 +1,73 @@
1
+ #include <common>
2
+
3
+ uniform sampler2D inputBuffer;
4
+
5
+ uniform float thresholdLevel;
6
+ uniform float thresholdRange;
7
+
8
+ in vec2 vCenterUv1;
9
+ in vec2 vCenterUv2;
10
+ in vec2 vCenterUv3;
11
+ in vec2 vCenterUv4;
12
+ in vec2 vRowUv1;
13
+ in vec2 vRowUv2;
14
+ in vec2 vRowUv3;
15
+ in vec2 vRowUv4;
16
+ in vec2 vRowUv5;
17
+ in vec2 vRowUv6;
18
+ in vec2 vRowUv7;
19
+ in vec2 vRowUv8;
20
+ in vec2 vRowUv9;
21
+
22
+ float clampToBorder(const vec2 uv) {
23
+ return float(uv.x >= 0.0 && uv.x <= 1.0 && uv.y >= 0.0 && uv.y <= 1.0);
24
+ }
25
+
26
+ // Reference: https://learnopengl.com/Guest-Articles/2022/Phys.-Based-Bloom
27
+ void main() {
28
+ vec3 color = 0.125 * texture2D(inputBuffer, vec2(vRowUv5)).rgb;
29
+ vec4 weight =
30
+ 0.03125 *
31
+ vec4(
32
+ clampToBorder(vRowUv1),
33
+ clampToBorder(vRowUv3),
34
+ clampToBorder(vRowUv7),
35
+ clampToBorder(vRowUv9)
36
+ );
37
+ color += weight.x * texture2D(inputBuffer, vec2(vRowUv1)).rgb;
38
+ color += weight.y * texture2D(inputBuffer, vec2(vRowUv3)).rgb;
39
+ color += weight.z * texture2D(inputBuffer, vec2(vRowUv7)).rgb;
40
+ color += weight.w * texture2D(inputBuffer, vec2(vRowUv9)).rgb;
41
+
42
+ weight =
43
+ 0.0625 *
44
+ vec4(
45
+ clampToBorder(vRowUv2),
46
+ clampToBorder(vRowUv4),
47
+ clampToBorder(vRowUv6),
48
+ clampToBorder(vRowUv8)
49
+ );
50
+ color += weight.x * texture2D(inputBuffer, vec2(vRowUv2)).rgb;
51
+ color += weight.y * texture2D(inputBuffer, vec2(vRowUv4)).rgb;
52
+ color += weight.z * texture2D(inputBuffer, vec2(vRowUv6)).rgb;
53
+ color += weight.w * texture2D(inputBuffer, vec2(vRowUv8)).rgb;
54
+
55
+ weight =
56
+ 0.125 *
57
+ vec4(
58
+ clampToBorder(vRowUv2),
59
+ clampToBorder(vRowUv4),
60
+ clampToBorder(vRowUv6),
61
+ clampToBorder(vRowUv8)
62
+ );
63
+ color += weight.x * texture2D(inputBuffer, vec2(vCenterUv1)).rgb;
64
+ color += weight.y * texture2D(inputBuffer, vec2(vCenterUv2)).rgb;
65
+ color += weight.z * texture2D(inputBuffer, vec2(vCenterUv3)).rgb;
66
+ color += weight.w * texture2D(inputBuffer, vec2(vCenterUv4)).rgb;
67
+
68
+ float l = luminance(color);
69
+ float scale = saturate(
70
+ smoothstep(thresholdLevel, thresholdLevel + thresholdRange, l)
71
+ );
72
+ gl_FragColor = vec4(color * scale, 1.0);
73
+ }
@@ -0,0 +1,34 @@
1
+ uniform vec2 texelSize;
2
+
3
+ out vec2 vCenterUv1;
4
+ out vec2 vCenterUv2;
5
+ out vec2 vCenterUv3;
6
+ out vec2 vCenterUv4;
7
+ out vec2 vRowUv1;
8
+ out vec2 vRowUv2;
9
+ out vec2 vRowUv3;
10
+ out vec2 vRowUv4;
11
+ out vec2 vRowUv5;
12
+ out vec2 vRowUv6;
13
+ out vec2 vRowUv7;
14
+ out vec2 vRowUv8;
15
+ out vec2 vRowUv9;
16
+
17
+ void main() {
18
+ vec2 uv = position.xy * 0.5 + 0.5;
19
+ vCenterUv1 = uv + texelSize * vec2(-1.0, 1.0);
20
+ vCenterUv2 = uv + texelSize * vec2(1.0, 1.0);
21
+ vCenterUv3 = uv + texelSize * vec2(-1.0, -1.0);
22
+ vCenterUv4 = uv + texelSize * vec2(1.0, -1.0);
23
+ vRowUv1 = uv + texelSize * vec2(-2.0, 2.0);
24
+ vRowUv2 = uv + texelSize * vec2(0.0, 2.0);
25
+ vRowUv3 = uv + texelSize * vec2(2.0, 2.0);
26
+ vRowUv4 = uv + texelSize * vec2(-2.0, 0.0);
27
+ vRowUv5 = uv + texelSize;
28
+ vRowUv6 = uv + texelSize * vec2(2.0, 0.0);
29
+ vRowUv7 = uv + texelSize * vec2(-2.0, -2.0);
30
+ vRowUv8 = uv + texelSize * vec2(0.0, -2.0);
31
+ vRowUv9 = uv + texelSize * vec2(2.0, -2.0);
32
+
33
+ gl_Position = vec4(position.xy, 1.0, 1.0);
34
+ }
@@ -0,0 +1,17 @@
1
+ uniform sampler2D geometryBuffer;
2
+
3
+ void mainImage(const vec4 inputColor, const vec2 uv, out vec4 outputColor) {
4
+ vec4 normalMetalnessRoughness = texture2D(geometryBuffer, uv);
5
+
6
+ #ifdef OUTPUT_NORMAL
7
+ vec3 normal = unpackVec2ToNormal(texture2D(geometryBuffer, uv).xy);
8
+ outputColor = vec4(normal * 0.5 + 0.5, inputColor.a);
9
+ #endif // OUTPUT_NORMAL
10
+
11
+ #ifdef OUTPUT_PBR
12
+ outputColor = vec4(
13
+ vec3(normalMetalnessRoughness.b, normalMetalnessRoughness.a, 0.0),
14
+ inputColor.a
15
+ );
16
+ #endif // OUTPUT_PBR
17
+ }
@@ -0,0 +1,12 @@
1
+ uniform sampler2D bloomBuffer;
2
+ uniform sampler2D featuresBuffer;
3
+ uniform float intensity;
4
+
5
+ void mainImage(const vec4 inputColor, const vec2 uv, out vec4 outputColor) {
6
+ vec3 bloom = texture2D(bloomBuffer, uv).rgb;
7
+ vec3 features = texture2D(featuresBuffer, uv).rgb;
8
+ outputColor = vec4(
9
+ inputColor.rgb + (bloom + features) * intensity,
10
+ inputColor.a
11
+ );
12
+ }
@@ -0,0 +1,73 @@
1
+ #include <common>
2
+
3
+ #define SQRT_2 (0.7071067811865476)
4
+
5
+ uniform sampler2D inputBuffer;
6
+
7
+ uniform vec2 texelSize;
8
+ uniform float ghostAmount;
9
+ uniform float haloAmount;
10
+ uniform float chromaticAberration;
11
+
12
+ in vec2 vUv;
13
+ in vec2 vAspectRatio;
14
+
15
+ vec3 sampleGhost(const vec2 direction, const vec3 color, const float offset) {
16
+ vec2 suv = clamp(1.0 - vUv + direction * offset, 0.0, 1.0);
17
+ vec3 result = texture2D(inputBuffer, suv).rgb * color;
18
+
19
+ // Falloff at the perimeter.
20
+ float d = clamp(length(0.5 - suv) / (0.5 * SQRT_2), 0.0, 1.0);
21
+ result *= pow(1.0 - d, 3.0);
22
+ return result;
23
+ }
24
+
25
+ vec4 sampleGhosts(float amount) {
26
+ vec3 color = vec3(0.0);
27
+ vec2 direction = vUv - 0.5;
28
+ color += sampleGhost(direction, vec3(0.8, 0.8, 1.0), -5.0);
29
+ color += sampleGhost(direction, vec3(1.0, 0.8, 0.4), -1.5);
30
+ color += sampleGhost(direction, vec3(0.9, 1.0, 0.8), -0.4);
31
+ color += sampleGhost(direction, vec3(1.0, 0.8, 0.4), -0.2);
32
+ color += sampleGhost(direction, vec3(0.9, 0.7, 0.7), -0.1);
33
+ color += sampleGhost(direction, vec3(0.5, 1.0, 0.4), 0.7);
34
+ color += sampleGhost(direction, vec3(0.5, 0.5, 0.5), 1.0);
35
+ color += sampleGhost(direction, vec3(1.0, 1.0, 0.6), 2.5);
36
+ color += sampleGhost(direction, vec3(0.5, 0.8, 1.0), 10.0);
37
+ return vec4(color * amount, 1.0);
38
+ }
39
+
40
+ // Reference: https://john-chapman.github.io/2017/11/05/pseudo-lens-flare.html
41
+ float cubicRingMask(const float x, const float radius, const float thickness) {
42
+ float v = min(abs(x - radius) / thickness, 1.0);
43
+ return 1.0 - v * v * (3.0 - 2.0 * v);
44
+ }
45
+
46
+ vec3 sampleHalo(const float radius) {
47
+ vec2 direction = normalize((vUv - 0.5) / vAspectRatio) * vAspectRatio;
48
+ vec3 offset = vec3(texelSize.x * chromaticAberration) * vec3(-1.0, 0.0, 1.0);
49
+ vec2 suv = fract(1.0 - vUv + direction * radius);
50
+ vec3 result = vec3(
51
+ texture2D(inputBuffer, suv + direction * offset.r).r,
52
+ texture2D(inputBuffer, suv + direction * offset.g).g,
53
+ texture2D(inputBuffer, suv + direction * offset.b).b
54
+ );
55
+
56
+ // Falloff at the center and perimeter.
57
+ vec2 wuv = (vUv - vec2(0.5, 0.0)) / vAspectRatio + vec2(0.5, 0.0);
58
+ float d = saturate(distance(wuv, vec2(0.5)));
59
+ result *= cubicRingMask(d, 0.45, 0.25);
60
+ return result;
61
+ }
62
+
63
+ vec4 sampleHalos(const float amount) {
64
+ vec3 color = vec3(0.0);
65
+ color += sampleHalo(0.3);
66
+ return vec4(color, 1.0) * amount;
67
+ }
68
+
69
+ void main() {
70
+ gl_FragColor += sampleGhosts(ghostAmount);
71
+ gl_FragColor += sampleHalos(haloAmount);
72
+ }
73
+
@@ -0,0 +1,10 @@
1
+ uniform vec2 texelSize;
2
+
3
+ out vec2 vUv;
4
+ out vec2 vAspectRatio;
5
+
6
+ void main() {
7
+ vUv = position.xy * 0.5 + 0.5;
8
+ vAspectRatio = vec2(texelSize.x / texelSize.y, 1.0);
9
+ gl_Position = vec4(position.xy, 1.0, 1.0);
10
+ }
@@ -0,0 +1,37 @@
1
+ uniform highp sampler2D normalBuffer;
2
+
3
+ uniform mat4 projectionMatrix;
4
+ uniform mat4 inverseProjectionMatrix;
5
+
6
+ vec3 reconstructNormal(const vec2 uv) {
7
+ float depth = readDepth(uv);
8
+ depth = reverseLogDepth(depth, cameraNear, cameraFar);
9
+ vec3 position = screenToView(
10
+ uv,
11
+ depth,
12
+ getViewZ(depth),
13
+ projectionMatrix,
14
+ inverseProjectionMatrix
15
+ );
16
+ vec3 dx = dFdx(position);
17
+ vec3 dy = dFdy(position);
18
+ return normalize(cross(dx, dy));
19
+ }
20
+
21
+ vec3 readNormal(const vec2 uv) {
22
+ #ifdef OCT_ENCODED
23
+ return unpackVec2ToNormal(texture2D(normalBuffer, uv).xy);
24
+ #else
25
+ return 2.0 * texture2D(normalBuffer, uv).xyz - 1.0;
26
+ #endif // OCT_ENCODED
27
+ }
28
+
29
+ void mainImage(const vec4 inputColor, const vec2 uv, out vec4 outputColor) {
30
+ #ifdef RECONSTRUCT_FROM_DEPTH
31
+ vec3 normal = reconstructNormal(uv);
32
+ #else
33
+ vec3 normal = readNormal(uv);
34
+ #endif // RECONSTRUCT_FROM_DEPTH
35
+
36
+ outputColor = vec4(normal * 0.5 + 0.5, inputColor.a);
37
+ }