@damienmortini/three
Version:
283 lines (224 loc) • 7.52 kB
JavaScript
import GradientNoiseShader from '@damienmortini/core/shader/noise/GradientNoiseShader.js';
import SkyShader from '@damienmortini/core/shader/SkyShader.js';
import {
BackSide,
IcosahedronBufferGeometry,
Mesh,
Vector3,
} from '../../../three/src/Three.js';
import THREEShaderMaterial from '../material/THREEShaderMaterial.js';
const skyShader = {
uniforms: {
sunPosition: new Vector3(0, 1, 0),
sunRayleigh: 1.5,
sunTurbidity: 6,
sunLuminance: 1,
sunMieCoefficient: 0.005,
sunMieDirectionalG: 0.8,
moonPosition: new Vector3(0, 1, 0),
moonRayleigh: 0,
moonTurbidity: 1.5,
moonLuminance: 1.1,
moonMieCoefficient: 0.005,
moonMieDirectionalG: 0.8,
displaySun: 1,
displayMoon: 1,
},
vertexShaderChunks: [
['start', `
varying vec3 vWorldPosition;
`],
['end', `
vec4 worldPosition = modelMatrix * vec4( position, 1.0 );
vWorldPosition = worldPosition.xyz;
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
`],
],
fragmentShaderChunks: [
['start', `
uniform vec3 sunPosition;
uniform float sunRayleigh;
uniform float sunTurbidity;
uniform float sunLuminance;
uniform float sunMieCoefficient;
uniform float sunMieDirectionalG;
uniform float displaySun;
uniform float displayMoon;
uniform vec3 moonPosition;
uniform float moonRayleigh;
uniform float moonTurbidity;
uniform float moonLuminance;
uniform float moonMieCoefficient;
uniform float moonMieDirectionalG;
varying vec3 vWorldPosition;
${SkyShader.computeSkyColor()}
${GradientNoiseShader.gradientNoise3D()}
float blendScreen(float base, float blend) {
return 1.0-((1.0-base)*(1.0-blend));
}
vec3 blendScreen(vec3 base, vec3 blend) {
return vec3(blendScreen(base.r,blend.r),blendScreen(base.g,blend.g),blendScreen(base.b,blend.b));
}
`],
['end', `
vec3 normalizedSunPosition = normalize(sunPosition);
vec3 normalizedMoonPosition = normalize(moonPosition);
vec4 skySunColor = computeSkyColor(vWorldPosition, normalizedSunPosition, ${SkyShader.SUN_ANGULAR_DIAMETER} * displaySun, sunRayleigh, sunTurbidity, sunLuminance, sunMieCoefficient, sunMieDirectionalG);
vec4 skyMoonColor = computeSkyColor(vWorldPosition, normalizedMoonPosition, ${SkyShader.MOON_ANGULAR_DIAMETER} * displayMoon, moonRayleigh, moonTurbidity, moonLuminance, moonMieCoefficient, moonMieDirectionalG);
float nightIntensity = 1. - smoothstep(-.05, 0., normalizedSunPosition.y);
float moonIntensity = max(0., -dot(normalize(sunPosition.xz), normalize(moonPosition.xz)));
// skyMoonColor *= moonIntensity;
skyMoonColor *= nightIntensity;
// Stars
vec3 rayDirection = normalize(vWorldPosition);
float starsIntensity = gradientNoise3D(rayDirection * 400.) * .5 + .5;
starsIntensity = pow(starsIntensity, 15.);
starsIntensity *= max(0., rayDirection.y);
starsIntensity *= 10.;
starsIntensity *= nightIntensity;
skyMoonColor.rgb = blendScreen(skyMoonColor.rgb, vec3(starsIntensity));
vec3 skyColor = blendScreen(skySunColor.rgb, skyMoonColor.rgb);
// gl_FragColor = vec4(skyColor, (skySunColor.a + skyMoonColor.a) / 2.);
gl_FragColor = vec4(skyColor, 1.);
`],
],
};
export default class Sky extends Mesh {
constructor({
radius = 1,
shaders = [],
} = {}) {
super(new IcosahedronBufferGeometry(radius, 3), new THREEShaderMaterial(Object.assign({
type: 'basic',
side: BackSide,
shaders,
}, skyShader)));
this._radius = radius;
this.sunInclination = Math.PI * 0.5;
this.sunAzimuth = 0;
this.moonInclination = Math.PI * 0.5;
this.moonAzimuth = Math.PI;
}
get radius() {
return this._radius;
}
_updatePositionFromInclinationAzimuth(position, inclination, azimuth) {
const theta = inclination;
const phi = azimuth + Math.PI * 0.5;
position.x = this._radius * Math.cos(phi) * Math.cos(theta);
position.y = this._radius * Math.sin(theta);
position.z = this._radius * Math.sin(phi) * Math.cos(theta);
}
get displaySun() {
return this.material.displaySun === 1;
}
set displaySun(value) {
this.material.displaySun = value ? 1 : 0;
}
get displayMoon() {
return this.material.displayMoon === 1;
}
set displayMoon(value) {
this.material.displayMoon = value ? 1 : 0;
}
get sunInclination() {
return this._sunInclination;
}
set sunInclination(value) {
this._sunInclination = value;
this._updatePositionFromInclinationAzimuth(this.sunPosition, this.sunInclination, this.sunAzimuth);
}
get sunAzimuth() {
return this._sunAzimuth;
}
set sunAzimuth(value) {
this._sunAzimuth = value;
this._updatePositionFromInclinationAzimuth(this.sunPosition, this.sunInclination, this.sunAzimuth);
}
get sunPosition() {
return this.material.sunPosition;
}
set sunPosition(value) {
this.material.sunPosition = value;
}
get sunRayleigh() {
return this.material.sunRayleigh;
}
set sunRayleigh(value) {
this.material.sunRayleigh = value;
}
get sunTurbidity() {
return this.material.sunTurbidity;
}
set sunTurbidity(value) {
this.material.sunTurbidity = value;
}
get sunLuminance() {
return this.material.sunLuminance;
}
set sunLuminance(value) {
this.material.sunLuminance = value;
}
get sunMieCoefficient() {
return this.material.sunMieCoefficient;
}
set sunMieCoefficient(value) {
this.material.sunMieCoefficient = value;
}
get sunMieDirectionalG() {
return this.material.sunMieDirectionalG;
}
set sunMieDirectionalG(value) {
this.material.sunMieDirectionalG = value;
}
get moonInclination() {
return this._moonInclination;
}
set moonInclination(value) {
this._moonInclination = value;
this._updatePositionFromInclinationAzimuth(this.moonPosition, this.moonInclination, this.moonAzimuth);
}
get moonAzimuth() {
return this._moonAzimuth;
}
set moonAzimuth(value) {
this._moonAzimuth = value;
this._updatePositionFromInclinationAzimuth(this.moonPosition, this.moonInclination, this.moonAzimuth);
}
get moonPosition() {
return this.material.moonPosition;
}
set moonPosition(value) {
this.material.moonPosition = value;
}
get moonRayleigh() {
return this.material.moonRayleigh;
}
set moonRayleigh(value) {
this.material.moonRayleigh = value;
}
get moonTurbidity() {
return this.material.moonTurbidity;
}
set moonTurbidity(value) {
this.material.moonTurbidity = value;
}
get moonLuminance() {
return this.material.moonLuminance;
}
set moonLuminance(value) {
this.material.moonLuminance = value;
}
get moonMieCoefficient() {
return this.material.moonMieCoefficient;
}
set moonMieCoefficient(value) {
this.material.moonMieCoefficient = value;
}
get moonMieDirectionalG() {
return this.material.moonMieDirectionalG;
}
set moonMieDirectionalG(value) {
this.material.moonMieDirectionalG = value;
}
}