react-native-cesium 1.2.7 → 1.2.9
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/android/CMakeLists.txt +24 -9
- package/android/src/main/cpp/CesiumBridgeAndroid.cpp +16 -3
- package/android/src/main/cpp/CesiumBridgeAndroid.h +2 -1
- package/android/src/main/cpp/vulkan/VulkanBackend.cpp +166 -67
- package/android/src/main/cpp/vulkan/VulkanBackend.h +60 -19
- package/android/src/main/cpp/vulkan/shaders/terrain.frag +36 -8
- package/android/src/main/java/com/margelo/nitro/reactnativecesium/CesiumBridgeJNI.kt +4 -3
- package/android/src/main/java/com/margelo/nitro/reactnativecesium/HybridCesiumView.kt +26 -7
- package/cpp/engine/CesiumEngine.cpp +487 -34
- package/cpp/engine/CesiumEngine.hpp +73 -4
- package/cpp/engine/GlobeCamera.cpp +0 -1
- package/cpp/renderer/RenderTypes.hpp +13 -0
- package/ios/CesiumBridge.h +14 -3
- package/ios/CesiumBridge.mm +72 -5
- package/ios/HybridCesiumView.swift +30 -13
- package/ios/metal/MetalBackend.h +22 -2
- package/ios/metal/MetalBackend.mm +248 -93
- package/lib/typescript/src/specs/cesium-view.nitro.d.ts +11 -3
- package/lib/typescript/src/specs/cesium-view.nitro.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/specs/cesium-view.nitro.ts +17 -3
|
@@ -27,7 +27,7 @@ layout(push_constant) uniform PC {
|
|
|
27
27
|
float translationY; // byte 112
|
|
28
28
|
float scaleX; // byte 116
|
|
29
29
|
float scaleY; // byte 120
|
|
30
|
-
float
|
|
30
|
+
float lodFade; // byte 124
|
|
31
31
|
} pc;
|
|
32
32
|
|
|
33
33
|
layout(set = 1, binding = 0) uniform sampler2D overlayTex;
|
|
@@ -56,6 +56,20 @@ vec3 hypsometricColor(float alt, float steep) {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
void main() {
|
|
59
|
+
#ifdef TERRAIN_DITHER
|
|
60
|
+
// ── LOD transition dither (IGN / Jorge Jimenez) ─────────────────────────────
|
|
61
|
+
// Compiled only into the dither pipeline so the solid pipeline keeps the GPU's
|
|
62
|
+
// early-Z optimisation enabled at full speed. Interleaved Gradient Noise
|
|
63
|
+
// produces a per-pixel threshold approximating blue noise without a texture
|
|
64
|
+
// lookup; the pattern is far less perceptible than Bayer 4×4.
|
|
65
|
+
// lodFade=1 → all pass; lodFade=0 → all discard.
|
|
66
|
+
{
|
|
67
|
+
float ign = fract(52.9829189 *
|
|
68
|
+
fract(0.06711056 * gl_FragCoord.x + 0.00583715 * gl_FragCoord.y));
|
|
69
|
+
if (pc.lodFade <= ign) { discard; }
|
|
70
|
+
}
|
|
71
|
+
#endif
|
|
72
|
+
|
|
59
73
|
// ── World position (RTC reconstruction) ────────────────────────────────────
|
|
60
74
|
// wp = tile-local pos + RTC centre (both float32 at ~6.4 Mm scale).
|
|
61
75
|
// ~0.75 m ULP — far better than eyeRelPos + cameraEcef at altitude.
|
|
@@ -86,10 +100,16 @@ void main() {
|
|
|
86
100
|
vec2 texUV = fragUV * vec2(pc.scaleX, pc.scaleY)
|
|
87
101
|
+ vec2(pc.translationX, pc.translationY);
|
|
88
102
|
texUV.y = 1.0 - texUV.y;
|
|
103
|
+
// Return the overlay RGBA directly — preserves any transparency at tile
|
|
104
|
+
// edges and avoids incorrectly stamping the coastline outline on top of
|
|
105
|
+
// satellite imagery. The dither discard above fires before this return,
|
|
106
|
+
// so LOD fading still works correctly on overlay tiles.
|
|
89
107
|
outColor = texture(overlayTex, texUV);
|
|
90
108
|
return;
|
|
91
109
|
}
|
|
92
110
|
|
|
111
|
+
vec3 lit;
|
|
112
|
+
{
|
|
93
113
|
// ── Hypsometric path ──────────────────────────────────────────────────────
|
|
94
114
|
vec3 dpdx_v = dFdx(localPos), dpdy_v = dFdy(localPos);
|
|
95
115
|
vec3 rawN = cross(dpdx_v, dpdy_v);
|
|
@@ -115,24 +135,32 @@ void main() {
|
|
|
115
135
|
vec3 oceanBlue = vec3(0.04, 0.26, 0.52);
|
|
116
136
|
float landAlt = (pc.hasWaterMask != 0u) ? max(rawAlt, 0.0) : rawAlt;
|
|
117
137
|
vec3 landLit = hypsometricColor(landAlt, steep) * (amb + diff * 0.72 + rim);
|
|
118
|
-
|
|
138
|
+
lit = mix(landLit, oceanBlue, waterVal);
|
|
119
139
|
|
|
120
140
|
// 1 km lat/lon grid — fades when sub-pixel to suppress Moiré.
|
|
121
141
|
const float gridLat = 1000.0 / 6371000.0;
|
|
122
|
-
|
|
142
|
+
// cosLat from pxy (already computed above for the Bowring iteration) —
|
|
143
|
+
// avoids a second cos() transcendental. pxy/a_e is the geocentric cosine;
|
|
144
|
+
// the ~0.2 % geodetic difference is imperceptible at grid-line scale.
|
|
145
|
+
float cosLat = max(pxy / 6378137.0, 0.001);
|
|
123
146
|
float gridLon = gridLat / cosLat;
|
|
124
147
|
float wLat = fwidth(lat) * 1.5, wLon = fwidth(lon) * 1.5;
|
|
125
148
|
float gridVis = clamp(min(gridLat / max(wLat, 1e-9),
|
|
126
149
|
gridLon / max(wLon, 1e-9)), 0.0, 1.0);
|
|
127
|
-
|
|
128
|
-
|
|
150
|
+
// GLSL mod() is floor-based (always non-negative) — equivalent to the
|
|
151
|
+
// original floor dance but one instruction cleaner.
|
|
152
|
+
float latCell = mod(lat, gridLat);
|
|
153
|
+
float lonCell = mod(lon, gridLon);
|
|
129
154
|
float dLat = min(latCell, gridLat - latCell);
|
|
130
155
|
float dLon = min(lonCell, gridLon - lonCell);
|
|
131
|
-
|
|
132
|
-
|
|
156
|
+
// Linear ramp instead of smoothstep cubic — visually identical for a
|
|
157
|
+
// 1.5 px anti-aliased line, saves two multiplies per component.
|
|
158
|
+
float gridA = max(clamp(1.0 - dLat / max(wLat, 1e-9), 0.0, 1.0),
|
|
159
|
+
clamp(1.0 - dLon / max(wLon, 1e-9), 0.0, 1.0)) * gridVis;
|
|
133
160
|
lit = mix(lit, vec3(0.15, 0.15, 0.15), gridA * 0.6);
|
|
161
|
+
} // end hypsometric block
|
|
134
162
|
|
|
135
|
-
// Coastline outline from water mask.
|
|
163
|
+
// Coastline outline from water mask (hypsometric path only — overlay returns above).
|
|
136
164
|
if (pc.isEllipsoidFallback == 0u) {
|
|
137
165
|
float dWater = fwidth(waterVal);
|
|
138
166
|
float coastPx = abs(waterVal - 0.5) / max(dWater * 0.5, 0.01);
|
|
@@ -9,8 +9,9 @@ import android.view.Surface
|
|
|
9
9
|
class CesiumBridgeJNI {
|
|
10
10
|
private var nativePtr: Long = nativeCreate()
|
|
11
11
|
|
|
12
|
-
fun init(surface: Surface, width: Int, height: Int, cacheDir: String, cacertPath: String
|
|
13
|
-
|
|
12
|
+
fun init(surface: Surface, width: Int, height: Int, cacheDir: String, cacertPath: String,
|
|
13
|
+
ionAccessToken: String = "", ionAssetId: Long = 1L) {
|
|
14
|
+
nativeInit(nativePtr, surface, width, height, cacheDir, cacertPath, ionAccessToken, ionAssetId)
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
fun shutdown() = nativeShutdown(nativePtr)
|
|
@@ -98,7 +99,7 @@ class CesiumBridgeJNI {
|
|
|
98
99
|
fun setMinAltitudeAboveTerrain(v: Float) = nativeSetMinAltitudeAboveTerrain(nativePtr, v)
|
|
99
100
|
|
|
100
101
|
private external fun nativeCreate(): Long
|
|
101
|
-
private external fun nativeInit(ptr: Long, surface: Surface, w: Int, h: Int, cacheDir: String, cacertPath: String)
|
|
102
|
+
private external fun nativeInit(ptr: Long, surface: Surface, w: Int, h: Int, cacheDir: String, cacertPath: String, ionAccessToken: String, ionAssetId: Long)
|
|
102
103
|
private external fun nativeShutdown(ptr: Long)
|
|
103
104
|
private external fun nativeDestroy(ptr: Long)
|
|
104
105
|
private external fun nativeResize(ptr: Long, w: Int, h: Int)
|
|
@@ -29,6 +29,10 @@ class HybridCesiumView(private val appContext: Context) : HybridCesiumViewSpec()
|
|
|
29
29
|
private var idleProbeAccumulator = 0.0
|
|
30
30
|
private var renderLoopActive = false
|
|
31
31
|
private val renderInFlight = AtomicBoolean(false)
|
|
32
|
+
// Last System.nanoTime() when tilesLoading was > 0. Used to keep the render
|
|
33
|
+
// loop at full speed for a grace period after loading finishes — prevents the
|
|
34
|
+
// cascade of idle gaps between LOD refinement phases. 0 = not yet seen.
|
|
35
|
+
private var lastLoadingTimeNs: Long = 0L
|
|
32
36
|
|
|
33
37
|
/// Set in `surfaceDestroyed` before any teardown work begins. Render-thread
|
|
34
38
|
/// callbacks and choreographer frame ticks check this flag and bail out so
|
|
@@ -199,11 +203,20 @@ class HybridCesiumView(private val appContext: Context) : HybridCesiumViewSpec()
|
|
|
199
203
|
return
|
|
200
204
|
}
|
|
201
205
|
|
|
202
|
-
|
|
206
|
+
// Post-loading grace period: keep the loop at full speed for 2 seconds
|
|
207
|
+
// after the last non-zero loading frame so LOD transitions complete quickly
|
|
208
|
+
// and the next refinement level is discovered without a multi-second idle gap.
|
|
209
|
+
val nowNs = System.nanoTime()
|
|
210
|
+
val inGracePeriod = lastLoadingTimeNs > 0L &&
|
|
211
|
+
(nowNs - lastLoadingTimeNs) < 2_000_000_000L
|
|
212
|
+
|
|
213
|
+
val shouldRender = b.shouldRenderNextFrame() || inGracePeriod
|
|
203
214
|
val nextImmediate: Boolean
|
|
204
215
|
if (shouldRender) {
|
|
205
216
|
idleProbeAccumulator = 0.0
|
|
206
217
|
b.renderFrame(nowSeconds)
|
|
218
|
+
// Stamp after renderFrame so the freshly-updated tile counts are used.
|
|
219
|
+
if (b.getMetricsTilesLoading() > 0) lastLoadingTimeNs = nowNs
|
|
207
220
|
nextImmediate = true
|
|
208
221
|
} else {
|
|
209
222
|
// Approximate dt for the idle probe; not used for motion.
|
|
@@ -273,7 +286,12 @@ class HybridCesiumView(private val appContext: Context) : HybridCesiumViewSpec()
|
|
|
273
286
|
val cacertPath = extractCacert()
|
|
274
287
|
rh.post {
|
|
275
288
|
val b = CesiumBridgeJNI()
|
|
276
|
-
|
|
289
|
+
// sqliteCacheMaxRows and taskProcessorThreads are consumed once inside
|
|
290
|
+
// CesiumEngine::initialize() (SqliteCache + TaskProcessor sizing).
|
|
291
|
+
// They must be seeded into config_ before init() calls buildEngine().
|
|
292
|
+
sqliteCacheMaxRows?.let { b.setSqliteCacheMaxRows(it.toInt()) }
|
|
293
|
+
taskProcessorThreads?.let { b.setTaskProcessorThreads(it.toInt()) }
|
|
294
|
+
b.init(surface, w, h, cacheDir, cacertPath, ionAccessToken, ionAssetId.toLong())
|
|
277
295
|
bridge = b
|
|
278
296
|
syncBridgePropsOnRenderThread(b)
|
|
279
297
|
|
|
@@ -300,12 +318,13 @@ class HybridCesiumView(private val appContext: Context) : HybridCesiumViewSpec()
|
|
|
300
318
|
b.setViewCorrection(q.w, q.x, q.y, q.z); pendingViewCorrection = null
|
|
301
319
|
}
|
|
302
320
|
|
|
321
|
+
// Ion credentials were seeded at init() time for parallel tileset
|
|
322
|
+
// fetch; call updateIonAccessToken here only as a hot-reload safety
|
|
323
|
+
// net in case the token changed between bridge teardown and rebuild.
|
|
303
324
|
if (ionAccessToken.isNotEmpty()) {
|
|
304
325
|
b.updateIonAccessToken(ionAccessToken, ionAssetId.toLong())
|
|
305
326
|
}
|
|
306
|
-
|
|
307
|
-
b.updateImageryAssetId(ionImageryAssetId.toLong())
|
|
308
|
-
}
|
|
327
|
+
b.updateImageryAssetId(ionImageryAssetId.toLong())
|
|
309
328
|
b.setMsaa(msaaSampleCount.toInt())
|
|
310
329
|
|
|
311
330
|
pushRateCaps()
|
|
@@ -497,8 +516,8 @@ class HybridCesiumView(private val appContext: Context) : HybridCesiumViewSpec()
|
|
|
497
516
|
culledScreenSpaceError?.let { b.setCulledScreenSpaceError(it) }
|
|
498
517
|
enableLodTransitionPeriod?.let { b.setEnableLodTransitionPeriod(it) }
|
|
499
518
|
lodTransitionLength?.let { b.setLodTransitionLength(it) }
|
|
500
|
-
sqliteCacheMaxRows
|
|
501
|
-
|
|
519
|
+
// sqliteCacheMaxRows and taskProcessorThreads are applied before init() in
|
|
520
|
+
// surfaceCreated; calling them here (after buildEngine) has no effect.
|
|
502
521
|
minAltitudeAboveTerrain?.let { b.setMinAltitudeAboveTerrain(it.toFloat()) }
|
|
503
522
|
}
|
|
504
523
|
|