{t`Choose Strategy`}: @@ -319,6 +278,59 @@ function Converter() { }
+ {(showExtraOptions || extraRender) && ( ++ { + setExtraOpts({ + ...extraOpts, + serpentine: e.target.checked, + }); + }} + /> + {t`Serpentine`} +
+ {t`Minimum Color Distance`}: + { + setExtraOpts({ + ...extraOpts, + minColorDistance: e.target.value, + }); + }} + /> + ++ { + setExtraOpts({ + ...extraOpts, + GIMPerror: e.target.checked, + }); + }} + /> + {t`Calculate like GIMP`} +
+{t`Choose Color Mode`}: {t`Add Grid (uncheck if you need a 1:1 template)`}
- {(gridEnabled) - ? ( -- { - setGridData({ - ...gridData, - light: e.target.checked, - }); - }} - /> - {t`Light Grid`} -
- {t`Offset`} X: - { - setGridData({ - ...gridData, - offsetX: e.target.value, - }); - }} - /> - - {t`Offset`} Y: - { - setGridData({ - ...gridData, - offsetY: e.target.value, - }); - }} - /> - -+ { + setGridData({ + ...gridData, + light: e.target.checked, + }); + }} + /> + {t`Light Grid`} +
+ {t`Offset`} X: + { + setGridData({ + ...gridData, + offsetX: e.target.value, + }); + }} + /> + + {t`Offset`} Y: + { + setGridData({ + ...gridData, + offsetY: e.target.value, + }); + }} + /> + + + )}{t`Scale Image`}
- {(scalingEnabled) - ? ( -- { - selectScaleKeepRatio(e.target.checked); - }} - /> - {t`Keep Ratio`} -
-- { - setScaleData({ - ...scaleData, - aa: e.target.checked, - }); - }} - /> - {t`Anti Aliasing`} -
- -+ { + selectScaleKeepRatio(e.target.checked); + }} + /> + {t`Keep Ratio`} +
++ { + setScaleData({ + ...scaleData, + aa: e.target.checked, + }); + }} + /> + {t`Anti Aliasing`} +
+ + + )} + {(inputImageCanvas) ? (...
diff --git a/src/components/Menu.jsx b/src/components/Menu.jsx index df556b8..6a4e127 100644 --- a/src/components/Menu.jsx +++ b/src/components/Menu.jsx @@ -17,9 +17,9 @@ const Menu = () => { const menuOpen = useSelector((state) => state.gui.menuOpen); useEffect(() => { - window.setTimeout(() => { - if (menuOpen) setRender(true); - }, 10); + if (menuOpen) { + setTimeout(() => setRender(true), 10); + } }, [menuOpen]); const onTransitionEnd = () => { diff --git a/src/components/UserMessages.jsx b/src/components/UserMessages.jsx index 6bf6b14..3b08cbf 100644 --- a/src/components/UserMessages.jsx +++ b/src/components/UserMessages.jsx @@ -26,7 +26,7 @@ const UserMessages = () => { && (
{t`Please verify your mail address
- or your account could get deleted after a few days.`}
+ or your account could get deleted after a few days.`}
{(verifyAnswer)
? (
> 8, chunkId & 0xFF]);
return Buffer.concat([index, pixels]);
},
diff --git a/src/socket/packets/README.md b/src/socket/packets/README.md
new file mode 100644
index 0000000..d758a2a
--- /dev/null
+++ b/src/socket/packets/README.md
@@ -0,0 +1,6 @@
+# Binary Websocket Packages
+
+Note that the node Server receives in [Buffer](https://nodejs.org/api/buffer.html), while the client receives [DataViews](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView) and sends ArrayBuffers.
+Therefor the server can't share the same code with the client for hydrate / dehydrate.
+Most packages are unidirectional so hydrate is for either client or server and dehydrate for the other one.
+Bidrectional packages have two files, one for Client, another one for Server.
diff --git a/src/socket/packets/RegisterCanvas.js b/src/socket/packets/RegisterCanvas.js
index d122dab..c7dcef5 100644
--- a/src/socket/packets/RegisterCanvas.js
+++ b/src/socket/packets/RegisterCanvas.js
@@ -1,16 +1,13 @@
-/* @flow */
-
-
const OP_CODE = 0xA0;
export default {
OP_CODE,
- hydrate(data: Buffer) {
- // SERVER (Client)
+ hydrate(data) {
+ // SERVER (Receiver)
const canvasId = data[1];
return canvasId;
},
- dehydrate(canvasId): ArrayBuffer {
+ dehydrate(canvasId) {
// CLIENT (Sender)
const buffer = new ArrayBuffer(1 + 1);
const view = new DataView(buffer);
diff --git a/src/socket/packets/RegisterChunk.js b/src/socket/packets/RegisterChunk.js
index 6e68392..ed31a30 100644
--- a/src/socket/packets/RegisterChunk.js
+++ b/src/socket/packets/RegisterChunk.js
@@ -1,16 +1,13 @@
-/* @flow */
-
-
const OP_CODE = 0xA1;
export default {
OP_CODE,
- hydrate(data: Buffer) {
- // SERVER (Client)
+ hydrate(data) {
+ // SERVER (Receiver)
const i = data[1] << 8 | data[2];
return i;
},
- dehydrate(chunkid): ArrayBuffer {
+ dehydrate(chunkid) {
// CLIENT (Sender)
const buffer = new ArrayBuffer(1 + 2);
const view = new DataView(buffer);
diff --git a/src/socket/packets/RegisterMultipleChunks.js b/src/socket/packets/RegisterMultipleChunks.js
index e4c99c8..f2a0b44 100644
--- a/src/socket/packets/RegisterMultipleChunks.js
+++ b/src/socket/packets/RegisterMultipleChunks.js
@@ -1,11 +1,11 @@
-/* @flow */
-
-
const OP_CODE = 0xA3;
export default {
OP_CODE,
- dehydrate(chunks: Array): ArrayBuffer {
+ /*
+ * @param chunks Array of chunks
+ */
+ dehydrate(chunks) {
// CLIENT (Sender)
const buffer = new ArrayBuffer(1 + 1 + chunks.length * 2);
const view = new Uint16Array(buffer);
diff --git a/src/store/rendererHook.js b/src/store/rendererHook.js
index 3799771..ffca3aa 100644
--- a/src/store/rendererHook.js
+++ b/src/store/rendererHook.js
@@ -1,7 +1,6 @@
/*
* Hooks for renderer
*
- * @flow
*/
import {
diff --git a/src/styles/default.css b/src/styles/default.css
index f219281..22ae3e3 100644
--- a/src/styles/default.css
+++ b/src/styles/default.css
@@ -354,6 +354,22 @@ tr:nth-child(even) {
visibility: visible;
}
+.convBox {
+ border-style: solid;
+ border-color: #D4D4D4;
+ border-width: 2px;
+ padding: 2px;
+ display: inline-block;
+ max-height: 0px;
+ visibility: hidden;
+ transition: 0.3s;
+ overflow: hidden;
+}
+.convBox.show {
+ visibility: visible;
+ max-height: 160px;
+}
+
#helpbutton {
left: 16px;
top: 180px;
diff --git a/src/ui/InfiniteGridHelper.js b/src/ui/InfiniteGridHelper.js
index e9b548e..d7d9af7 100644
--- a/src/ui/InfiniteGridHelper.js
+++ b/src/ui/InfiniteGridHelper.js
@@ -3,123 +3,93 @@
* https://github.com/Fyrestar/THREE.InfiniteGridHelper
* MIT License
*
- * @flow
*/
/* eslint-disable max-len */
import * as THREE from 'three';
-const InfiniteGridHelper = function InfiniteGridHelper(
- size1,
- size2,
- color,
- distance,
-) {
- color = color || new THREE.Color('white');
- size1 = size1 || 10;
- size2 = size2 || 100;
+export default class InfiniteGridHelper extends THREE.Mesh {
+ constructor(size1, size2, color, distance, axes = 'xzy') {
+ color = color || new THREE.Color('white');
+ size1 = size1 || 10;
+ size2 = size2 || 100;
- distance = distance || 8000;
+ distance = distance || 8000;
+ const planeAxes = axes.substr(0, 2);
+ const geometry = new THREE.PlaneBufferGeometry(2, 2, 1, 1);
+ const material = new THREE.ShaderMaterial({
- const geometry = new THREE.PlaneBufferGeometry(2, 2, 1, 1);
+ side: THREE.DoubleSide,
- const material = new THREE.ShaderMaterial({
-
- side: THREE.DoubleSide,
-
- uniforms: {
- uSize1: {
- value: size1,
+ uniforms: {
+ uSize1: { value: size1 },
+ uSize2: {
+ value: size2,
+ },
+ uColor: {
+ value: color,
+ },
+ uDistance: {
+ value: distance,
+ },
},
- uSize2: {
- value: size2,
+ transparent: true,
+
+ vertexShader: `
+ varying vec3 worldPosition;
+ uniform float uDistance;
+ void main() {
+ vec3 pos = position.${axes} * uDistance;
+ pos.${planeAxes} += cameraPosition.${planeAxes};
+
+ worldPosition = pos;
+
+ gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
+ }
+ `,
+
+ fragmentShader: `
+ varying vec3 worldPosition;
+
+ uniform float uSize1;
+ uniform float uSize2;
+ uniform vec3 uColor;
+ uniform float uDistance;
+
+ float getGrid(float size) {
+ vec2 r = worldPosition.${planeAxes} / size;
+
+ vec2 grid = abs(fract(r - 0.5) - 0.5) / fwidth(r);
+ float line = min(grid.x, grid.y);
+
+ return 1.0 - min(line, 1.0);
+ }
+
+ void main() {
+ float d = 1.0 - min(distance(cameraPosition.${planeAxes}, worldPosition.${planeAxes}) / uDistance, 1.0);
+
+ float g1 = getGrid(uSize1);
+ float g2 = getGrid(uSize2);
+
+
+ gl_FragColor = vec4(uColor.rgb, mix(g2, g1, g1) * pow(d, 3.0));
+ gl_FragColor.a = mix(0.5 * gl_FragColor.a, gl_FragColor.a, g2);
+
+ if ( gl_FragColor.a <= 0.0 ) discard;
+
+
+ }
+
+ `,
+
+ extensions: {
+ derivatives: true,
},
- uColor: {
- value: color,
- },
- uDistance: {
- value: distance,
- },
- },
- transparent: true,
- vertexShader: `
-
- varying vec3 worldPosition;
-
- uniform float uDistance;
-
- void main() {
-
- vec3 pos = position.xzy * uDistance;
- pos.xz += cameraPosition.xz;
-
- worldPosition = pos;
-
- gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
-
- }
- `,
+ });
+ super(geometry, material);
- fragmentShader: `
-
- varying vec3 worldPosition;
-
- uniform float uSize1;
- uniform float uSize2;
- uniform vec3 uColor;
- uniform float uDistance;
-
-
-
- float getGrid(float size) {
-
- vec2 r = worldPosition.xz / size;
-
-
- vec2 grid = abs(fract(r - 0.5) - 0.5) / fwidth(r);
- float line = min(grid.x, grid.y);
-
-
- return 1.0 - min(line, 1.0);
- }
-
- void main() {
-
-
- float d = 1.0 - min(distance(cameraPosition.xz, worldPosition.xz) / uDistance, 1.0);
-
- float g1 = getGrid(uSize1);
- float g2 = getGrid(uSize2);
-
-
- gl_FragColor = vec4(uColor.rgb, mix(g2, g1, g1) * pow(d, 3.0));
- gl_FragColor.a = mix(0.5 * gl_FragColor.a, gl_FragColor.a, g2);
-
- if ( gl_FragColor.a <= 0.0 ) discard;
-
-
- }
-
- `,
-
- extensions: {
- derivatives: true,
- },
-
- });
-
-
- THREE.Mesh.call(this, geometry, material);
-
- this.frustumCulled = false;
-};
-
-InfiniteGridHelper.prototype = {
- ...THREE.Mesh.prototype,
- ...THREE.Object3D.prototype,
- ...THREE.EventDispatcher.prototype,
-};
-
-export default InfiniteGridHelper;
+ this.frustumCulled = false;
+ }
+}
diff --git a/src/ui/Renderer3D.js b/src/ui/Renderer3D.js
index e0d4763..e6b4707 100644
--- a/src/ui/Renderer3D.js
+++ b/src/ui/Renderer3D.js
@@ -5,7 +5,7 @@
*/
import * as THREE from 'three';
-import { Sky } from './Sky';
+import Sky from './Sky';
import InfiniteGridHelper from './InfiniteGridHelper';
import VoxelPainterControls from '../controls/VoxelPainterControls';
@@ -99,7 +99,6 @@ class Renderer {
rayleigh: 2,
mieCoefficient: 0.005,
mieDirectionalG: 0.8,
- luminance: 1,
inclination: 0.49, // elevation / inclination
azimuth: 0.25, // Facing front,
sun: !true,
@@ -107,7 +106,6 @@ class Renderer {
const { uniforms } = sky.material;
uniforms.turbidity.value = effectController.turbidity;
uniforms.rayleigh.value = effectController.rayleigh;
- uniforms.luminance.value = effectController.luminance;
uniforms.mieCoefficient.value = effectController.mieCoefficient;
uniforms.mieDirectionalG.value = effectController.mieDirectionalG;
uniforms.sunPosition.value.set(400000, 400000, 400000);
diff --git a/src/ui/Sky.js b/src/ui/Sky.js
index c3e4e87..6ecaa31 100644
--- a/src/ui/Sky.js
+++ b/src/ui/Sky.js
@@ -1,12 +1,13 @@
/**
- * @author zz85 / https://github.com/zz85
+ * From example code at:
+ * https://github.com/mrdoob/three.js/blob/dev/examples/js/objects/Sky.js
*
* Based on "A Practical Analytic Model for Daylight"
* aka The Preetham Model, the de facto standard analytic skydome model
- * http://www.cs.utah.edu/~shirley/papers/sunsky/sunsky.pdf
+ * https://www.researchgate.net/publication/220720443_A_Practical_Analytic_Model_for_Daylight
*
* First implemented by Simon Wallner
- * http://www.simonwallner.at/projects/atmospheric-scattering
+ * http://simonwallner.at/project/atmospheric-scattering/
*
* Improved by Martin Upitis
* http://blenderartists.org/forum/showthread.php?245954-preethams-sky-impementation-HDR
@@ -14,224 +15,207 @@
* Three.js integration by zz85 http://twitter.com/blurspline
*/
-/*
- * taken from three.js examples
- */
-/* eslint-disable */
+/* eslint-disable max-len */
-import {
- BackSide,
- BoxBufferGeometry,
- Mesh,
- ShaderMaterial,
- UniformsUtils,
- Vector3
-} from 'three';
+import * as THREE from 'three';
-var Sky = function () {
+export default class Sky extends THREE.Mesh {
+ static isSky = true;
- var shader = Sky.SkyShader;
-
- var material = new ShaderMaterial( {
- fragmentShader: shader.fragmentShader,
- vertexShader: shader.vertexShader,
- uniforms: UniformsUtils.clone( shader.uniforms ),
- side: BackSide
- } );
-
- Mesh.call( this, new BoxBufferGeometry( 1, 1, 1 ), material );
-
-};
-
-Sky.prototype = Object.create( Mesh.prototype );
+ constructor() {
+ const shader = Sky.SkyShader;
+ const material = new THREE.ShaderMaterial({
+ name: 'SkyShader',
+ fragmentShader: shader.fragmentShader,
+ vertexShader: shader.vertexShader,
+ uniforms: THREE.UniformsUtils.clone(shader.uniforms),
+ side: THREE.BackSide,
+ depthWrite: false,
+ });
+ super(new THREE.BoxGeometry(1, 1, 1), material);
+ }
+}
Sky.SkyShader = {
+ uniforms: {
+ turbidity: {
+ value: 2,
+ },
+ rayleigh: {
+ value: 1,
+ },
+ mieCoefficient: {
+ value: 0.005,
+ },
+ mieDirectionalG: {
+ value: 0.8,
+ },
+ sunPosition: {
+ value: new THREE.Vector3(),
+ },
+ up: {
+ value: new THREE.Vector3(0, 1, 0),
+ },
+ },
+ vertexShader:
+/* glsl */
+`
+ uniform vec3 sunPosition;
+ uniform float rayleigh;
+ uniform float turbidity;
+ uniform float mieCoefficient;
+ uniform vec3 up;
- uniforms: {
- "luminance": { value: 1 },
- "turbidity": { value: 2 },
- "rayleigh": { value: 1 },
- "mieCoefficient": { value: 0.005 },
- "mieDirectionalG": { value: 0.8 },
- "sunPosition": { value: new Vector3() },
- "up": { value: new Vector3( 0, 1, 0 ) }
- },
+ varying vec3 vWorldPosition;
+ varying vec3 vSunDirection;
+ varying float vSunfade;
+ varying vec3 vBetaR;
+ varying vec3 vBetaM;
+ varying float vSunE;
- vertexShader: [
- 'uniform vec3 sunPosition;',
- 'uniform float rayleigh;',
- 'uniform float turbidity;',
- 'uniform float mieCoefficient;',
- 'uniform vec3 up;',
+ // constants for atmospheric scattering
+ const float e = 2.71828182845904523536028747135266249775724709369995957;
+ const float pi = 3.141592653589793238462643383279502884197169;
- 'varying vec3 vWorldPosition;',
- 'varying vec3 vSunDirection;',
- 'varying float vSunfade;',
- 'varying vec3 vBetaR;',
- 'varying vec3 vBetaM;',
- 'varying float vSunE;',
+ // wavelength of used primaries, according to preetham
+ const vec3 lambda = vec3( 680E-9, 550E-9, 450E-9 );
+ // this pre-calcuation replaces older TotalRayleigh(vec3 lambda) function:
+ // (8.0 * pow(pi, 3.0) * pow(pow(n, 2.0) - 1.0, 2.0) * (6.0 + 3.0 * pn)) / (3.0 * N * pow(lambda, vec3(4.0)) * (6.0 - 7.0 * pn))
+ const vec3 totalRayleigh = vec3( 5.804542996261093E-6, 1.3562911419845635E-5, 3.0265902468824876E-5 );
- // constants for atmospheric scattering
- 'const float e = 2.71828182845904523536028747135266249775724709369995957;',
- 'const float pi = 3.141592653589793238462643383279502884197169;',
+ // mie stuff
+ // K coefficient for the primaries
+ const float v = 4.0;
+ const vec3 K = vec3( 0.686, 0.678, 0.666 );
+ // MieConst = pi * pow( ( 2.0 * pi ) / lambda, vec3( v - 2.0 ) ) * K
+ const vec3 MieConst = vec3( 1.8399918514433978E14, 2.7798023919660528E14, 4.0790479543861094E14 );
- // wavelength of used primaries, according to preetham
- 'const vec3 lambda = vec3( 680E-9, 550E-9, 450E-9 );',
- // this pre-calcuation replaces older TotalRayleigh(vec3 lambda) function:
- // (8.0 * pow(pi, 3.0) * pow(pow(n, 2.0) - 1.0, 2.0) * (6.0 + 3.0 * pn)) / (3.0 * N * pow(lambda, vec3(4.0)) * (6.0 - 7.0 * pn))
- 'const vec3 totalRayleigh = vec3( 5.804542996261093E-6, 1.3562911419845635E-5, 3.0265902468824876E-5 );',
+ // earth shadow hack
+ // cutoffAngle = pi / 1.95;
+ const float cutoffAngle = 1.6110731556870734;
+ const float steepness = 1.5;
+ const float EE = 1000.0;
- // mie stuff
- // K coefficient for the primaries
- 'const float v = 4.0;',
- 'const vec3 K = vec3( 0.686, 0.678, 0.666 );',
- // MieConst = pi * pow( ( 2.0 * pi ) / lambda, vec3( v - 2.0 ) ) * K
- 'const vec3 MieConst = vec3( 1.8399918514433978E14, 2.7798023919660528E14, 4.0790479543861094E14 );',
+ float sunIntensity( float zenithAngleCos ) {
+ zenithAngleCos = clamp( zenithAngleCos, -1.0, 1.0 );
+ return EE * max( 0.0, 1.0 - pow( e, -( ( cutoffAngle - acos( zenithAngleCos ) ) / steepness ) ) );
+ }
- // earth shadow hack
- // cutoffAngle = pi / 1.95;
- 'const float cutoffAngle = 1.6110731556870734;',
- 'const float steepness = 1.5;',
- 'const float EE = 1000.0;',
+ vec3 totalMie( float T ) {
+ float c = ( 0.2 * T ) * 10E-18;
+ return 0.434 * c * MieConst;
+ }
- 'float sunIntensity( float zenithAngleCos ) {',
- ' zenithAngleCos = clamp( zenithAngleCos, -1.0, 1.0 );',
- ' return EE * max( 0.0, 1.0 - pow( e, -( ( cutoffAngle - acos( zenithAngleCos ) ) / steepness ) ) );',
- '}',
+ void main() {
- 'vec3 totalMie( float T ) {',
- ' float c = ( 0.2 * T ) * 10E-18;',
- ' return 0.434 * c * MieConst;',
- '}',
+ vec4 worldPosition = modelMatrix * vec4( position, 1.0 );
+ vWorldPosition = worldPosition.xyz;
- 'void main() {',
+ gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
+ gl_Position.z = gl_Position.w; // set z to camera.far
- ' vec4 worldPosition = modelMatrix * vec4( position, 1.0 );',
- ' vWorldPosition = worldPosition.xyz;',
+ vSunDirection = normalize( sunPosition );
- ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );',
- ' gl_Position.z = gl_Position.w;', // set z to camera.far
+ vSunE = sunIntensity( dot( vSunDirection, up ) );
- ' vSunDirection = normalize( sunPosition );',
+ vSunfade = 1.0 - clamp( 1.0 - exp( ( sunPosition.y / 450000.0 ) ), 0.0, 1.0 );
- ' vSunE = sunIntensity( dot( vSunDirection, up ) );',
+ float rayleighCoefficient = rayleigh - ( 1.0 * ( 1.0 - vSunfade ) );
- ' vSunfade = 1.0 - clamp( 1.0 - exp( ( sunPosition.y / 450000.0 ) ), 0.0, 1.0 );',
+ // extinction (absorbtion + out scattering)
+ // rayleigh coefficients
+ vBetaR = totalRayleigh * rayleighCoefficient;
- ' float rayleighCoefficient = rayleigh - ( 1.0 * ( 1.0 - vSunfade ) );',
+ // mie coefficients
+ vBetaM = totalMie( turbidity ) * mieCoefficient;
- // extinction (absorbtion + out scattering)
- // rayleigh coefficients
- ' vBetaR = totalRayleigh * rayleighCoefficient;',
+ }`,
+ fragmentShader:
+/* glsl */
+`
+ varying vec3 vWorldPosition;
+ varying vec3 vSunDirection;
+ varying float vSunfade;
+ varying vec3 vBetaR;
+ varying vec3 vBetaM;
+ varying float vSunE;
- // mie coefficients
- ' vBetaM = totalMie( turbidity ) * mieCoefficient;',
+ uniform float mieDirectionalG;
+ uniform vec3 up;
- '}'
- ].join( '\n' ),
+ const vec3 cameraPos = vec3( 0.0, 0.0, 0.0 );
- fragmentShader: [
- 'varying vec3 vWorldPosition;',
- 'varying vec3 vSunDirection;',
- 'varying float vSunfade;',
- 'varying vec3 vBetaR;',
- 'varying vec3 vBetaM;',
- 'varying float vSunE;',
+ // constants for atmospheric scattering
+ const float pi = 3.141592653589793238462643383279502884197169;
- 'uniform float luminance;',
- 'uniform float mieDirectionalG;',
- 'uniform vec3 up;',
+ const float n = 1.0003; // refractive index of air
+ const float N = 2.545E25; // number of molecules per unit volume for air at 288.15K and 1013mb (sea level -45 celsius)
- 'const vec3 cameraPos = vec3( 0.0, 0.0, 0.0 );',
+ // optical length at zenith for molecules
+ const float rayleighZenithLength = 8.4E3;
+ const float mieZenithLength = 1.25E3;
+ // 66 arc seconds -> degrees, and the cosine of that
+ const float sunAngularDiameterCos = 0.999956676946448443553574619906976478926848692873900859324;
- // constants for atmospheric scattering
- 'const float pi = 3.141592653589793238462643383279502884197169;',
+ // 3.0 / ( 16.0 * pi )
+ const float THREE_OVER_SIXTEENPI = 0.05968310365946075;
+ // 1.0 / ( 4.0 * pi )
+ const float ONE_OVER_FOURPI = 0.07957747154594767;
- 'const float n = 1.0003;', // refractive index of air
- 'const float N = 2.545E25;', // number of molecules per unit volume for air at 288.15K and 1013mb (sea level -45 celsius)
+ float rayleighPhase( float cosTheta ) {
+ return THREE_OVER_SIXTEENPI * ( 1.0 + pow( cosTheta, 2.0 ) );
+ }
- // optical length at zenith for molecules
- 'const float rayleighZenithLength = 8.4E3;',
- 'const float mieZenithLength = 1.25E3;',
- // 66 arc seconds -> degrees, and the cosine of that
- 'const float sunAngularDiameterCos = 0.999956676946448443553574619906976478926848692873900859324;',
+ float hgPhase( float cosTheta, float g ) {
+ float g2 = pow( g, 2.0 );
+ float inverse = 1.0 / pow( 1.0 - 2.0 * g * cosTheta + g2, 1.5 );
+ return ONE_OVER_FOURPI * ( ( 1.0 - g2 ) * inverse );
+ }
- // 3.0 / ( 16.0 * pi )
- 'const float THREE_OVER_SIXTEENPI = 0.05968310365946075;',
- // 1.0 / ( 4.0 * pi )
- 'const float ONE_OVER_FOURPI = 0.07957747154594767;',
+ void main() {
- 'float rayleighPhase( float cosTheta ) {',
- ' return THREE_OVER_SIXTEENPI * ( 1.0 + pow( cosTheta, 2.0 ) );',
- '}',
+ vec3 direction = normalize( vWorldPosition - cameraPos );
- 'float hgPhase( float cosTheta, float g ) {',
- ' float g2 = pow( g, 2.0 );',
- ' float inverse = 1.0 / pow( 1.0 - 2.0 * g * cosTheta + g2, 1.5 );',
- ' return ONE_OVER_FOURPI * ( ( 1.0 - g2 ) * inverse );',
- '}',
+ // optical length
+ // cutoff angle at 90 to avoid singularity in next formula.
+ float zenithAngle = acos( max( 0.0, dot( up, direction ) ) );
+ float inverse = 1.0 / ( cos( zenithAngle ) + 0.15 * pow( 93.885 - ( ( zenithAngle * 180.0 ) / pi ), -1.253 ) );
+ float sR = rayleighZenithLength * inverse;
+ float sM = mieZenithLength * inverse;
- // Filmic ToneMapping http://filmicgames.com/archives/75
- 'const float A = 0.15;',
- 'const float B = 0.50;',
- 'const float C = 0.10;',
- 'const float D = 0.20;',
- 'const float E = 0.02;',
- 'const float F = 0.30;',
+ // combined extinction factor
+ vec3 Fex = exp( -( vBetaR * sR + vBetaM * sM ) );
- 'const float whiteScale = 1.0748724675633854;', // 1.0 / Uncharted2Tonemap(1000.0)
+ // in scattering
+ float cosTheta = dot( direction, vSunDirection );
- 'vec3 Uncharted2Tonemap( vec3 x ) {',
- ' return ( ( x * ( A * x + C * B ) + D * E ) / ( x * ( A * x + B ) + D * F ) ) - E / F;',
- '}',
+ float rPhase = rayleighPhase( cosTheta * 0.5 + 0.5 );
+ vec3 betaRTheta = vBetaR * rPhase;
+ float mPhase = hgPhase( cosTheta, mieDirectionalG );
+ vec3 betaMTheta = vBetaM * mPhase;
- 'void main() {',
- // optical length
- // cutoff angle at 90 to avoid singularity in next formula.
- ' float zenithAngle = acos( max( 0.0, dot( up, normalize( vWorldPosition - cameraPos ) ) ) );',
- ' float inverse = 1.0 / ( cos( zenithAngle ) + 0.15 * pow( 93.885 - ( ( zenithAngle * 180.0 ) / pi ), -1.253 ) );',
- ' float sR = rayleighZenithLength * inverse;',
- ' float sM = mieZenithLength * inverse;',
+ vec3 Lin = pow( vSunE * ( ( betaRTheta + betaMTheta ) / ( vBetaR + vBetaM ) ) * ( 1.0 - Fex ), vec3( 1.5 ) );
+ Lin *= mix( vec3( 1.0 ), pow( vSunE * ( ( betaRTheta + betaMTheta ) / ( vBetaR + vBetaM ) ) * Fex, vec3( 1.0 / 2.0 ) ), clamp( pow( 1.0 - dot( up, vSunDirection ), 5.0 ), 0.0, 1.0 ) );
- // combined extinction factor
- ' vec3 Fex = exp( -( vBetaR * sR + vBetaM * sM ) );',
+ // nightsky
+ float theta = acos( direction.y ); // elevation --> y-axis, [-pi/2, pi/2]
+ float phi = atan( direction.z, direction.x ); // azimuth --> x-axis [-pi/2, pi/2]
+ vec2 uv = vec2( phi, theta ) / vec2( 2.0 * pi, pi ) + vec2( 0.5, 0.0 );
+ vec3 L0 = vec3( 0.1 ) * Fex;
- // in scattering
- ' float cosTheta = dot( normalize( vWorldPosition - cameraPos ), vSunDirection );',
+ // composition + solar disc
+ float sundisk = smoothstep( sunAngularDiameterCos, sunAngularDiameterCos + 0.00002, cosTheta );
+ L0 += ( vSunE * 19000.0 * Fex ) * sundisk;
- ' float rPhase = rayleighPhase( cosTheta * 0.5 + 0.5 );',
- ' vec3 betaRTheta = vBetaR * rPhase;',
+ vec3 texColor = ( Lin + L0 ) * 0.04 + vec3( 0.0, 0.0003, 0.00075 );
- ' float mPhase = hgPhase( cosTheta, mieDirectionalG );',
- ' vec3 betaMTheta = vBetaM * mPhase;',
+ vec3 retColor = pow( texColor, vec3( 1.0 / ( 1.2 + ( 1.2 * vSunfade ) ) ) );
- ' vec3 Lin = pow( vSunE * ( ( betaRTheta + betaMTheta ) / ( vBetaR + vBetaM ) ) * ( 1.0 - Fex ), vec3( 1.5 ) );',
- ' Lin *= mix( vec3( 1.0 ), pow( vSunE * ( ( betaRTheta + betaMTheta ) / ( vBetaR + vBetaM ) ) * Fex, vec3( 1.0 / 2.0 ) ), clamp( pow( 1.0 - dot( up, vSunDirection ), 5.0 ), 0.0, 1.0 ) );',
+ gl_FragColor = vec4( retColor, 1.0 );
- // nightsky
- ' vec3 direction = normalize( vWorldPosition - cameraPos );',
- ' float theta = acos( direction.y ); // elevation --> y-axis, [-pi/2, pi/2]',
- ' float phi = atan( direction.z, direction.x ); // azimuth --> x-axis [-pi/2, pi/2]',
- ' vec2 uv = vec2( phi, theta ) / vec2( 2.0 * pi, pi ) + vec2( 0.5, 0.0 );',
- ' vec3 L0 = vec3( 0.1 ) * Fex;',
-
- // composition + solar disc
- ' float sundisk = smoothstep( sunAngularDiameterCos, sunAngularDiameterCos + 0.00002, cosTheta );',
- ' L0 += ( vSunE * 19000.0 * Fex ) * sundisk;',
-
- ' vec3 texColor = ( Lin + L0 ) * 0.04 + vec3( 0.0, 0.0003, 0.00075 );',
-
- ' vec3 curr = Uncharted2Tonemap( ( log2( 2.0 / pow( luminance, 4.0 ) ) ) * texColor );',
- ' vec3 color = curr * whiteScale;',
-
- ' vec3 retColor = pow( color, vec3( 1.0 / ( 1.2 + ( 1.2 * vSunfade ) ) ) );',
-
- ' gl_FragColor = vec4( retColor, 1.0 );',
-
- '}'
- ].join( '\n' )
+ #include