diff --git a/src/main.js b/src/main.js index 20bcc47..4fcac74 100644 --- a/src/main.js +++ b/src/main.js @@ -1,12 +1,15 @@ import * as THREE from 'three'; import { OrbitControls } from 'three/examples/jsm/Addons.js'; +import { EffectComposer } from 'three/examples/jsm/Addons.js'; +import { RenderPass } from 'three/examples/jsm/Addons.js'; +import { UnrealBloomPass } from 'three/examples/jsm/Addons.js'; import GUI from 'lil-gui'; import Stats from 'stats.js' import gsap from 'gsap'; // import sun -import { sun } from './sun.js'; +import { sun, sunMaterial, glowMaterial } from './sun.js'; // Import planets and orbital groups import { planetData, orbitalGroups } from './planets.js'; @@ -67,13 +70,13 @@ scene.background = environmentMap const sunlightColor = new THREE.Color(0xffe7ba); // Point light -const pointLight = new THREE.PointLight(sunlightColor, 6000, 1000, 2); +const pointLight = new THREE.PointLight(sunlightColor, 16000, 1000, 2); pointLight.position.copy(sun.position); sun.add(pointLight); // Ambient light -const ambientLight = new THREE.AmbientLight(0xffffff, 0.1); -// scene.add(ambientLight); +const ambientLight = new THREE.AmbientLight(0x404040, 0.1); +scene.add(ambientLight); /** * Camera @@ -85,19 +88,15 @@ scene.add(camera); /** * Renderer */ -// Renderer const renderer = new THREE.WebGLRenderer({ canvas: canvas, antialias: true, physicallyCorrectLights: true, powerPreference: "high-performance", + devicePixelRatio: Math.min(window.devicePixelRatio, 2) }); renderer.setSize(window.innerWidth, window.innerHeight); -renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)); -renderer.castShadow = true; -renderer.outputColorSpace = THREE.SRGBColorSpace; -renderer.toneMapping = THREE.ReinhardToneMapping; -renderer.toneMappingExposure = 2.3; + // Handle window resize for responsiveness window.addEventListener('resize', () => @@ -363,6 +362,18 @@ performanceFolder.close(); // Set camera position based on sun radius camera.position.set(-76, 28, sun.geometry.parameters.radius * 10); +// Effect Composer +const effectComposer = new EffectComposer(renderer); +effectComposer.addPass(new RenderPass(scene, camera)); + +// Unreal Bloom Pass +const bloomPass = new UnrealBloomPass(new THREE.Vector2(window.innerWidth, window.innerHeight), + 1.0, + 1.8, + 1.0 +); +effectComposer.addPass(bloomPass); + // Clock const clock = new THREE.Clock(); @@ -380,6 +391,13 @@ const tick = () => updatePlanets(elapsedTime, speed); updateMoons(elapsedTime, speed); + // Update time uniform + sunMaterial.uniforms.uTime.value = elapsedTime; + + // Update camera position uniform + sunMaterial.uniforms.uCameraPosition.value = camera.position; + glowMaterial.uniforms.uCameraPosition.value = camera.position; + // Update camera position to follow selected planet if (objectToFollow) { @@ -394,10 +412,11 @@ const tick = () => controls.update(); // Update shader time uniform - sun.material.uniforms.uTime.value = elapsedTime; + sunMaterial.uniforms.uTime.value = elapsedTime; // Update the renderer renderer.render(scene, camera); + // effectComposer.render(); // Call tick again on the next frame window.requestAnimationFrame(tick); diff --git a/src/shaders/glow.frag b/src/shaders/glow.frag deleted file mode 100644 index 5ad441a..0000000 --- a/src/shaders/glow.frag +++ /dev/null @@ -1,31 +0,0 @@ -precision mediump float; - -uniform float uInnerRadius; -uniform float uOuterRadius; -uniform float uGlowIntensity; -uniform vec2 uCenter; -uniform vec3 uSunColor; -uniform vec3 uGlowColor; -uniform vec3 uCameraPosition; - -varying vec3 vPosition; -varying vec3 vNormal; - - -void main() -{ - // Calculate the view direction - vec3 viewDirection = normalize(uCameraPosition - vPosition); - - // Calculate the Fresnel effect - float fresnel = pow(1.0 - dot(vNormal, viewDirection), 3.0); - - // // Calculate the glow effect based on distance - float dist = distance(gl_FragCoord.xy, uCenter.xy); - float glow = smoothstep(uInnerRadius, uOuterRadius, dist); - - // Blend the Fresnel effect with the glow effect - vec3 glowColor = mix(uSunColor * fresnel, vec3(0.0), glow); - - gl_FragColor = vec4(uGlowColor * glow * uGlowIntensity, glow); -} diff --git a/src/shaders/sun.frag b/src/shaders/sun.frag deleted file mode 100644 index 7dab2d0..0000000 --- a/src/shaders/sun.frag +++ /dev/null @@ -1,246 +0,0 @@ -/** -* @file sun.frag -* @brief Fragment shader for the sun -* @details This shader is used to render the sun. It uses a combination of fractal brownian motion and contrast to create a noise effect on the sun. The noise is then used to blend between two colours to create a dynamic sun texture. -* @author Mitch Campbell -* @note This shader is based on the work of Ian McEwan, Ashima Arts, and Stefan Gustavson. It is a modified version of the GLSL simplex noise functions by Stefan Gustavson. -*/ - -// -// Description : Array and textureless GLSL 2D/3D/4D simplex -// noise functions. -// Author : Ian McEwan, Ashima Arts. -// Maintainer : stegu -// Lastmod : 20110822 (ijm) -// License : Copyright (C) 2011 Ashima Arts. All rights reserved. -// Distributed under the MIT License. See LICENSE file. -// https://github.com/ashima/webgl-noise -// https://github.com/stegu/webgl-noise -// - -#define PI 3.14159265358979 - - -precision mediump float; - -uniform float uTime; -uniform float uScatteringIntensity; -uniform vec3 uCameraPosition; - -varying vec2 vUv; -varying vec3 vPosition; -varying vec3 vNormal; - -vec4 mod289(vec4 x) { - return x - floor(x * (1.0 / 289.0)) * 289.0; } - -float mod289(float x) { - return x - floor(x * (1.0 / 289.0)) * 289.0; } - -vec4 permute(vec4 x) { - return mod289(((x*34.0)+10.0)*x); -} - -float permute(float x) { - return mod289(((x*34.0)+10.0)*x); -} - -vec4 taylorInvSqrt(vec4 r) -{ - return 1.79284291400159 - 0.85373472095314 * r; -} - -float taylorInvSqrt(float r) -{ - return 1.79284291400159 - 0.85373472095314 * r; -} - -vec4 grad4(float j, vec4 ip) -{ - const vec4 ones = vec4(1.0, 1.0, 1.0, -1.0); - vec4 p,s; - - p.xyz = floor( fract (vec3(j) * ip.xyz) * 7.0) * ip.z - 1.0; - p.w = 1.5 - dot(abs(p.xyz), ones.xyz); - s = vec4(lessThan(p, vec4(0.0))); - p.xyz = p.xyz + (s.xyz*2.0 - 1.0) * s.www; - - return p; -} - -// (sqrt(5) - 1)/4 = F4, used once below -#define F4 0.309016994374947451 - -float snoise(vec4 v) -{ - const vec4 C = vec4( 0.138196601125011, // (5 - sqrt(5))/20 G4 - 0.276393202250021, // 2 * G4 - 0.414589803375032, // 3 * G4 - -0.447213595499958); // -1 + 4 * G4 - -// First corner - vec4 i = floor(v + dot(v, vec4(F4)) ); - vec4 x0 = v - i + dot(i, C.xxxx); - -// Other corners - -// Rank sorting originally contributed by Bill Licea-Kane, AMD (formerly ATI) - vec4 i0; - vec3 isX = step( x0.yzw, x0.xxx ); - vec3 isYZ = step( x0.zww, x0.yyz ); -// i0.x = dot( isX, vec3( 1.0 ) ); - i0.x = isX.x + isX.y + isX.z; - i0.yzw = 1.0 - isX; -// i0.y += dot( isYZ.xy, vec2( 1.0 ) ); - i0.y += isYZ.x + isYZ.y; - i0.zw += 1.0 - isYZ.xy; - i0.z += isYZ.z; - i0.w += 1.0 - isYZ.z; - - // i0 now contains the unique values 0,1,2,3 in each channel - vec4 i3 = clamp( i0, 0.0, 1.0 ); - vec4 i2 = clamp( i0-1.0, 0.0, 1.0 ); - vec4 i1 = clamp( i0-2.0, 0.0, 1.0 ); - - // x0 = x0 - 0.0 + 0.0 * C.xxxx - // x1 = x0 - i1 + 1.0 * C.xxxx - // x2 = x0 - i2 + 2.0 * C.xxxx - // x3 = x0 - i3 + 3.0 * C.xxxx - // x4 = x0 - 1.0 + 4.0 * C.xxxx - vec4 x1 = x0 - i1 + C.xxxx; - vec4 x2 = x0 - i2 + C.yyyy; - vec4 x3 = x0 - i3 + C.zzzz; - vec4 x4 = x0 + C.wwww; - -// Permutations - i = mod289(i); - float j0 = permute( permute( permute( permute(i.w) + i.z) + i.y) + i.x); - vec4 j1 = permute( permute( permute( permute ( - i.w + vec4(i1.w, i2.w, i3.w, 1.0 )) - + i.z + vec4(i1.z, i2.z, i3.z, 1.0 )) - + i.y + vec4(i1.y, i2.y, i3.y, 1.0 )) - + i.x + vec4(i1.x, i2.x, i3.x, 1.0 )); - -// Gradients: 7x7x6 points over a cube, mapped onto a 4-cross polytope -// 7*7*6 = 294, which is close to the ring size 17*17 = 289. - vec4 ip = vec4(1.0/294.0, 1.0/49.0, 1.0/7.0, 0.0) ; - - vec4 p0 = grad4(j0, ip); - vec4 p1 = grad4(j1.x, ip); - vec4 p2 = grad4(j1.y, ip); - vec4 p3 = grad4(j1.z, ip); - vec4 p4 = grad4(j1.w, ip); - -// Normalise gradients - vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3))); - p0 *= norm.x; - p1 *= norm.y; - p2 *= norm.z; - p3 *= norm.w; - p4 *= taylorInvSqrt(dot(p4,p4)); - -// Mix contributions from the five corners - vec3 m0 = max(0.6 - vec3(dot(x0,x0), dot(x1,x1), dot(x2,x2)), 0.0); - vec2 m1 = max(0.6 - vec2(dot(x3,x3), dot(x4,x4) ), 0.0); - m0 = m0 * m0; - m1 = m1 * m1; - return 49.0 * ( dot(m0*m0, vec3( dot( p0, x0 ), dot( p1, x1 ), dot( p2, x2 ))) - + dot(m1*m1, vec2( dot( p3, x3 ), dot( p4, x4 ) ) ) ) ; - -} - -/** -* @brief Fractal Brownian Motion -* @param p Position -* @author Yuri Artiukh, Mitch Campbell -* Inspired by Yuri Artiukh -* https://www.youtube.com/watch?v=3krH52AhPqk&list=TLPQMDYwODIwMjTE4AJqdMZT_Q&index=10 -*/ -float fbm(vec4 p) -{ - float sum = 0.0; - float amplitude = 1.0; - float scale = 1.0; - float persistence = 0.9; // Persistence factor - float lacunarity = 2.0; // Lacunarity factor - const int octaves = 4; - - // Loop through octaves - for (int i = 0; i < octaves; i++) - { - sum += snoise(p * scale) * amplitude; - p.w += 100.0; - amplitude *= persistence; - scale *= lacunarity; - } - return sum; -} - -/** -* @brief Contrast function -* @author Mitch Campbell -* @param val Value -* @param factor Factor -* @return Contrast value -*/ -float contrast(float val, float factor) -{ - return (val - 0.5) * factor + 0.5; -} - -/** -* @brief Rayleigh Phase function -* @author Mitch Campbell -* @param lightDir Light direction -* @param viewDir View direction -* @return Rayleigh phase -*/ -vec3 rayleighPhase(vec3 lightDir, vec3 viewDir) -{ - float cosTheta = dot(lightDir, viewDir); - return vec3(3.0 / (16.0 * PI)) * (1.0 + cosTheta * cosTheta); -} - -/** -* @brief Implement a tone mapping function for HDR lighting -* @author Mitch Campbell -* @param color Colour -* @return Tone mapped colour -*/ -vec3 toneMap(vec3 color) -{ - return color / (color + vec3(1.0)); -} - -/** -* @brief Main function for the sun fragment shader -* @author Mitch Campbell -*/ -void main() -{ - vec3 viewDirection = normalize(uCameraPosition - vPosition); - - // Noise - vec4 p1 = vec4(vPosition * 0.2, uTime * 0.2); - vec4 p2 = vec4(vPosition * 2.0, uTime * 0.4); - float baseNoise = fbm(p1); - float detailNoise = fbm(p2); - float combinedNoise = mix(baseNoise, detailNoise, 0.5); - combinedNoise = contrast(combinedNoise, 1.15); - - // Colour - vec3 color1 = vec3(1.0, 0.42, 0.0); - vec3 color2 = vec3(1.0, 1.0, 0.0); - vec3 finalColor = mix(color1, color2, combinedNoise); - - // Scattering Effect - vec3 scattering = rayleighPhase(normalize(vPosition), viewDirection); - finalColor += scattering * uScatteringIntensity; - - // Fresnel Effect - float fresnel = pow(1.0 - dot(vNormal, viewDirection), 1.0); - finalColor += fresnel * vec3(1.0) * 0.5; - - // Apply the noise to the sun texture color - gl_FragColor = vec4(toneMap(finalColor), 1.0); -} diff --git a/src/shaders/sun.vert b/src/shaders/sun.vert deleted file mode 100644 index b401bb5..0000000 --- a/src/shaders/sun.vert +++ /dev/null @@ -1,33 +0,0 @@ -/** -* @file sun.vert -* @brief Vertex shader for the sun -* @author Mitch Campbell -*/ - -precision mediump float; - -attribute vec2 uv; // Texture coordinates -attribute vec3 position; // Vertex position -attribute vec3 normal; // Vertex normal - -varying vec2 vUv; -varying vec3 vPosition; -varying vec3 vNormal; - -uniform mat4 modelMatrix; -uniform mat4 viewMatrix; -uniform mat4 projectionMatrix; - - -/** -* @brief Main function for the vertex shader -* @details This function sets the texture coordinates and position of the vertex -*/ -void main() -{ - vUv = uv; - vPosition = position; - - vPosition = (modelMatrix * vec4(position, 1.0)).xyz; - gl_Position = projectionMatrix * viewMatrix * vec4(vPosition, 1.0); -} diff --git a/static/environmentMaps/skybox/back.png b/static/environmentMaps/skybox/back.png index 6c3d079..44d0eb2 100644 Binary files a/static/environmentMaps/skybox/back.png and b/static/environmentMaps/skybox/back.png differ diff --git a/static/environmentMaps/skybox/bottom.png b/static/environmentMaps/skybox/bottom.png index 8946971..0695830 100644 Binary files a/static/environmentMaps/skybox/bottom.png and b/static/environmentMaps/skybox/bottom.png differ diff --git a/static/environmentMaps/skybox/cubemap.png b/static/environmentMaps/skybox/cubemap.png deleted file mode 100644 index 7c91d06..0000000 Binary files a/static/environmentMaps/skybox/cubemap.png and /dev/null differ diff --git a/static/environmentMaps/skybox/front.png b/static/environmentMaps/skybox/front.png index 24764ef..521e2cf 100644 Binary files a/static/environmentMaps/skybox/front.png and b/static/environmentMaps/skybox/front.png differ diff --git a/static/environmentMaps/skybox/left.png b/static/environmentMaps/skybox/left.png index 4fc1db6..e2ce1f8 100644 Binary files a/static/environmentMaps/skybox/left.png and b/static/environmentMaps/skybox/left.png differ diff --git a/static/environmentMaps/skybox/right.png b/static/environmentMaps/skybox/right.png index 721634f..149e0dd 100644 Binary files a/static/environmentMaps/skybox/right.png and b/static/environmentMaps/skybox/right.png differ diff --git a/static/environmentMaps/skybox/top.png b/static/environmentMaps/skybox/top.png index b42a2a4..2cabe71 100644 Binary files a/static/environmentMaps/skybox/top.png and b/static/environmentMaps/skybox/top.png differ diff --git a/static/textures/night.jpg b/static/textures/night.jpg new file mode 100644 index 0000000..d5cfb85 Binary files /dev/null and b/static/textures/night.jpg differ diff --git a/static/textures/specularClouds.jpg b/static/textures/specularClouds.jpg new file mode 100644 index 0000000..ae57dbb Binary files /dev/null and b/static/textures/specularClouds.jpg differ