فهرست منبع

clean up PMREMGEnerator, incorporate global encodings.glsl. Add into the THREE namespace, move into examples.

Ben Houston 10 سال پیش
والد
کامیت
49f49beada
3فایلهای تغییر یافته به همراه448 افزوده شده و 0 حذف شده
  1. 67 0
      examples/js/loaders/HDRCubeMapLoader.js
  2. 223 0
      examples/js/pmrem/PMREMGenerator.js
  3. 158 0
      examples/js/pmrem/PMREM_CubeUVPacker.js

+ 67 - 0
examples/js/loaders/HDRCubeMapLoader.js

@@ -0,0 +1,67 @@
+/**
+ * @author Prashant Sharma / spidersharma03
+ */
+
+THREE.HDRCubeMapLoader = function (manager) {
+    this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
+    // override in sub classes
+    this.hdrLoader = new THREE.RGBELoader();
+}
+
+THREE.HDRCubeMapLoader.prototype.load = function(urls, onLoad, onProgress, onError) {
+    var texture = new THREE.CubeTexture( [] );
+    texture.encoding = THREE.RGBE;
+    var scope = this.hdrLoader;
+
+    var loaded = 0;
+
+     function loadHDRData(i, onLoad, onProgress, onError) {
+        var loader = new THREE.XHRLoader( this.manager );
+        loader.setResponseType( 'arraybuffer' );
+
+        loader.load( urls[i], function ( buffer ) {
+                loaded++;
+
+                var texData = scope._parser( buffer );
+
+                if ( ! texData ) return;
+
+                if ( undefined !== texData.image ) {
+                        texture[i].images = texData.image;
+                }
+                else if ( undefined !== texData.data ) {
+                        var dataTexture = new THREE.DataTexture(texData.data, texData.width, texData.height);
+                        dataTexture.format = texData.format;
+                        dataTexture.type = texData.type;
+                        dataTexture.minFilter = THREE.LinearFilter;
+                        dataTexture.magFilter = THREE.LinearFilter;
+                        dataTexture.generateMipmaps = false;
+                        texture.images[i] = dataTexture;
+                }
+
+                if(loaded === 6) {
+                        texture.needsUpdate = true;
+
+                        if ( undefined !== texData.format ) {
+
+                                texture.format = texData.format;
+
+                        }
+                        if ( undefined !== texData.type ) {
+
+                                texture.type = texData.type;
+
+                        }
+                        texture.minFilter = THREE.LinearFilter;
+                        texture.magFilter = THREE.LinearFilter;
+                        texture.generateMipmaps = false;
+                        if ( onLoad ) onLoad( texture );
+                }
+        }, onProgress, onError );
+    }
+
+    for(var i=0; i<urls.length; i++) {
+        loadHDRData(i, onLoad, onProgress, onError);
+    }
+    return texture;
+};

+ 223 - 0
examples/js/pmrem/PMREMGenerator.js

@@ -0,0 +1,223 @@
+/**
+ * @author Prashant Sharma / spidersharma03
+ * @author Ben Houston / bhouston, https://clara.io
+ */
+
+ THREE.PMREMGenerator = function( cubeTexture ) {
+
+	if ( cubeTexture instanceof THREE.CubeTexture ) {
+
+		if ( cubeTexture.images[ 0 ] === undefined )
+		  console.error( "CubeTexture Not Initialized" );
+      if(cubeTexture.images[ 0 ] instanceof THREE.DataTexture) {
+          this.resolution = cubeTexture.images[ 0 ].image.width;
+      }
+      else {
+          this.resolution = cubeTexture.images[ 0 ].width;
+      }
+
+	}
+	else if ( cubeTexture instanceof THREE.WebGLRenderTargetCube ) {
+		if ( cubeTexture === undefined ) console.error( "Render Target Not Initialized" );
+		this.resolution = cubeTexture.width;
+	}
+	else {
+		console.error( "Wrong Input to PMREMGenerator" );
+	}
+
+	this.sourceTexture = cubeTexture;
+
+  // encoded formats do not interpolate well, thus turn off interpolation for them
+  var textureFilter = ( sourceTexture.encoding === THREE.Linear ) ? THREE.LinearFilter : THREE.NearestFilter;
+  this.sourceTexture.minFilter = this.sourceTexture.magFilter = textureFilter;
+
+	this.cubeLods = [];
+
+	var size = this.resolution;
+  var params = { format: THREE.RGBAFormat, magFilter: textureFilter, minFilter: textureFilter };
+
+	this.numLods = Math.log2( size ) - 2;
+  for ( var i = 0; i < this.numLods; i ++ ) {
+		var renderTarget = new THREE.WebGLRenderTargetCube( size, size, params );
+		renderTarget.texture.generateMipmaps = false;
+    renderTarget.encoding = this.sourceTexture.encoding;
+		this.cubeLods.push( renderTarget );
+		size = Math.max( 16, size / 2 );
+	}
+
+	this.camera = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0.0, 1000 );
+
+  this.shader = this.getShader();
+	this.planeMesh = new THREE.Mesh( new THREE.PlaneGeometry( 2, 2, 0 ), this.shader );
+	this.planeMesh.material.side = THREE.DoubleSide;
+	this.scene = new THREE.Scene();
+	this.scene.add( this.planeMesh );
+	this.scene.add( this.camera );
+
+	this.shader.uniforms[ "sourceTexture" ].value = this.sourceTexture;
+	this.shader.uniforms[ "encoding" ].value = this.sourceTexture.encoding;
+};
+
+THREE.PMREMGenerator.prototype = {
+
+	constructor : PMREMGenerator,
+
+	update: function( renderer ) {
+
+		this.shader.uniforms[ "sourceTexture" ].value = this.sourceTexture;
+		for ( var i = 0; i < this.numLods; i ++ ) {
+
+			var r = i / ( this.numLods - 1 );
+			this.shader.uniforms[ "roughness" ].value = r * 0.9;
+			var size = this.cubeLods[ i ].width;
+			this.shader.uniforms[ "mapSize" ].value = size;
+			this.renderToCubeMapTarget( renderer, this.cubeLods[ i ] );
+			if ( i < 5 )
+			this.shader.uniforms[ "sourceTexture" ].value = this.cubeLods[ i ];
+
+		}
+
+	},
+
+	renderToCubeMapTarget: function( renderer, renderTarget ) {
+
+		for ( var i = 0; i < 6; i ++ ) {
+		  this.renderToCubeMapTargetFace( renderer, renderTarget, i )
+    }
+
+	},
+
+	renderToCubeMapTargetFace: function( renderer, renderTarget, faceIndex ) {
+
+		renderTarget.texture.generateMipmaps = false;
+		renderTarget.activeCubeFace = faceIndex;
+		this.shader.uniforms[ "faceIndex" ].value = faceIndex;
+		renderer.render( this.scene, this.camera, renderTarget, true );
+
+	},
+
+  getShader: function() {
+
+    return new THREE.ShaderMaterial( {
+
+      uniforms: {
+        "faceIndex": { type: 'i', value: 0 },
+        "roughness": { type: 'f', value: 0.5 },
+        "mapSize": { type: 'f', value: 0.5 },
+        "sourceTexture": { type: 't', value: null },
+        "encoding": { type: 'i', value: 3002},
+        "testColor": { type: 'v3', value: new THREE.Vector3( 1, 1, 1 ) }
+      },
+
+      vertexShader:
+        "varying vec2 vUv;\n\
+        void main() {\n\
+           vUv = uv;\n\
+           gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\
+        }",
+
+      fragmentShader:
+        "varying vec2 vUv;\n\
+        uniform int faceIndex;\n\
+        uniform float roughness;\n\
+        uniform samplerCube sourceTexture;\n\
+        uniform float mapSize;\n\
+        uniform vec3 testColor;\n\
+        uniform int encoding;\n\
+        \n\
+        float rnd(vec2 uv) {\n\
+           return fract(sin(dot(uv, vec2(12.9898, 78.233) * 2.0)) * 43758.5453);\n\
+        }\n\
+        float GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n\
+           float a = ggxRoughness + 0.0001;\n\
+           a *= a;\n\
+           return ( 2.0 / a - 2.0 );\n\
+        }\n\
+        const float PI = 3.14159265358979;\n\
+        vec3 ImportanceSamplePhong(vec2 uv, mat3 vecSpace, float specPow) {\n\
+           float phi = uv.y * 2.0 * PI;\n\
+           float cosTheta = pow(1.0 - uv.x, 1.0 / (specPow + 1.0));\n\
+           float sinTheta = sqrt(1.0 - cosTheta * cosTheta);\n\
+           vec3 sampleDir = vec3(cos(phi) * sinTheta, sin(phi) * sinTheta, cosTheta);\n\
+           return vecSpace * sampleDir;\n\
+        }\n\
+        vec3 ImportanceSampleGGX( vec2 uv, mat3 vecSpace, float Roughness )\n\
+        {\n\
+               float a = Roughness * Roughness;\n\
+               float Phi = 2.0 * PI * uv.x;\n\
+               float CosTheta = sqrt( (1.0 - uv.y) / ( 1.0 + (a*a - 1.0) * uv.y ) );\n\
+               float SinTheta = sqrt( 1.0 - CosTheta * CosTheta );\n\
+               return vecSpace * vec3(SinTheta * cos( Phi ), SinTheta * sin( Phi ), CosTheta);\n\
+        }\n\
+        mat3 matrixFromVector(vec3 n) {\n\
+           float a = 1.0 / (1.0 + n.z);\n\
+           float b = -n.x * n.y * a;\n\
+           vec3 b1 = vec3(1.0 - n.x * n.x * a, b, -n.x);\n\
+           vec3 b2 = vec3(b, 1.0 - n.y * n.y * a, -n.y);\n\
+           return mat3(b1, b2, n);\n\
+        }\n\
+        \n\
+        vec4 testColorMap() {\n\
+           vec4 color;\n\
+           if(faceIndex == 0)\n\
+               color = vec4(1.0,0.0,0.0,1.0);\n\
+           else if(faceIndex == 1)\n\
+               color = vec4(0.0,1.0,0.0,1.0);\n\
+           else if(faceIndex == 2)\n\
+               color = vec4(0.0,0.0,1.0,1.0);\n\
+           else if(faceIndex == 3)\n\
+               color = vec4(1.0,1.0,0.0,1.0);\n\
+           else if(faceIndex == 4)\n\
+               color = vec4(0.0,1.0,1.0,1.0);\n\
+           else\n\
+               color = vec4(1.0,0.0,1.0,1.0);\n\
+           return color;\n\
+        }",
+  			THREE.ShaderChunk[ "encodings" ],
+        "void main() {\n\
+           vec3 sampleDirection;\n\
+           vec2 uv = vUv*2.0 - 1.0;\n\
+           float offset = -1.0/mapSize;\n\
+           const float a = -1.0;\n\
+           const float b = 1.0;\n\
+           float c = -1.0 + offset;\n\
+           float d = 1.0 - offset;\n\
+           float bminusa = b - a;\n\
+           uv.x = (uv.x - a)/bminusa * d - (uv.x - b)/bminusa * c;\n\
+           uv.y = (uv.y - a)/bminusa * d - (uv.y - b)/bminusa * c;\n\
+           if (faceIndex==0) {\n\
+               sampleDirection = vec3(1.0, -uv.y, -uv.x);\n\
+           }\n\
+           else if (faceIndex==1) {\n\
+               sampleDirection = vec3(-1.0, -uv.y, uv.x);\n\
+           } else if (faceIndex==2) {\n\
+               sampleDirection = vec3(uv.x, 1.0, uv.y);\n\
+           } else if (faceIndex==3) {\n\
+               sampleDirection = vec3(uv.x, -1.0, -uv.y);\n\
+           } else if (faceIndex==4) {\n\
+               sampleDirection = vec3(uv.x, -uv.y, 1.0);\n\
+           } else {\n\
+               sampleDirection = vec3(-uv.x, -uv.y, -1.0);\n\
+           }\n\
+           mat3 vecSpace = matrixFromVector(normalize(sampleDirection));\n\
+           vec3 rgbColor = vec3(0.0);\n\
+           const int NumSamples = 1024;\n\
+           vec3 vect;\n\
+           float weight = 0.0;\n\
+           for(int i=0; i<NumSamples; i++) {\n\
+               float sini = sin(float(i));\n\
+               float cosi = cos(float(i));\n\
+               float rand = rnd(vec2(sini, cosi));\n\
+               vect = ImportanceSampleGGX(vec2(float(i) / float(NumSamples), rand), vecSpace, roughness);\n\
+               float dotProd = dot(vect, normalize(sampleDirection));\n\
+               weight += dotProd;\n\
+               vec3 color = texelDecode(textureCube(sourceTexture, vect), encoding).rgb;\n\
+               rgbColor.rgb += color;\n\
+           }\n\
+           rgbColor /= float(NumSamples);\n\
+           gl_FragColor = texelEncode( rgbColor, encoding );\n\
+        }"
+      }
+    );
+  }
+};

+ 158 - 0
examples/js/pmrem/PMREM_CubeUVPacker.js

@@ -0,0 +1,158 @@
+/**
+ * @author Prashant Sharma / spidersharma03
+ */
+
+var vertexShaderPMREMCubeUV = "precision highp float;\
+                   varying vec2 vUv;\
+                   void main() {\
+                        vUv = uv;\
+                        gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\
+                   }";
+
+var fragmentShaderPMREMCubeUV = "precision highp float;\
+    varying vec2 vUv;\
+    uniform samplerCube cubeTexture;\
+    uniform float mapSize;\
+    uniform vec3 testColor;\
+    uniform int faceIndex;\
+    \
+    const float PI = 3.14159265358979;\
+    vec4 sampleCubeMap(float phi, float theta) {\
+        float sinTheta = sin(theta);\
+        float cosTheta = cos(theta);\
+        vec3 sampleDir = vec3(cos(phi) * sinTheta, cosTheta, sin(phi) * sinTheta);\
+        vec4 color = textureCube(cubeTexture, sampleDir);\
+        return color * vec4(testColor, 1.0);\
+    }\
+    void main() {\
+        vec3 sampleDirection;\
+        vec2 uv = vUv;\
+        uv = uv * 2.0 - 1.0;\
+        uv.y *= -1.0;\
+        if(faceIndex == 0) {\
+            sampleDirection = normalize(vec3(1.0, uv.y, -uv.x));\
+        }\
+        else if(faceIndex == 1) {\
+            sampleDirection = normalize(vec3(uv.x, 1.0, uv.y));\
+        }\
+        else if(faceIndex == 2) {\
+            sampleDirection = normalize(vec3(uv.x, uv.y, 1.0));\
+        }\
+        else if(faceIndex == 3) {\
+            sampleDirection = normalize(vec3(-1.0, uv.y, uv.x));\
+        }\
+        else if(faceIndex == 4) {\
+            sampleDirection = normalize(vec3(uv.x, -1.0, -uv.y));\
+        }\
+        else {\
+            sampleDirection = normalize(vec3(-uv.x, uv.y, -1.0));\
+        }\
+        vec4 color = textureCube(cubeTexture, (sampleDirection));\
+        gl_FragColor = color * vec4(testColor, 1.0);\
+    }\
+";
+var uniformsPMREMCubeUV = {
+	"faceIndex": { type: 'i', value: 0 },
+	"mapSize": { type: 'f', value: 0 },
+	"cubeTexture": { type: 't', value: null },
+	"testColor": { type: 'v3', value: new THREE.Vector3( 1, 1, 1 ) }
+};
+
+var testColor = [];
+testColor.push( new THREE.Vector3( 1, 0, 0 ) );
+testColor.push( new THREE.Vector3( 0, 1, 0 ) );
+testColor.push( new THREE.Vector3( 0, 0, 1 ) );
+testColor.push( new THREE.Vector3( 1, 1, 0 ) );
+testColor.push( new THREE.Vector3( 0, 1, 1 ) );
+testColor.push( new THREE.Vector3( 1, 0, 1 ) );
+testColor.push( new THREE.Vector3( 1, 1, 1 ) );
+testColor.push( new THREE.Vector3( 0.5, 1, 0.5 ) );
+
+var PMREM_CubeUVPacker = function( cubeTextureLods, numLods ) {
+
+	this.cubeLods = cubeTextureLods;
+	this.numLods = numLods;
+	var size = cubeTextureLods[ 0 ].width * 4;
+
+	this.CubeUVRenderTarget = new THREE.WebGLRenderTarget( size, size,
+	{ format: THREE.RGBAFormat, magFilter: THREE.LinearFilter, minFilter: THREE.LinearFilter } );
+	this.CubeUVRenderTarget.texture.generateMipmaps = false;
+                this.CubeUVRenderTarget.mapping = THREE.CubeUVReflectionMapping;
+	this.camera = new THREE.OrthographicCamera( - size * 0.5, size * 0.5, - size * 0.5, size * 0.5, 0.0, 1000 );
+                this.CubeUVRenderTarget.encoding = this.cubeLods[0].encoding;
+
+	this.scene = new THREE.Scene();
+	this.scene.add( this.camera );
+
+	this.objects = [];
+	var xOffset = 0;
+	var faceOffsets = [];
+	faceOffsets.push( new THREE.Vector2( 0, 0 ) );
+	faceOffsets.push( new THREE.Vector2( 1, 0 ) );
+	faceOffsets.push( new THREE.Vector2( 2, 0 ) );
+	faceOffsets.push( new THREE.Vector2( 0, 1 ) );
+	faceOffsets.push( new THREE.Vector2( 1, 1 ) );
+	faceOffsets.push( new THREE.Vector2( 2, 1 ) );
+	var yOffset = 0;
+	var textureResolution = size;
+	size = cubeTextureLods[ 0 ].width;
+
+	var offset2 = 0;
+	var c = 4.0;
+	this.numLods = Math.log2( cubeTextureLods[ 0 ].width ) - 2;
+	for ( var i = 0; i < this.numLods; i ++ ) {
+
+		var offset1 = ( textureResolution - textureResolution / c ) * 0.5;
+		if ( size > 16 )
+		c *= 2;
+		var nMips = size > 16 ? 6 : 1;
+		var mipOffsetX = 0;
+		var mipOffsetY = 0;
+		var mipSize = size;
+		for ( var j = 0; j < nMips; j ++ ) {
+
+			// Mip Maps
+			for ( var k = 0; k < 6; k ++ ) {
+
+				// 6 Cube Faces
+				var material = new THREE.ShaderMaterial();
+				material.vertexShader = vertexShaderPMREMCubeUV;
+				material.fragmentShader = fragmentShaderPMREMCubeUV;
+				material.uniforms = THREE.UniformsUtils.clone( uniformsPMREMCubeUV );
+				material.uniforms[ "cubeTexture" ].value = this.cubeLods[ i ];
+				material.uniforms[ "faceIndex" ].value = k;
+				material.uniforms[ "mapSize" ].value = mipSize;
+				var color = material.uniforms[ "testColor" ].value;
+				//color.copy(testColor[j]);
+				var planeMesh = new THREE.Mesh(
+				new THREE.PlaneGeometry( mipSize, mipSize, 0 ),
+				material );
+				planeMesh.position.x = faceOffsets[ k ].x * mipSize - offset1 + mipOffsetX;
+				planeMesh.position.y = faceOffsets[ k ].y * mipSize - offset1 + offset2 + mipOffsetY;
+				planeMesh.material.side = THREE.DoubleSide;
+				this.scene.add( planeMesh );
+				this.objects.push( planeMesh );
+
+			}
+			mipOffsetY += 1.75 * mipSize;
+			mipOffsetX += 1.25 * mipSize;
+			mipSize /= 2;
+
+		}
+		offset2 += 2 * size;
+		if ( size > 16 )
+		size /= 2;
+
+	}
+
+};
+
+PMREM_CubeUVPacker.prototype = {
+	constructor : PMREM_CubeUVPacker,
+
+	update: function( renderer ) {
+
+		renderer.render( this.scene, this.camera, this.CubeUVRenderTarget, true );
+
+	}
+};

粤ICP备19079148号