add controls
This commit is contained in:
parent
afe89c4c79
commit
d08cdd4177
26
package-lock.json
generated
26
package-lock.json
generated
@ -11,7 +11,9 @@
|
|||||||
"three": "^0.147.0"
|
"three": "^0.147.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/dat.gui": "^0.7.9",
|
||||||
"@types/three": "^0.146.0",
|
"@types/three": "^0.146.0",
|
||||||
|
"dat.gui": "^0.7.9",
|
||||||
"typescript": "^4.6.4",
|
"typescript": "^4.6.4",
|
||||||
"vite": "^3.2.3",
|
"vite": "^3.2.3",
|
||||||
"vite-plugin-plain-text": "^1.2.1"
|
"vite-plugin-plain-text": "^1.2.1"
|
||||||
@ -281,6 +283,12 @@
|
|||||||
"node": ">= 10"
|
"node": ">= 10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/dat.gui": {
|
||||||
|
"version": "0.7.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/dat.gui/-/dat.gui-0.7.9.tgz",
|
||||||
|
"integrity": "sha512-UiqZasQIask5cUwWOO6BgOjP1dNj9ChYtmeAb4WTKs5IJ7ha3ATRTeXY7/TzlmEZznh40lS6Ov5BdNA+tU+fWQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/@types/three": {
|
"node_modules/@types/three": {
|
||||||
"version": "0.146.0",
|
"version": "0.146.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/three/-/three-0.146.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/three/-/three-0.146.0.tgz",
|
||||||
@ -296,6 +304,12 @@
|
|||||||
"integrity": "sha512-IUMDPSXnYIbEO2IereEFcgcqfDREOgmbGqtrMpVPpACTU6pltYLwHgVkrnYv0XhWEcjio9sYEfIEzgn3c7nDqA==",
|
"integrity": "sha512-IUMDPSXnYIbEO2IereEFcgcqfDREOgmbGqtrMpVPpACTU6pltYLwHgVkrnYv0XhWEcjio9sYEfIEzgn3c7nDqA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/dat.gui": {
|
||||||
|
"version": "0.7.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/dat.gui/-/dat.gui-0.7.9.tgz",
|
||||||
|
"integrity": "sha512-sCNc1OHobc+Erc1HqiswYgHdVNpSJUlk/Hz8vzOCsER7rl+oF/4+v8GXFUyCgtXpoCX6+bnmg07DedLvBLwYKQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/esbuild": {
|
"node_modules/esbuild": {
|
||||||
"version": "0.15.18",
|
"version": "0.15.18",
|
||||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.18.tgz",
|
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.18.tgz",
|
||||||
@ -1002,6 +1016,12 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
|
"@types/dat.gui": {
|
||||||
|
"version": "0.7.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/dat.gui/-/dat.gui-0.7.9.tgz",
|
||||||
|
"integrity": "sha512-UiqZasQIask5cUwWOO6BgOjP1dNj9ChYtmeAb4WTKs5IJ7ha3ATRTeXY7/TzlmEZznh40lS6Ov5BdNA+tU+fWQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"@types/three": {
|
"@types/three": {
|
||||||
"version": "0.146.0",
|
"version": "0.146.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/three/-/three-0.146.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/three/-/three-0.146.0.tgz",
|
||||||
@ -1017,6 +1037,12 @@
|
|||||||
"integrity": "sha512-IUMDPSXnYIbEO2IereEFcgcqfDREOgmbGqtrMpVPpACTU6pltYLwHgVkrnYv0XhWEcjio9sYEfIEzgn3c7nDqA==",
|
"integrity": "sha512-IUMDPSXnYIbEO2IereEFcgcqfDREOgmbGqtrMpVPpACTU6pltYLwHgVkrnYv0XhWEcjio9sYEfIEzgn3c7nDqA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"dat.gui": {
|
||||||
|
"version": "0.7.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/dat.gui/-/dat.gui-0.7.9.tgz",
|
||||||
|
"integrity": "sha512-sCNc1OHobc+Erc1HqiswYgHdVNpSJUlk/Hz8vzOCsER7rl+oF/4+v8GXFUyCgtXpoCX6+bnmg07DedLvBLwYKQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"esbuild": {
|
"esbuild": {
|
||||||
"version": "0.15.18",
|
"version": "0.15.18",
|
||||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.18.tgz",
|
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.18.tgz",
|
||||||
|
@ -9,7 +9,9 @@
|
|||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/dat.gui": "^0.7.9",
|
||||||
"@types/three": "^0.146.0",
|
"@types/three": "^0.146.0",
|
||||||
|
"dat.gui": "^0.7.9",
|
||||||
"typescript": "^4.6.4",
|
"typescript": "^4.6.4",
|
||||||
"vite": "^3.2.3",
|
"vite": "^3.2.3",
|
||||||
"vite-plugin-plain-text": "^1.2.1"
|
"vite-plugin-plain-text": "^1.2.1"
|
||||||
|
@ -5,6 +5,7 @@ import {
|
|||||||
Object3D,
|
Object3D,
|
||||||
ShaderMaterial,
|
ShaderMaterial,
|
||||||
SphereGeometry,
|
SphereGeometry,
|
||||||
|
Vector3,
|
||||||
} from 'three';
|
} from 'three';
|
||||||
|
|
||||||
import { plainText as vertexShader } from './shaders/atmosphere.vert';
|
import { plainText as vertexShader } from './shaders/atmosphere.vert';
|
||||||
@ -17,7 +18,7 @@ export class Atmosphere extends Object3D {
|
|||||||
public Scale = 1;
|
public Scale = 1;
|
||||||
public ScaleDepth = 0.25;
|
public ScaleDepth = 0.25;
|
||||||
public G = -0.95;
|
public G = -0.95;
|
||||||
public Wavelength = [0.65, 0.57, 0.475];
|
public Wavelength = new Vector3(0.65, 0.57, 0.475);
|
||||||
|
|
||||||
public geom?: SphereGeometry;
|
public geom?: SphereGeometry;
|
||||||
public mesh?: Mesh;
|
public mesh?: Mesh;
|
||||||
@ -35,12 +36,30 @@ export class Atmosphere extends Object3D {
|
|||||||
this.initialize();
|
this.initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set planetRadius(radius: number) {
|
||||||
|
const thickness = this.thickness;
|
||||||
|
this.innerRadius = radius;
|
||||||
|
this.outerRadius = radius + thickness;
|
||||||
|
this.refreshScale();
|
||||||
|
}
|
||||||
|
get planetRadius() {
|
||||||
|
return this.innerRadius;
|
||||||
|
}
|
||||||
|
|
||||||
|
set thickness(thickness: number) {
|
||||||
|
this.outerRadius = thickness + this.innerRadius;
|
||||||
|
this.refreshScale();
|
||||||
|
}
|
||||||
|
get thickness() {
|
||||||
|
return this.outerRadius - this.innerRadius;
|
||||||
|
}
|
||||||
|
|
||||||
setUniforms(shader: ShaderMaterial) {
|
setUniforms(shader: ShaderMaterial) {
|
||||||
shader.uniforms.invWavelength = {
|
shader.uniforms.invWavelength = {
|
||||||
value: [
|
value: [
|
||||||
1 / Math.pow(this.Wavelength[0], 4),
|
1 / Math.pow(this.Wavelength.x, 4),
|
||||||
1 / Math.pow(this.Wavelength[1], 4),
|
1 / Math.pow(this.Wavelength.y, 4),
|
||||||
1 / Math.pow(this.Wavelength[2], 4),
|
1 / Math.pow(this.Wavelength.z, 4),
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
shader.uniforms.outerRadius = { value: this.outerRadius };
|
shader.uniforms.outerRadius = { value: this.outerRadius };
|
||||||
@ -60,8 +79,18 @@ export class Atmosphere extends Object3D {
|
|||||||
}
|
}
|
||||||
|
|
||||||
initialize() {
|
initialize() {
|
||||||
|
if (this.geom) {
|
||||||
|
this.geom.dispose();
|
||||||
|
this.mesh && this.remove(this.mesh);
|
||||||
|
}
|
||||||
this.geom = new SphereGeometry(this.outerRadius, 128, 128);
|
this.geom = new SphereGeometry(this.outerRadius, 128, 128);
|
||||||
this.mesh = new Mesh(this.geom, this.shader);
|
this.mesh = new Mesh(this.geom, this.shader);
|
||||||
this.add(this.mesh);
|
this.add(this.mesh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private refreshScale() {
|
||||||
|
this.Scale = 1 / (this.outerRadius - this.innerRadius);
|
||||||
|
this.setUniforms(this.shader);
|
||||||
|
this.initialize();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
38
src/globe.ts
38
src/globe.ts
@ -7,6 +7,7 @@ import {
|
|||||||
Color,
|
Color,
|
||||||
DirectionalLight,
|
DirectionalLight,
|
||||||
ShaderMaterial,
|
ShaderMaterial,
|
||||||
|
MeshPhongMaterial,
|
||||||
} from 'three';
|
} from 'three';
|
||||||
|
|
||||||
import { plainText as vertexShader } from './shaders/earth.vert';
|
import { plainText as vertexShader } from './shaders/earth.vert';
|
||||||
@ -14,15 +15,31 @@ import { plainText as fragmentShader } from './shaders/earth.frag';
|
|||||||
import { Atmosphere } from './atmosphere';
|
import { Atmosphere } from './atmosphere';
|
||||||
|
|
||||||
export class Globe extends Object3D {
|
export class Globe extends Object3D {
|
||||||
private sphere = new SphereGeometry(1, 128, 128);
|
private sphere?: SphereGeometry;
|
||||||
private atmosphere = new Atmosphere(1, 1.05);
|
private clouds = new SphereGeometry(1.02, 64, 64);
|
||||||
private earthMaterial?: ShaderMaterial;
|
public atmosphere = new Atmosphere(1, 1.05);
|
||||||
|
public earthMaterial?: ShaderMaterial;
|
||||||
public earthMesh?: Mesh;
|
public earthMesh?: Mesh;
|
||||||
|
|
||||||
private loader = new TextureLoader();
|
private loader = new TextureLoader();
|
||||||
|
|
||||||
|
constructor(private planetRadius: number) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
set radius(radius: number) {
|
||||||
|
this.planetRadius = radius;
|
||||||
|
this.atmosphere.planetRadius = radius;
|
||||||
|
this.earthMaterial && this.atmosphere.setUniforms(this.earthMaterial);
|
||||||
|
this.createMesh();
|
||||||
|
}
|
||||||
|
get radius() {
|
||||||
|
return this.planetRadius;
|
||||||
|
}
|
||||||
|
|
||||||
public async loadTexture(name: string) {
|
public async loadTexture(name: string) {
|
||||||
return new Promise<Texture>((resolve, reject) => {
|
return new Promise<Texture>((resolve, reject) => {
|
||||||
this.loader.load(`/${name}`, resolve, undefined, reject);
|
this.loader.load(`./${name}`, resolve, undefined, reject);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,10 +72,19 @@ export class Globe extends Object3D {
|
|||||||
|
|
||||||
this.atmosphere.setUniforms(this.earthMaterial);
|
this.atmosphere.setUniforms(this.earthMaterial);
|
||||||
this.atmosphere.setLight(light);
|
this.atmosphere.setLight(light);
|
||||||
this.earthMesh = new Mesh(this.sphere, this.earthMaterial);
|
this.createMesh();
|
||||||
this.add(this.earthMesh);
|
|
||||||
this.add(this.atmosphere);
|
this.add(this.atmosphere);
|
||||||
}
|
}
|
||||||
|
|
||||||
public tick() {}
|
public tick() {}
|
||||||
|
|
||||||
|
private createMesh() {
|
||||||
|
if (this.sphere) {
|
||||||
|
this.sphere.dispose();
|
||||||
|
this.earthMesh && this.remove(this.earthMesh);
|
||||||
|
}
|
||||||
|
this.sphere = new SphereGeometry(this.planetRadius, 128, 128);
|
||||||
|
this.earthMesh = new Mesh(this.sphere, this.earthMaterial);
|
||||||
|
this.add(this.earthMesh);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
55
src/main.ts
55
src/main.ts
@ -3,6 +3,7 @@ import { Renderer } from './renderer';
|
|||||||
import { DirectionalLight } from 'three';
|
import { DirectionalLight } from 'three';
|
||||||
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
|
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
|
||||||
import './style.css';
|
import './style.css';
|
||||||
|
import { GUI } from 'dat.gui';
|
||||||
|
|
||||||
const main = new Renderer();
|
const main = new Renderer();
|
||||||
|
|
||||||
@ -10,7 +11,7 @@ const dirLight = new DirectionalLight(0xffffff, 1);
|
|||||||
dirLight.position.set(10, 10, 10);
|
dirLight.position.set(10, 10, 10);
|
||||||
main.scene.add(dirLight);
|
main.scene.add(dirLight);
|
||||||
|
|
||||||
const globe = new Globe();
|
const globe = new Globe(1);
|
||||||
main.resize();
|
main.resize();
|
||||||
globe.initialize(dirLight).catch(console.error);
|
globe.initialize(dirLight).catch(console.error);
|
||||||
main.scene.add(globe);
|
main.scene.add(globe);
|
||||||
@ -19,6 +20,58 @@ main.camera.position.set(0, 0, 2);
|
|||||||
|
|
||||||
const control = new OrbitControls(main.camera, main.canvas);
|
const control = new OrbitControls(main.camera, main.canvas);
|
||||||
|
|
||||||
|
const gui = new GUI();
|
||||||
|
const atmosGui = gui.addFolder('Atmosphere');
|
||||||
|
const updateAtmosShader = () => {
|
||||||
|
globe.atmosphere.setUniforms(globe.atmosphere.shader);
|
||||||
|
globe.atmosphere.setUniforms(globe.earthMaterial!);
|
||||||
|
};
|
||||||
|
// any's because for some reason the generic expects a string indexed record
|
||||||
|
atmosGui
|
||||||
|
.add<any>(globe.atmosphere.Wavelength, 'x', 0, 1)
|
||||||
|
.name('R')
|
||||||
|
.onChange(updateAtmosShader);
|
||||||
|
atmosGui
|
||||||
|
.add<any>(globe.atmosphere.Wavelength, 'y', 0, 1)
|
||||||
|
.name('G')
|
||||||
|
.onChange(updateAtmosShader);
|
||||||
|
atmosGui
|
||||||
|
.add<any>(globe.atmosphere.Wavelength, 'z', 0, 1)
|
||||||
|
.name('B')
|
||||||
|
.onChange(updateAtmosShader);
|
||||||
|
|
||||||
|
atmosGui
|
||||||
|
.add<any>(globe.atmosphere, 'thickness', 0.001, 0.5)
|
||||||
|
.name('Thickness')
|
||||||
|
.onChange(updateAtmosShader);
|
||||||
|
atmosGui
|
||||||
|
.add<any>(globe.atmosphere, 'ScaleDepth', 0.01, 1)
|
||||||
|
.name('Scale depth')
|
||||||
|
.onChange(updateAtmosShader);
|
||||||
|
atmosGui
|
||||||
|
.add<any>(globe.atmosphere, 'Rayleigh', 0.0001, 0.01)
|
||||||
|
.onChange(updateAtmosShader);
|
||||||
|
atmosGui
|
||||||
|
.add<any>(globe.atmosphere, 'Mie', 0.0001, 0.01)
|
||||||
|
.onChange(updateAtmosShader);
|
||||||
|
atmosGui
|
||||||
|
.add<any>(globe.atmosphere, 'Exposure', 0, 100)
|
||||||
|
.onChange(updateAtmosShader);
|
||||||
|
atmosGui.open();
|
||||||
|
|
||||||
|
const planetGui = gui.addFolder('Planet');
|
||||||
|
planetGui
|
||||||
|
.add<any>(globe.rotation, 'x', -Math.PI * 2, Math.PI * 2, 0.01)
|
||||||
|
.name('Rotation X');
|
||||||
|
planetGui
|
||||||
|
.add<any>(globe.rotation, 'y', -Math.PI * 2, Math.PI * 2, 0.01)
|
||||||
|
.name('Rotation Y');
|
||||||
|
planetGui
|
||||||
|
.add<any>(globe.rotation, 'z', -Math.PI * 2, Math.PI * 2, 0.01)
|
||||||
|
.name('Rotation Z');
|
||||||
|
// planetGui.add<any>(globe, 'radius', 1, 100).name('Radius');
|
||||||
|
planetGui.open();
|
||||||
|
|
||||||
function tick() {
|
function tick() {
|
||||||
requestAnimationFrame(tick);
|
requestAnimationFrame(tick);
|
||||||
control.update();
|
control.update();
|
||||||
|
@ -1,10 +1,16 @@
|
|||||||
#define EARTH
|
#define EARTH
|
||||||
|
#include <common>
|
||||||
|
#include <normal_pars_vertex>
|
||||||
|
|
||||||
varying vec3 vViewPosition;
|
varying vec3 vViewPosition;
|
||||||
varying vec3 vLightDirection;
|
varying vec3 vLightDirection;
|
||||||
varying vec2 vUv;
|
varying vec2 vUv;
|
||||||
varying vec3 vEyeNormal;
|
varying vec3 vEyeNormal;
|
||||||
#include <common>
|
|
||||||
#include <normal_pars_vertex>
|
varying vec3 v3Direction;
|
||||||
|
varying vec3 c0;
|
||||||
|
varying vec3 c1;
|
||||||
|
|
||||||
uniform vec3 light;
|
uniform vec3 light;
|
||||||
|
|
||||||
uniform vec3 invWavelength; // 1 / pow(wavelength, 4) for the red, green, and blue channels
|
uniform vec3 invWavelength; // 1 / pow(wavelength, 4) for the red, green, and blue channels
|
||||||
@ -19,10 +25,6 @@ uniform float scaleDepth; // The scale depth (i.e. the altitude at which the
|
|||||||
const int nSamples = 2;
|
const int nSamples = 2;
|
||||||
const float fSamples = 1.0;
|
const float fSamples = 1.0;
|
||||||
|
|
||||||
varying vec3 v3Direction;
|
|
||||||
varying vec3 c0;
|
|
||||||
varying vec3 c1;
|
|
||||||
|
|
||||||
float dscale(float fCos) {
|
float dscale(float fCos) {
|
||||||
float x = 1.0 - fCos;
|
float x = 1.0 - fCos;
|
||||||
return scaleDepth * exp(-0.00287 + x * (0.459 + x * (3.83 + x * (-6.80 + x * 5.25))));
|
return scaleDepth * exp(-0.00287 + x * (0.459 + x * (3.83 + x * (-6.80 + x * 5.25))));
|
||||||
|
@ -3,4 +3,5 @@ import plainText from 'vite-plugin-plain-text';
|
|||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [plainText.default(/\.vert|\.frag$/)],
|
plugins: [plainText.default(/\.vert|\.frag$/)],
|
||||||
|
base: '',
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user