From 67a00ebb99e55c4746db6603cee4639efd93070c Mon Sep 17 00:00:00 2001 From: Elias Hasle Date: Mon, 26 Aug 2019 14:20:48 +0200 Subject: [PATCH] Introduce FogExp with class, GLSL, docs and current applications Also correct TS docstring and misspelled name in test file for FogExp2, and doc for standard Fog. Includes the change to distance-based depth, as well as corrections to better support mediump. Makes #17316 and #17324 obsolete. --- docs/api/en/scenes/Fog.html | 2 +- docs/api/en/scenes/FogExp.html | 48 +++++++++++++++++++ docs/list.js | 2 + editor/js/Sidebar.Scene.js | 10 +++- editor/js/Viewport.js | 5 +- src/Three.js | 1 + src/loaders/ObjectLoader.js | 5 ++ src/renderers/WebGLRenderer.js | 2 +- .../shaders/ShaderChunk/fog_fragment.glsl.js | 17 +++++-- .../ShaderChunk/fog_pars_fragment.glsl.js | 4 +- .../ShaderChunk/fog_pars_vertex.glsl.js | 2 +- .../shaders/ShaderChunk/fog_vertex.glsl.js | 2 +- src/renderers/webgl/WebGLProgram.js | 2 + src/renderers/webgl/WebGLPrograms.js | 3 +- src/scenes/Fog.d.ts | 2 +- src/scenes/FogExp.d.ts | 22 +++++++++ src/scenes/FogExp.js | 40 ++++++++++++++++ src/scenes/FogExp2.d.ts | 2 +- test/three.source.unit.js | 1 + test/unit/src/scenes/FogExp.tests.js | 47 ++++++++++++++++++ test/unit/src/scenes/FogExp2.tests.js | 2 +- 21 files changed, 205 insertions(+), 16 deletions(-) create mode 100644 docs/api/en/scenes/FogExp.html create mode 100644 src/scenes/FogExp.d.ts create mode 100644 src/scenes/FogExp.js create mode 100644 test/unit/src/scenes/FogExp.tests.js diff --git a/docs/api/en/scenes/Fog.html b/docs/api/en/scenes/Fog.html index 197d612cb34e09..ac31df194eef5e 100644 --- a/docs/api/en/scenes/Fog.html +++ b/docs/api/en/scenes/Fog.html @@ -10,7 +10,7 @@

[name]

-

This class contains the parameters that define linear fog, i.e., that grows linearly denser with the distance.

+

This class contains the parameters that define smooth ranged fog, i.e., that grows smoothly denser from the near to the far distance.

Constructor

diff --git a/docs/api/en/scenes/FogExp.html b/docs/api/en/scenes/FogExp.html new file mode 100644 index 00000000000000..72e94d0c233a5a --- /dev/null +++ b/docs/api/en/scenes/FogExp.html @@ -0,0 +1,48 @@ + + + + + + + + + + +

[name]

+ +

This class contains the parameters that define exponential fog, i.e., that grows exponentially denser with the distance.

+ + +

Constructor

+ + +

[name]( [param:Integer color], [param:Float density] )

+ +

The color parameter is passed to the [page:Color] constructor to set the color property. Color can be a hexadecimal integer or a CSS-style string.

+

Properties

+ +

[property:String name]

+

Optional name of the object (doesn't need to be unique). Default is an empty string.

+ +

[property:Color color]

+

Fog color. Example: If set to black, far away objects will be rendered black.

+ +

[property:Float density]

+

Defines how fast the fog will grow dense.

+

Default is 0.015.

+ +

Methods

+ +

[method:FogExp clone]()

+

Returns a new FogExp instance with the same parameters as this one.

+ +

[method:FogExp toJSON]()

+

Return FogExp data in JSON format.

+ +

Source

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/list.js b/docs/list.js index eee2418bfe9a2a..274dba5a4b10f9 100644 --- a/docs/list.js +++ b/docs/list.js @@ -328,6 +328,7 @@ var list = { "Scenes": { "Fog": "api/en/scenes/Fog", + "FogExp": "api/en/scenes/FogExp", "FogExp2": "api/en/scenes/FogExp2", "Scene": "api/en/scenes/Scene" }, @@ -771,6 +772,7 @@ var list = { "场景": { "Fog": "api/zh/scenes/Fog", + "FogExp": "api/en/scenes/FogExp", //ZH doc missing for now "FogExp2": "api/zh/scenes/FogExp2", "Scene": "api/zh/scenes/Scene" }, diff --git a/editor/js/Sidebar.Scene.js b/editor/js/Sidebar.Scene.js index 17dcee66e3df85..1bb06a633323ab 100644 --- a/editor/js/Sidebar.Scene.js +++ b/editor/js/Sidebar.Scene.js @@ -144,7 +144,8 @@ Sidebar.Scene = function ( editor ) { 'None': 'None', 'Fog': 'Linear', - 'FogExp2': 'Exponential' + 'FogExp': 'Exponential', + 'FogExp2': 'Exp. squared' } ).setWidth( '150px' ); fogType.onChange( function () { @@ -237,6 +238,11 @@ Sidebar.Scene = function ( editor ) { fogNear.setValue( scene.fog.near ); fogFar.setValue( scene.fog.far ); + } else if ( scene.fog.isFogExp ) { + + fogType.setValue( "FogExp" ); + fogDensity.setValue( scene.fog.density ); + } else if ( scene.fog.isFogExp2 ) { fogType.setValue( "FogExp2" ); @@ -261,7 +267,7 @@ Sidebar.Scene = function ( editor ) { fogPropertiesRow.setDisplay( type === 'None' ? 'none' : '' ); fogNear.setDisplay( type === 'Fog' ? '' : 'none' ); fogFar.setDisplay( type === 'Fog' ? '' : 'none' ); - fogDensity.setDisplay( type === 'FogExp2' ? '' : 'none' ); + fogDensity.setDisplay( ( type === 'FogExp' || type === 'FogExp2' ) ? '' : 'none' ); } diff --git a/editor/js/Viewport.js b/editor/js/Viewport.js index 085f384042d32e..7a8a8c2b0fcc3f 100644 --- a/editor/js/Viewport.js +++ b/editor/js/Viewport.js @@ -470,6 +470,9 @@ var Viewport = function ( editor ) { case 'Fog': scene.fog = new THREE.Fog(); break; + case 'FogExp': + scene.fog = new THREE.FogExp(); + break; case 'FogExp2': scene.fog = new THREE.FogExp2(); break; @@ -488,7 +491,7 @@ var Viewport = function ( editor ) { scene.fog.near = fogNear; scene.fog.far = fogFar; - } else if ( scene.fog.isFogExp2 ) { + } else if ( scene.fog.isFogExp || scene.fog.isFogExp2 ) { scene.fog.color.setHex( fogColor ); scene.fog.density = fogDensity; diff --git a/src/Three.js b/src/Three.js index b95c7128b2b781..059ec895a917be 100644 --- a/src/Three.js +++ b/src/Three.js @@ -9,6 +9,7 @@ export { ShaderLib } from './renderers/shaders/ShaderLib.js'; export { UniformsLib } from './renderers/shaders/UniformsLib.js'; export { UniformsUtils } from './renderers/shaders/UniformsUtils.js'; export { ShaderChunk } from './renderers/shaders/ShaderChunk.js'; +export { FogExp } from './scenes/FogExp.js'; export { FogExp2 } from './scenes/FogExp2.js'; export { Fog } from './scenes/Fog.js'; export { Scene } from './scenes/Scene.js'; diff --git a/src/loaders/ObjectLoader.js b/src/loaders/ObjectLoader.js index d2b2afeea56f06..50fa7cb9ecfdb2 100644 --- a/src/loaders/ObjectLoader.js +++ b/src/loaders/ObjectLoader.js @@ -32,6 +32,7 @@ import { Mesh } from '../objects/Mesh.js'; import { SkinnedMesh } from '../objects/SkinnedMesh.js'; import { Shape } from '../extras/core/Shape.js'; import { Fog } from '../scenes/Fog.js'; +import { FogExp } from '../scenes/FogExp.js'; import { FogExp2 } from '../scenes/FogExp2.js'; import { HemisphereLight } from '../lights/HemisphereLight.js'; import { SpotLight } from '../lights/SpotLight.js'; @@ -759,6 +760,10 @@ ObjectLoader.prototype = Object.assign( Object.create( Loader.prototype ), { object.fog = new Fog( data.fog.color, data.fog.near, data.fog.far ); + } else if ( data.fog.type === 'FogExp' ) { + + object.fog = new FogExp( data.fog.color, data.fog.density ); + } else if ( data.fog.type === 'FogExp2' ) { object.fog = new FogExp2( data.fog.color, data.fog.density ); diff --git a/src/renderers/WebGLRenderer.js b/src/renderers/WebGLRenderer.js index 80c08b2c8ffc40..59e13b24569fcd 100644 --- a/src/renderers/WebGLRenderer.js +++ b/src/renderers/WebGLRenderer.js @@ -2220,7 +2220,7 @@ function WebGLRenderer( parameters ) { uniforms.fogNear.value = fog.near; uniforms.fogFar.value = fog.far; - } else if ( fog.isFogExp2 ) { + } else if ( fog.isFogExp || fog.isFogExp2 ) { uniforms.fogDensity.value = fog.density; diff --git a/src/renderers/shaders/ShaderChunk/fog_fragment.glsl.js b/src/renderers/shaders/ShaderChunk/fog_fragment.glsl.js index 996a17e149d156..c7482d7c990d5c 100644 --- a/src/renderers/shaders/ShaderChunk/fog_fragment.glsl.js +++ b/src/renderers/shaders/ShaderChunk/fog_fragment.glsl.js @@ -2,12 +2,23 @@ export default /* glsl */` #ifdef USE_FOG #ifdef FOG_EXP2 - - float fogFactor = 1.0 - exp( - fogDensity * fogDensity * fogDepth * fogDepth ); + + vec3 scaledFogPosition = fogDensity * fogPosition; + float fogFactor = 1.0 - exp( - dot( scaledFogPosition, scaledFogPosition ) ); #else - float fogFactor = smoothstep( fogNear, fogFar, fogDepth ); + float fogDepth = precisionSafeLength( fogPosition ); + + #ifdef FOG_EXP + + float fogFactor = whiteComplement( exp( - fogDensity * fogDepth ) ); + + #else + + float fogFactor = smoothstep( fogNear, fogFar, fogDepth ); + + #endif #endif diff --git a/src/renderers/shaders/ShaderChunk/fog_pars_fragment.glsl.js b/src/renderers/shaders/ShaderChunk/fog_pars_fragment.glsl.js index 808c7c55cc222a..5207460468ffe3 100644 --- a/src/renderers/shaders/ShaderChunk/fog_pars_fragment.glsl.js +++ b/src/renderers/shaders/ShaderChunk/fog_pars_fragment.glsl.js @@ -2,9 +2,9 @@ export default /* glsl */` #ifdef USE_FOG uniform vec3 fogColor; - varying float fogDepth; + varying vec3 fogPosition; - #ifdef FOG_EXP2 + #if defined( FOG_EXP ) || defined( FOG_EXP2 ) uniform float fogDensity; diff --git a/src/renderers/shaders/ShaderChunk/fog_pars_vertex.glsl.js b/src/renderers/shaders/ShaderChunk/fog_pars_vertex.glsl.js index 284d460f48543b..5e64204c8e8df3 100644 --- a/src/renderers/shaders/ShaderChunk/fog_pars_vertex.glsl.js +++ b/src/renderers/shaders/ShaderChunk/fog_pars_vertex.glsl.js @@ -1,7 +1,7 @@ export default /* glsl */` #ifdef USE_FOG - varying float fogDepth; + varying vec3 fogPosition; #endif `; diff --git a/src/renderers/shaders/ShaderChunk/fog_vertex.glsl.js b/src/renderers/shaders/ShaderChunk/fog_vertex.glsl.js index ecfc773911a311..0028bcbc19cfb2 100644 --- a/src/renderers/shaders/ShaderChunk/fog_vertex.glsl.js +++ b/src/renderers/shaders/ShaderChunk/fog_vertex.glsl.js @@ -1,7 +1,7 @@ export default /* glsl */` #ifdef USE_FOG - fogDepth = -mvPosition.z; + fogPosition = mvPosition.xyz; #endif `; diff --git a/src/renderers/webgl/WebGLProgram.js b/src/renderers/webgl/WebGLProgram.js index 39e8378dc7f46e..6ec39d7afb96e0 100644 --- a/src/renderers/webgl/WebGLProgram.js +++ b/src/renderers/webgl/WebGLProgram.js @@ -448,6 +448,7 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters '#define MAX_BONES ' + parameters.maxBones, ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '', + ( parameters.useFog && parameters.fogExp ) ? '#define FOG_EXP' : '', ( parameters.useFog && parameters.fogExp2 ) ? '#define FOG_EXP2' : '', parameters.map ? '#define USE_MAP' : '', @@ -585,6 +586,7 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters '#define GAMMA_FACTOR ' + gammaFactorDefine, ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '', + ( parameters.useFog && parameters.fogExp ) ? '#define FOG_EXP' : '', ( parameters.useFog && parameters.fogExp2 ) ? '#define FOG_EXP2' : '', parameters.map ? '#define USE_MAP' : '', diff --git a/src/renderers/webgl/WebGLPrograms.js b/src/renderers/webgl/WebGLPrograms.js index f7a08b7c54bee4..123c1c7392e1bf 100644 --- a/src/renderers/webgl/WebGLPrograms.js +++ b/src/renderers/webgl/WebGLPrograms.js @@ -32,7 +32,7 @@ function WebGLPrograms( renderer, extensions, capabilities ) { "map", "mapEncoding", "matcap", "matcapEncoding", "envMap", "envMapMode", "envMapEncoding", "lightMap", "aoMap", "emissiveMap", "emissiveMapEncoding", "bumpMap", "normalMap", "objectSpaceNormalMap", "tangentSpaceNormalMap", "clearcoatNormalMap", "displacementMap", "specularMap", "roughnessMap", "metalnessMap", "gradientMap", - "alphaMap", "combine", "vertexColors", "vertexTangents", "fog", "useFog", "fogExp2", + "alphaMap", "combine", "vertexColors", "vertexTangents", "fog", "useFog", "fogExp", "fogExp2", "flatShading", "sizeAttenuation", "logarithmicDepthBuffer", "skinning", "maxBones", "useVertexTexture", "morphTargets", "morphNormals", "maxMorphTargets", "maxMorphNormals", "premultipliedAlpha", @@ -180,6 +180,7 @@ function WebGLPrograms( renderer, extensions, capabilities ) { fog: !! fog, useFog: material.fog, + fogExp: ( fog && fog.isFogExp ), fogExp2: ( fog && fog.isFogExp2 ), flatShading: material.flatShading, diff --git a/src/scenes/Fog.d.ts b/src/scenes/Fog.d.ts index e992d145b75417..e0b692b7d47b40 100644 --- a/src/scenes/Fog.d.ts +++ b/src/scenes/Fog.d.ts @@ -8,7 +8,7 @@ export interface IFog { } /** - * This class contains the parameters that define linear fog, i.e., that grows linearly denser with the distance. + * This class contains the parameters that define smooth ranged fog, i.e., that grows smoothly denser from the near to the far distance. */ export class Fog implements IFog { diff --git a/src/scenes/FogExp.d.ts b/src/scenes/FogExp.d.ts new file mode 100644 index 00000000000000..adbb0b8e1da492 --- /dev/null +++ b/src/scenes/FogExp.d.ts @@ -0,0 +1,22 @@ +import { Color } from './../math/Color'; +import { IFog } from './Fog'; +/** + * This class contains the parameters that define exponential fog, i.e., that grows exponentially denser with the distance. + */ +export class FogExp implements IFog { + + constructor( hex: number | string, density?: number ); + + name: string; + color: Color; + + /** + * Defines how fast the fog will grow dense. + * Default is 0.015. + */ + density: number; + + clone(): this; + toJSON(): any; + +} diff --git a/src/scenes/FogExp.js b/src/scenes/FogExp.js new file mode 100644 index 00000000000000..58252ae4d16230 --- /dev/null +++ b/src/scenes/FogExp.js @@ -0,0 +1,40 @@ +/** + * @author mrdoob / http://mrdoob.com/ + * @author alteredq / http://alteredqualia.com/ + * @author EliasHasle / http://eliashasle.github.io/ + */ + +import { Color } from '../math/Color.js'; + +function FogExp( color, density ) { + + this.name = ''; + + this.color = new Color( color ); + this.density = ( density !== undefined ) ? density : 0.015; + +} + +Object.assign( FogExp.prototype, { + + isFogExp: true, + + clone: function () { + + return new FogExp( this.color, this.density ); + + }, + + toJSON: function ( /* meta */ ) { + + return { + type: 'FogExp', + color: this.color.getHex(), + density: this.density + }; + + } + +} ); + +export { FogExp }; diff --git a/src/scenes/FogExp2.d.ts b/src/scenes/FogExp2.d.ts index b9897b29d9a33b..2f475245b66bfb 100644 --- a/src/scenes/FogExp2.d.ts +++ b/src/scenes/FogExp2.d.ts @@ -1,7 +1,7 @@ import { Color } from './../math/Color'; import { IFog } from './Fog'; /** - * This class contains the parameters that define linear fog, i.e., that grows exponentially denser with the distance. + * This class contains the parameters that define exponential squared fog, which gives a clear view near the camera and a faster than exponentially densening fog farther from the camera. */ export class FogExp2 implements IFog { diff --git a/test/three.source.unit.js b/test/three.source.unit.js index 7ef2c85dbeb820..4e257a43caa618 100644 --- a/test/three.source.unit.js +++ b/test/three.source.unit.js @@ -273,6 +273,7 @@ import './unit/src/renderers/webvr/WebVRManager.tests'; //src/scenes import './unit/src/scenes/Fog.tests'; +import './unit/src/scenes/FogExp.tests'; import './unit/src/scenes/FogExp2.tests'; import './unit/src/scenes/Scene.tests'; diff --git a/test/unit/src/scenes/FogExp.tests.js b/test/unit/src/scenes/FogExp.tests.js new file mode 100644 index 00000000000000..7cdae81d6f6e98 --- /dev/null +++ b/test/unit/src/scenes/FogExp.tests.js @@ -0,0 +1,47 @@ +/** + * @author TristanVALCKE / https://github.com/Itee + */ +/* global QUnit */ + +import { FogExp } from '../../../../src/scenes/FogExp'; + +export default QUnit.module( 'FogExp', () => { + + QUnit.module( 'Scene', () => { + + // INHERITANCE + QUnit.todo( "Extending", ( assert ) => { + + assert.ok( false, "everything's gonna be alright" ); + + } ); + + // INSTANCING + QUnit.todo( "Instancing", ( assert ) => { + + assert.ok( false, "everything's gonna be alright" ); + + } ); + + // PUBLIC STUFF + QUnit.todo( "isFogExp", ( assert ) => { + + assert.ok( false, "everything's gonna be alright" ); + + } ); + + QUnit.todo( "clone", ( assert ) => { + + assert.ok( false, "everything's gonna be alright" ); + + } ); + + QUnit.todo( "toJSON", ( assert ) => { + + assert.ok( false, "everything's gonna be alright" ); + + } ); + + } ); + +} ); diff --git a/test/unit/src/scenes/FogExp2.tests.js b/test/unit/src/scenes/FogExp2.tests.js index 2fcaeb5ebecdd4..0825e76a248153 100644 --- a/test/unit/src/scenes/FogExp2.tests.js +++ b/test/unit/src/scenes/FogExp2.tests.js @@ -5,7 +5,7 @@ import { FogExp2 } from '../../../../src/scenes/FogExp2'; -export default QUnit.module( 'FoxExp2', () => { +export default QUnit.module( 'FogExp2', () => { QUnit.module( 'Scene', () => {