Browse Source

Editor: added handling of fog to "World" section.

Not sure if helpers should be fogged or not. It does look pretty weird when they are not fogged. Also having helpers fogged helps to get a sense of the fog effect over larger space.

Maybe there could be a checkbox for enabling this, to be able to see things if they need to be modified while in the fog.

Also found and fixed a bug deep in WebGLRenderer, where shaders were not recompiled when changing fog types because fog type wasn't taken into account when creating shader code hash. Phew, that was a tough one to figure out. This Editor thingie really forces us to dust all nooks and cranies of the codebase ;)
alteredq 12 years ago
parent
commit
021837a028

+ 15 - 2
build/three.js

@@ -12088,6 +12088,12 @@ THREE.Fog = function ( hex, near, far ) {
 	this.near = ( near !== undefined ) ? near : 1;
 	this.far = ( far !== undefined ) ? far : 1000;
 
+};
+
+THREE.Fog.prototype.clone = function () {
+
+	return new THREE.Fog( this.color.getHex(), this.near, this.far );
+
 };
 /**
  * @author mrdoob / http://mrdoob.com/
@@ -12099,6 +12105,12 @@ THREE.FogExp2 = function ( hex, density ) {
 	this.color = new THREE.Color( hex );
 	this.density = ( density !== undefined ) ? density : 0.00025;
 
+};
+
+THREE.FogExp2.prototype.clone = function () {
+
+	return new THREE.FogExp2( this.color.getHex(), this.density );
+
 };
 /**
  * @author mrdoob / http://mrdoob.com/
@@ -20460,6 +20472,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 			fog: fog,
 			useFog: material.fog,
+			fogExp: fog instanceof THREE.FogExp2,
 
 			sizeAttenuation: material.sizeAttenuation,
 
@@ -21750,7 +21763,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 			if ( programInfo.code === code ) {
 
-				// console.log( "Code already compiled." /*: \n\n" + code*/ );
+				//console.log( "Code already compiled." /*: \n\n" + code*/ );
 
 				programInfo.usedTimes ++;
 
@@ -21894,7 +21907,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 			_this.physicallyBasedShading ? "#define PHYSICALLY_BASED_SHADING" : "",
 
 			( parameters.useFog && parameters.fog ) ? "#define USE_FOG" : "",
-			( parameters.useFog && parameters.fog instanceof THREE.FogExp2 ) ? "#define FOG_EXP2" : "",
+			( parameters.useFog && parameters.fogExp ) ? "#define FOG_EXP2" : "",
 
 			parameters.map ? "#define USE_MAP" : "",
 			parameters.envMap ? "#define USE_ENVMAP" : "",

+ 10 - 10
build/three.min.js

@@ -271,7 +271,7 @@ a);return a};THREE.SpriteAlignment={};THREE.SpriteAlignment.topLeft=new THREE.Ve
 THREE.SpriteAlignment.bottomRight=new THREE.Vector2(-1,1);THREE.Scene=function(){THREE.Object3D.call(this);this.overrideMaterial=this.fog=null;this.matrixAutoUpdate=!1;this.__objects=[];this.__lights=[];this.__objectsAdded=[];this.__objectsRemoved=[]};THREE.Scene.prototype=Object.create(THREE.Object3D.prototype);
 THREE.Scene.prototype.__addObject=function(a){if(a instanceof THREE.Light)-1===this.__lights.indexOf(a)&&this.__lights.push(a),a.target&&void 0===a.target.parent&&this.add(a.target);else if(!(a instanceof THREE.Camera||a instanceof THREE.Bone)&&-1===this.__objects.indexOf(a)){this.__objects.push(a);this.__objectsAdded.push(a);var b=this.__objectsRemoved.indexOf(a);-1!==b&&this.__objectsRemoved.splice(b,1)}for(b=0;b<a.children.length;b++)this.__addObject(a.children[b])};
 THREE.Scene.prototype.__removeObject=function(a){if(a instanceof THREE.Light){var b=this.__lights.indexOf(a);-1!==b&&this.__lights.splice(b,1)}else a instanceof THREE.Camera||(b=this.__objects.indexOf(a),-1!==b&&(this.__objects.splice(b,1),this.__objectsRemoved.push(a),b=this.__objectsAdded.indexOf(a),-1!==b&&this.__objectsAdded.splice(b,1)));for(b=0;b<a.children.length;b++)this.__removeObject(a.children[b])};
-THREE.Fog=function(a,b,c){this.color=new THREE.Color(a);this.near=void 0!==b?b:1;this.far=void 0!==c?c:1E3};THREE.FogExp2=function(a,b){this.color=new THREE.Color(a);this.density=void 0!==b?b:2.5E-4};
+THREE.Fog=function(a,b,c){this.color=new THREE.Color(a);this.near=void 0!==b?b:1;this.far=void 0!==c?c:1E3};THREE.Fog.prototype.clone=function(){return new THREE.Fog(this.color.getHex(),this.near,this.far)};THREE.FogExp2=function(a,b){this.color=new THREE.Color(a);this.density=void 0!==b?b:2.5E-4};THREE.FogExp2.prototype.clone=function(){return new THREE.FogExp2(this.color.getHex(),this.density)};
 THREE.CanvasRenderer=function(a){function b(a){z!==a&&(z=q.globalAlpha=a)}function c(a){u!==a&&(a===THREE.NormalBlending?q.globalCompositeOperation="source-over":a===THREE.AdditiveBlending?q.globalCompositeOperation="lighter":a===THREE.SubtractiveBlending&&(q.globalCompositeOperation="darker"),u=a)}function d(a){t!==a&&(t=q.strokeStyle=a)}function e(a){E!==a&&(E=q.fillStyle=a)}console.log("THREE.CanvasRenderer",THREE.REVISION);var a=a||{},f=this,g,h,i,j=new THREE.Projector,m=void 0!==a.canvas?a.canvas:
 document.createElement("canvas"),n,l,p,o,q=m.getContext("2d"),r=new THREE.Color(0),s=0,z=1,u=0,t=null,E=null,A=null,v=null,x=null,B,F,H,J,I=new THREE.RenderableVertex,L=new THREE.RenderableVertex,C,G,R,P,Q,Y,oa,N,M,da,S,K,O=new THREE.Color,ha=new THREE.Color,Z=new THREE.Color,aa=new THREE.Color,ia=new THREE.Color,U=new THREE.Color,ea=new THREE.Color,eb={},Aa={},Ja,Ta,ra,Ma,qb,nb,fb,Wa,zb,Ab,ob=new THREE.Rectangle,Na=new THREE.Rectangle,ka=new THREE.Rectangle,kb=!1,Ha=new THREE.Color,cb=new THREE.Color,
 lb=new THREE.Color,ua=new THREE.Vector3,gb,Xa,rb,va,Ya,Za,a=16;gb=document.createElement("canvas");gb.width=gb.height=2;Xa=gb.getContext("2d");Xa.fillStyle="rgba(0,0,0,1)";Xa.fillRect(0,0,2,2);rb=Xa.getImageData(0,0,2,2);va=rb.data;Ya=document.createElement("canvas");Ya.width=Ya.height=a;Za=Ya.getContext("2d");Za.translate(-a/2,-a/2);Za.scale(a,a);a--;this.domElement=m;this.sortElements=this.sortObjects=this.autoClear=!0;this.info={render:{vertices:0,faces:0}};this.setSize=function(a,b){n=a;l=b;p=
@@ -468,16 +468,16 @@ Ca.value[Va],Ca.array[Ga]=jb.x,Ca.array[Ga+1]=jb.y,Ca.array[Ga+2]=jb.z,Ga+=3;els
 !fa.dynamic),fa.verticesNeedUpdate=!1,fa.colorsNeedUpdate=!1):(ka=e(Aa,fa),ua=ka.attributes&&r(ka),(fa.verticesNeedUpdate||fa.colorsNeedUpdate||Aa.sortParticles||ua)&&i(fa,k.DYNAMIC_DRAW,Aa),fa.verticesNeedUpdate=!1,fa.colorsNeedUpdate=!1,ka.attributes&&s(ka)))}};this.initMaterial=function(a,b,c,d){var e,f,g,h,i,j,l,m,n;a instanceof THREE.MeshDepthMaterial?n="depth":a instanceof THREE.MeshNormalMaterial?n="normal":a instanceof THREE.MeshBasicMaterial?n="basic":a instanceof THREE.MeshLambertMaterial?
 n="lambert":a instanceof THREE.MeshPhongMaterial?n="phong":a instanceof THREE.LineBasicMaterial?n="basic":a instanceof THREE.ParticleBasicMaterial&&(n="particle_basic");if(n){var o=THREE.ShaderLib[n];a.uniforms=THREE.UniformsUtils.clone(o.uniforms);a.vertexShader=o.vertexShader;a.fragmentShader=o.fragmentShader}var p,q,s;e=p=q=s=o=0;for(f=b.length;e<f;e++)g=b[e],g.onlyShadow||(g instanceof THREE.DirectionalLight&&p++,g instanceof THREE.PointLight&&q++,g instanceof THREE.SpotLight&&s++,g instanceof
 THREE.HemisphereLight&&o++);q+s+p+o<=S?e=p:(e=Math.ceil(S*p/(q+p)),s=q=S-e,o=e);f=q;g=s;h=o;o=p=0;for(s=b.length;o<s;o++)q=b[o],q.castShadow&&(q instanceof THREE.SpotLight&&p++,q instanceof THREE.DirectionalLight&&!q.shadowCascade&&p++);m=p;fc&&d&&d.useVertexTexture?l=1024:(b=k.getParameter(k.MAX_VERTEX_UNIFORM_VECTORS),b=Math.floor((b-20)/4),void 0!==d&&d instanceof THREE.SkinnedMesh&&(b=Math.min(d.bones.length,b),b<d.bones.length&&console.warn("WebGLRenderer: too many bones - "+d.bones.length+", this GPU supports just "+
-b+" (try OpenGL instead of ANGLE)")),l=b);var r;a:{q=a.fragmentShader;s=a.vertexShader;o=a.uniforms;b=a.attributes;p=a.defines;var c={map:!!a.map,envMap:!!a.envMap,lightMap:!!a.lightMap,bumpMap:!!a.bumpMap,normalMap:!!a.normalMap,specularMap:!!a.specularMap,vertexColors:a.vertexColors,fog:c,useFog:a.fog,sizeAttenuation:a.sizeAttenuation,skinning:a.skinning,maxBones:l,useVertexTexture:fc&&d&&d.useVertexTexture,boneTextureWidth:d&&d.boneTextureWidth,boneTextureHeight:d&&d.boneTextureHeight,morphTargets:a.morphTargets,
-morphNormals:a.morphNormals,maxMorphTargets:this.maxMorphTargets,maxMorphNormals:this.maxMorphNormals,maxDirLights:e,maxPointLights:f,maxSpotLights:g,maxHemiLights:h,maxShadows:m,shadowMapEnabled:this.shadowMapEnabled&&d.receiveShadow,shadowMapSoft:this.shadowMapSoft,shadowMapDebug:this.shadowMapDebug,shadowMapCascade:this.shadowMapCascade,alphaTest:a.alphaTest,metal:a.metal,perPixel:a.perPixel,wrapAround:a.wrapAround,doubleSided:a.side===THREE.DoubleSide,flipSided:a.side===THREE.BackSide},t,u,v,
-d=[];n?d.push(n):(d.push(q),d.push(s));for(u in p)d.push(u),d.push(p[u]);for(t in c)d.push(t),d.push(c[t]);n=d.join();t=0;for(u=O.length;t<u;t++)if(d=O[t],d.code===n){d.usedTimes++;r=d.program;break a}t=[];for(v in p)u=p[v],!1!==u&&(u="#define "+v+" "+u,t.push(u));u=t.join("\n");v=k.createProgram();t=["precision "+R+" float;",u,gc?"#define VERTEX_TEXTURES":"",K.gammaInput?"#define GAMMA_INPUT":"",K.gammaOutput?"#define GAMMA_OUTPUT":"",K.physicallyBasedShading?"#define PHYSICALLY_BASED_SHADING":"",
-"#define MAX_DIR_LIGHTS "+c.maxDirLights,"#define MAX_POINT_LIGHTS "+c.maxPointLights,"#define MAX_SPOT_LIGHTS "+c.maxSpotLights,"#define MAX_HEMI_LIGHTS "+c.maxHemiLights,"#define MAX_SHADOWS "+c.maxShadows,"#define MAX_BONES "+c.maxBones,c.map?"#define USE_MAP":"",c.envMap?"#define USE_ENVMAP":"",c.lightMap?"#define USE_LIGHTMAP":"",c.bumpMap?"#define USE_BUMPMAP":"",c.normalMap?"#define USE_NORMALMAP":"",c.specularMap?"#define USE_SPECULARMAP":"",c.vertexColors?"#define USE_COLOR":"",c.skinning?
-"#define USE_SKINNING":"",c.useVertexTexture?"#define BONE_TEXTURE":"",c.boneTextureWidth?"#define N_BONE_PIXEL_X "+c.boneTextureWidth.toFixed(1):"",c.boneTextureHeight?"#define N_BONE_PIXEL_Y "+c.boneTextureHeight.toFixed(1):"",c.morphTargets?"#define USE_MORPHTARGETS":"",c.morphNormals?"#define USE_MORPHNORMALS":"",c.perPixel?"#define PHONG_PER_PIXEL":"",c.wrapAround?"#define WRAP_AROUND":"",c.doubleSided?"#define DOUBLE_SIDED":"",c.flipSided?"#define FLIP_SIDED":"",c.shadowMapEnabled?"#define USE_SHADOWMAP":
-"",c.shadowMapSoft?"#define SHADOWMAP_SOFT":"",c.shadowMapDebug?"#define SHADOWMAP_DEBUG":"",c.shadowMapCascade?"#define SHADOWMAP_CASCADE":"",c.sizeAttenuation?"#define USE_SIZEATTENUATION":"","uniform mat4 modelMatrix;\nuniform mat4 modelViewMatrix;\nuniform mat4 projectionMatrix;\nuniform mat4 viewMatrix;\nuniform mat3 normalMatrix;\nuniform vec3 cameraPosition;\nattribute vec3 position;\nattribute vec3 normal;\nattribute vec2 uv;\nattribute vec2 uv2;\n#ifdef USE_COLOR\nattribute vec3 color;\n#endif\n#ifdef USE_MORPHTARGETS\nattribute vec3 morphTarget0;\nattribute vec3 morphTarget1;\nattribute vec3 morphTarget2;\nattribute vec3 morphTarget3;\n#ifdef USE_MORPHNORMALS\nattribute vec3 morphNormal0;\nattribute vec3 morphNormal1;\nattribute vec3 morphNormal2;\nattribute vec3 morphNormal3;\n#else\nattribute vec3 morphTarget4;\nattribute vec3 morphTarget5;\nattribute vec3 morphTarget6;\nattribute vec3 morphTarget7;\n#endif\n#endif\n#ifdef USE_SKINNING\nattribute vec4 skinIndex;\nattribute vec4 skinWeight;\n#endif\n"].join("\n");
+b+" (try OpenGL instead of ANGLE)")),l=b);var r;a:{q=a.fragmentShader;s=a.vertexShader;o=a.uniforms;b=a.attributes;p=a.defines;var c={map:!!a.map,envMap:!!a.envMap,lightMap:!!a.lightMap,bumpMap:!!a.bumpMap,normalMap:!!a.normalMap,specularMap:!!a.specularMap,vertexColors:a.vertexColors,fog:c,useFog:a.fog,fogExp:c instanceof THREE.FogExp2,sizeAttenuation:a.sizeAttenuation,skinning:a.skinning,maxBones:l,useVertexTexture:fc&&d&&d.useVertexTexture,boneTextureWidth:d&&d.boneTextureWidth,boneTextureHeight:d&&
+d.boneTextureHeight,morphTargets:a.morphTargets,morphNormals:a.morphNormals,maxMorphTargets:this.maxMorphTargets,maxMorphNormals:this.maxMorphNormals,maxDirLights:e,maxPointLights:f,maxSpotLights:g,maxHemiLights:h,maxShadows:m,shadowMapEnabled:this.shadowMapEnabled&&d.receiveShadow,shadowMapSoft:this.shadowMapSoft,shadowMapDebug:this.shadowMapDebug,shadowMapCascade:this.shadowMapCascade,alphaTest:a.alphaTest,metal:a.metal,perPixel:a.perPixel,wrapAround:a.wrapAround,doubleSided:a.side===THREE.DoubleSide,
+flipSided:a.side===THREE.BackSide},t,u,v,d=[];n?d.push(n):(d.push(q),d.push(s));for(u in p)d.push(u),d.push(p[u]);for(t in c)d.push(t),d.push(c[t]);n=d.join();t=0;for(u=O.length;t<u;t++)if(d=O[t],d.code===n){d.usedTimes++;r=d.program;break a}t=[];for(v in p)u=p[v],!1!==u&&(u="#define "+v+" "+u,t.push(u));u=t.join("\n");v=k.createProgram();t=["precision "+R+" float;",u,gc?"#define VERTEX_TEXTURES":"",K.gammaInput?"#define GAMMA_INPUT":"",K.gammaOutput?"#define GAMMA_OUTPUT":"",K.physicallyBasedShading?
+"#define PHYSICALLY_BASED_SHADING":"","#define MAX_DIR_LIGHTS "+c.maxDirLights,"#define MAX_POINT_LIGHTS "+c.maxPointLights,"#define MAX_SPOT_LIGHTS "+c.maxSpotLights,"#define MAX_HEMI_LIGHTS "+c.maxHemiLights,"#define MAX_SHADOWS "+c.maxShadows,"#define MAX_BONES "+c.maxBones,c.map?"#define USE_MAP":"",c.envMap?"#define USE_ENVMAP":"",c.lightMap?"#define USE_LIGHTMAP":"",c.bumpMap?"#define USE_BUMPMAP":"",c.normalMap?"#define USE_NORMALMAP":"",c.specularMap?"#define USE_SPECULARMAP":"",c.vertexColors?
+"#define USE_COLOR":"",c.skinning?"#define USE_SKINNING":"",c.useVertexTexture?"#define BONE_TEXTURE":"",c.boneTextureWidth?"#define N_BONE_PIXEL_X "+c.boneTextureWidth.toFixed(1):"",c.boneTextureHeight?"#define N_BONE_PIXEL_Y "+c.boneTextureHeight.toFixed(1):"",c.morphTargets?"#define USE_MORPHTARGETS":"",c.morphNormals?"#define USE_MORPHNORMALS":"",c.perPixel?"#define PHONG_PER_PIXEL":"",c.wrapAround?"#define WRAP_AROUND":"",c.doubleSided?"#define DOUBLE_SIDED":"",c.flipSided?"#define FLIP_SIDED":
+"",c.shadowMapEnabled?"#define USE_SHADOWMAP":"",c.shadowMapSoft?"#define SHADOWMAP_SOFT":"",c.shadowMapDebug?"#define SHADOWMAP_DEBUG":"",c.shadowMapCascade?"#define SHADOWMAP_CASCADE":"",c.sizeAttenuation?"#define USE_SIZEATTENUATION":"","uniform mat4 modelMatrix;\nuniform mat4 modelViewMatrix;\nuniform mat4 projectionMatrix;\nuniform mat4 viewMatrix;\nuniform mat3 normalMatrix;\nuniform vec3 cameraPosition;\nattribute vec3 position;\nattribute vec3 normal;\nattribute vec2 uv;\nattribute vec2 uv2;\n#ifdef USE_COLOR\nattribute vec3 color;\n#endif\n#ifdef USE_MORPHTARGETS\nattribute vec3 morphTarget0;\nattribute vec3 morphTarget1;\nattribute vec3 morphTarget2;\nattribute vec3 morphTarget3;\n#ifdef USE_MORPHNORMALS\nattribute vec3 morphNormal0;\nattribute vec3 morphNormal1;\nattribute vec3 morphNormal2;\nattribute vec3 morphNormal3;\n#else\nattribute vec3 morphTarget4;\nattribute vec3 morphTarget5;\nattribute vec3 morphTarget6;\nattribute vec3 morphTarget7;\n#endif\n#endif\n#ifdef USE_SKINNING\nattribute vec4 skinIndex;\nattribute vec4 skinWeight;\n#endif\n"].join("\n");
 u=["precision "+R+" float;",c.bumpMap||c.normalMap?"#extension GL_OES_standard_derivatives : enable":"",u,"#define MAX_DIR_LIGHTS "+c.maxDirLights,"#define MAX_POINT_LIGHTS "+c.maxPointLights,"#define MAX_SPOT_LIGHTS "+c.maxSpotLights,"#define MAX_HEMI_LIGHTS "+c.maxHemiLights,"#define MAX_SHADOWS "+c.maxShadows,c.alphaTest?"#define ALPHATEST "+c.alphaTest:"",K.gammaInput?"#define GAMMA_INPUT":"",K.gammaOutput?"#define GAMMA_OUTPUT":"",K.physicallyBasedShading?"#define PHYSICALLY_BASED_SHADING":"",
-c.useFog&&c.fog?"#define USE_FOG":"",c.useFog&&c.fog instanceof THREE.FogExp2?"#define FOG_EXP2":"",c.map?"#define USE_MAP":"",c.envMap?"#define USE_ENVMAP":"",c.lightMap?"#define USE_LIGHTMAP":"",c.bumpMap?"#define USE_BUMPMAP":"",c.normalMap?"#define USE_NORMALMAP":"",c.specularMap?"#define USE_SPECULARMAP":"",c.vertexColors?"#define USE_COLOR":"",c.metal?"#define METAL":"",c.perPixel?"#define PHONG_PER_PIXEL":"",c.wrapAround?"#define WRAP_AROUND":"",c.doubleSided?"#define DOUBLE_SIDED":"",c.flipSided?
-"#define FLIP_SIDED":"",c.shadowMapEnabled?"#define USE_SHADOWMAP":"",c.shadowMapSoft?"#define SHADOWMAP_SOFT":"",c.shadowMapDebug?"#define SHADOWMAP_DEBUG":"",c.shadowMapCascade?"#define SHADOWMAP_CASCADE":"","uniform mat4 viewMatrix;\nuniform vec3 cameraPosition;\n"].join("\n");u=H("fragment",u+q);t=H("vertex",t+s);k.attachShader(v,t);k.attachShader(v,u);k.linkProgram(v);k.getProgramParameter(v,k.LINK_STATUS)||console.error("Could not initialise shader\nVALIDATE_STATUS: "+k.getProgramParameter(v,
-k.VALIDATE_STATUS)+", gl error ["+k.getError()+"]");k.deleteShader(u);k.deleteShader(t);v.uniforms={};v.attributes={};var x;t="viewMatrix modelViewMatrix projectionMatrix normalMatrix modelMatrix cameraPosition morphTargetInfluences".split(" ");c.useVertexTexture?t.push("boneTexture"):t.push("boneGlobalMatrices");for(x in o)t.push(x);x=t;t=0;for(u=x.length;t<u;t++)d=x[t],v.uniforms[d]=k.getUniformLocation(v,d);t="position normal uv uv2 tangent color skinIndex skinWeight".split(" ");for(x=0;x<c.maxMorphTargets;x++)t.push("morphTarget"+
+c.useFog&&c.fog?"#define USE_FOG":"",c.useFog&&c.fogExp?"#define FOG_EXP2":"",c.map?"#define USE_MAP":"",c.envMap?"#define USE_ENVMAP":"",c.lightMap?"#define USE_LIGHTMAP":"",c.bumpMap?"#define USE_BUMPMAP":"",c.normalMap?"#define USE_NORMALMAP":"",c.specularMap?"#define USE_SPECULARMAP":"",c.vertexColors?"#define USE_COLOR":"",c.metal?"#define METAL":"",c.perPixel?"#define PHONG_PER_PIXEL":"",c.wrapAround?"#define WRAP_AROUND":"",c.doubleSided?"#define DOUBLE_SIDED":"",c.flipSided?"#define FLIP_SIDED":
+"",c.shadowMapEnabled?"#define USE_SHADOWMAP":"",c.shadowMapSoft?"#define SHADOWMAP_SOFT":"",c.shadowMapDebug?"#define SHADOWMAP_DEBUG":"",c.shadowMapCascade?"#define SHADOWMAP_CASCADE":"","uniform mat4 viewMatrix;\nuniform vec3 cameraPosition;\n"].join("\n");u=H("fragment",u+q);t=H("vertex",t+s);k.attachShader(v,t);k.attachShader(v,u);k.linkProgram(v);k.getProgramParameter(v,k.LINK_STATUS)||console.error("Could not initialise shader\nVALIDATE_STATUS: "+k.getProgramParameter(v,k.VALIDATE_STATUS)+
+", gl error ["+k.getError()+"]");k.deleteShader(u);k.deleteShader(t);v.uniforms={};v.attributes={};var x;t="viewMatrix modelViewMatrix projectionMatrix normalMatrix modelMatrix cameraPosition morphTargetInfluences".split(" ");c.useVertexTexture?t.push("boneTexture"):t.push("boneGlobalMatrices");for(x in o)t.push(x);x=t;t=0;for(u=x.length;t<u;t++)d=x[t],v.uniforms[d]=k.getUniformLocation(v,d);t="position normal uv uv2 tangent color skinIndex skinWeight".split(" ");for(x=0;x<c.maxMorphTargets;x++)t.push("morphTarget"+
 x);for(x=0;x<c.maxMorphNormals;x++)t.push("morphNormal"+x);for(r in b)t.push(r);r=t;x=0;for(t=r.length;x<t;x++)u=r[x],v.attributes[u]=k.getAttribLocation(v,u);v.id=ha++;O.push({program:v,code:n,usedTimes:1});K.info.memory.programs=O.length;r=v}a.program=r;r=a.program.attributes;0<=r.position&&k.enableVertexAttribArray(r.position);0<=r.color&&k.enableVertexAttribArray(r.color);0<=r.normal&&k.enableVertexAttribArray(r.normal);0<=r.tangent&&k.enableVertexAttribArray(r.tangent);a.skinning&&(0<=r.skinIndex&&
 0<=r.skinWeight)&&(k.enableVertexAttribArray(r.skinIndex),k.enableVertexAttribArray(r.skinWeight));if(a.attributes)for(j in a.attributes)void 0!==r[j]&&0<=r[j]&&k.enableVertexAttribArray(r[j]);if(a.morphTargets){a.numSupportedMorphTargets=0;v="morphTarget";for(j=0;j<this.maxMorphTargets;j++)x=v+j,0<=r[x]&&(k.enableVertexAttribArray(r[x]),a.numSupportedMorphTargets++)}if(a.morphNormals){a.numSupportedMorphNormals=0;v="morphNormal";for(j=0;j<this.maxMorphNormals;j++)x=v+j,0<=r[x]&&(k.enableVertexAttribArray(r[x]),
 a.numSupportedMorphNormals++)}a.uniformsList=[];for(i in a.uniforms)a.uniformsList.push([a.uniforms[i],i])};this.setFaceCulling=function(a,b){a?(!b||"ccw"===b?k.frontFace(k.CCW):k.frontFace(k.CW),"back"===a?k.cullFace(k.BACK):"front"===a?k.cullFace(k.FRONT):k.cullFace(k.FRONT_AND_BACK),k.enable(k.CULL_FACE)):k.disable(k.CULL_FACE)};this.setMaterialFaces=function(a){var b=a.side===THREE.DoubleSide,a=a.side===THREE.BackSide;Ja!==b&&(b?k.disable(k.CULL_FACE):k.enable(k.CULL_FACE),Ja=b);Ta!==a&&(a?k.frontFace(k.CW):

+ 3 - 0
editor/index.html

@@ -68,6 +68,9 @@
 				materialChanged: new SIGNALS.Signal(),
 				clearColorChanged: new SIGNALS.Signal(),
 				cameraChanged: new SIGNALS.Signal(),
+				fogTypeChanged: new SIGNALS.Signal(),
+				fogColorChanged: new SIGNALS.Signal(),
+				fogParametersChanged: new SIGNALS.Signal(),
 				windowResize: new SIGNALS.Signal()
 
 			};

+ 20 - 3
editor/js/UI.js

@@ -693,6 +693,9 @@ UI.Number = function ( position ) {
 	this.min = - Infinity;
 	this.max = Infinity;
 
+	this.precision = 2;
+	this.step = 1;
+
 	this.onChangeCallback = null;
 
 	var distance = 0;
@@ -718,9 +721,9 @@ UI.Number = function ( position ) {
 
 		distance += movementX - movementY;
 
-		var number = onMouseDownValue + ( distance / ( event.shiftKey ? 10 : 100 ) );
+		var number = onMouseDownValue + ( distance / ( event.shiftKey ? 10 : 100 ) ) * scope.step;
 
-		dom.value = Math.min( scope.max, Math.max( scope.min, number ) ).toFixed( 2 );
+		dom.value = Math.min( scope.max, Math.max( scope.min, number ) ).toFixed( scope.precision );
 
 		if ( scope.onChangeCallback ) scope.onChangeCallback();
 
@@ -800,7 +803,7 @@ UI.Number.prototype.getValue = function () {
 
 UI.Number.prototype.setValue = function ( value ) {
 
-	this.dom.value = value.toFixed( 2 );
+	this.dom.value = value.toFixed( this.precision );
 
 	return this;
 
@@ -815,6 +818,20 @@ UI.Number.prototype.setRange = function ( min, max ) {
 
 };
 
+UI.Number.prototype.setPrecision = function ( precision ) {
+
+	this.precision = precision;
+
+	if ( precision > 2 ) {
+
+		this.step = Math.pow( 10, -( precision - 1 ) );
+
+	}
+
+	return this;
+
+};
+
 UI.Number.prototype.onChange = function ( callback ) {
 
 	this.onChangeCallback = callback;

+ 130 - 10
editor/js/ui/Sidebar.Properties.World.js

@@ -20,19 +20,79 @@ Sidebar.Properties.World = function ( signals ) {
 
 	// fog
 
-	var fogRow = new UI.Panel();
-	var fog = new UI.Select( 'absolute' ).setOptions( {
+	var fogTypeRow = new UI.Panel();
+	var fogType = new UI.Select( 'absolute' ).setOptions( {
 
 		'None': 'None',
-		'Fog': 'Fog',
-		'FogExp2': 'FogExp2'
+		'Fog': 'Linear',
+		'FogExp2': 'Exponential'
 
-	} ).setLeft( '100px' ).setWidth( '150px' ).setColor( '#444' ).setFontSize( '12px' ).onChange( updateFog );
+	} ).setLeft( '100px' ).setWidth( '150px' ).setColor( '#444' ).setFontSize( '12px' ).onChange( updateFogType );
 
-	fogRow.add( new UI.Text().setValue( 'Fog' ).setColor( '#666' ) );
-	fogRow.add( fog );
+	fogTypeRow.add( new UI.Text().setValue( 'Fog type' ).setColor( '#666' ) );
+	fogTypeRow.add( fogType );
 
-	container.add( fogRow );
+	container.add( fogTypeRow );
+
+	// fog color
+
+	var fogColorRow = new UI.Panel();
+	fogColorRow.setDisplay( 'none' );
+
+	var fogColor = new UI.Color( 'absolute' ).setLeft( '100px' ).setValue( '#aaaaaa' ).onChange( updateFogColor );
+
+	fogColorRow.add( new UI.Text().setValue( 'Fog color' ).setColor( '#666' ) );
+	fogColorRow.add( fogColor );
+
+	container.add( fogColorRow );
+
+	// clear color lock
+
+	var colorLockEnabled = true;
+
+	var colorLockRow = new UI.Panel();
+	colorLockRow.setDisplay( 'inline-block' ).setLeft( '100px' ).setMargin( '0px' );
+
+	var colorLock = new UI.Checkbox( 'relative' ).setLeft( '10px' ).setValue( colorLockEnabled ).onChange( updateColorLock );
+	colorLockRow.add( colorLock );
+
+	fogColorRow.add( colorLockRow );
+
+	// fog near
+
+	var fogNearRow = new UI.Panel();
+	fogNearRow.setDisplay( 'none' );
+
+	var fogNear = new UI.Number( 'absolute' ).setLeft( '100px' ).setWidth( '60px' ).setRange( 0, Infinity ).setValue( 1 ).onChange( updateFogParameters );
+
+	fogNearRow.add( new UI.Text().setValue( 'Fog near' ).setColor( '#666' ) );
+	fogNearRow.add( fogNear );
+
+	container.add( fogNearRow );
+
+	var fogFarRow = new UI.Panel();
+	fogFarRow.setDisplay( 'none' );
+
+	// fog far
+
+	var fogFar = new UI.Number( 'absolute' ).setLeft( '100px' ).setWidth( '60px' ).setRange( 0, Infinity ).setValue( 5000 ).onChange( updateFogParameters );
+
+	fogFarRow.add( new UI.Text().setValue( 'Fog far' ).setColor( '#666' ) );
+	fogFarRow.add( fogFar );
+
+	container.add( fogFarRow );
+
+	// fog density
+
+	var fogDensityRow = new UI.Panel();
+	fogDensityRow.setDisplay( 'none' );
+
+	var fogDensity = new UI.Number( 'absolute' ).setLeft( '100px' ).setWidth( '60px' ).setRange( 0, 0.1 ).setPrecision( 5 ).setValue( 0.00025 ).onChange( updateFogParameters );
+
+	fogDensityRow.add( new UI.Text().setValue( 'Fog density' ).setColor( '#666' ) );
+	fogDensityRow.add( fogDensity );
+
+	container.add( fogDensityRow );
 
 	//
 
@@ -42,9 +102,69 @@ Sidebar.Properties.World = function ( signals ) {
 
 	}
 
-	function updateFog() {
+	function updateFogType() {
+
+		var type = fogType.getValue();
+
+		if ( type === "None" ) {
+
+			fogColorRow.setDisplay( 'none' );
+
+		} else {
+
+			fogColorRow.setDisplay( '' );
+
+		}
+
+		if ( type === "Fog" ) {
+
+			fogNearRow.setDisplay( '' );
+			fogFarRow.setDisplay( '' );
+
+		} else {
+
+			fogNearRow.setDisplay( 'none' );
+			fogFarRow.setDisplay( 'none' );
+
+		}
+
+		if ( type === "FogExp2" ) {
+
+			fogDensityRow.setDisplay( '' );
+
+		} else {
+
+			fogDensityRow.setDisplay( 'none' );
+
+		}
+
+		signals.fogTypeChanged.dispatch( type );
+
+	}
+
+	function updateFogColor() {
+
+		signals.fogColorChanged.dispatch( fogColor.getHexValue() );
+
+		if ( colorLockEnabled )  {
+
+			clearColor.setValue( fogColor.getValue() );
+			updateClearColor();
+
+		}
+
+	}
+
+	function updateFogParameters() {
+
+		signals.fogParametersChanged.dispatch( fogNear.getValue(), fogFar.getValue(), fogDensity.getValue() );
+
+	}
+
+	function updateColorLock() {
 
-		console.log( "fog", fog.getValue() );
+		colorLockEnabled = colorLock.getValue();
+		updateFogColor();
 
 	}
 

+ 105 - 0
editor/js/ui/Viewport.js

@@ -60,6 +60,14 @@ var Viewport = function ( signals ) {
 	light2.position.set( - 1, - 0.5, 0 ).normalize();
 	scene.add( light2 );
 
+	// fog
+
+	var oldFogType = "None";
+	var oldFogColor = 0xaaaaaa;
+	var oldFogNear = 1;
+	var oldFogFar = 5000;
+	var oldFogDensity = 0.00025;
+
 	// default objects names
 
 	camera.name = "Camera";
@@ -412,6 +420,65 @@ var Viewport = function ( signals ) {
 
 	} );
 
+	signals.fogTypeChanged.add( function ( fogType ) {
+
+		if ( fogType !== oldFogType ) {
+
+			if ( fogType === "None" ) {
+
+				scene.fog = null;
+
+			} else if ( fogType === "Fog" ) {
+
+				scene.fog = new THREE.Fog( oldFogColor, oldFogNear, oldFogFar );
+
+			} else if ( fogType === "FogExp2" ) {
+
+				scene.fog = new THREE.FogExp2( oldFogColor, oldFogDensity );
+
+			}
+
+			updateMaterials( scene );
+
+			var enableHelpersFog = true;
+
+			if ( enableHelpersFog )	{
+
+				sceneHelpers.fog = scene.fog;
+				updateMaterials( sceneHelpers );
+
+			}
+
+			oldFogType = fogType;
+
+		}
+
+		render();
+
+	} );
+
+	signals.fogColorChanged.add( function ( fogColor ) {
+
+		oldFogColor = fogColor;
+
+		updateFog( scene );
+
+		render();
+
+	} );
+
+	signals.fogParametersChanged.add( function ( near, far, density ) {
+
+		oldFogNear = near;
+		oldFogFar = far;
+		oldFogDensity = density;
+
+		updateFog( scene );
+
+		render();
+
+	} );
+
 	signals.windowResize.add( function () {
 
 		camera.aspect = container.dom.offsetWidth / container.dom.offsetHeight;
@@ -436,6 +503,44 @@ var Viewport = function ( signals ) {
 
 	//
 
+	function updateMaterials( root ) {
+
+		root.traverse( function ( node ) {
+
+			if ( node.material ) {
+
+				node.material.needsUpdate = true;
+
+			}
+
+			if ( node.geometry && node.geometry.materials ) {
+
+				for ( var i = 0; i < node.geometry.materials.length; i ++ ) {
+
+					node.geometry.materials[ i ].needsUpdate = true;
+
+				}
+
+			}
+
+		} );
+
+	}
+
+	function updateFog( root ) {
+
+		if ( root.fog ) {
+
+			root.fog.color.setHex( oldFogColor );
+
+			if ( root.fog.near !== undefined ) root.fog.near = oldFogNear;
+			if ( root.fog.far !== undefined ) root.fog.far = oldFogFar;
+			if ( root.fog.density !== undefined ) root.fog.density = oldFogDensity;
+
+		}
+
+	}
+
 	function animate() {
 
 		requestAnimationFrame( animate );

+ 3 - 2
src/renderers/WebGLRenderer.js

@@ -4744,6 +4744,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 			fog: fog,
 			useFog: material.fog,
+			fogExp: fog instanceof THREE.FogExp2,
 
 			sizeAttenuation: material.sizeAttenuation,
 
@@ -6034,7 +6035,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 			if ( programInfo.code === code ) {
 
-				// console.log( "Code already compiled." /*: \n\n" + code*/ );
+				//console.log( "Code already compiled." /*: \n\n" + code*/ );
 
 				programInfo.usedTimes ++;
 
@@ -6178,7 +6179,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 			_this.physicallyBasedShading ? "#define PHYSICALLY_BASED_SHADING" : "",
 
 			( parameters.useFog && parameters.fog ) ? "#define USE_FOG" : "",
-			( parameters.useFog && parameters.fog instanceof THREE.FogExp2 ) ? "#define FOG_EXP2" : "",
+			( parameters.useFog && parameters.fogExp ) ? "#define FOG_EXP2" : "",
 
 			parameters.map ? "#define USE_MAP" : "",
 			parameters.envMap ? "#define USE_ENVMAP" : "",

+ 6 - 0
src/scenes/Fog.js

@@ -11,3 +11,9 @@ THREE.Fog = function ( hex, near, far ) {
 	this.far = ( far !== undefined ) ? far : 1000;
 
 };
+
+THREE.Fog.prototype.clone = function () {
+
+	return new THREE.Fog( this.color.getHex(), this.near, this.far );
+
+};

+ 6 - 0
src/scenes/FogExp2.js

@@ -9,3 +9,9 @@ THREE.FogExp2 = function ( hex, density ) {
 	this.density = ( density !== undefined ) ? density : 0.00025;
 
 };
+
+THREE.FogExp2.prototype.clone = function () {
+
+	return new THREE.FogExp2( this.color.getHex(), this.density );
+
+};