JSFiddle - React, Tailwind, and code Playground
HTML
<script src="https://threejs.org/build/three.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script>
// custom blend shader
THREE.AdditiveBlendShader = {
uniforms: {
"tDiffuse1": { value: null },
"tDiffuse2": { value: null }
},
vertexShader: [
"varying vec2 vUv;",
"void main() {",
"vUv = uv;",
"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
"}"
].join("\n"),
fragmentShader: [
"uniform sampler2D tDiffuse1;",
"uniform sampler2D tDiffuse2;",
"varying vec2 vUv;",
"void main() {",
"vec4 texel1 = texture2D( tDiffuse1, vUv );",
"vec4 texel2 = texture2D( tDiffuse2, vUv );",
"gl_FragColor = texel1 + texel2;",
"}"
].join("\n")
};
//
THREE.AtmoShader = {
uniforms: {
"c": { value: 0.5 },
"p": { value: 4 }
},
vertexShader: [
"varying vec3 vNormal;",
"void main() {",
"vNormal = normalize( normalMatrix * normal );",
"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
"}"
].join("\n"),
fragmentShader: [
"uniform float c;",
"uniform float p;",
"varying vec3 vNormal;",
"void main() {",
"float intensity = pow( c - dot( vNormal, vec3( 0.0, 0.0, 1.0 ) ), p ); ",
"gl_FragColor = vec4( 1.0, 1.0, 1.0, 1.0 ) * intensity;",
"}"
].join("\n")
};
</script>
JavaScript
var scene, sceneAtmo, sceneFX, camera, cameraFX, renderer;
var renderTarget1, renderTarget2;
init();
animate();
function init() {
scene = new THREE.Scene();
sceneAtmo = new THREE.Scene();
// background
var background = new THREE.CubeTextureLoader()
.setPath( 'https://threejs.org/examples/textures/cube/MilkyWay/' )
.load( [ 'dark-s_px.jpg', 'dark-s_nx.jpg', 'dark-s_py.jpg', 'dark-s_ny.jpg', 'dark-s_pz.jpg', 'dark-s_nz.jpg' ] );
background.format = THREE.RGBFormat;
scene.background = background;
// camera
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.set( 0, 150, 400 );
camera.lookAt( scene.position );
scene.add( camera );
// moon mesh
var texture = new THREE.TextureLoader().load( 'https://i.imgur.com/rmMgEG5.jpg' );
var geometryMoon = new THREE.SphereBufferGeometry( 100, 32, 16 );
var materialMoon = new THREE.MeshBasicMaterial( { map: texture } );
var moon = new THREE.Mesh( geometryMoon, materialMoon );
scene.add( moon );
//
var materialAtmo = new THREE.ShaderMaterial( {
uniforms: THREE.UniformsUtils.clone( THREE.AtmoShader.uniforms ),
vertexShader: THREE.AtmoShader.vertexShader,
fragmentShader: THREE.AtmoShader.fragmentShader
} );
var meshGlow = new THREE.Mesh( geometryMoon, materialAtmo );
meshGlow.scale.set( 1.2, 1.2, 1.2 );
// atmosphere should provide light from behind the sphere, so only render the back side
meshGlow.material.side = THREE.BackSide;
sceneAtmo.add( meshGlow );
// clone earlier sphere geometry to block light correctly
// and make it a bit smaller so that light blends into surface a bit
var materialBlack = new THREE.MeshBasicMaterial( { color: 0x000000 } );
var meshBlack = new THREE.Mesh( geometryMoon, materialBlack );
sceneAtmo.add( meshBlack );
//
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth,...