Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Examples: Add TSL Earth #29003

Merged
merged 1 commit into from
Jul 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/files.json
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,7 @@
"webgpu_textures_partialupdate",
"webgpu_tsl_coffee_smoke",
"webgpu_tsl_compute_attractors_particles",
"webgpu_tsl_earth",
"webgpu_tsl_editor",
"webgpu_tsl_galaxy",
"webgpu_tsl_raging_sea",
Expand Down
Binary file added examples/screenshots/webgpu_tsl_earth.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/textures/planets/earth_day_4096.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/textures/planets/earth_night_4096.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
203 changes: 203 additions & 0 deletions examples/webgpu_tsl_earth.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgpu - earth</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<link type="text/css" rel="stylesheet" href="main.css">
</head>
<body>

<div id="info">
<a href="https://threejs.org" target="_blank" rel="noopener">three.js webgpu</a> - earth
<br>
Based on <a href="https://threejs-journey.com/lessons/earth-shaders" target="_blank" rel="noopener">Three.js Journey</a> lesson
<br>
Earth textures from <a href="https://www.solarsystemscope.com/textures/" target="_blank" rel="noopener">Solar System Scope</a> (resized and merged)
</div>

<script type="importmap">
{
"imports": {
"three": "../build/three.webgpu.js",
"three/tsl": "../build/three.webgpu.js",
"three/addons/": "./jsm/"
}
}
</script>

<script type="module">

import * as THREE from 'three';
import { step, normalWorld, output, texture, vec3, vec4, normalize, positionWorld, cameraPosition, color, uniform, mix, uv, max } from 'three/tsl';

import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { GUI } from 'three/addons/libs/lil-gui.module.min.js';

let camera, scene, renderer, controls, globe, clock;

init();

function init() {

clock = new THREE.Clock();

camera = new THREE.PerspectiveCamera( 25, window.innerWidth / window.innerHeight, 0.1, 100 );
camera.position.set( 4.5, 2, 3 );

scene = new THREE.Scene();

// sun

const sun = new THREE.DirectionalLight( '#ffffff', 2 );
sun.position.set( 0, 0, 3 );
scene.add( sun );

// uniforms

const atmosphereDayColor = uniform( color( '#4db2ff' ) );
const atmosphereTwilightColor = uniform( color( '#bc490b' ) );
const roughnessLow = uniform( 0.25 );
const roughnessHigh = uniform( 0.35 );

// textures

const textureLoader = new THREE.TextureLoader();

const dayTexture = textureLoader.load( './textures/planets/earth_day_4096.jpg' );
dayTexture.colorSpace = THREE.SRGBColorSpace;
dayTexture.anisotropy = 8;

const nightTexture = textureLoader.load( './textures/planets/earth_night_4096.jpg' );
nightTexture.colorSpace = THREE.SRGBColorSpace;
nightTexture.anisotropy = 8;

const bumpRoughnessCloudsTexture = textureLoader.load( './textures/planets/earth_bump_roughness_clouds_4096.jpg' );
bumpRoughnessCloudsTexture.anisotropy = 8;

// fresnel

const viewDirection = positionWorld.sub( cameraPosition ).normalize();
const fresnel = viewDirection.dot( normalWorld ).abs().oneMinus().toVar();

// sun orientation

const sunOrientation = normalWorld.dot( normalize( sun.position ) ).toVar();

// atmosphere color

const atmosphereColor = mix( atmosphereTwilightColor, atmosphereDayColor, sunOrientation.smoothstep( - 0.25, 0.75 ) );

// globe

const globeMaterial = new THREE.MeshStandardNodeMaterial();

const cloudsStrength = texture( bumpRoughnessCloudsTexture, uv() ).b.smoothstep( 0.2, 1 );

globeMaterial.colorNode = mix( texture( dayTexture ), vec3( 1 ), cloudsStrength.mul( 2 ) );

const roughness = max(
texture( bumpRoughnessCloudsTexture ).g,
step( 0.01, cloudsStrength )
);
globeMaterial.roughnessNode = roughness.remap( 0, 1, roughnessLow, roughnessHigh );

const night = texture( nightTexture );
const dayStrength = sunOrientation.smoothstep( - 0.25, 0.5 );

const atmosphereDayStrength = sunOrientation.smoothstep( - 0.5, 1 );
const atmosphereMix = atmosphereDayStrength.mul( fresnel.pow( 2 ) ).clamp( 0, 1 );

let finalOutput = mix( night.rgb, output.rgb, dayStrength );
finalOutput = mix( finalOutput, atmosphereColor, atmosphereMix );

globeMaterial.outputNode = vec4( finalOutput, output.a );

const bumpElevation = max(
texture( bumpRoughnessCloudsTexture ).r,
cloudsStrength
);
globeMaterial.normalNode = bumpElevation.bumpMap();

const sphereGeometry = new THREE.SphereGeometry( 1, 64, 64 );
globe = new THREE.Mesh( sphereGeometry, globeMaterial );
scene.add( globe );

// atmosphere

const atmosphereMaterial = new THREE.MeshBasicNodeMaterial( { side: THREE.BackSide, transparent: true } );
let alpha = fresnel.remap( 0.73, 1, 1, 0 ).pow( 3 );
alpha = alpha.mul( sunOrientation.smoothstep( - 0.5, 1 ) );
atmosphereMaterial.outputNode = vec4( atmosphereColor, alpha );

const atmosphere = new THREE.Mesh( sphereGeometry, atmosphereMaterial );
atmosphere.scale.setScalar( 1.04 );
scene.add( atmosphere );

// debug

const gui = new GUI();

gui
.addColor( { color: atmosphereDayColor.value.getHex( THREE.SRGBColorSpace ) }, 'color' )
.onChange( ( value ) => {

atmosphereDayColor.value.set( value );

} )
.name( 'atmosphereDayColor' );

gui
.addColor( { color: atmosphereTwilightColor.value.getHex( THREE.SRGBColorSpace ) }, 'color' )
.onChange( ( value ) => {

atmosphereTwilightColor.value.set( value );

} )
.name( 'atmosphereTwilightColor' );

gui.add( roughnessLow, 'value', 0, 1, 0.001 ).name( 'roughnessLow' );
gui.add( roughnessHigh, 'value', 0, 1, 0.001 ).name( 'roughnessHigh' );

// renderer

renderer = new THREE.WebGPURenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setAnimationLoop( animate );
document.body.appendChild( renderer.domElement );

// controls

controls = new OrbitControls( camera, renderer.domElement );
controls.enableDamping = true;
controls.minDistance = 0.1;
controls.maxDistance = 50;

window.addEventListener( 'resize', onWindowResize );

}

function onWindowResize() {

camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();

renderer.setSize( window.innerWidth, window.innerHeight );

}

async function animate() {

const delta = clock.getDelta();
globe.rotation.y += delta * 0.025;

controls.update();

renderer.render( scene, camera );

}

</script>
</body>
</html>
1 change: 1 addition & 0 deletions test/e2e/puppeteer.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ const exceptionList = [
'webgpu_tsl_compute_attractors_particles',
'webgpu_tsl_raging_sea',
'webgpu_tsl_halftone',
'webgpu_tsl_earth',

// WebGPU idleTime and parseTime too low
'webgpu_compute_particles',
Expand Down