@openglobus/og 0.20.1 → 0.20.3

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 (35) hide show
  1. package/css/og.css +55 -23
  2. package/lib/@openglobus/js/Globe.d.ts +3 -0
  3. package/lib/@openglobus/js/control/Atmosphere.d.ts +27 -3
  4. package/lib/@openglobus/js/control/AtmosphereConfig.d.ts +59 -0
  5. package/lib/@openglobus/js/control/index.d.ts +29 -29
  6. package/lib/@openglobus/js/scene/Planet.d.ts +6 -0
  7. package/lib/@openglobus/js/shaders/atmos.d.ts +19 -3
  8. package/lib/@openglobus/js/shaders/drawnode.d.ts +2 -1
  9. package/lib/@openglobus/js/webgl/Handler.d.ts +3 -1
  10. package/lib/@openglobus/og.css +1 -1
  11. package/lib/@openglobus/og.esm.js +1 -1
  12. package/lib/@openglobus/og.esm.js.map +1 -1
  13. package/lib/@openglobus/og.umd.js +1 -1
  14. package/lib/@openglobus/og.umd.js.map +1 -1
  15. package/lib/js/Globe.d.ts +3 -0
  16. package/lib/js/Globe.js +6 -1
  17. package/lib/js/control/Atmosphere.d.ts +27 -3
  18. package/lib/js/control/Atmosphere.js +109 -43
  19. package/lib/js/control/AtmosphereConfig.d.ts +59 -0
  20. package/lib/js/control/AtmosphereConfig.js +348 -0
  21. package/lib/js/control/DebugInfo.js +5 -4
  22. package/lib/js/control/Lighting.js +13 -5
  23. package/lib/js/control/index.d.ts +29 -29
  24. package/lib/js/control/index.js +29 -29
  25. package/lib/js/layer/Layer.js +2 -2
  26. package/lib/js/scene/Planet.d.ts +6 -0
  27. package/lib/js/scene/Planet.js +24 -10
  28. package/lib/js/shaders/atmos.d.ts +19 -3
  29. package/lib/js/shaders/atmos.js +40 -26
  30. package/lib/js/shaders/drawnode.d.ts +2 -1
  31. package/lib/js/shaders/drawnode.js +15 -12
  32. package/lib/js/ui/Slider.js +3 -3
  33. package/lib/js/webgl/Handler.d.ts +3 -1
  34. package/lib/js/webgl/Handler.js +38 -28
  35. package/package.json +8 -8
@@ -1,4 +1,20 @@
1
1
  import { Program } from '../webgl/Program';
2
- export declare const COMMON = "\n \n \n float getLerpValue(in float min, in float max, in float between)\n {\n return (clamp(between, min, max) - min) / (max - min);\n }\n \n vec3 aces(vec3 color) \n {\n float a = 2.51;\n float b = 0.03;\n float c = 2.43;\n float d = 0.59;\n float e = 0.14;\n return clamp((color * (a * color + b)) / (color * (c * color + d ) + e), 0.0, 1.0);\n }\n \n bool intersectSphere(vec3 rayOrigin, vec3 rayDirection, float radius, inout float t1, inout float t2) \n {\n float b = dot(rayDirection, rayOrigin);\n float c = dot(rayOrigin, rayOrigin) - radius * radius;\n float d = b * b - c;\n if (d < 0.0) {\n return false;\n }\n t1 = -b - sqrt(d);\n t2 = -b + sqrt(d);\n return true;\n }\n \n bool intersectSphere(vec3 rayOrigin, vec3 rayDirection, float radius, inout float t) \n {\n float b = dot(rayDirection, rayOrigin);\n float c = dot(rayOrigin, rayOrigin) - radius * radius;\n float d = b * b - c;\n if (d < 0.0) {\n return false;\n }\n t = -b - sqrt(d);\n return true;\n }\n \n bool intersectEllipsoid( in vec3 ro, in vec3 rd, in vec3 ra, inout float t )\n {\n vec3 ocn = ro/ra;\n vec3 rdn = rd/ra;\n float a = dot( rdn, rdn );\n float b = dot( ocn, rdn );\n float c = dot( ocn, ocn );\n float h = b*b - a*(c-1.0);\n \n if (h < 0.0) \n { \n return false; \n }\n \n t = (-b-sqrt(h))/a;\n \n return true;\n }\n \n bool intersectEllipsoid( in vec3 ro, in vec3 rd, in vec3 ra, inout float t1, inout float t2)\n {\n vec3 ocn = ro/ra;\n vec3 rdn = rd/ra;\n float a = dot( rdn, rdn );\n float b = dot( ocn, rdn );\n float c = dot( ocn, ocn );\n float h = b*b - a*(c-1.0);\n \n if (h < 0.0) \n { \n return false; \n }\n \n h = sqrt(h);\n t1 = (-b-h)/a;\n t2 = (-b+h)/a;\n \n return true;\n }\n \n vec3 normalEllipsoid( in vec3 pos, in vec3 ra )\n {\n return normalize( pos/(ra*ra) );\n }\n\n \n #define PI 3.1415926538\n #define ATMOS_HEIGHT 100000.0\n #define RAYLEIGH_SCALE 0.08\n #define MIE_SCALE 0.012\n \n #define SAMPLE_COUNT 16\n #define SQRT_SAMPLE_COUNT 4\n \n const float GROUND_ALBEDO = 0.05 / PI;\n\n // Sphere\n const float BOTTOM_RADIUS = 6356752.3142451793;\n const float TOP_RADIUS = 6356752.3142451793 + ATMOS_HEIGHT;\n \n // Ellipsoid\n const vec3 bottomRadii = vec3(6378137.0, 6378137.0, 6356752.3142451793); \n const vec3 topRadii = bottomRadii + ATMOS_HEIGHT;\n \n const vec3 SPHERE_TO_ELLIPSOID_SCALE = vec3(BOTTOM_RADIUS) / bottomRadii; \n \n const vec2 rayleighMieHeights = vec2(RAYLEIGH_SCALE, MIE_SCALE) * ATMOS_HEIGHT;\n \n const vec3 rayleighScatteringCoefficient = vec3(5.802, 13.558, 33.100) * 1e-6;\n \n const float mieScatteringCoefficient = 3.996e-06;\n const float mieExtinctionCoefficient = 4.440e-06;\n const vec3 ozoneAbsorptionCoefficient = vec3(0.650, 1.881, 0.085) * 1e-6;\n \n const float SUN_ANGULAR_RADIUS = 0.004685;\n const float SUN_INTENSITY = 1.0; \n \n vec3 sunWithBloom(vec3 rayDir, vec3 sunDir) \n {\n float minSunCosTheta = cos(SUN_ANGULAR_RADIUS); \n float cosTheta = dot(rayDir, sunDir);\n if (cosTheta >= minSunCosTheta) return vec3(1.0); \n float offset = minSunCosTheta - cosTheta;\n float gaussianBloom = exp(-offset*15000.0)*0.7;\n float invBloom = 1.0/(0.09 + offset*200.0)*0.01;\n return vec3(gaussianBloom + invBloom);\n }\n \n float rayleighPhase(float angle) \n {\n return 3.0 / (16.0 * PI) * (1.0 + (angle * angle));\n }\n \n float miePhase(float angle) \n {\n float g = 0.8;\n return 3.0 / (8.0 * PI) * ((1.0 - g * g) * (1.0 + angle * angle)) / ((2.0 + g * g) * pow(1.0 + g * g - 2.0 * g * angle, 1.5));\n }\n \n vec3 opticalDepth(float height, float angle) \n {\n vec3 rayOrigin = vec3(0.0, BOTTOM_RADIUS + height, 0.0);\n vec3 rayDirection = vec3(sqrt(1.0 - angle * angle), angle, 0.0);\n float t1, t2;\n intersectSphere(rayOrigin, rayDirection, TOP_RADIUS, t1, t2);\n float segmentLength = t2 / float(SAMPLE_COUNT);\n \n float t = segmentLength * 0.5;\n vec3 opticalDepth = vec3(0.0);\n \n for (int i = 0; i < SAMPLE_COUNT; i++) \n {\n vec3 position = rayOrigin + t * rayDirection;\n float height = length(position) - BOTTOM_RADIUS;\n opticalDepth.xy += exp(-height / rayleighMieHeights) * segmentLength;\n \n // density of the ozone layer is modeled as a triangular \n // function that is 30 km wide and centered at 25 km altitude\n opticalDepth.z += (1.0 - min(abs(height - 25e3) / 15e3, 1.0)) * segmentLength; \n t += segmentLength;\n }\n \n return opticalDepth;\n }\n \n vec3 transmittance(float height, float angle) \n {\n vec3 opticalDepth = opticalDepth(height, angle);\n return exp(-(rayleighScatteringCoefficient * opticalDepth.x + mieExtinctionCoefficient * opticalDepth.y + ozoneAbsorptionCoefficient * opticalDepth.z));\n }";
3
- export declare function transmittance(): Program;
4
- export declare function scattering(): Program;
2
+ import { NumberArray3 } from "../math/Vec3";
3
+ export interface AtmosphereParameters {
4
+ ATMOS_HEIGHT: number;
5
+ RAYLEIGH_SCALE: number;
6
+ MIE_SCALE: number;
7
+ GROUND_ALBEDO: number;
8
+ BOTTOM_RADIUS: number;
9
+ rayleighScatteringCoefficient: NumberArray3;
10
+ mieScatteringCoefficient: number;
11
+ mieExtinctionCoefficient: number;
12
+ ozoneAbsorptionCoefficient: NumberArray3;
13
+ SUN_ANGULAR_RADIUS: number;
14
+ SUN_INTENSITY: number;
15
+ ozoneDensityHeight: number;
16
+ ozoneDensityWide: number;
17
+ }
18
+ export declare const COMMON: (atmosParams?: AtmosphereParameters) => string;
19
+ export declare function transmittance(atmosParams?: AtmosphereParameters): Program;
20
+ export declare function scattering(atmosParams?: AtmosphereParameters): Program;
@@ -1,39 +1,57 @@
1
1
  import { Program } from '../webgl/Program';
2
2
  import { UTILS } from './utils';
3
- export const COMMON = `
4
-
3
+ const DEFAULT_PARAMS = {
4
+ ATMOS_HEIGHT: 100000.0,
5
+ RAYLEIGH_SCALE: 0.08,
6
+ MIE_SCALE: 0.012,
7
+ GROUND_ALBEDO: 0.05,
8
+ BOTTOM_RADIUS: 6356752.3142451793,
9
+ rayleighScatteringCoefficient: [5.802, 13.558, 33.100],
10
+ mieScatteringCoefficient: 3.996,
11
+ mieExtinctionCoefficient: 4.440,
12
+ ozoneAbsorptionCoefficient: [0.650, 1.881, 0.085],
13
+ SUN_ANGULAR_RADIUS: 0.004685,
14
+ SUN_INTENSITY: 1.0,
15
+ ozoneDensityHeight: 25e3,
16
+ ozoneDensityWide: 15e3,
17
+ };
18
+ export const COMMON = (atmosParams = DEFAULT_PARAMS) => `
5
19
  ${UTILS}
6
20
 
7
21
  #define PI 3.1415926538
8
- #define ATMOS_HEIGHT 100000.0
9
- #define RAYLEIGH_SCALE 0.08
10
- #define MIE_SCALE 0.012
22
+ #define ATMOS_HEIGHT ${atmosParams.ATMOS_HEIGHT.toFixed(2)}
23
+ #define RAYLEIGH_SCALE ${atmosParams.RAYLEIGH_SCALE.toFixed(5)}
24
+ #define MIE_SCALE ${atmosParams.MIE_SCALE.toFixed(5)}
11
25
 
12
26
  #define SAMPLE_COUNT 16
13
27
  #define SQRT_SAMPLE_COUNT 4
14
28
 
15
- const float GROUND_ALBEDO = 0.05 / PI;
29
+ const float GROUND_ALBEDO = ${atmosParams.GROUND_ALBEDO.toFixed(2)} / PI;
16
30
 
17
31
  // Sphere
18
- const float BOTTOM_RADIUS = 6356752.3142451793;
19
- const float TOP_RADIUS = 6356752.3142451793 + ATMOS_HEIGHT;
20
-
32
+ const float BOTTOM_RADIUS = ${atmosParams.BOTTOM_RADIUS.toFixed(10)};
33
+ const float TOP_RADIUS = BOTTOM_RADIUS + ATMOS_HEIGHT;
34
+ const float EQUATORIAL_RADIUS = 6378137.0;
35
+
21
36
  // Ellipsoid
22
- const vec3 bottomRadii = vec3(6378137.0, 6378137.0, 6356752.3142451793);
37
+ const vec3 bottomRadii = vec3(EQUATORIAL_RADIUS, EQUATORIAL_RADIUS, BOTTOM_RADIUS);
23
38
  const vec3 topRadii = bottomRadii + ATMOS_HEIGHT;
24
39
 
25
40
  const vec3 SPHERE_TO_ELLIPSOID_SCALE = vec3(BOTTOM_RADIUS) / bottomRadii;
26
41
 
27
42
  const vec2 rayleighMieHeights = vec2(RAYLEIGH_SCALE, MIE_SCALE) * ATMOS_HEIGHT;
28
43
 
29
- const vec3 rayleighScatteringCoefficient = vec3(5.802, 13.558, 33.100) * 1e-6;
44
+ const vec3 rayleighScatteringCoefficient = vec3(${atmosParams.rayleighScatteringCoefficient[0].toFixed(5)}, ${atmosParams.rayleighScatteringCoefficient[1].toFixed(5)}, ${atmosParams.rayleighScatteringCoefficient[2].toFixed(5)}) * 1e-6;
30
45
 
31
- const float mieScatteringCoefficient = 3.996e-06;
32
- const float mieExtinctionCoefficient = 4.440e-06;
33
- const vec3 ozoneAbsorptionCoefficient = vec3(0.650, 1.881, 0.085) * 1e-6;
46
+ const float mieScatteringCoefficient = ${atmosParams.mieScatteringCoefficient.toFixed(3)} * 1e-6;
47
+ const float mieExtinctionCoefficient = ${atmosParams.mieExtinctionCoefficient.toFixed(3)} * 1e-6;
48
+ const vec3 ozoneAbsorptionCoefficient = vec3(${atmosParams.ozoneAbsorptionCoefficient[0].toFixed(5)}, ${atmosParams.ozoneAbsorptionCoefficient[1].toFixed(5)}, ${atmosParams.ozoneAbsorptionCoefficient[2].toFixed(5)}) * 1e-6;
34
49
 
35
- const float SUN_ANGULAR_RADIUS = 0.004685;
36
- const float SUN_INTENSITY = 1.0;
50
+ const float SUN_ANGULAR_RADIUS = ${atmosParams.SUN_ANGULAR_RADIUS.toFixed(10)};
51
+ const float SUN_INTENSITY = ${atmosParams.SUN_INTENSITY.toFixed(2)};
52
+
53
+ const float ozoneDensityHeight = ${atmosParams.ozoneDensityHeight.toFixed(1)};//25e3;
54
+ const float ozoneDensityWide = ${atmosParams.ozoneDensityWide.toFixed(1)};//15e3;
37
55
 
38
56
  vec3 sunWithBloom(vec3 rayDir, vec3 sunDir)
39
57
  {
@@ -73,10 +91,7 @@ export const COMMON = `
73
91
  vec3 position = rayOrigin + t * rayDirection;
74
92
  float height = length(position) - BOTTOM_RADIUS;
75
93
  opticalDepth.xy += exp(-height / rayleighMieHeights) * segmentLength;
76
-
77
- // density of the ozone layer is modeled as a triangular
78
- // function that is 30 km wide and centered at 25 km altitude
79
- opticalDepth.z += (1.0 - min(abs(height - 25e3) / 15e3, 1.0)) * segmentLength;
94
+ opticalDepth.z += (1.0 - min(abs(height - ozoneDensityHeight) / ozoneDensityWide, 1.0)) * segmentLength;
80
95
  t += segmentLength;
81
96
  }
82
97
 
@@ -88,7 +103,7 @@ export const COMMON = `
88
103
  vec3 opticalDepth = opticalDepth(height, angle);
89
104
  return exp(-(rayleighScatteringCoefficient * opticalDepth.x + mieExtinctionCoefficient * opticalDepth.y + ozoneAbsorptionCoefficient * opticalDepth.z));
90
105
  }`;
91
- export function transmittance() {
106
+ export function transmittance(atmosParams) {
92
107
  return new Program("transmittance", {
93
108
  uniforms: {
94
109
  iResolution: "vec2"
@@ -106,7 +121,7 @@ export function transmittance() {
106
121
  fragmentShader: `
107
122
  precision highp float;
108
123
 
109
- ${COMMON}
124
+ ${COMMON(atmosParams)}
110
125
 
111
126
  uniform vec2 iResolution;
112
127
 
@@ -119,7 +134,7 @@ export function transmittance() {
119
134
  }`
120
135
  });
121
136
  }
122
- export function scattering() {
137
+ export function scattering(atmosParams) {
123
138
  return new Program("scattering", {
124
139
  uniforms: {
125
140
  iResolution: "vec2",
@@ -141,7 +156,7 @@ export function scattering() {
141
156
  uniform sampler2D transmittanceTexture;
142
157
  uniform vec2 iResolution;
143
158
 
144
- ${COMMON}
159
+ ${COMMON(atmosParams)}
145
160
 
146
161
  vec3 transmittanceFromTexture(float height, float angle)
147
162
  {
@@ -223,8 +238,7 @@ export function scattering() {
223
238
  vec3 hitPoint = rayOrigin + rayDirection * distanceToGround;
224
239
  vec3 normal = normalize(hitPoint);
225
240
  float diffuseAngle = max(dot(normal, lightDirection), 0.0);
226
- float earthAlbedo = 0.05;
227
- light += transmittanceCamera * transmittanceLight * (earthAlbedo / PI) * diffuseAngle;
241
+ light += transmittanceCamera * transmittanceLight * GROUND_ALBEDO * diffuseAngle;
228
242
  }
229
243
  }
230
244
  }
@@ -1,8 +1,9 @@
1
+ import { AtmosphereParameters } from "./atmos";
1
2
  import { Program } from "../webgl/Program";
2
3
  export declare function drawnode_screen_nl(): Program;
3
4
  export declare function drawnode_screen_wl_webgl1NoAtmos(): Program;
4
5
  export declare function drawnode_screen_wl_webgl2NoAtmos(): Program;
5
- export declare function drawnode_screen_wl_webgl2Atmos(): Program;
6
+ export declare function drawnode_screen_wl_webgl2Atmos(atmosParams?: AtmosphereParameters): Program;
6
7
  export declare function drawnode_colorPicking(): Program;
7
8
  export declare function drawnode_heightPicking(): Program;
8
9
  export declare function drawnode_depth(): Program;
@@ -1,4 +1,4 @@
1
- import * as atmos from "./atmos";
1
+ import { COMMON } from "./atmos";
2
2
  import { Program } from "../webgl/Program";
3
3
  import { UTILS } from './utils';
4
4
  // REMEMBER!
@@ -468,7 +468,7 @@ export function drawnode_screen_wl_webgl2NoAtmos() {
468
468
  }`
469
469
  });
470
470
  }
471
- export function drawnode_screen_wl_webgl2Atmos() {
471
+ export function drawnode_screen_wl_webgl2Atmos(atmosParams) {
472
472
  return new Program("drawnode_screen_wl", {
473
473
  uniforms: {
474
474
  projectionMatrix: "mat4",
@@ -591,7 +591,7 @@ export function drawnode_screen_wl_webgl2Atmos() {
591
591
 
592
592
  ${DEF_BLEND}
593
593
 
594
- ${atmos.COMMON}
594
+ ${COMMON(atmosParams)}
595
595
 
596
596
  vec3 transmittanceFromTexture(float height, float angle)
597
597
  {
@@ -619,14 +619,21 @@ export function drawnode_screen_wl_webgl2Atmos() {
619
619
  }
620
620
 
621
621
  void atmosGroundColor(out vec4 fragColor, in vec3 normal)
622
- {
622
+ {
623
+ vec3 cameraPosition = cameraPosition;
624
+
625
+ if(length(cameraPosition * SPHERE_TO_ELLIPSOID_SCALE) < BOTTOM_RADIUS + 1.0){
626
+ cameraPosition = normalize(cameraPosition * SPHERE_TO_ELLIPSOID_SCALE) * (BOTTOM_RADIUS + 1.0) / SPHERE_TO_ELLIPSOID_SCALE;
627
+ }
628
+
623
629
  vec3 rayDirection = normalize(v_vertex - cameraPosition);
624
630
  vec3 lightDir = normalize(sunPos);
625
631
 
626
632
  rayDirection = normalize(rayDirection * SPHERE_TO_ELLIPSOID_SCALE);
627
633
  vec3 camPos = cameraPosition * SPHERE_TO_ELLIPSOID_SCALE;
628
634
  lightDir = normalize(lightDir * SPHERE_TO_ELLIPSOID_SCALE);
629
-
635
+
636
+
630
637
  vec3 light = vec3(0.0);
631
638
  vec3 transmittanceFromCameraToSpace = vec3(1.0);
632
639
  float offset = 0.0;
@@ -656,13 +663,9 @@ export function drawnode_screen_wl_webgl2Atmos() {
656
663
  float distanceToGround = 0.0;
657
664
 
658
665
  bool hitGround = intersectSphere(camPos, rayDirection, BOTTOM_RADIUS, distanceToGround) && distanceToGround > 0.0;
659
-
660
- // Fix black dots on the edge of atmosphere
661
- // if(camHeight < 700000.0 || !hitGround)
662
- // {
663
- // distanceToGround = distance(camPos, v_vertex * SPHERE_TO_ELLIPSOID_SCALE);
664
- // }
665
-
666
+ //intersectSphere(camPos, rayDirection, BOTTOM_RADIUS, distanceToGround);
667
+
668
+
666
669
  if(length(v_vertex * SPHERE_TO_ELLIPSOID_SCALE) > BOTTOM_RADIUS){
667
670
  distanceToGround = distance(camPos, v_vertex * SPHERE_TO_ELLIPSOID_SCALE);
668
671
  }
@@ -18,7 +18,7 @@ class Slider extends View {
18
18
  })
19
19
  });
20
20
  this._onResize = () => {
21
- this._setOffset(this._value * this.$panel.clientWidth / (this._max - this._min));
21
+ this._setOffset((this._value - this._min) * this.$panel.clientWidth / (this._max - this._min));
22
22
  };
23
23
  this._onMouseWheel = (e) => {
24
24
  //@ts-ignore
@@ -57,7 +57,7 @@ class Slider extends View {
57
57
  let clientX = clamp(e.clientX, rect.left, rect.right);
58
58
  let dx = this._startPosX - clientX;
59
59
  this._startPosX = clientX;
60
- this.value = (this.$pointer.offsetLeft - dx) * (this._max - this._min) / this.$panel.clientWidth;
60
+ this.value = this._value - dx * (this._max - this._min) / this.$panel.clientWidth;
61
61
  };
62
62
  this._onMouseUp = () => {
63
63
  document.removeEventListener("mouseup", this._onMouseUp);
@@ -95,7 +95,7 @@ class Slider extends View {
95
95
  if (val !== this._value) {
96
96
  this._value = clamp(val, this._min, this._max);
97
97
  this.$input.value = this._value.toString();
98
- this._setOffset(this._value * this.$panel.clientWidth / (this._max - this._min));
98
+ this._setOffset((this._value - this._min) * this.$panel.clientWidth / (this._max - this._min));
99
99
  this.events.dispatch(this.events.change, this._value, this);
100
100
  }
101
101
  }
@@ -56,6 +56,7 @@ export interface IDefaultTextureParams {
56
56
  * @param {Array.<string>} [params.extensions] - Additional WebGL extension list. Available by default: EXT_texture_filter_anisotropic.
57
57
  */
58
58
  declare class Handler {
59
+ protected _throttledDrawFrame: () => void;
59
60
  /**
60
61
  * Events.
61
62
  * @public
@@ -158,6 +159,7 @@ declare class Handler {
158
159
  resizeObserver?: ResizeObserver;
159
160
  protected _requestAnimationFrameId: number;
160
161
  constructor(canvasTarget: string | HTMLCanvasElement | undefined, params?: IHandlerParameters);
162
+ set frameDelay(delay: number);
161
163
  isInitialized(): boolean;
162
164
  protected _createCanvas(): void;
163
165
  /**
@@ -431,7 +433,7 @@ declare class Handler {
431
433
  * Draw single frame.
432
434
  * @public
433
435
  */
434
- drawFrame(): void;
436
+ drawFrame: () => void;
435
437
  /**
436
438
  * Clearing gl frame.
437
439
  * @public
@@ -6,6 +6,7 @@ import { ImageCanvas } from "../ImageCanvas";
6
6
  import { Vec2 } from "../math/Vec2";
7
7
  import { ProgramController } from "./ProgramController";
8
8
  import { Stack } from "../Stack";
9
+ import { throttle } from "../utils/shared";
9
10
  const vendorPrefixes = ["", "WEBKIT_", "MOZ_"];
10
11
  const CONTEXT_TYPE = ["webgl2", "webgl"];
11
12
  // Maximal mipmap levels
@@ -25,7 +26,35 @@ class Handler {
25
26
  constructor(canvasTarget, params = {}) {
26
27
  this.framebufferStack = new Stack();
27
28
  this._requestAnimationFrameId = 0;
29
+ /**
30
+ * Draw single frame.
31
+ * @public
32
+ */
33
+ this.drawFrame = () => {
34
+ /** Calculating frame time */
35
+ let now = window.performance.now();
36
+ this.deltaTime = now - this._lastAnimationFrameTime;
37
+ this._lastAnimationFrameTime = now;
38
+ this.defaultClock.tick(this.deltaTime);
39
+ for (let i = 0; i < this._clocks.length; i++) {
40
+ this._clocks[i].tick(this.deltaTime);
41
+ }
42
+ /** Canvas resize checking */
43
+ let canvas = this.canvas;
44
+ if (Math.floor(canvas.clientWidth * this._params.pixelRatio) !== canvas.width || Math.floor(canvas.clientHeight * this._params.pixelRatio) !== canvas.height) {
45
+ if (canvas.clientWidth === 0 || canvas.clientHeight === 0) {
46
+ this.stop();
47
+ }
48
+ else if (!document.hidden) {
49
+ this.start();
50
+ this.setSize(canvas.clientWidth, canvas.clientHeight);
51
+ }
52
+ }
53
+ /** Draw frame */
54
+ this._frameCallback();
55
+ };
28
56
  this.events = createEvents(["visibilitychange", "resize"]);
57
+ this._throttledDrawFrame = this.drawFrame;
29
58
  this.defaultClock = new Clock();
30
59
  this._clocks = [];
31
60
  this.deltaTime = 0;
@@ -69,6 +98,14 @@ class Handler {
69
98
  this.initialize();
70
99
  }
71
100
  }
101
+ set frameDelay(delay) {
102
+ if (delay === 0) {
103
+ this._throttledDrawFrame = this.drawFrame;
104
+ }
105
+ else {
106
+ this._throttledDrawFrame = throttle(this.drawFrame, delay);
107
+ }
108
+ }
72
109
  isInitialized() {
73
110
  return this._initialized;
74
111
  }
@@ -786,33 +823,6 @@ class Handler {
786
823
  let c = this.canvas;
787
824
  return c ? new Vec2(Math.round(c.width * 0.5), Math.round(c.height * 0.5)) : new Vec2();
788
825
  }
789
- /**
790
- * Draw single frame.
791
- * @public
792
- */
793
- drawFrame() {
794
- /** Calculating frame time */
795
- let now = window.performance.now();
796
- this.deltaTime = now - this._lastAnimationFrameTime;
797
- this._lastAnimationFrameTime = now;
798
- this.defaultClock.tick(this.deltaTime);
799
- for (let i = 0; i < this._clocks.length; i++) {
800
- this._clocks[i].tick(this.deltaTime);
801
- }
802
- /** Canvas resize checking */
803
- let canvas = this.canvas;
804
- if (Math.floor(canvas.clientWidth * this._params.pixelRatio) !== canvas.width || Math.floor(canvas.clientHeight * this._params.pixelRatio) !== canvas.height) {
805
- if (canvas.clientWidth === 0 || canvas.clientHeight === 0) {
806
- this.stop();
807
- }
808
- else if (!document.hidden) {
809
- this.start();
810
- this.setSize(canvas.clientWidth, canvas.clientHeight);
811
- }
812
- }
813
- /** Draw frame */
814
- this._frameCallback();
815
- }
816
826
  /**
817
827
  * Clearing gl frame.
818
828
  * @public
@@ -853,7 +863,7 @@ class Handler {
853
863
  */
854
864
  _animationFrameCallback() {
855
865
  this._requestAnimationFrameId = window.requestAnimationFrame(() => {
856
- this.drawFrame();
866
+ this._throttledDrawFrame();
857
867
  this._requestAnimationFrameId && this._animationFrameCallback();
858
868
  });
859
869
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openglobus/og",
3
- "version": "0.20.1",
3
+ "version": "0.20.3",
4
4
  "description": "[openglobus](https://www.openglobus.org/) is a javascript/typescript library designed to display interactive 3d maps and planets with map tiles, imagery and vector data, markers, and 3D objects. It uses the WebGL technology, open source, and completely free.",
5
5
  "directories": {
6
6
  "example": "./sandbox"
@@ -44,8 +44,8 @@
44
44
  "@rollup/plugin-terser": "^0.4.4",
45
45
  "@rollup/plugin-typescript": "^11.1.6",
46
46
  "@types/jest": "^29.5.12",
47
- "@typescript-eslint/eslint-plugin": "^7.10.0",
48
- "@typescript-eslint/parser": "^7.10.0",
47
+ "@typescript-eslint/eslint-plugin": "^7.14.1",
48
+ "@typescript-eslint/parser": "^7.14.1",
49
49
  "clean-jsdoc-theme": "^4.3.0",
50
50
  "eslint": "^8.57.0",
51
51
  "jest": "^29.7.0",
@@ -53,15 +53,15 @@
53
53
  "jest-environment-jsdom": "^29.7.0",
54
54
  "jsdoc": "^4.0.3",
55
55
  "jsdoc-babel": "^0.5.0",
56
- "lint-staged": "^15.2.4",
56
+ "lint-staged": "^15.2.7",
57
57
  "local-web-server": "^5.3.3",
58
- "postcss": "^8.4.38",
59
- "prettier": "^3.2.5",
58
+ "postcss": "^8.4.39",
59
+ "prettier": "^3.3.2",
60
60
  "rollup": "^4.18.0",
61
61
  "rollup-plugin-copy": "^3.5.0",
62
62
  "rollup-plugin-postcss": "^4.0.2",
63
- "ts-jest": "^29.1.3",
64
- "typescript": "^5.4.5"
63
+ "ts-jest": "^29.1.5",
64
+ "typescript": "^5.5.2"
65
65
  },
66
66
  "lint-staged": {
67
67
  "*.{js,ts}": [