Skip to content

Commit

Permalink
Add atmosphere demo (#887)
Browse files Browse the repository at this point in the history
* Add initial code for atmosphere demo

* Get it working

* Add atmosphere demo
  • Loading branch information
gkjohnson authored Dec 21, 2024
1 parent 22d5584 commit a3732a2
Show file tree
Hide file tree
Showing 6 changed files with 605 additions and 178 deletions.
42 changes: 42 additions & 0 deletions example/r3f/atmosphere.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@react-three/fiber Cesium Ion</title>
<style>
html {
overflow: hidden;
font-family: Arial, Helvetica, sans-serif;
user-select: none;
}

#info {
position: absolute;
top: 0;
left: 0;
color: white;
width: 100%;
text-align: center;
padding: 5px;
pointer-events: none;
line-height: 1.5em;
z-index: 1;
}

#info a {
color: white;
pointer-events: all;
}
</style>
</head>
<body>
<div id="info">
Example using <a href="https://cloud.google.com/blog/products/maps-platform/create-immersive-3d-map-experiences-photorealistic-3d-tiles">Google Photorealistic Tiles</a> & <a href="https://github.com/takram-design-engineering/three-geospatial">@takram/three-geospatial</a> atmosphere effects.
<br/>
Google Cloud API Token required.
</div>
<div id="root"></div>
<script type="module" src="./atmosphere.jsx"></script>
</body>
</html>
183 changes: 183 additions & 0 deletions example/r3f/atmosphere.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
import { StrictMode, useRef } from 'react';
import { createRoot } from 'react-dom/client';

// TilesRenderer, controls and attribution imports
import {
TilesPlugin,
TilesRenderer,
TilesAttributionOverlay,
GlobeControls,
CompassGizmo,
CameraTransition,
} from '3d-tiles-renderer/r3f';

// Plugins
import {
GoogleCloudAuthPlugin,
UpdateOnChangePlugin,
TileCompressionPlugin,
TilesFadePlugin,
GLTFExtensionsPlugin,
} from '3d-tiles-renderer/plugins';
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';

// R3F, DREI and LEVA imports
import { Canvas, useFrame, useThree } from '@react-three/fiber';
import { useControls } from 'leva';
import { MathUtils } from 'three';

// Postprocessing
import { EffectComposer, SMAA, ToneMapping } from '@react-three/postprocessing';
import { EffectMaterial, ToneMappingMode } from 'postprocessing';

// Atmosphere
import {
AerialPerspective,
Atmosphere,
Sky,
Stars,
} from '@takram/three-atmosphere/r3f';
import { Dithering, LensFlare, } from '@takram/three-geospatial-effects/r3f';
import { toCreasedNormals } from 'three/examples/jsm/utils/BufferGeometryUtils.js';

// Plugin to generate creased normals for the tiles
class TileCreasedNormalsPlugin {

processTileModel( scene ) {

scene.traverse( c => {

if ( c.geometry ) {

c.geometry = toCreasedNormals( c.geometry, MathUtils.degToRad( 30 ) );

}

} );

}

}

const dracoLoader = new DRACOLoader().setDecoderPath( 'https://www.gstatic.com/draco/v1/decoders/' );
function App() {

const levaParams = {
apiToken: {
value: localStorage.getItem( 'google-token' ) || 'put-your-api-key-here',
onChange: ( value ) => localStorage.setItem( 'google-token', value ),
transient: false,
},
ortho: false,
};

// TODO: the renderer is rerendering due to floating point issues
// - see if we should trigger an invalidate on tiles plugin add and params change
// - see if we need to trigger a force update on plugin add for the UpdateOnChange plugin

const camera = useThree( ( { camera } ) => camera );
const gl = useThree( ( { gl } ) => gl );
gl.toneMappingExposure = 10;

const atmosphereRef = useRef( null );
const composerRef = useRef( null );
useFrame( () => {

atmosphereRef.current?.updateByDate( Date.now() );

const composer = composerRef.current;
if ( composer != null ) {

composer.passes.forEach( pass => {

if ( pass.fullscreenMaterial instanceof EffectMaterial ) {

pass.fullscreenMaterial.adoptCameraSettings( camera );

}

} );

}

} );

window.CAMERA = camera;

const { apiToken, ortho } = useControls( levaParams );
return (
<>
<TilesRenderer>
<TilesPlugin plugin={ GoogleCloudAuthPlugin } args={ { apiToken } } />
<TilesPlugin plugin={ GLTFExtensionsPlugin } dracoLoader={ dracoLoader } />
<TilesPlugin plugin={ TileCompressionPlugin } />
<TilesPlugin plugin={ UpdateOnChangePlugin } />
<TilesPlugin plugin={ TilesFadePlugin } />
<TilesPlugin plugin={ TileCreasedNormalsPlugin } />

{/* Controls */}
<GlobeControls enableDamping={ true } />

{/* Attributions */}
<TilesAttributionOverlay />

{/* Add compass gizmo */}
<CompassGizmo overrideRenderLoop={ false } />
</TilesRenderer>

{/* Atmosphere set up */}
<Atmosphere
ref={ atmosphereRef }
textures='https://takram-design-engineering.github.io/three-geospatial/atmosphere'
correctAltitude={ true }
photometric={ true }
>
{/* Background */}
<Sky />
<Stars data='https://takram-design-engineering.github.io/three-geospatial/atmosphere/stars.bin' />

{/* Atmosphere effects */}
<EffectComposer ref={ composerRef } multisampling={ 0 } enableNormalPass>
<AerialPerspective
sunIrradiance={ true }
skyIrradiance={ true }
transmittance={ true }
inscatter={ true }
correctGeometricError={ true }
irradianceScale={ 2 / Math.PI }
/>
<LensFlare />
<ToneMapping mode={ ToneMappingMode.AGX } />
<SMAA />
<Dithering />
</EffectComposer>
</Atmosphere>
<CameraTransition mode={ ortho ? 'orthographic' : 'perspective' }/>
</>
);

}

createRoot( document.getElementById( 'root' ) ).render(
<StrictMode>
<Canvas
frameloop='demand'
camera={ {
position: [ 0, 1.5 * 1e7, 0 ],
rotation: [ - Math.PI / 2, 0, Math.PI ],
} }
style={ {
width: '100%',
height: '100%',
position: 'absolute',
margin: 0,
left: 0,
top: 0,
} }
flat
>
<App />
</Canvas>
</StrictMode>,
);

4 changes: 0 additions & 4 deletions example/r3f/globe.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,6 @@ function App() {
>
<color attach="background" args={ [ 0x111111 ] } />

{/*
3D Tiles renderer tile set
Use a "key" property to ensure the tiles renderer gets recreated when the api token or asset change
*/}
<TilesRenderer group={ { rotation: [ - Math.PI / 2, 0, 0 ] } }>
<TilesPlugin plugin={ GoogleCloudAuthPlugin } args={ { apiToken } } />
<TilesPlugin plugin={ GLTFExtensionsPlugin } dracoLoader={ dracoLoader } />
Expand Down
Loading

0 comments on commit a3732a2

Please sign in to comment.