├── src
├── fonts
│ └── README.md
├── models
│ └── README.md
├── sounds
│ └── README.md
├── textures
│ ├── corona.jpg
│ ├── lenseFlare.jpg
│ ├── lenseFlareSun.jpg
│ ├── lenseFlareBlur.jpg
│ ├── lenseFlareDisk.jpg
│ ├── lenseFlareRing.jpg
│ ├── lenseFlareSun copy.jpg
│ └── lenseFlareSunDesat.jpg
├── js
│ ├── shaders
│ │ ├── custom.vert
│ │ ├── texture.vert
│ │ ├── normalMap.vert
│ │ ├── glow.frag
│ │ ├── custom.frag
│ │ ├── noise.vert
│ │ ├── glow.vert
│ │ ├── noise.frag
│ │ ├── planet.vert
│ │ ├── roughnessMap.frag
│ │ ├── textureMap.frag
│ │ ├── atmosRing.frag
│ │ ├── stars.frag
│ │ ├── planet.frag
│ │ ├── atmos.frag
│ │ ├── noiseMap.frag
│ │ ├── atmosRing.vert
│ │ ├── normalMap.frag
│ │ ├── texture.frag
│ │ ├── flowNoiseMap.frag
│ │ ├── cloudMap.frag
│ │ └── nebula.frag
│ ├── views
│ │ ├── LoadingBar.js
│ │ ├── RoughnessMap.js
│ │ ├── TextureMap.js
│ │ ├── NormalMap.js
│ │ ├── CloudMap.js
│ │ ├── RenderQueue.js
│ │ ├── StarMap.js
│ │ ├── NebulaMap.js
│ │ ├── NoiseMap.js
│ │ ├── Map.js
│ │ ├── Glow.js
│ │ ├── Stars.js
│ │ ├── Atmosphere.js
│ │ ├── Nebula.js
│ │ ├── AbstractVRApplication.js
│ │ ├── NebulaeGradient.js
│ │ ├── AtmosphereRing.js
│ │ ├── Sun.js
│ │ ├── Clouds.js
│ │ ├── AbstractApplication.js
│ │ ├── SunTexture.js
│ │ ├── atmosReference.js
│ │ ├── Biome.js
│ │ └── Planet.js
│ ├── main.js
│ ├── mainWagner.js
│ └── mainVR.js
├── app.js
└── css
│ └── style.css
├── .gitignore
├── config
├── prod.env.js
├── dev.env.js
└── index.js
├── dist.zip
├── .gitattributes
├── README.md
├── package.json
└── index.html
/src/fonts/README.md:
--------------------------------------------------------------------------------
1 | Your fonts here.
--------------------------------------------------------------------------------
/src/models/README.md:
--------------------------------------------------------------------------------
1 | Your models here.
--------------------------------------------------------------------------------
/src/sounds/README.md:
--------------------------------------------------------------------------------
1 | Your sounds here.
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/*
2 | *.log
3 | .DS_Store
4 | dist
5 | wwww
6 | .idea/
--------------------------------------------------------------------------------
/config/prod.env.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | NODE_ENV: '"production"'
3 | }
--------------------------------------------------------------------------------
/dist.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/colordodge/ProceduralPlanet/HEAD/dist.zip
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/src/textures/corona.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/colordodge/ProceduralPlanet/HEAD/src/textures/corona.jpg
--------------------------------------------------------------------------------
/src/textures/lenseFlare.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/colordodge/ProceduralPlanet/HEAD/src/textures/lenseFlare.jpg
--------------------------------------------------------------------------------
/src/textures/lenseFlareSun.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/colordodge/ProceduralPlanet/HEAD/src/textures/lenseFlareSun.jpg
--------------------------------------------------------------------------------
/src/js/shaders/custom.vert:
--------------------------------------------------------------------------------
1 | void main() {
2 | gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
3 | }
4 |
--------------------------------------------------------------------------------
/src/textures/lenseFlareBlur.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/colordodge/ProceduralPlanet/HEAD/src/textures/lenseFlareBlur.jpg
--------------------------------------------------------------------------------
/src/textures/lenseFlareDisk.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/colordodge/ProceduralPlanet/HEAD/src/textures/lenseFlareDisk.jpg
--------------------------------------------------------------------------------
/src/textures/lenseFlareRing.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/colordodge/ProceduralPlanet/HEAD/src/textures/lenseFlareRing.jpg
--------------------------------------------------------------------------------
/src/textures/lenseFlareSun copy.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/colordodge/ProceduralPlanet/HEAD/src/textures/lenseFlareSun copy.jpg
--------------------------------------------------------------------------------
/src/textures/lenseFlareSunDesat.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/colordodge/ProceduralPlanet/HEAD/src/textures/lenseFlareSunDesat.jpg
--------------------------------------------------------------------------------
/src/app.js:
--------------------------------------------------------------------------------
1 | import 'css/style.css'
2 | //import Main from 'js/main'
3 | //import Main from 'js/mainWagner'
4 | import Main from 'js/main'
5 |
6 | new Main();
7 |
--------------------------------------------------------------------------------
/src/js/shaders/texture.vert:
--------------------------------------------------------------------------------
1 | varying vec2 vUv;
2 |
3 | void main() {
4 | vUv = uv;
5 | gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
6 | }
7 |
--------------------------------------------------------------------------------
/config/dev.env.js:
--------------------------------------------------------------------------------
1 | var merge = require('webpack-merge')
2 | var prodEnv = require('./prod.env')
3 |
4 | module.exports = merge(prodEnv, {
5 | NODE_ENV: '"development"'
6 | })
--------------------------------------------------------------------------------
/src/js/shaders/normalMap.vert:
--------------------------------------------------------------------------------
1 | varying vec2 vUv;
2 |
3 | void main() {
4 | vUv = uv;
5 | gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
6 | }
7 |
--------------------------------------------------------------------------------
/src/js/shaders/glow.frag:
--------------------------------------------------------------------------------
1 | uniform vec3 glowColor;
2 | varying float intensity;
3 |
4 | void main()
5 | {
6 | vec3 glow = glowColor * intensity;
7 | gl_FragColor = vec4( glow, 1.0 );
8 | }
9 |
--------------------------------------------------------------------------------
/src/js/shaders/custom.frag:
--------------------------------------------------------------------------------
1 | import noise from 'glsl-noise/simplex/2d'
2 |
3 | void main() {
4 |
5 | float brightness = noise(gl_FragCoord.xx);
6 |
7 | gl_FragColor = vec4(vec3(brightness), 1.0);
8 | //gl_FragColor = vec4(#ffff00, 1.0);
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Procedural Planets in WebGL using three.js
2 |
3 | [Live Demo](http://colordodge.com/ProceduralPlanet)
4 |
5 | [Gallery](https://imgur.com/a/OwfIwj4)
6 |
7 | ## How to install
8 |
9 | * Run `npm install`
10 | * Run `npm run dev`
11 | * Open http://localhost:8080
12 |
--------------------------------------------------------------------------------
/src/js/shaders/noise.vert:
--------------------------------------------------------------------------------
1 | attribute vec4 position;
2 | attribute vec2 uv;
3 | uniform mat4 projectionMatrix;
4 | uniform mat4 modelViewMatrix;
5 |
6 | varying vec2 vUv;
7 |
8 | void main () {
9 | vUv = uv;
10 | gl_Position = projectionMatrix * modelViewMatrix * position;
11 | }
--------------------------------------------------------------------------------
/src/js/shaders/glow.vert:
--------------------------------------------------------------------------------
1 | uniform vec3 viewVector;
2 | uniform float c;
3 | uniform float p;
4 | varying float intensity;
5 |
6 | void main()
7 | {
8 | vec3 vNormal = normalize( normalMatrix * normal );
9 | vec3 vNormel = normalize( normalMatrix * viewVector );
10 | intensity = pow( c - dot(vNormal, vNormel), p );
11 |
12 | gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
13 | }
14 |
--------------------------------------------------------------------------------
/src/js/shaders/noise.frag:
--------------------------------------------------------------------------------
1 | precision mediump float;
2 |
3 | // glslify fancy imports
4 | import noise from 'glsl-noise/simplex/3d';
5 |
6 | varying vec2 vUv;
7 |
8 | void main () {
9 | float n = noise(vec3(vUv.xy * 10.0, 1.0));
10 | n = smoothstep(0.0, 0.1, n);
11 |
12 | // glslify-hex allows for the color strings
13 | vec3 color = mix(vec3(1.0,0.0,1.0), vec3(0.0,1.0,0.0), n);
14 | gl_FragColor = vec4(color, 1.0);
15 | }
16 |
--------------------------------------------------------------------------------
/src/js/shaders/planet.vert:
--------------------------------------------------------------------------------
1 |
2 | varying vec3 vNormal;
3 | varying vec3 vPosition;
4 | varying vec3 cameraVector;
5 |
6 | uniform float time;
7 |
8 | void main() {
9 | // gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
10 |
11 | // vPosition = normalize(position) * scale;
12 | vPosition = position;
13 | vNormal = normal;
14 | cameraVector = cameraPosition - vPosition;
15 |
16 | // vec3 newPosition = position + normal * amplitude * displacement;
17 | vec3 newPosition = position;
18 | gl_Position = projectionMatrix * modelViewMatrix * vec4( newPosition, 1.0 );
19 | }
20 |
--------------------------------------------------------------------------------
/src/js/shaders/roughnessMap.frag:
--------------------------------------------------------------------------------
1 |
2 | varying vec2 vUv;
3 | uniform float resolution;
4 | uniform sampler2D heightMap;
5 | uniform float waterLevel;
6 |
7 | float getBrightness(vec4 color) {
8 | return 1.0 - (0.2126*color.r + 0.7152*color.g + 0.0722*color.b);
9 | }
10 |
11 | void main() {
12 |
13 | float x = vUv.x;
14 | float y = vUv.y;
15 |
16 | float pixelSize = 1.0 / resolution;
17 |
18 | float n = texture2D(heightMap, vec2(x, y)).r;
19 | float roughness = 0.0;
20 |
21 | if (n < waterLevel) {
22 | roughness = 0.75;
23 | } else {
24 | roughness = 0.9;
25 | }
26 |
27 | gl_FragColor = vec4(vec3(roughness), 1.0);
28 | }
29 |
--------------------------------------------------------------------------------
/src/js/views/LoadingBar.js:
--------------------------------------------------------------------------------
1 |
2 | export default class LoadingBar {
3 |
4 | constructor() {
5 | this.base = document.createElement("div");
6 | this.base.id = "loadingBarHolder";
7 | this.base.innerHTML = 'Rendering
';
8 | }
9 |
10 | update(progress) {
11 | this.bar = document.getElementById("loadingBar");
12 | this.bar.style.width = "" + progress * 100 + "%";
13 | }
14 |
15 | show() {
16 | document.body.appendChild(this.base);
17 | this.bar = document.getElementById("loadingBar");
18 | this.bar.style.width = "0%";
19 | }
20 |
21 | hide() {
22 | document.body.removeChild(this.base);
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/src/js/shaders/textureMap.frag:
--------------------------------------------------------------------------------
1 | import noise from 'glsl-noise/classic/4d'
2 |
3 | varying vec2 vUv;
4 |
5 | uniform sampler2D biomeMap;
6 | uniform sampler2D heightMap;
7 | uniform sampler2D moistureMap;
8 |
9 | void main() {
10 | float x = vUv.x;
11 | float y = vUv.y;
12 |
13 | float n1 = texture2D(heightMap, vec2(x, y)).r;
14 | float n2 = texture2D(moistureMap, vec2(x, y)).r;
15 |
16 | vec4 color = texture2D(biomeMap, vec2(n2, n1));
17 |
18 | // if (n1 < 0.5) {
19 | // vec4 water = vec4(0.0, 0.4, 0.9, 1.0);
20 | // // vec4 water = vec4(1.0, 0.2, 0.0, 1.0);
21 | // color = mix(water, color, 0.3);
22 | // }
23 | //
24 | // if (n1 < 0.5 && n1 > 0.4) {
25 | // vec4 coast = vec4(vec3(1.0), 1.0);
26 | // float amount = 1.0 - ((0.5 - n1) * 10.0);
27 | // color = mix(color, coast, amount*0.3);
28 | // }
29 |
30 | // color = vec4(1.0);
31 |
32 | gl_FragColor = color;
33 | }
34 |
--------------------------------------------------------------------------------
/src/js/shaders/atmosRing.frag:
--------------------------------------------------------------------------------
1 |
2 | // Source: http://jsfiddle.net/VsWb9/770/
3 |
4 | //
5 | // Atmospheric scattering fragment shader
6 | //
7 | // Author: Sean O'Neil
8 | //
9 | // Copyright (c) 2004 Sean O'Neil
10 | //
11 |
12 | uniform vec3 v3LightPos;
13 | uniform float g;
14 | uniform float g2;
15 | uniform vec3 atmosphereColor;
16 |
17 | varying vec3 v3Direction;
18 | varying vec3 c0;
19 | varying vec3 c1;
20 |
21 | // Calculates the Mie phase function
22 | float getMiePhase(float fCos, float fCos2, float g, float g2)
23 | {
24 | return 1.5 * ((1.0 - g2) / (2.0 + g2)) * (1.0 + fCos2) / pow(1.0 + g2 - 2.0 * g * fCos, 1.5);
25 | }
26 |
27 | // Calculates the Rayleigh phase function
28 | float getRayleighPhase(float fCos2)
29 | {
30 | return 0.75 + 0.75 * fCos2;
31 | }
32 |
33 | void main (void)
34 | {
35 | float fCos = dot(v3LightPos, v3Direction) / length(v3Direction);
36 | float fCos2 = fCos * fCos;
37 |
38 | vec3 color = getRayleighPhase(fCos2) * c0 + getMiePhase(fCos, fCos2, g, g2) * c1;
39 |
40 | gl_FragColor = vec4(color, 1.0);
41 | gl_FragColor.a = gl_FragColor.b;
42 | }
43 |
--------------------------------------------------------------------------------
/config/index.js:
--------------------------------------------------------------------------------
1 | // see http://vuejs-templates.github.io/webpack for documentation.
2 | var path = require('path')
3 |
4 | module.exports = {
5 | build: {
6 | env: require('./prod.env'),
7 | index: path.resolve(__dirname, '../dist/index.html'),
8 | assetsRoot: path.resolve(__dirname, '../dist'),
9 | assetsSubDirectory: 'static',
10 | assetsPublicPath: '/',
11 | productionSourceMap: true,
12 | // Gzip off by default as many popular static hosts such as
13 | // Surge or Netlify already gzip all static assets for you.
14 | // Before setting to `true`, make sure to:
15 | // npm install --save-dev compression-webpack-plugin
16 | productionGzip: false,
17 | productionGzipExtensions: ['js', 'css']
18 | },
19 | dev: {
20 | env: require('./dev.env'),
21 | port: 8080,
22 | assetsSubDirectory: 'static',
23 | assetsPublicPath: '/',
24 | proxyTable: {},
25 | // CSS Sourcemaps off by default because relative paths are "buggy"
26 | // with this option, according to the CSS-Loader README
27 | // (https://github.com/webpack/css-loader#sourcemaps)
28 | // In our experience, they generally work as expected,
29 | // just be aware of this issue when enabling this option.
30 | cssSourceMap: false
31 | }
32 | }
--------------------------------------------------------------------------------
/src/js/views/RoughnessMap.js:
--------------------------------------------------------------------------------
1 | import * as THREE from 'three'
2 | import vertShader from 'shaders/texture.vert'
3 | import fragShader from 'shaders/roughnessMap.frag'
4 | import Map from 'views/Map.js'
5 |
6 | class RoughnessMap extends Map {
7 |
8 | constructor() {
9 | super();
10 | this.setup();
11 | super.setup();
12 | }
13 |
14 | setup() {
15 | this.mats = [];
16 |
17 | for (let i = 0; i < 6; i++) {
18 | this.mats[i] = new THREE.ShaderMaterial({
19 | uniforms: {
20 | resolution: {type: "f", value: 0},
21 | waterLevel: {type: "f", value: 0},
22 | heightMap: {type: "t", value: new THREE.Texture()}
23 | },
24 | vertexShader: vertShader,
25 | fragmentShader: fragShader,
26 | transparent: true,
27 | depthWrite: false
28 | });
29 | }
30 | }
31 |
32 | render(props) {
33 | // props.resolution
34 | // props.heightMaps[]
35 | // props.waterLevel
36 |
37 | for (let i = 0; i < 6; i++) {
38 | this.mats[i].uniforms.resolution.value = props.resolution;
39 | this.mats[i].uniforms.waterLevel.value = props.waterLevel;
40 | this.mats[i].uniforms.heightMap.value = props.heightMaps[i];
41 | this.mats[i].needsUpdate = true;
42 | }
43 |
44 | super.render(props);
45 | }
46 |
47 | }
48 |
49 | export default RoughnessMap;
50 |
--------------------------------------------------------------------------------
/src/js/views/TextureMap.js:
--------------------------------------------------------------------------------
1 | import * as THREE from 'three'
2 | import vertShader from 'shaders/texture.vert'
3 | import fragShader from 'shaders/textureMap.frag'
4 | import Map from 'views/Map.js'
5 |
6 | class TextureMap extends Map {
7 |
8 | constructor() {
9 | super();
10 | this.setup();
11 | super.setup();
12 | }
13 |
14 | setup() {
15 | this.mats = [];
16 |
17 | for (let i = 0; i < 6; i++) {
18 | this.mats[i] = new THREE.ShaderMaterial({
19 | uniforms: {
20 | biomeMap: {type: "t", value: new THREE.Texture()},
21 | heightMap: {type: "t", value: new THREE.Texture()},
22 | moistureMap: {type: "t", value: new THREE.Texture()}
23 | },
24 | vertexShader: vertShader,
25 | fragmentShader: fragShader,
26 | transparent: true,
27 | depthWrite: false
28 | });
29 | }
30 | }
31 |
32 | render(props) {
33 | // props.resolution
34 | // props.heightMaps[]
35 | // props.moistureMaps[]
36 | // props.biomeMap
37 |
38 | let resolution = props.resolution;
39 |
40 | for (let i = 0; i < 6; i++) {
41 |
42 | this.mats[i].uniforms.heightMap.value = props.heightMaps[i];
43 | this.mats[i].uniforms.moistureMap.value = props.moistureMaps[i];
44 | this.mats[i].uniforms.biomeMap.value = props.biomeMap;
45 | this.mats[i].needsUpdate = true;
46 | }
47 |
48 | super.render(props);
49 | }
50 |
51 | }
52 |
53 | export default TextureMap;
54 |
--------------------------------------------------------------------------------
/src/js/views/NormalMap.js:
--------------------------------------------------------------------------------
1 | import * as THREE from 'three'
2 | import vertShader from 'shaders/normalMap.vert'
3 | import fragShader from 'shaders/normalMap.frag'
4 | import Map from 'views/Map.js'
5 |
6 | class NormalMap extends Map{
7 |
8 | constructor() {
9 | super();
10 | this.setup();
11 | super.setup();
12 | }
13 |
14 | setup() {
15 | this.mats = [];
16 |
17 | for (let i = 0; i < 6; i++) {
18 | this.mats[i] = new THREE.ShaderMaterial({
19 | uniforms: {
20 | resolution: {type: "f", value: 0},
21 | waterLevel: {type: "f", value: 0},
22 | heightMap: {type: "t", value: new THREE.Texture()},
23 | textureMap: {type: "t", value: new THREE.Texture()}
24 | },
25 | vertexShader: vertShader,
26 | fragmentShader: fragShader,
27 | transparent: true,
28 | depthWrite: false
29 | });
30 | }
31 | }
32 |
33 | render(props) {
34 | // props.resolution
35 | // props.heightMaps[]
36 | // props.textureMaps[]
37 | // props.waterLevel
38 |
39 | for (let i = 0; i < 6; i++) {
40 | this.mats[i].uniforms.resolution.value = props.resolution;
41 | this.mats[i].uniforms.waterLevel.value = props.waterLevel;
42 | this.mats[i].uniforms.heightMap.value = props.heightMaps[i];
43 | this.mats[i].uniforms.textureMap.value = props.textureMaps[i];
44 | this.mats[i].needsUpdate = true;
45 | }
46 |
47 | super.render(props);
48 | }
49 |
50 | }
51 |
52 | export default NormalMap;
53 |
--------------------------------------------------------------------------------
/src/js/views/CloudMap.js:
--------------------------------------------------------------------------------
1 | import * as THREE from 'three'
2 | import vertShader from 'shaders/texture.vert'
3 | import fragShader from 'shaders/cloudMap.frag'
4 | import Map from 'views/Map.js'
5 |
6 | class CloudMap extends Map {
7 |
8 | constructor() {
9 | super();
10 | this.setup();
11 | super.setup();
12 | }
13 |
14 | setup() {
15 | this.mats = [];
16 |
17 | for (let i = 0; i < 6; i++) {
18 | this.mats[i] = new THREE.ShaderMaterial({
19 | uniforms: {
20 | index: {type: "i", value: i},
21 | seed: {type: "f", value: 0},
22 | resolution: {type: "f", value: 0},
23 | res1: {type: "f", value: 0},
24 | res2: {type: "f", value: 0},
25 | resMix: {type: "f", value: 0},
26 | mixScale: {type: "f", value: 0}
27 | },
28 | vertexShader: vertShader,
29 | fragmentShader: fragShader,
30 | transparent: true,
31 | depthWrite: false
32 | });
33 | }
34 | }
35 |
36 | render(props) {
37 | // props.seed
38 | // props.resolution
39 | // props.res1
40 | // props.res2
41 | // props.resMix
42 | // props.mixScale
43 |
44 | for (let i = 0; i < 6; i++) {
45 | this.mats[i].uniforms.seed.value = props.seed;
46 | this.mats[i].uniforms.resolution.value = props.resolution;
47 | this.mats[i].uniforms.res1.value = props.res1;
48 | this.mats[i].uniforms.res2.value = props.res2;
49 | this.mats[i].uniforms.resMix.value = props.resMix;
50 | this.mats[i].uniforms.mixScale.value = props.mixScale;
51 | this.mats[i].needsUpdate = true;
52 | }
53 |
54 | super.render(props);
55 | }
56 |
57 |
58 | }
59 |
60 | export default CloudMap;
61 |
--------------------------------------------------------------------------------
/src/js/views/RenderQueue.js:
--------------------------------------------------------------------------------
1 | import LoadingBar from 'views/LoadingBar.js'
2 |
3 | class RenderQueue {
4 |
5 | constructor() {
6 | this.actions = [];
7 | this.callbacks = [];
8 | this.skipFrame = false;
9 | this.lastTime = 0;
10 |
11 | this.totalActions = 0;
12 | this.loadingBar = new LoadingBar();
13 | }
14 |
15 | start() {
16 | this.startFrame = true;
17 | this.lastTime = Date.now();
18 | this.loadingBar.show();
19 | }
20 |
21 | update() {
22 | if (this.startFrame == false) {
23 | if (this.actions.length > 0) {
24 | this.doNextAction();
25 | } else {
26 | this.checkCallbacks();
27 | }
28 | } else {
29 | this.startFrame = false;
30 | // first frame after actions added
31 | this.totalActions = this.actions.length;
32 | }
33 | }
34 |
35 | doNextAction() {
36 |
37 | let thisTime = Date.now();
38 | let totalTime = thisTime - this.lastTime;
39 |
40 | this.lastTime = thisTime;
41 |
42 | this.actions[0]();
43 | this.actions.shift();
44 |
45 | let progress = this.actions.length / this.totalActions;
46 | progress = 1.0 - progress;
47 | this.loadingBar.update(progress);
48 | }
49 |
50 | addAction(action) {
51 | this.actions.push(action);
52 | }
53 |
54 | addCallback(callback) {
55 | this.callbacks.push(callback);
56 | }
57 |
58 | checkCallbacks() {
59 | if (this.callbacks.length > 0) {
60 | this.executeCallbacks();
61 | }
62 | }
63 |
64 | executeCallbacks() {
65 | for (let i=0; i {
39 | this.textures[i].setSize(resolution, resolution);
40 | this.textures[i].needsUpdate = true;
41 | this.textureCameras[i].left = -resolution/2;
42 | this.textureCameras[i].right = resolution/2;
43 | this.textureCameras[i].top = resolution/2;
44 | this.textureCameras[i].bottom = -resolution/2;
45 | this.textureCameras[i].updateProjectionMatrix();
46 | this.geos[i] = new THREE.PlaneGeometry(resolution, resolution);
47 | this.planes[i].geometry = this.geos[i];
48 | window.renderer.render(this.textureScenes[i], this.textureCameras[i], this.textures[i], true);
49 | this.geos[i].dispose();
50 |
51 | });
52 |
53 | }
54 | }
55 |
56 | }
57 |
58 | export default Map;
59 |
--------------------------------------------------------------------------------
/src/js/views/Glow.js:
--------------------------------------------------------------------------------
1 | import * as THREE from 'three'
2 | import shaderVert from 'shaders/glow.vert'
3 | import shaderFrag from 'shaders/glow.frag'
4 |
5 | class Glow {
6 |
7 | constructor() {
8 | this.view = new THREE.Object3D();
9 |
10 | this.randomizeColor();
11 |
12 | this.size = 1030;
13 | this.glow = 1.0;
14 |
15 | this.c = 1.0;
16 | this.p = 1.4;
17 |
18 | // window.gui.add(this, "glow", 0.0, 1.0);
19 |
20 | let glowFolder = window.gui.addFolder('Glow');
21 | glowFolder.add(this, "c", 0, 1).step(0.01);
22 | glowFolder.add(this, "p", 0, 6).step(0.01);
23 |
24 |
25 |
26 | this.mat = new THREE.ShaderMaterial({
27 | vertexShader: shaderVert,
28 | fragmentShader: shaderFrag,
29 | uniforms: {
30 | "c": { type: "f", value: 1.0 },
31 | "p": { type: "f", value: 1.4 },
32 | glowColor: { type: "c", value: new THREE.Color(0x00ffff) },
33 | viewVector: { type: "v3", value: window.camera.position }
34 | }
35 | });
36 |
37 | this.mat.transparent = true;
38 | this.mat.blending = THREE.AdditiveBlending;
39 | this.mat.side = THREE.BackSide;
40 |
41 | // this.mat = new THREE.MeshStandardMaterial({color: 0xFFFFFF});
42 |
43 | this.geo = new THREE.IcosahedronBufferGeometry(1, 6);
44 | this.sphere = new THREE.Mesh(this.geo, this.mat);
45 | this.sphere.scale.set(this.size, this.size, this.size);
46 | this.view.add(this.sphere);
47 | }
48 |
49 | update() {
50 | this.mat.uniforms.c.value = this.c;
51 | this.mat.uniforms.p.value = this.p;
52 | this.mat.uniforms.viewVector.value = new THREE.Vector3().subVectors( window.camera.position, this.sphere.position );
53 | }
54 |
55 | randomize() {
56 | this.randomizeColor();
57 | this.mat.uniforms.color.value = this.color;
58 | }
59 |
60 | randomizeColor() {
61 | this.color = new THREE.Color();
62 | this.color.r = window.rng();
63 | this.color.g = window.rng();
64 | this.color.b = window.rng();
65 | }
66 | }
67 |
68 | export default Glow;
69 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "scripts": {
3 | "dev": "node build/dev-server.js",
4 | "build": "node build/build.js"
5 | },
6 | "license": "WTFPL",
7 | "devDependencies": {
8 | "babel-core": "^6.21.0",
9 | "babel-loader": "^6.2.10",
10 | "babel-plugin-glslify": "^2.0.0",
11 | "babel-preset-es2015": "^6.18.0",
12 | "babelify": "^7.3.0",
13 | "browserify": "^14.3.0",
14 | "copy-webpack-plugin": "^4.0.1",
15 | "css-loader": "^0.28.2",
16 | "exports-loader": "^0.6.4",
17 | "extract-text-webpack-plugin": "^2.1.0",
18 | "glslify": "^5.1.0",
19 | "glslify-loader": "^1.0.2",
20 | "html-webpack-plugin": "^2.26.0",
21 | "ify-loader": "^1.0.4",
22 | "json-loader": "^0.5.4",
23 | "ora": "^1.2.0",
24 | "raw-loader": "^0.5.1",
25 | "shelljs": "^0.7.7",
26 | "style-loader": "^0.18.1",
27 | "webpack": "^2.2.0",
28 | "webpack-dev-server": "^2.2.0",
29 | "webpack-hot-middleware": "^2.18.0",
30 | "webpack-merge": "^4.1.0"
31 | },
32 | "dependencies": {
33 | "@superguigui/wagner": "^0.1.5",
34 | "crypto-random-string": "^1.0.0",
35 | "dat-gui": "^0.5.0",
36 | "dat.gui": "^0.6.1",
37 | "glsl-checker": "^1.0.1",
38 | "glsl-noise": "0.0.0",
39 | "glsl-worley": "^1.0.2",
40 | "glslify": "^5.0.0",
41 | "glslify-fancy-imports": "^1.0.1",
42 | "glslify-hex": "^2.0.1",
43 | "random-lorem": "^1.0.4",
44 | "seedrandom": "^2.4.3",
45 | "serve": "^6.4.8",
46 | "simplex-noise": "^2.3.0",
47 | "stats-js": "^1.0.0-alpha1",
48 | "three": "^0.85.2",
49 | "three.meshline": "^1.0.3",
50 | "tinycolor2": "^1.4.1",
51 | "webvr-polyfill": "^0.9.29",
52 | "webvr-ui": "^0.9.4"
53 | },
54 | "browserify": {
55 | "transform": [
56 | [
57 | "babelify",
58 | {
59 | "presets": [
60 | "es2015"
61 | ],
62 | "plugins": [
63 | "glslify"
64 | ]
65 | }
66 | ],
67 | "glslify"
68 | ]
69 | },
70 | "glslify": {
71 | "transform": [
72 | "glslify-fancy-imports",
73 | "glslify-hex"
74 | ]
75 | },
76 | "engines": {
77 | "node": ">= 4.0.0",
78 | "npm": ">= 3.0.0"
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/src/js/main.js:
--------------------------------------------------------------------------------
1 | import * as THREE from 'three'
2 | import WAGNER from '@superguigui/wagner/'
3 | import MultiPassBloomPass from '@superguigui/wagner/src/passes/bloom/MultiPassBloomPass'
4 | import GodrayPass from '@superguigui/wagner/src/passes/godray/godraypass'
5 | import AbstractApplication from 'views/AbstractApplication'
6 | import shaderVert from 'shaders/custom.vert'
7 | import shaderFrag from 'shaders/custom.frag'
8 | import Planet from 'views/Planet'
9 | import RenderQueue from 'views/RenderQueue'
10 |
11 |
12 | class Main extends AbstractApplication {
13 |
14 | constructor(){
15 | super();
16 |
17 | // texture loading example
18 | // var texture = new THREE.TextureLoader().load( 'assets/textures/crate.gif' );
19 |
20 | // this.initPostprocessing();
21 |
22 | this.createBrandTag();
23 |
24 | window.renderQueue = new RenderQueue();
25 |
26 | this.planet = new Planet();
27 | this.scene.add(this.planet.view);
28 |
29 | this.animate();
30 | }
31 |
32 | initPostprocessing() {
33 | this._renderer.autoClearColor = true;
34 | this.composer = new WAGNER.Composer(this._renderer);
35 | this.bloomPass = new MultiPassBloomPass({
36 | blurAmount: 3,
37 | applyZoomBlur: false
38 | });
39 | this.godrayPass = new GodrayPass();
40 |
41 | let folder = window.gui.addFolder("Post Processing");
42 | this.bloom = true;
43 | folder.add(this, "bloom");
44 | folder.add(this.bloomPass.params, "blurAmount", 0, 5);
45 |
46 |
47 | }
48 |
49 | createBrandTag() {
50 | let a = document.createElement("a");
51 | a.href = "http://www.colordodge.com";
52 | a.innerHTML = "Colordodge
";
53 | document.body.appendChild(a);
54 | }
55 |
56 | animate() {
57 | super.animate();
58 |
59 | window.renderQueue.update();
60 | this.planet.update();
61 |
62 | // if (this.bloom) {
63 | // this.composer.reset();
64 | // this.composer.render(this._scene, this._camera);
65 | // // this.composer.pass(this.bloomPass);
66 | // this.composer.pass(this.godrayPass);
67 | // this.composer.toScreen();
68 | // }
69 |
70 |
71 |
72 | }
73 |
74 | }
75 |
76 | export default Main;
77 |
--------------------------------------------------------------------------------
/src/js/shaders/stars.frag:
--------------------------------------------------------------------------------
1 | import noise from 'glsl-noise/classic/3d'
2 | import worley3D from 'glsl-worley/worley3D'
3 |
4 | varying vec2 vUv;
5 | uniform int index;
6 | uniform float seed;
7 | uniform float resolution;
8 | uniform float res1;
9 | uniform float res2;
10 | uniform float resMix;
11 | uniform float mixScale;
12 | uniform sampler2D nebulaeMap;
13 |
14 |
15 | vec3 getSphericalCoord(int index, float x, float y, float width) {
16 | width /= 2.0;
17 | x -= width;
18 | y -= width;
19 | vec3 coord = vec3(0.0, 0.0, 0.0);
20 |
21 | if (index == 0) {coord.x=width; coord.y=-y; coord.z=-x;}
22 | else if (index == 1) {coord.x=-width; coord.y=-y; coord.z=x;}
23 | else if (index == 2) {coord.x=x; coord.y=width; coord.z=y;}
24 | else if (index == 3) {coord.x=x; coord.y=-width; coord.z=-y;}
25 | else if (index == 4) {coord.x=x; coord.y=-y; coord.z=width;}
26 | else if (index == 5) {coord.x=-x; coord.y=-y; coord.z=-width;}
27 |
28 | return normalize(coord);
29 | }
30 |
31 |
32 | float simplex(vec3 pos, float seed) {
33 | float n = noise(vec3(pos + seed));
34 | // return (n + 1.0) * 0.5;
35 | n = (n + 1.0) * 0.5;
36 | // n = 2.0 * (0.5 - abs(0.5 - n));
37 | return n;
38 | }
39 |
40 | float baseNoise(vec3 pos, float frq, float seed ) {
41 | const int octaves = 16;
42 | float amp = 0.5;
43 |
44 | float n = 0.0;
45 | float gain = 1.0;
46 | for(int i=0; i
25 |
26 | Try it without a headset
27 | `
28 | document.body.insertAdjacentHTML( 'beforeend', uiVR );
29 |
30 | const uiOptions = {
31 | color: 'black',
32 | background: 'white',
33 | corners: 'square'
34 | };
35 |
36 | this._vrButton = new webvrui.EnterVRButton(this._renderer.domElement, uiOptions);
37 | this._vrButton.on('exit', () => {
38 | this._camera.quaternion.set(0, 0, 0, 1);
39 | this._camera.position.set(0, this._controls.userHeight, 0);
40 | });
41 | this._vrButton.on('hide', function() {
42 | document.getElementById('ui').style.display = 'none';
43 | });
44 | this._vrButton.on('show', function() {
45 | document.getElementById('ui').style.display = 'inherit';
46 | });
47 | document.getElementById('vr-button').appendChild(this._vrButton.domElement);
48 | document.getElementById('magic-window').addEventListener('click', () => {
49 | this._vrButton.requestEnterFullscreen();
50 | });
51 |
52 |
53 | this._effect = new THREE.VREffect(this._renderer);
54 | this._effect.setSize(window.innerWidth, window.innerHeight);
55 |
56 | window.addEventListener( 'resize', this.onWindowResize.bind(this), false );
57 |
58 | }
59 |
60 | get renderer(){
61 |
62 | return this._renderer;
63 |
64 | }
65 |
66 | get camera(){
67 |
68 | return this._camera;
69 |
70 | }
71 |
72 | get scene(){
73 |
74 | return this._scene;
75 |
76 | }
77 |
78 | get effect(){
79 |
80 | return this._effect;
81 |
82 | }
83 |
84 | get controls(){
85 |
86 | return this._controls;
87 |
88 | }
89 |
90 |
91 | onWindowResize() {
92 |
93 | this._camera.aspect = window.innerWidth / window.innerHeight;
94 | this._camera.updateProjectionMatrix();
95 |
96 | this._renderer.setSize( window.innerWidth, window.innerHeight );
97 |
98 | }
99 |
100 | animate(timestamp) {
101 | this._effect.requestAnimationFrame( this.animate.bind(this) );
102 | this._controls.update();
103 | this._effect.render(this._scene, this._camera);
104 |
105 | }
106 |
107 |
108 | }
109 | export default AbstractVRApplication;
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Procedural Planet
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/src/js/views/NebulaeGradient.js:
--------------------------------------------------------------------------------
1 | import * as THREE from 'three'
2 |
3 |
4 | class NebulaeGradient {
5 |
6 | constructor() {
7 |
8 | this.canvas = document.createElement("canvas");
9 | this.canvas.id = "nebulaeCanvas";
10 | this.canvas.width = 512;
11 | this.canvas.height = 512;
12 | this.canvas.style.width = "200px";
13 | this.canvas.style.height = "200px";
14 | this.width = this.canvas.width;
15 | this.height = this.canvas.height;
16 | this.ctx = this.canvas.getContext("2d");
17 |
18 | document.body.appendChild(this.canvas);
19 | this.toggleCanvasDisplay(false);
20 | }
21 |
22 | generateTexture() {
23 |
24 | let h = this.randRange(0.0, 1.0);
25 | let s = this.randRange(0.2, 0.8);
26 | let l = this.randRange(0.2, 0.6);
27 | this.baseColor = new THREE.Color().setHSL(h, s, l);
28 | this.colorAngle = this.randRange(0.0, 0.5);
29 |
30 | this.fillBaseColor();
31 | this.drawShapes();
32 |
33 | this.texture = new THREE.CanvasTexture(this.canvas);
34 |
35 | }
36 |
37 | toggleCanvasDisplay(value) {
38 | if (value) {
39 | this.canvas.style.display = "block";
40 | } else {
41 | this.canvas.style.display = "none";
42 | }
43 | }
44 |
45 | fillBaseColor() {
46 | this.ctx.fillStyle = this.toCanvasColor(this.baseColor);
47 | this.ctx.fillRect(0, 0, this.width, this.height);
48 | }
49 |
50 | drawShapes() {
51 | let numCircles = Math.round(this.randRange(20, 50));
52 | for (let i=0; i 0.6) {
11 | // bright *= 0.3;
12 | // }
13 | return bright;
14 | }
15 |
16 | void main() {
17 |
18 | float x = vUv.x;
19 | float y = vUv.y;
20 | // float x = gl_FragCoord.x / 1024.0;
21 | // float y = gl_FragCoord.y / 1024.0;
22 | float pixelSize = 1.0 / resolution;
23 |
24 |
25 | // Value from trial & error.
26 | // Seems to work fine for the scales we are dealing with.
27 | // float strength = scale.Y / 16;
28 | float strength = 0.8;
29 |
30 |
31 | float level = texture2D(heightMap, vec2(x, y)).r;
32 | float water = waterLevel;
33 | // float mod = 1.0;
34 | // if (level < water) {
35 | // mod = 0.1;
36 | // }
37 |
38 |
39 |
40 | float tl = getBrightness(texture2D(textureMap, vec2(x-pixelSize, y-pixelSize)));
41 | float l = getBrightness(texture2D(textureMap, vec2(x-pixelSize, y)));
42 | float bl = getBrightness(texture2D(textureMap, vec2(x-pixelSize, y+pixelSize)));
43 | float b = getBrightness(texture2D(textureMap, vec2(x, y+pixelSize)));
44 | float br = getBrightness(texture2D(textureMap, vec2(x+pixelSize, y+pixelSize)));
45 | float r = getBrightness(texture2D(textureMap, vec2(x+pixelSize, y)));
46 | float tr = getBrightness(texture2D(textureMap, vec2(x+pixelSize, y-pixelSize)));
47 | float t = getBrightness(texture2D(textureMap, vec2(x, y-pixelSize)));
48 |
49 |
50 | float tl2 = getBrightness(texture2D(heightMap, vec2(x-pixelSize, y-pixelSize)));
51 | float l2 = getBrightness(texture2D(heightMap, vec2(x-pixelSize, y)));
52 | float bl2 = getBrightness(texture2D(heightMap, vec2(x-pixelSize, y+pixelSize)));
53 | float b2 = getBrightness(texture2D(heightMap, vec2(x, y+pixelSize)));
54 | float br2 = getBrightness(texture2D(heightMap, vec2(x+pixelSize, y+pixelSize)));
55 | float r2 = getBrightness(texture2D(heightMap, vec2(x+pixelSize, y)));
56 | float tr2 = getBrightness(texture2D(heightMap, vec2(x+pixelSize, y-pixelSize)));
57 | float t2 = getBrightness(texture2D(heightMap, vec2(x, y-pixelSize)));
58 |
59 | float ratio = 1.0;
60 |
61 | if (level > water) {
62 | float diff = water - level;
63 | ratio = 1.0 - (diff*1.0);
64 | }
65 |
66 | tl = mix(tl, tl2, ratio);
67 | l = mix(l, l2, ratio);
68 | bl = mix(bl, bl2, ratio);
69 | b = mix(b, b2, ratio);
70 | br = mix(br, br2, ratio);
71 | r = mix(r, r2, ratio);
72 | tr = mix(tr, tr2, ratio);
73 | t = mix(t, t2, ratio);
74 |
75 | // float level = getBrightness(texture2D(heightMap, vec2(x, y)));
76 |
77 |
78 | // smooth out the normal map for the water
79 | float factor = 0.01;
80 | float depth = 0.5;
81 | if (level < water) {
82 | // strength = 0.00;
83 | tl = mix(depth, tl, factor);
84 | l = mix(depth, l, factor);
85 | bl = mix(depth, bl, factor);
86 | b = mix(depth, b, factor);
87 | br = mix(depth, br, factor);
88 | r = mix(depth, r, factor);
89 | tr = mix(depth, tr, factor);
90 | t = mix(depth, t, factor);
91 | }
92 |
93 |
94 | // Compute dx using Sobel:
95 | // -1 0 1
96 | // -2 0 2
97 | // -1 0 1
98 | float dX = tr + 2.0 * r + br - tl - 2.0 * l - bl;
99 |
100 | // Compute dy using Sobel:
101 | // -1 -2 -1
102 | // 0 0 0
103 | // 1 2 1
104 | float dY = bl + 2.0 * b + br - tl - 2.0 * t - tr;
105 |
106 |
107 | vec3 N = vec3(dX, dY, 1.0 / strength);
108 |
109 | //
110 | // if (level < 0.5) {
111 | // N.x = 0.5;
112 | // N.y = 0.5;
113 | // N.z = -0.5;
114 | //
115 | // }
116 |
117 | normalize(N);
118 |
119 | //convert (-1.0 , 1.0) to (0.0 , 1.0), if necessary
120 | //Vector3 scale = new Vector3(0.5f, 0.5f, 0.5f);
121 | //Vector3.Multiply(ref N, ref scale, out N);
122 | //Vector3.Add(ref N, ref scale, out N);
123 |
124 | N = N * 0.5 + 0.5;
125 |
126 |
127 | gl_FragColor = vec4(N, 1.0);
128 | }
129 |
--------------------------------------------------------------------------------
/src/js/views/Clouds.js:
--------------------------------------------------------------------------------
1 | import * as THREE from 'three'
2 | import CloudMap from 'views/CloudMap.js'
3 | import tinycolor from 'tinycolor2'
4 |
5 | class Clouds {
6 |
7 | constructor() {
8 | this.view = new THREE.Object3D();
9 |
10 | this.materials = [];
11 | this.roughness = 0.9;
12 | this.metalness = 0.5;
13 | this.normalScale = 5.0;
14 | this.clouds = 1.0;
15 |
16 |
17 | this.resolution = 1024;
18 | this.size = 1001;
19 |
20 |
21 | this.color = new THREE.Color(0xffffff);
22 |
23 | this.cloudColor = [this.color.r*255, this.color.g*255, this.color.b*255];
24 |
25 | this.cloudMaps = [];
26 |
27 | this.setup();
28 |
29 |
30 | let cloudControl = window.gui.add(this, "clouds", 0.0, 1.0);
31 | cloudControl.onChange(value => { this.updateMaterial(); });
32 |
33 | let colorControl = window.gui.addColor(this, "cloudColor");
34 | colorControl.onChange(value => {
35 | this.color.r = value[0] / 255;
36 | this.color.g = value[1] / 255;
37 | this.color.b = value[2] / 255;
38 | this.updateMaterial();
39 | });
40 |
41 | }
42 |
43 | update() {
44 | //
45 | }
46 |
47 | setup() {
48 |
49 | this.cloudMap = new CloudMap();
50 | this.cloudMaps = this.cloudMap.maps;
51 |
52 | for (let i=0; i<6; i++) {
53 | let material = new THREE.MeshStandardMaterial({
54 | color: this.color,
55 | transparent: true,
56 | });
57 | this.materials[i] = material;
58 | }
59 |
60 | let geo = new THREE.BoxGeometry(1, 1, 1, 64, 64, 64);
61 | let radius = this.size;
62 | for (var i in geo.vertices) {
63 | var vertex = geo.vertices[i];
64 | vertex.normalize().multiplyScalar(radius);
65 | }
66 | this.computeGeometry(geo);
67 | this.sphere = new THREE.Mesh(geo, this.materials);
68 | this.view.add(this.sphere);
69 | }
70 |
71 | render(props) {
72 | this.seed = this.randRange(0, 1000);
73 | let cloudSize = this.randRange(0.5, 1.0);
74 |
75 | let mixScale = this.map_range(props.waterLevel*props.waterLevel, 0, 0.8, 0.0, 3.0);
76 |
77 |
78 | this.cloudMap.render({
79 | seed: this.seed,
80 | resolution: this.resolution,
81 | res1: this.randRange(0.1, 1.0),
82 | res2: this.randRange(0.1, 1.0),
83 | resMix: this.randRange(0.1, 1.0),
84 | mixScale: this.randRange(0.1, 1.0)
85 | });
86 |
87 | this.updateMaterial();
88 | }
89 |
90 | map_range(value, low1, high1, low2, high2) {
91 | return low2 + (high2 - low2) * (value - low1) / (high1 - low1);
92 | }
93 |
94 | updateMaterial() {
95 | for (let i=0; i<6; i++) {
96 | let material = this.materials[i];
97 | material.roughness = this.roughness;
98 | material.metalness = this.metalness;
99 | material.opacity = this.clouds;
100 | material.map = this.cloudMaps[i],
101 | // material.alphaMap = this.cloudMaps[i],
102 | // material.bumpMap = this.cloudMaps[i],
103 | // material.bumpScale = 1.0,
104 | material.color = this.color
105 | }
106 | }
107 |
108 | randomizeColor() {
109 |
110 | this.color.r = this.randRange(0.7, 1.0);
111 | this.color.g = this.randRange(0.7, 1.0);
112 | this.color.b = this.randRange(0.7, 1.0);
113 |
114 | this.updateMaterial();
115 | }
116 |
117 |
118 | randRange(low, high) {
119 | let range = high - low;
120 | let n = window.rng() * range;
121 | return low + n;
122 | }
123 |
124 | computeGeometry(geometry) {
125 | // geometry.makeGroups();
126 | geometry.computeVertexNormals()
127 | geometry.computeFaceNormals();
128 | geometry.computeMorphNormals();
129 | geometry.computeBoundingSphere();
130 | geometry.computeBoundingBox();
131 | // geometry.computeLineDistances();
132 |
133 | geometry.verticesNeedUpdate = true;
134 | geometry.elementsNeedUpdate = true;
135 | geometry.uvsNeedUpdate = true;
136 | geometry.normalsNeedUpdate = true;
137 | // geometry.tangentsNeedUpdate = true;
138 | geometry.colorsNeedUpdate = true;
139 | geometry.lineDistancesNeedUpdate = true;
140 | // geometry.buffersNeedUpdate = true;
141 | geometry.groupsNeedUpdate = true;
142 | }
143 |
144 | }
145 |
146 | export default Clouds;
147 |
--------------------------------------------------------------------------------
/src/css/style.css:
--------------------------------------------------------------------------------
1 | body {
2 | width: 100%;
3 | height: 100%;
4 | background-color: #000;
5 | color: #fff;
6 | margin: 0px;
7 | padding: 0;
8 | overflow: hidden;
9 | font-family: Arial, "Helvetica Neue", Helvetica, sans-serif;
10 | }
11 |
12 | #brandTag
13 | {
14 | position: fixed;
15 | display: block;
16 | top: 0px;
17 | left: 30px;
18 | color: white;
19 | background-color: rgba(0, 0, 0, 0.8);
20 | z-index: 1000;
21 | text-align: center;
22 | padding: 12px 12px 12px 12px;
23 | font-size: 18px;
24 | font-family: "Helvetica", sans-serif;
25 | transition-property: color, background-color, padding;
26 | transition-duration: 0.3s;
27 | }
28 | @media (width < 600px) {
29 |
30 | }
31 |
32 | @media screen and (max-width: 600px) {
33 | #brandTag
34 | {
35 | display: none;
36 | }
37 | #infoBoxHolder
38 | {
39 | display: none;
40 | }
41 | }
42 |
43 | @media screen and (min-width: 600px) {
44 | #infoBoxHolderMobile {
45 | display: none;
46 | }
47 | #newPlanetButtonHolder {
48 | display: none;
49 | }
50 | }
51 |
52 | #brandTag:hover
53 | {
54 | color: black;
55 | background-color: white;
56 | padding: 24px 12px 12px 12px;
57 | }
58 |
59 | #infoBoxHolder {
60 | position: absolute;
61 | z-index: 1000;
62 | top: 0px;
63 | right: 20px;
64 | color: #FFFFFF;
65 | background-color: rgba(0, 0, 0, 0.8);
66 | width: 245px;
67 | }
68 |
69 | #infoBox {
70 | padding: 12px 12px 12px 12px;
71 | font-size: 14px;
72 | font-family: "Helvetica-Light", sans-serif;
73 | line-height: 18px;
74 | }
75 |
76 | #planetName {
77 | font-size: 24px;
78 | line-height: 28px;
79 | }
80 |
81 | #instructions {
82 | font-size: 10px;
83 | }
84 |
85 | #infoBoxHolderMobile {
86 | position: absolute;
87 | z-index: 1000;
88 | top: 0px;
89 | width: 100%;
90 |
91 | }
92 |
93 | #infoBoxMobile {
94 |
95 | margin: 0 auto;
96 |
97 | width: 245px;
98 | color: #FFFFFF;
99 | background-color: rgba(0, 0, 0, 0.8);
100 | padding: 12px 12px 12px 12px;
101 | font-size: 14px;
102 | font-family: "Helvetica-Light", sans-serif;
103 | line-height: 18px;
104 | text-align: center;
105 | }
106 |
107 | #planetNameMobile {
108 | font-size: 24px;
109 | line-height: 28px;
110 | }
111 |
112 |
113 | #newPlanetButtonHolder {
114 | position: absolute;
115 | z-index: 1000;
116 | bottom: 0px;
117 | width: 100%;
118 | }
119 |
120 | #newPlanetButton {
121 | margin: 0 auto;
122 |
123 | width: 145px;
124 | color: #FFFFFF;
125 | background-color: rgba(0, 0, 0, 0.8);
126 | padding: 12px 12px 12px 12px;
127 | font-size: 18px;
128 | font-family: "Helvetica-Light", sans-serif;
129 | line-height: 18px;
130 | text-align: center;
131 | }
132 |
133 | #line {
134 | background-color: rgba(255, 255, 255, 0.2);
135 | width: 100%;
136 | height: 1px;
137 | }
138 |
139 |
140 | #biomeCanvas {
141 | position: absolute;
142 | z-index: 1000;
143 | bottom: 0px;
144 | right: 0px;
145 | }
146 |
147 | #nebulaeCanvas {
148 | position: absolute;
149 | z-index: 1000;
150 | bottom: 0px;
151 | left: 0px;
152 | }
153 |
154 | #sunCanvas {
155 | position: absolute;
156 | z-index: 1000;
157 | bottom: 0px;
158 | right: 0px;
159 | }
160 |
161 | /* Position the button VR on the bottom of the page. */
162 | #ui {
163 | position: absolute;
164 | bottom: 10px;
165 | left: 50%;
166 | transform: translate(-50%, -50%);
167 | text-align: center;
168 | font-family: 'Karla', sans-serif;
169 | z-index: 1;
170 | }
171 |
172 | a#magic-window {
173 | display: block;
174 | color: white;
175 | margin-top: 1em;
176 | }
177 |
178 | #loadingBarHolder {
179 | position: absolute;
180 |
181 | left: 0px;
182 | right: 0px;
183 | top: 0px;
184 | bottom: 0px;
185 | margin: auto;
186 |
187 | width: 245px;
188 | height: 100px;
189 |
190 | text-align: center;
191 | font-size: 18px;
192 | font-family: "Helvetica-Light", sans-serif;
193 |
194 | /* border: 1px solid #222222; */
195 | padding: 20px;
196 | padding-top: 30px;
197 | background-color: rgba(0, 0, 0, 0.8);
198 | z-index: 2000;
199 | }
200 |
201 | #loadingBarBase {
202 | width: 100%;
203 | height: 50%;
204 | margin-top: 10px;
205 | background-color: #333333;
206 | }
207 |
208 | #loadingBar {
209 | width: 50%;
210 | height: 100%;
211 | background-color: #777777;
212 | }
213 |
--------------------------------------------------------------------------------
/src/js/shaders/texture.frag:
--------------------------------------------------------------------------------
1 | import noise from 'glsl-noise/simplex/3d'
2 |
3 |
4 | varying vec2 vUv;
5 | uniform int index;
6 |
7 | int mod(int x, int m) {
8 | return int(mod(float(x), float(m)));
9 | }
10 |
11 | float random5(vec3 co) {
12 | return fract(sin(dot(co.xyz ,vec3(12.9898,78.233,1.23456))) * 43758.5453);
13 | }
14 |
15 |
16 | float random4(float x, float y, float z) {
17 | return random5(vec3(x, y, z));
18 | }
19 |
20 | float random4(int x, int y, int z) {
21 | return random4(float(x), float(y), float(z));
22 | }
23 |
24 | float interpolation(float a, float b, float x) {
25 | float ft = x * 3.1415927;
26 | float f = (1.0 - cos(ft)) * 0.5;
27 | return a*(1.0-f) + b*f;
28 | }
29 |
30 | float tricosine(vec3 coordFloat) {
31 | vec3 coord0 = vec3(floor(coordFloat.x), floor(coordFloat.y), floor(coordFloat.z));
32 | vec3 coord1 = vec3(coord0.x+1.0, coord0.y+1.0, coord0.z+1.0);
33 | float xd = (coordFloat.x - coord0.x)/max(1.0, (coord1.x-coord0.x));
34 | float yd = (coordFloat.y - coord0.y)/max(1.0, (coord1.y-coord0.y));
35 | float zd = (coordFloat.z - coord0.z)/max(1.0, (coord1.z-coord0.z));
36 | float c00 = interpolation(random4(coord0.x, coord0.y, coord0.z), random4(coord1.x, coord0.y, coord0.z), xd);
37 | float c10 = interpolation(random4(coord0.x, coord1.y, coord0.z), random4(coord1.x, coord1.y, coord0.z), xd);
38 | float c01 = interpolation(random4(coord0.x, coord0.y, coord1.z), random4(coord1.x, coord0.y, coord1.z), xd);
39 | float c11 = interpolation(random4(coord0.x, coord1.y, coord1.z), random4(coord1.x, coord1.y, coord1.z), xd);
40 | float c0 = interpolation(c00, c10, yd);
41 | float c1 = interpolation(c01, c11, yd);
42 | float c = interpolation(c0, c1, zd);
43 |
44 | return c;
45 | }
46 |
47 | float nearestNeighbour(vec3 coordFloat) {
48 | return random4(int(floor(coordFloat.x)), int(floor(coordFloat.y)), int(floor(coordFloat.z)));
49 | }
50 |
51 | float helper(float x, float y, float z, float resolution) {
52 | x = (x+1.0)/2.0*resolution;
53 | y = (y+1.0)/2.0*resolution;
54 | z = (z+1.0)/2.0*resolution;
55 |
56 | vec3 coordFloat = vec3(x, y, z);
57 | float interpolated = tricosine(coordFloat);
58 | // float interpolated = noise(coordFloat);
59 |
60 | return interpolated*2.0 - 1.0;
61 | }
62 |
63 | vec3 scalarField(float x, float y, float z) {
64 | float resolution1 = 4.0;
65 | float resolution2 = 16.0;
66 | float resolution3 = 32.0;
67 | float resolution4 = 64.0;
68 | float resolution5 = 128.0;
69 | float resolutionMax = 256.0;
70 |
71 | vec3 coordFloat = vec3(0.0, 0.0, 0.0);
72 |
73 | float level1 = helper(x, y, z, resolution1);
74 | float level2 = helper(x, y, z, resolution2);
75 | float level3 = helper(x, y, z, resolution3);
76 | float level4 = helper(x, y, z, resolution4);
77 | float level5 = helper(x, y, z, resolution5);
78 | float levelMax = helper(x, y, z, resolutionMax);
79 |
80 | float c = 0.5;
81 | c *= 1.0 + level1*0.8;
82 | c *= 1.0 + level2*0.4;
83 | c *= 1.0 + level3*0.2;
84 | c *= 1.0 + level4*0.1;
85 | c *= 1.0 + level5*0.05;
86 | c *= 1.0 + levelMax*(0.025);
87 |
88 | if (c < 0.45) c *= 0.8;
89 |
90 | c = clamp(c, 0.0, 1.0);
91 | vec3 water = vec3(0.0, 0.2, 0.4) * (0.4+c*0.5);
92 | vec3 land = vec3(0.2, 0.4, 0.3) * c*0.8;
93 | vec3 peak = vec3(0.42, 0.4, 0.42) * c;
94 | // vec3 water = vec3(0.6, 0.2, 0.2) * (0.2 + c*0.3);
95 | // vec3 land = vec3(0.5, 0.4, 0.1) * c;
96 | // vec3 peak = vec3(0.2, 0.1, 0.32) * c;
97 |
98 | if (c < 0.5) {
99 | return water;
100 | }
101 | else if (c < 0.8) {
102 | return land;
103 | }
104 | else {
105 | return peak;
106 | }
107 |
108 | // return vec3(c);
109 | }
110 |
111 | vec3 getSphericalCoord(int index, float x, float y, float width) {
112 | width /= 2.0;
113 | x -= width;
114 | y -= width;
115 | vec3 coord = vec3(0.0, 0.0, 0.0);
116 |
117 | if (index == 0) {coord.x=width; coord.y=-y; coord.z=-x;}
118 | else if (index == 1) {coord.x=-width; coord.y=-y; coord.z=x;}
119 | else if (index == 2) {coord.x=x; coord.y=width; coord.z=y;}
120 | else if (index == 3) {coord.x=x; coord.y=-width; coord.z=-y;}
121 | else if (index == 4) {coord.x=x; coord.y=-y; coord.z=width;}
122 | else if (index == 5) {coord.x=-x; coord.y=-y; coord.z=-width;}
123 |
124 | return normalize(coord);
125 | }
126 |
127 | void main() {
128 | float x = vUv.x;
129 | float y = 1.0 - vUv.y;
130 | vec3 sphericalCoord = getSphericalCoord(index, x*1024.0, y*1024.0, 1024.0);
131 |
132 | vec3 color = scalarField(sphericalCoord.x, sphericalCoord.y, sphericalCoord.z);
133 |
134 | gl_FragColor = vec4(color.x, color.y, color.z, 1.0);
135 | }
136 |
--------------------------------------------------------------------------------
/src/js/shaders/flowNoiseMap.frag:
--------------------------------------------------------------------------------
1 | import noise from 'glsl-noise/classic/3d'
2 |
3 | varying vec2 vUv;
4 | uniform int index;
5 | uniform float seed;
6 | uniform float resolution;
7 | uniform float res1;
8 | uniform float res2;
9 | uniform float resMix;
10 | uniform float mixScale;
11 | uniform float doesRidged;
12 | const int octaves = 16;
13 |
14 | // #define M_PI 3.1415926535897932384626433832795;
15 |
16 |
17 | vec3 getSphericalCoord(int index, float x, float y, float width) {
18 | width /= 2.0;
19 | x -= width;
20 | y -= width;
21 | vec3 coord = vec3(0.0, 0.0, 0.0);
22 |
23 | if (index == 0) {coord.x=width; coord.y=-y; coord.z=-x;}
24 | else if (index == 1) {coord.x=-width; coord.y=-y; coord.z=x;}
25 | else if (index == 2) {coord.x=x; coord.y=width; coord.z=y;}
26 | else if (index == 3) {coord.x=x; coord.y=-width; coord.z=-y;}
27 | else if (index == 4) {coord.x=x; coord.y=-y; coord.z=width;}
28 | else if (index == 5) {coord.x=-x; coord.y=-y; coord.z=-width;}
29 |
30 | return normalize(coord);
31 | }
32 |
33 | float simplexRidged(vec3 pos, float seed) {
34 | float n = noise(vec3(pos + seed));
35 | n = (n + 1.0) * 0.5;
36 | n = 2.0 * (0.5 - abs(0.5 - n));
37 | return n;
38 | }
39 |
40 | float simplex(vec3 pos, float seed) {
41 | float n = noise(vec3(pos + seed));
42 | return (n + 1.0) * 0.5;
43 | }
44 |
45 | float baseNoise(vec3 pos, float frq, float seed ) {
46 | float amp = 0.5;
47 |
48 | float n = 0.0;
49 | float gain = 1.0;
50 | for(int i=0; i {
52 | this.directionalLight.color.r = this.sunColor.r / 255;
53 | this.directionalLight.color.g = this.sunColor.g / 255;
54 | this.directionalLight.color.b = this.sunColor.b / 255;
55 | });
56 |
57 | lightFolder.add(this.directionalLight, "intensity", 0.0, 3.0);
58 | // this.dirLightControl.onChange(value => {});
59 |
60 | this.ambientColor = {r:255, g:255, b:255};
61 | this.ambientControl = lightFolder.addColor(this, "ambientColor").onChange(value => {
62 | this.ambientLight.color.r = this.ambientColor.r / 255;
63 | this.ambientLight.color.g = this.ambientColor.g / 255;
64 | this.ambientLight.color.b = this.ambientColor.b / 255;
65 | });
66 |
67 | lightFolder.add(this.ambientLight, "intensity", 0.0, 2.0);
68 |
69 | let cameraFolder = gui.addFolder('Camera');
70 |
71 | cameraFolder.add(this._controls, "autoRotate");
72 |
73 | this.fovControl = cameraFolder.add(this._camera, "fov", 20, 120);
74 | this.fovControl.onChange(value => { this._camera.updateProjectionMatrix() });
75 |
76 | // stats
77 | this.stats = new Stats();
78 | this.stats.setMode(0);
79 | // document.body.appendChild(this.stats.domElement);
80 | this.stats.domElement.style.position = 'absolute';
81 | this.stats.domElement.style.left = '10px';
82 | this.stats.domElement.style.top = '0px';
83 |
84 | window.addEventListener( 'resize', this.onWindowResize.bind(this), false );
85 | window.addEventListener( 'keydown', (e) => { this.onKeyDown(e) }, false );
86 |
87 |
88 | window.gui.close();
89 | }
90 |
91 | get renderer(){
92 |
93 | return this._renderer;
94 |
95 | }
96 |
97 | get camera(){
98 |
99 | return this._camera;
100 |
101 | }
102 |
103 | get scene(){
104 |
105 | return this._scene;
106 |
107 | }
108 |
109 | onKeyDown(e) {
110 | if (e.keyCode == '72')
111 | {
112 | var brandTag = document.getElementById("brandTag");
113 | var infoBoxHolder = document.getElementById("infoBoxHolder");
114 | if (brandTag.style.visibility == "hidden") {
115 | brandTag.style.visibility = "visible";
116 | infoBoxHolder.style.visibility = "visible";
117 | } else {
118 | brandTag.style.visibility = "hidden";
119 | infoBoxHolder.style.visibility = "hidden";
120 | }
121 | }
122 | }
123 |
124 | onWindowResize() {
125 |
126 | this._camera.aspect = window.innerWidth / window.innerHeight;
127 | this._camera.updateProjectionMatrix();
128 |
129 | this._renderer.setSize( window.innerWidth, window.innerHeight );
130 |
131 | }
132 |
133 | animate(timestamp) {
134 | this.stats.begin();
135 | requestAnimationFrame( this.animate.bind(this) );
136 |
137 | this._controls.update();
138 | this._renderer.render( this._scene, this._camera );
139 | this.stats.end();
140 | }
141 |
142 |
143 | }
144 | export default AbstractApplication;
145 |
--------------------------------------------------------------------------------
/src/js/shaders/cloudMap.frag:
--------------------------------------------------------------------------------
1 | import noise from 'glsl-noise/classic/4d'
2 |
3 | varying vec2 vUv;
4 | uniform int index;
5 | uniform float seed;
6 | uniform float resolution;
7 | uniform float res1;
8 | uniform float res2;
9 | uniform float resMix;
10 | uniform float mixScale;
11 |
12 | vec3 getSphericalCoord(int index, float x, float y, float width) {
13 | width /= 2.0;
14 | x -= width;
15 | y -= width;
16 | vec3 coord = vec3(0.0, 0.0, 0.0);
17 |
18 | if (index == 0) {coord.x=width; coord.y=-y; coord.z=-x;}
19 | else if (index == 1) {coord.x=-width; coord.y=-y; coord.z=x;}
20 | else if (index == 2) {coord.x=x; coord.y=width; coord.z=y;}
21 | else if (index == 3) {coord.x=x; coord.y=-width; coord.z=-y;}
22 | else if (index == 4) {coord.x=x; coord.y=-y; coord.z=width;}
23 | else if (index == 5) {coord.x=-x; coord.y=-y; coord.z=-width;}
24 |
25 | return normalize(coord);
26 | }
27 |
28 | // float simplexRidged(vec3 pos, float seed) {
29 | // float n = noise(vec4(pos, seed));
30 | // n = (n + 1.0) * 0.5;
31 | // n = 2.0 * (0.5 - abs(0.5 - n));
32 | // return n;
33 | // }
34 |
35 | float simplexRidged(vec3 pos, float seed) {
36 | float n = noise(vec4(pos, seed));
37 | // n = (n + 1.0) * 0.5;
38 | // n = 2.0 * (0.5 - abs(0.5 - n));
39 | n = abs(n);
40 | return n;
41 | }
42 |
43 | float simplex(vec3 pos, float seed) {
44 | float n = noise(vec4(pos, seed));
45 | // return (n + 1.0) * 0.5;
46 | n = (n + 1.0) * 0.5;
47 | // n = 2.0 * (0.5 - abs(0.5 - n));
48 | return n;
49 | }
50 |
51 | float baseNoise(vec3 pos, float frq, float seed ) {
52 | const int octaves = 16;
53 | float amp = 0.5;
54 |
55 | float n = 0.0;
56 | float gain = 1.0;
57 | for(int i=0; i 0 ) {
134 |
135 | if ( this.INTERSECTED != intersects[ 0 ].object ) {
136 |
137 | if ( this.INTERSECTED ) this.INTERSECTED.material.emissive.setHex( this.INTERSECTED.currentHex );
138 |
139 | this.INTERSECTED = intersects[ 0 ].object;
140 | this.INTERSECTED.currentHex = this.INTERSECTED.material.emissive.getHex();
141 | this.INTERSECTED.material.emissive.setHex( 0xff0000 );
142 |
143 | }
144 |
145 | } else {
146 |
147 | if ( this.INTERSECTED ) this.INTERSECTED.material.emissive.setHex( this.INTERSECTED.currentHex );
148 |
149 | this.INTERSECTED = undefined;
150 |
151 | }
152 |
153 | // Keep cubes inside room
154 |
155 | for ( let i = 0; i < this.room.children.length; i ++ ) {
156 |
157 | const cube = this.room.children[ i ];
158 |
159 | cube.userData.velocity.multiplyScalar( 1 - ( 0.001 * delta ) );
160 |
161 | cube.position.add( cube.userData.velocity );
162 |
163 | if ( cube.position.x < - 3 || cube.position.x > 3 ) {
164 |
165 | cube.position.x = THREE.Math.clamp( cube.position.x, - 3, 3 );
166 | cube.userData.velocity.x = - cube.userData.velocity.x;
167 |
168 | }
169 |
170 | if ( cube.position.y < - 3 || cube.position.y > 3 ) {
171 |
172 | cube.position.y = THREE.Math.clamp( cube.position.y, - 3, 3 );
173 | cube.userData.velocity.y = - cube.userData.velocity.y;
174 |
175 | }
176 |
177 | if ( cube.position.z < - 3 || cube.position.z > 3 ) {
178 |
179 | cube.position.z = THREE.Math.clamp( cube.position.z, - 3, 3 );
180 | cube.userData.velocity.z = - cube.userData.velocity.z;
181 |
182 | }
183 |
184 | cube.rotation.x += cube.userData.velocity.x * 2 * delta;
185 | cube.rotation.y += cube.userData.velocity.y * 2 * delta;
186 | cube.rotation.z += cube.userData.velocity.z * 2 * delta;
187 |
188 | }
189 |
190 | this.controls.update();
191 | this.effect.render(this.scene, this.camera);
192 |
193 | }
194 |
195 | }
196 | export default Main;
--------------------------------------------------------------------------------
/src/js/views/atmosReference.js:
--------------------------------------------------------------------------------
1 | // Initialize THREE.js
2 | var scene = new THREE.Scene();
3 | var width = window.innerWidth - 200;
4 | var camera = new THREE.PerspectiveCamera( 30, width / window.innerHeight, 0.1, 20000 );
5 | var renderer = new THREE.WebGLRenderer({
6 | antialias: true
7 | });
8 |
9 | renderer.setSize( width, window.innerHeight);
10 | document.body.appendChild( renderer.domElement );
11 |
12 | // Initialize global variables
13 | // Geometries
14 | var radius = 100;
15 | var planetGeometry = new THREE.SphereGeometry( radius, 70, 70);
16 | var sunGeometry = new THREE.SphereGeometry( radius, 40, 40);
17 | radius += 0.1; // Prevents clipping problems between atmosphere and planet
18 | var atmosphereGeometry = new THREE.SphereGeometry(radius*1.025, 100, 100);
19 | var atmosphereGroundGeometry = new THREE.SphereGeometry(radius*1.01, 70, 70);
20 |
21 | var sunColor = new THREE.Vector4(1,0.765,0.302,1);
22 | var clock = new THREE.Clock();
23 | var sunPos = new THREE.Vector3(0, 0, 4000);
24 | var placeholderColor = new THREE.Vector4(0,0,0,1);
25 |
26 | // Atmsphere variable used in the atmosphere shader
27 | var atmosphere = {
28 | Kr: 0.0025,
29 | Km: 0.0010,
30 | ESun: 20.0,
31 | g: -0.950,
32 | innerRadius: 100,
33 | outerRadius: 102.5,
34 | wavelength: [0.650, 0.570, 0.475],
35 | scaleDepth: 0.25,
36 | mieScaleDepth: 0.1
37 | };
38 |
39 | // Initialize UI sliders
40 | $("#noiseIntensity").noUiSlider({ range: { 'min': 1, 'max': 100 }, snap: false, start: 50 });
41 | $("#noiseVariation").noUiSlider({ range: { 'min': 1, 'max': 100 }, snap: false, start: 50 });
42 | $("#waterLevel").noUiSlider({ range: { 'min': -25, 'max': 25 }, snap: false, start: 2.20 });
43 |
44 | $("#waterLevel").Link('lower').to($("#waterLevelValue"));
45 | $("#noiseIntensity").Link('lower').to($("#noiseIntensityValue"));
46 | $("#noiseVariation").Link('lower').to($("#noiseVariationValue"));
47 |
48 | // Load shaders
49 | SHADER_LOADER.load(
50 | function (data)
51 | {
52 | // Initialize uniforms to send to the shaders
53 | planetUniforms = {
54 | time: { type: "f", value: 0 },
55 | level: { type: "f", value: camera.position.length()},
56 | sunPos: {type: "v3", value: sunPos},
57 | diffuseLight: {type: "v4", value: sunColor},
58 | diffuseMaterial: {type: "v4", value: placeholderColor},
59 | sealevel: {type: "f", value: 0},
60 | noiseIntensity: {type: "f", value: 0},
61 | noiseType: {type: "f", value: 1},
62 | noiseVariation: {type: "f", value: 0},
63 | waterColor: {type: "v3", value: placeholderColor},
64 | renderLevels: {type: "fv1", value: [6000.0, 6000.0, 6000.0, 5000.0, 1800.0, 950.0, 850.0, 500.0, 500, 500]},
65 | shoreColor: {type: "v3", value: placeholderColor},
66 | cloudColor: {type: "v3", value: placeholderColor},
67 | renderClouds: {type: "f", value: 1}
68 | };
69 |
70 | sunUniforms = {
71 | diffuseLight: {type: "v4", value : sunColor}
72 | }
73 |
74 | // Used for the atmosphere shader
75 | atmosphereUniforms = {
76 | v3LightPosition: {type: "v3",value: new THREE.Vector3(0,0,1)},
77 | v3InvWavelength: {type: "v3",value: new THREE.Vector3(1 / Math.pow(atmosphere.wavelength[0], 4), 1 / Math.pow(atmosphere.wavelength[1], 4), 1 / Math.pow(atmosphere.wavelength[2], 4))},
78 | fCameraHeight: {type: "f",value: 0},
79 | fCameraHeight2: {type: "f",value: 0},
80 | fInnerRadius: {type: "f",value: atmosphere.innerRadius},
81 | fInnerRadius2: {type: "f",value: atmosphere.innerRadius * atmosphere.innerRadius},
82 | fOuterRadius: {type: "f",value: atmosphere.outerRadius},
83 | fOuterRadius2: {type: "f",value: atmosphere.outerRadius * atmosphere.outerRadius},
84 | fKrESun: {type: "f",value: atmosphere.Kr * atmosphere.ESun},
85 | fKmESun: {type: "f",value: atmosphere.Km * atmosphere.ESun},
86 | fKr4PI: {type: "f",value: atmosphere.Kr * 4.0 * Math.PI},
87 | fKm4PI: {type: "f",value: atmosphere.Km * 4.0 * Math.PI},
88 | fScale: {type: "f",value: 1 / (atmosphere.outerRadius - atmosphere.innerRadius)},
89 | fScaleDepth: {type: "f",value: atmosphere.scaleDepth},
90 | fScaleOverScaleDepth: {type: "f",value: 1 / (atmosphere.outerRadius - atmosphere.innerRadius) / atmosphere.scaleDepth},
91 | g: {type: "f",value: atmosphere.g},
92 | g2: {type: "f",value: atmosphere.g * atmosphere.g},
93 | nSamples: {type: "i",value: 3},
94 | fSamples: {type: "f",value: 3.0},
95 | atmosphereColor: {type: "v3",value: placeholderColor},
96 | tDisplacement: {type: "t",value: 0},
97 | tSkyboxDiffuse: {type: "t",value: 0},
98 | fNightScale: {type: "f",value: 1},
99 | level: { type: "f", value: camera.position.length()}
100 | };
101 |
102 | // Load shaders using Shader Loader JS
103 | var vShader = data.shader.vertex;
104 | var fShader = data.shader.fragment;
105 | var vShaderSun = data.shaderSun.vertex;
106 | var fShaderSun = data.shaderSun.fragment;
107 | var vShaderAtmosphere = data.shaderAtmosphere.vertex;
108 | var fShaderAtmosphere = data.shaderAtmosphere.fragment;
109 | var vShaderAtmosphereGround = data.shaderAtmosphereGround.vertex;
110 | var fShaderAtmosphereGround = data.shaderAtmosphereGround.fragment;
111 |
112 | // Create shader materials
113 | planetShader = new THREE.ShaderMaterial({
114 | uniforms: planetUniforms,
115 | vertexShader: vShader,
116 | fragmentShader: fShader
117 | });
118 |
119 | sunShader = new THREE.ShaderMaterial({
120 | uniforms: sunUniforms,
121 | vertexShader: vShaderSun,
122 | fragmentShader: fShaderSun
123 | });
124 |
125 | // The atmosphere outside the planet
126 | atmosphereShader = new THREE.ShaderMaterial({
127 | uniforms: atmosphereUniforms,
128 | vertexShader: vShaderAtmosphere,
129 | fragmentShader: fShaderAtmosphere,
130 | transparent: true,
131 | side: THREE.BackSide
132 | });
133 |
134 | // The atmosphere on the planet
135 | atmosphereGroundShader = new THREE.ShaderMaterial({
136 | uniforms: atmosphereUniforms,
137 | vertexShader: vShaderAtmosphereGround,
138 | fragmentShader: fShaderAtmosphereGround,
139 | transparent: true,
140 | });
141 |
142 | initialize();
143 | }
144 | );
145 |
146 | // Let's get this party started
147 | function initialize() {
148 | // Create meshes
149 | planetMesh = new THREE.Mesh(planetGeometry, planetShader);
150 | sunMesh = new THREE.Mesh(sunGeometry, sunShader);
151 | atmosphereMesh = new THREE.Mesh(atmosphereGeometry, atmosphereShader);
152 | atmosphereGroundMesh = new THREE.Mesh(atmosphereGroundGeometry, atmosphereGroundShader);
153 |
154 | // Add meshes
155 | scene.add( planetMesh );
156 | scene.add( sunMesh );
157 | scene.add( atmosphereMesh );
158 | scene.add( atmosphereGroundMesh );
159 |
160 | // Alter meshes
161 | sunMesh.scale.set(3,3,3);
162 | sunMesh.position.set(sunPos.x,sunPos.y,sunPos.z);
163 |
164 | // Handle user controls
165 | controls = new THREE.TrackballControls( camera, renderer.domElement);
166 | controls.target.set( 0, 0, 0 );
167 | controls.minDistance = 200.0;
168 | controls.maxDistance = 5000;
169 | controls.zoomSpeed = 0.1;
170 | controls.rotateSpeed = 0.05;
171 | controls.noPan = true;
172 |
173 | camera.position = new THREE.Vector3(atmosphere.innerRadius*6,atmosphere.innerRadius,atmosphere.innerRadius*2);
174 |
175 | render();
176 | };
177 |
178 | // Rendering function, runs (hopefully) many times every frame
179 | function render() {
180 | // Update uniforms
181 | var delta = clock.getDelta();
182 | updateUniforms(delta);
183 |
184 | // Update world
185 | planetMesh.rotation.y += 0.001;
186 | controls.update();
187 |
188 | if($('#renderAtmosphere').prop('checked')) {
189 | atmosphereMesh.visible = true;
190 | atmosphereGroundMesh.visible = true;
191 | } else {
192 | atmosphereMesh.visible = false;
193 | atmosphereGroundMesh.visible = false;
194 | }
195 |
196 | if($('#renderClouds').prop('checked'))
197 | planetUniforms.renderClouds.value = 1;
198 | else
199 | planetUniforms.renderClouds.value = 0;
200 |
201 | renderer.render( scene, camera );
202 |
203 | // Call render again
204 | requestAnimationFrame( render );
205 | };
206 |
207 | function updateUniforms(delta) {
208 | var atmosphereColor;
209 | var color = $("#atmosphereColor").val();
210 |
211 | // Handle atmosphere color
212 | switch(color) {
213 | case "Blue":
214 | atmosphereColor = new THREE.Vector3(0.72,0.77,0.35);
215 | break;
216 | case "Pink":
217 | atmosphereColor = new THREE.Vector3(0.42,0.97,0.375);
218 | break;
219 | case "Green":
220 | atmosphereColor = new THREE.Vector3(0.72,0.37,0.575);
221 | break;
222 | case "Orange":
223 | atmosphereColor = new THREE.Vector3(0.36,0.524,0.79);
224 | break;
225 | case "White":
226 | atmosphereColor = new THREE.Vector3(0.66,0.424,0.34);
227 | break;
228 | }
229 |
230 | // Update planet uniforms
231 | planetUniforms.time.value += delta;
232 | planetUniforms.level.value = camera.position.distanceTo(new THREE.Vector3(0,0,0));
233 | planetUniforms.sealevel.value = $("#waterLevel").val()/120;
234 | planetUniforms.noiseIntensity.value = $("#noiseIntensity").val()/1000;
235 | planetUniforms.noiseType.value = $("#noiseType").val();
236 | planetUniforms.noiseVariation.value = $("#noiseVariation").val()/70;
237 | planetUniforms.waterColor.value = new THREE.Vector3(document.getElementById('waterColor').color.rgb[0],document.getElementById('waterColor').color.rgb[1],document.getElementById('waterColor').color.rgb[2]);
238 | planetUniforms.shoreColor.value = new THREE.Vector3(document.getElementById('shoreColor').color.rgb[0],document.getElementById('shoreColor').color.rgb[1],document.getElementById('shoreColor').color.rgb[2]);
239 | planetUniforms.cloudColor.value = new THREE.Vector3(document.getElementById('cloudColor').color.rgb[0],document.getElementById('cloudColor').color.rgb[1],document.getElementById('cloudColor').color.rgb[2]);
240 | planetUniforms.diffuseMaterial.value = new THREE.Vector4(document.getElementById('landColor').color.rgb[0],document.getElementById('landColor').color.rgb[1],document.getElementById('landColor').color.rgb[2],1);
241 |
242 | // Atmosphere
243 | var cameraHeight = camera.position.length();
244 | atmosphereUniforms.fCameraHeight.value = cameraHeight;
245 | atmosphereUniforms.fCameraHeight2.value = cameraHeight * cameraHeight;
246 | atmosphereUniforms.v3InvWavelength.value = new THREE.Vector3(1 / Math.pow(atmosphereColor.x,4),1 / Math.pow(atmosphereColor.y,4),1 / Math.pow(atmosphereColor.z,4));
247 | atmosphereUniforms.level.value = camera.position.distanceTo(new THREE.Vector3(0,0,0));
248 | }
249 |
250 | // Update window if resized
251 | $(window).resize(function( event ) {
252 | width = window.innerWidth - 200;
253 | renderer.setSize( width, window.innerHeight);
254 | camera.aspect = width / window.innerHeight;
255 | camera.updateProjectionMatrix();
256 | });
257 |
258 | // Handle user browser notification
259 | // IE can't even render the planet
260 | // FF produces weird noise artefacts that I don't have time to fix ( related to sphere geometry? )
261 | var isFirefox = typeof InstallTrigger !== 'undefined';
262 | var isIE = /*@cc_on!@*/false || !!document.documentMode;
263 | if(isIE || isFirefox){
264 | $("body").before("This application runs the best in the newest versions of safari or chrome
");
265 | $("#renderClouds").remove();
266 | $("#renderCloudsP").remove();
267 | }
268 |
--------------------------------------------------------------------------------
/src/js/views/Biome.js:
--------------------------------------------------------------------------------
1 | import * as THREE from 'three'
2 |
3 |
4 | class Biome {
5 |
6 | constructor() {
7 |
8 | this.canvas = document.createElement("canvas");
9 | this.canvas.id = "biomeCanvas";
10 | this.canvas.width = 512;
11 | this.canvas.height = 512;
12 | this.canvas.style.width = "200px";
13 | this.canvas.style.height = "200px";
14 | this.width = this.canvas.width;
15 | this.height = this.canvas.height;
16 | this.ctx = this.canvas.getContext("2d");
17 |
18 | document.body.appendChild(this.canvas);
19 | this.toggleCanvasDisplay(false);
20 |
21 | }
22 |
23 | generateTexture(props) {
24 |
25 | this.waterLevel = props.waterLevel;
26 |
27 | let h = this.randRange(0.0, 1.0);
28 | let s = this.randRange(0.0, 0.7);
29 | let l = this.randRange(0.0, 0.6);
30 | this.baseColor = new THREE.Color().setHSL(h, s, l);
31 | this.colorAngle = this.randRange(0.2, 0.4)
32 | this.satRange = this.randRange(0.3, 0.5);
33 | this.lightRange = this.randRange(0.3, 0.5);
34 | this.circleSize = this.randRange(30, 250);
35 | // this.circleSize = 100;
36 |
37 |
38 | this.drawBase();
39 |
40 | // circles
41 | let numCircles = Math.round(this.randRange(50, 100));
42 | numCircles = 100;
43 | for (let i=0; i 0.7) {
330 | // let diff = c.l - 0.7;
331 | // c.l = 0.7 - diff;
332 | // }
333 |
334 | // c.s = this.randRange(0.0, 0.7);
335 | // c.l = this.randRange(0.0, 1.0);
336 |
337 | newColor.setHSL(c.h, c.s, c.l);
338 |
339 | // newColor.offsetHSL(hOffset, sOffset, lOffset);
340 |
341 | return {r: Math.round(newColor.r*255),
342 | g: Math.round(newColor.g*255),
343 | b: Math.round(newColor.b*255)};
344 |
345 | }
346 |
347 | // randomColor() {
348 | //
349 | // let newColor = this.baseColor.clone();
350 | //
351 | // let hOffset = 0.0;
352 | // let range = 0.1;
353 | // let n = this.randRange(0,1);
354 | // if (n < 0.33) {
355 | // hOffset = 0.0 + this.randRange(-range, range);
356 | // } else if (n < 0.66) {
357 | // hOffset = this.colorAngle + this.randRange(-range, range);
358 | // } else {
359 | // hOffset = -this.colorAngle + this.randRange(-range, range);
360 | // }
361 | //
362 | // newColor.offsetHSL(hOffset, 0, 0);
363 | // let c = newColor.getHSL();
364 | // newColor.setHSL(c.h, this.randRange(0.0, 0.8), this.randRange(0.0, 0.6));
365 | //
366 | // return {r: Math.round(newColor.r*255),
367 | // g: Math.round(newColor.g*255),
368 | // b: Math.round(newColor.b*255)};
369 | //
370 | // }
371 |
372 | toCanvasColor(c) {
373 | return "rgba("+Math.round(c.r*255)+", "+Math.round(c.g*255)+", "+Math.round(c.b*255)+", 1.0)";
374 | }
375 |
376 | randRange(low, high) {
377 | let range = high - low;
378 | let n = window.rng() * range;
379 | return low + n;
380 | }
381 |
382 | mix(v1, v2, amount) {
383 | let dist = v2 - v1;
384 | return v1 + (dist * amount);
385 | }
386 |
387 | }
388 |
389 | export default Biome;
390 |
--------------------------------------------------------------------------------
/src/js/views/Planet.js:
--------------------------------------------------------------------------------
1 | import * as THREE from 'three'
2 | import textureVert from 'shaders/texture.vert'
3 | import textureFrag from 'shaders/textureMap.frag'
4 | import normalMapFrag from 'shaders/normalMap.frag'
5 | import normalMapVert from 'shaders/normalMap.vert'
6 | import roughnessMapFrag from 'shaders/roughnessMap.frag'
7 | import Biome from 'views/Biome'
8 | import Atmosphere from 'views/Atmosphere.js'
9 | import NoiseMap from 'views/NoiseMap.js'
10 | import TextureMap from 'views/TextureMap.js'
11 | import NormalMap from 'views/NormalMap.js'
12 | import RoughnessMap from 'views/RoughnessMap.js'
13 | import Clouds from 'views/Clouds.js'
14 | import Stars from 'views/Stars.js'
15 | import Nebula from 'views/Nebula.js'
16 | import Sun from 'views/Sun.js'
17 | import Glow from 'views/Glow.js'
18 | import NebulaeGradient from 'views/NebulaeGradient.js'
19 | import seedrandom from 'seedrandom'
20 | import randomString from 'crypto-random-string'
21 | import AtmosphereRing from 'views/AtmosphereRing.js'
22 | import randomLorem from 'random-lorem'
23 |
24 |
25 | class Planet {
26 |
27 | constructor() {
28 |
29 | this.seedString = "Scarlett";
30 | this.initSeed();
31 |
32 | this.view = new THREE.Object3D();
33 |
34 | this.materials = [];
35 | this.roughness = 0.8;
36 | this.metalness = 0.5;
37 | this.normalScale = 3.0;
38 | this.resolution = 1024;
39 | this.size = 1000;
40 | this.waterLevel = 0.0;
41 | // this.waterLevel = 0.5;
42 |
43 | this.heightMaps = [];
44 | this.moistureMaps = [];
45 | this.textureMaps = [];
46 | this.normalMaps = [];
47 | this.roughnessMaps = [];
48 |
49 | let matFolder = gui.addFolder('Material');
50 |
51 | this.roughnessControl = matFolder.add(this, "roughness", 0.0, 1.0);
52 | this.roughnessControl.onChange(value => { this.updateMaterial(); });
53 |
54 | this.metalnessControl = matFolder.add(this, "metalness", 0.0, 1.0);
55 | this.metalnessControl.onChange(value => { this.updateMaterial(); });
56 |
57 | this.normalScaleControl = matFolder.add(this, "normalScale", -3.0, 6.0).listen();
58 | this.normalScaleControl.onChange(value => { this.updateMaterial(); });
59 |
60 | // debug options
61 | this.displayMap = "textureMap";
62 | let debugFolder = gui.addFolder('Debug');
63 | this.displayMapControl = debugFolder.add(this, "displayMap", ["textureMap", "heightMap", "moistureMap", "normalMap", "roughnessMap"]);
64 | this.displayMapControl.onChange(value => { this.updateMaterial(); });
65 |
66 | this.showBiomeMap = false;
67 | this.showBiomeMapControl = debugFolder.add(this, "showBiomeMap");
68 | this.showBiomeMapControl.onChange(value => {
69 | if (this.biome) {
70 | this.biome.toggleCanvasDisplay(value);
71 | }
72 | });
73 |
74 | this.showNebulaMap = false;
75 | this.showNebulaMapControl = debugFolder.add(this, "showNebulaMap");
76 | this.showNebulaMapControl.onChange(value => {
77 | if (this.nebulaeGradient) {
78 | this.nebulaeGradient.toggleCanvasDisplay(value);
79 | }
80 | });
81 |
82 |
83 |
84 |
85 | this.biome = new Biome();
86 | this.nebulaeGradient = new NebulaeGradient();
87 |
88 | this.createScene();
89 | this.createStars();
90 | this.createNebula();
91 | this.createSun();
92 | // this.createClouds();
93 | // this.createGlow();
94 |
95 | // this.atmosphereRing = new AtmosphereRing();
96 | // this.view.add(this.atmosphereRing.view);
97 |
98 | this.createAtmosphere();
99 | this.loadSeedFromURL();
100 |
101 |
102 | ////////////////// environment gui
103 | let enviromentFolder = gui.addFolder('Environment');
104 | enviromentFolder.add(this.atmosphere, "atmosphere", 0.0, 1.0).step(0.01);
105 | enviromentFolder.add(this.nebula, "nebula", 0.0, 1.0).step(0.01).onChange(value => {
106 | this.nebula.updateMaterial();
107 | });
108 |
109 |
110 | this.rotate = true;
111 | this.autoGenerate = false;
112 | this.autoGenCountCurrent = 0;
113 | this.autoGenTime = 3*60;
114 | this.autoGenCountMax = this.autoGenTime * 60;
115 |
116 | window.gui.add(this, "rotate");
117 |
118 | this.resolutionControl = window.gui.add(this, "resolution", [256, 512, 1024, 2048, 4096]);
119 | this.resolutionControl.onChange(value => { this.regenerate(); });
120 |
121 | debugFolder.add(this, "autoGenerate");
122 | this.autoGenTimeControl = debugFolder.add(this, "autoGenTime", 30, 300).step(1);
123 | this.autoGenTimeControl.onChange(value => { this.autoGenCountMax = this.autoGenTime * 60 });
124 |
125 | this.seedStringControl = window.gui.add(this, "seedString").listen();
126 | this.seedStringControl.onFinishChange(value => { this.loadSeedFromTextfield(); });
127 | // window.gui.add(this, "regenerate");
128 | window.gui.add(this, "randomize");
129 |
130 | document.addEventListener('keydown', (event) => {
131 | if (event.keyCode == 32) {
132 | this.randomize();
133 | }
134 | });
135 |
136 | window.onpopstate = (event) => {
137 | this.loadSeedFromURL();
138 | };
139 |
140 | this.renderUI();
141 |
142 | }
143 |
144 | update() {
145 | if (this.rotate) {
146 | this.ground.rotation.y += 0.0005;
147 | this.stars.view.rotation.y += 0.0003;
148 | this.nebula.view.rotation.y += 0.0003;
149 | // this.clouds.view.rotation.y += 0.0007;
150 | }
151 |
152 | this.atmosphere.update();
153 |
154 |
155 |
156 | // this.glow.update();
157 |
158 | if (this.autoGenerate) {
159 | this.autoGenCountCurrent++;
160 | if (this.autoGenCountCurrent > this.autoGenCountMax) {
161 | this.randomize();
162 | }
163 | }
164 |
165 | this.stars.view.position.copy(window.camera.position);
166 | this.nebula.view.position.copy(window.camera.position);
167 |
168 | // this.atmosphereRing.update();
169 |
170 | }
171 |
172 | renderUI(){
173 | let infoBoxHolder = document.createElement("div");
174 | infoBoxHolder.setAttribute("id", "infoBoxHolder");
175 | document.body.appendChild(infoBoxHolder);
176 |
177 | let infoBox = document.createElement("div");
178 | infoBox.setAttribute("id", "infoBox");
179 | infoBox.innerHTML = "Planet
H - Show/Hide UI
SPACEBAR - New Planet
";
180 | infoBoxHolder.appendChild(infoBox);
181 |
182 | let line = document.createElement("div");
183 | line.setAttribute("id", "line");
184 | infoBoxHolder.appendChild(line);
185 | infoBoxHolder.appendChild(window.gui.domElement);
186 |
187 | // mobile info box
188 | let mobileInfoBox = document.createElement("div");
189 | mobileInfoBox.setAttribute("id", "infoBoxHolderMobile");
190 | mobileInfoBox.innerHTML = "";
191 | document.body.appendChild(mobileInfoBox);
192 |
193 | this.updatePlanetName();
194 |
195 | // new planet button
196 | let newPlanetButtonHolder = document.createElement("div");
197 | newPlanetButtonHolder.setAttribute("id", "newPlanetButtonHolder");
198 | newPlanetButtonHolder.innerHTML = "New Planet
";
199 | document.body.appendChild(newPlanetButtonHolder);
200 |
201 | let newPlanetButton = document.getElementById("newPlanetButton");
202 | newPlanetButton.addEventListener('click', (e) => {this.randomize()} );
203 | }
204 |
205 | updatePlanetName() {
206 | let planetName = document.getElementById("planetName");
207 | if (planetName != null) {
208 | planetName.innerHTML = this.seedString;
209 | }
210 |
211 | let planetNameMobile = document.getElementById("planetNameMobile");
212 | if (planetNameMobile != null) {
213 | planetNameMobile.innerHTML = this.seedString;
214 | }
215 | }
216 |
217 | initSeed() {
218 | window.rng = seedrandom(this.seedString);
219 | }
220 |
221 | loadSeedFromURL() {
222 | this.seedString = this.getParameterByName("seed");
223 | if (this.seedString) {
224 | console.log("seed string exists");
225 | this.regenerate();
226 | } else {
227 | console.log("no seed string");
228 | this.randomize();
229 | }
230 |
231 | }
232 |
233 | loadSeedFromTextfield() {
234 | let url = this.updateQueryString("seed", this.seedString);
235 | window.history.pushState({seed: this.seedString}, this.seedString, url);
236 | this.regenerate();
237 | }
238 |
239 | regenerate() {
240 | this.autoGenCountCurrent = 0;
241 | this.renderScene();
242 | }
243 |
244 | randomize() {
245 | // this.seedString = randomString(10);
246 |
247 | let n = Math.random();
248 | let wordCount = 0;
249 | if (n > 0.8) wordCount = 1;
250 | else if (n > 0.4) wordCount = 2;
251 | else wordCount = 3;
252 |
253 | this.seedString = "";
254 | for (let i=0; i {
393 | this.updateMaterial();
394 | });
395 | }
396 |
397 | updateMaterial() {
398 | for (let i=0; i<6; i++) {
399 | let material = this.materials[i];
400 | material.roughness = this.roughness;
401 | material.metalness = this.metalness;
402 |
403 | if (this.displayMap == "textureMap") {
404 | material.map = this.textureMaps[i];
405 | material.normalMap = this.normalMaps[i];
406 | material.normalScale = new THREE.Vector2(this.normalScale, this.normalScale);
407 | material.roughnessMap = this.roughnessMaps[i];
408 | // material.metalnessMap = this.roughnessMaps[i];
409 | }
410 | else if (this.displayMap == "heightMap") {
411 | material.map = this.heightMaps[i];
412 | material.normalMap = null;
413 | material.roughnessMap = null;
414 | }
415 | else if (this.displayMap == "moistureMap") {
416 | material.map = this.moistureMaps[i];
417 | material.normalMap = null;
418 | material.roughnessMap = null;
419 | }
420 | else if (this.displayMap == "normalMap") {
421 | material.map = this.normalMaps[i];
422 | material.normalMap = null;
423 | material.roughnessMap = null;
424 | }
425 | else if (this.displayMap == "roughnessMap") {
426 | material.map = this.roughnessMaps[i];
427 | material.normalMap = null;
428 | material.roughnessMap = null;
429 | }
430 |
431 | material.needsUpdate = true;
432 | }
433 | }
434 |
435 | renderBiomeTexture() {
436 | this.biome.generateTexture({waterLevel: this.waterLevel});
437 | }
438 |
439 | renderNebulaeGradient() {
440 | this.nebulaeGradient.generateTexture();
441 | }
442 |
443 | createAtmosphere() {
444 | this.atmosphere = new Atmosphere();
445 | // this.atmosphere.color = this.glow.color;
446 | this.view.add(this.atmosphere.view);
447 | }
448 |
449 | createGlow() {
450 | this.glow = new Glow();
451 | // this.glow.color = this.atmosphere.color;
452 | this.view.add(this.glow.view);
453 | }
454 |
455 | createClouds() {
456 | this.clouds = new Clouds();
457 | this.view.add(this.clouds.view);
458 | }
459 |
460 | createStars() {
461 | this.stars = new Stars();
462 | this.view.add(this.stars.view);
463 | }
464 |
465 | createNebula() {
466 | this.nebula = new Nebula();
467 | this.view.add(this.nebula.view);
468 | }
469 |
470 | createSun() {
471 | this.sun = new Sun();
472 | this.view.add(this.sun.view);
473 | }
474 |
475 | updateNormalScaleForRes(value) {
476 | if (value == 256) this.normalScale = 0.25;
477 | if (value == 512) this.normalScale = 0.5;
478 | if (value == 1024) this.normalScale = 1.0;
479 | if (value == 2048) this.normalScale = 1.5;
480 | if (value == 4096) this.normalScale = 3.0;
481 | }
482 |
483 | randRange(low, high) {
484 | let range = high - low;
485 | let n = window.rng() * range;
486 | return low + n;
487 | }
488 |
489 | computeGeometry(geometry) {
490 | // geometry.makeGroups();
491 | geometry.computeVertexNormals()
492 | geometry.computeFaceNormals();
493 | geometry.computeMorphNormals();
494 | geometry.computeBoundingSphere();
495 | geometry.computeBoundingBox();
496 | // geometry.computeLineDistances();
497 |
498 | geometry.verticesNeedUpdate = true;
499 | geometry.elementsNeedUpdate = true;
500 | geometry.uvsNeedUpdate = true;
501 | geometry.normalsNeedUpdate = true;
502 | // geometry.tangentsNeedUpdate = true;
503 | geometry.colorsNeedUpdate = true;
504 | geometry.lineDistancesNeedUpdate = true;
505 | // geometry.buffersNeedUpdate = true;
506 | geometry.groupsNeedUpdate = true;
507 | }
508 |
509 | updateQueryString(key, value, url) {
510 | if (!url) url = window.location.href;
511 | var re = new RegExp("([?&])" + key + "=.*?(&|#|$)(.*)", "gi"),
512 | hash;
513 |
514 | if (re.test(url)) {
515 | if (typeof value !== 'undefined' && value !== null)
516 | return url.replace(re, '$1' + key + "=" + value + '$2$3');
517 | else {
518 | hash = url.split('#');
519 | url = hash[0].replace(re, '$1$3').replace(/(&|\?)$/, '');
520 | if (typeof hash[1] !== 'undefined' && hash[1] !== null)
521 | url += '#' + hash[1];
522 | return url;
523 | }
524 | }
525 | else {
526 | if (typeof value !== 'undefined' && value !== null) {
527 | var separator = url.indexOf('?') !== -1 ? '&' : '?';
528 | hash = url.split('#');
529 | url = hash[0] + separator + key + '=' + value;
530 | if (typeof hash[1] !== 'undefined' && hash[1] !== null)
531 | url += '#' + hash[1];
532 | return url;
533 | }
534 | else
535 | return url;
536 | }
537 | }
538 |
539 | getParameterByName(name, url) {
540 | if (!url) url = window.location.href;
541 | name = name.replace(/[\[\]]/g, "\\$&");
542 | var regex = new RegExp("[?&]" + name + "(=([^]*)|&|#|$)"),
543 | results = regex.exec(url);
544 | if (!results) return null;
545 | if (!results[2]) return '';
546 | return decodeURIComponent(results[2].replace(/\+/g, " "));
547 | }
548 |
549 | }
550 |
551 | export default Planet;
552 |
--------------------------------------------------------------------------------