未验证 提交 36b48d3b 编写于 作者: M Michael Herzog 提交者: GitHub

WebGLRenderer: Integrate PMREM. (#22178)

* WebGLRenderer: Integrate PMREM

* Examples: Update screenshot.
上级 18a9dfe4
......@@ -61,7 +61,7 @@ class CubeTexturePass extends Pass {
this.cubeCamera.quaternion.setFromRotationMatrix( this.camera.matrixWorld );
this.cubeMesh.material.uniforms.envMap.value = this.envMap;
this.cubeMesh.material.uniforms.flipEnvMap.value = ( this.envMap.isCubeTexture && this.envMap._needsFlipEnvMap ) ? - 1 : 1;
this.cubeMesh.material.uniforms.flipEnvMap.value = ( this.envMap.isCubeTexture && this.envMap.isRenderTargetTexture === false ) ? - 1 : 1;
this.cubeMesh.material.uniforms.opacity.value = this.opacity;
this.cubeMesh.material.transparent = ( this.opacity < 1.0 );
......
......@@ -40,17 +40,14 @@
scene = new THREE.Scene();
new RGBELoader()
.setDataType( THREE.UnsignedByteType )
.setDataType( THREE.FloatType )
.setPath( 'textures/equirectangular/' )
.load( 'royal_esplanade_1k.hdr', function ( texture ) {
const envMap = pmremGenerator.fromEquirectangular( texture ).texture;
texture.mapping = THREE.EquirectangularReflectionMapping;
scene.background = envMap;
scene.environment = envMap;
texture.dispose();
pmremGenerator.dispose();
scene.background = texture;
scene.environment = texture;
render();
......@@ -90,9 +87,6 @@
renderer.outputEncoding = THREE.sRGBEncoding;
container.appendChild( renderer.domElement );
const pmremGenerator = new THREE.PMREMGenerator( renderer );
pmremGenerator.compileEquirectangularShader();
const controls = new OrbitControls( camera, renderer.domElement );
controls.addEventListener( 'change', render ); // use if there is no animation loop
controls.minDistance = 2;
......
......@@ -158,14 +158,14 @@
// Load background and generate envMap
new RGBELoader()
.setDataType( THREE.UnsignedByteType )
.setDataType( THREE.FloatType )
.setPath( 'textures/equirectangular/' )
.load( 'venice_sunset_1k.hdr', function ( texture ) {
envMap = pmremGenerator.fromEquirectangular( texture ).texture;
pmremGenerator.dispose();
texture.mapping = THREE.EquirectangularReflectionMapping;
background = envMap;
envMap = texture;
background = texture;
//
......@@ -175,9 +175,6 @@
} );
const pmremGenerator = new THREE.PMREMGenerator( renderer );
pmremGenerator.compileEquirectangularShader();
}
function initScene( sceneInfo ) {
......
......@@ -40,17 +40,14 @@
scene = new THREE.Scene();
new RGBELoader()
.setDataType( THREE.UnsignedByteType )
.setDataType( THREE.FloatType )
.setPath( 'textures/equirectangular/' )
.load( 'quarry_01_1k.hdr', function ( texture ) {
const envMap = pmremGenerator.fromEquirectangular( texture ).texture;
texture.mapping = THREE.EquirectangularReflectionMapping;
scene.background = envMap;
scene.environment = envMap;
texture.dispose();
pmremGenerator.dispose();
scene.background = texture;
scene.environment = texture;
// model
......@@ -73,9 +70,6 @@
renderer.outputEncoding = THREE.sRGBEncoding;
container.appendChild( renderer.domElement );
const pmremGenerator = new THREE.PMREMGenerator( renderer );
pmremGenerator.compileEquirectangularShader();
const controls = new OrbitControls( camera, renderer.domElement );
controls.minDistance = 0.5;
controls.maxDistance = 10;
......
......@@ -43,17 +43,14 @@
scene = new THREE.Scene();
new RGBELoader()
.setDataType( THREE.UnsignedByteType )
.setDataType( THREE.FloatType )
.setPath( 'textures/equirectangular/' )
.load( 'quarry_01_1k.hdr', function ( texture ) {
const envMap = pmremGenerator.fromEquirectangular( texture ).texture;
texture.mapping = THREE.EquirectangularReflectionMapping;
scene.background = envMap;
scene.environment = envMap;
texture.dispose();
pmremGenerator.dispose();
scene.background = texture;
scene.environment = texture;
render();
......@@ -94,9 +91,6 @@
renderer.outputEncoding = THREE.sRGBEncoding;
container.appendChild( renderer.domElement );
const pmremGenerator = new THREE.PMREMGenerator( renderer );
pmremGenerator.compileEquirectangularShader();
const controls = new OrbitControls( camera, renderer.domElement );
controls.addEventListener( 'change', render ); // use if there is no animation loop
controls.minDistance = 2;
......
......@@ -32,7 +32,6 @@
let container, stats;
let camera, scene, renderer, controls;
let torusMesh, planeMesh;
let pngCubeRenderTarget, exrCubeRenderTarget;
let pngBackground, exrBackground;
init();
......@@ -70,38 +69,22 @@
planeMesh.rotation.x = - Math.PI * 0.5;
scene.add( planeMesh );
THREE.DefaultLoadingManager.onLoad = function ( ) {
new EXRLoader().load( 'textures/piz_compressed.exr', function ( texture ) {
pmremGenerator.dispose();
texture.mapping = THREE.EquirectangularReflectionMapping;
exrBackground = texture;
};
new EXRLoader()
.setDataType( THREE.UnsignedByteType )
.load( 'textures/piz_compressed.exr', function ( texture ) {
exrCubeRenderTarget = pmremGenerator.fromEquirectangular( texture );
exrBackground = exrCubeRenderTarget.texture;
texture.dispose();
} );
} );
new THREE.TextureLoader().load( 'textures/equirectangular.png', function ( texture ) {
texture.mapping = THREE.EquirectangularReflectionMapping;
texture.encoding = THREE.sRGBEncoding;
pngCubeRenderTarget = pmremGenerator.fromEquirectangular( texture );
pngBackground = pngCubeRenderTarget.texture;
texture.dispose();
pngBackground = texture;
} );
const pmremGenerator = new THREE.PMREMGenerator( renderer );
pmremGenerator.compileEquirectangularShader();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
......@@ -163,11 +146,11 @@
switch ( params.envMap ) {
case 'EXR':
newEnvMap = exrCubeRenderTarget ? exrCubeRenderTarget.texture : null;
newEnvMap = exrBackground;
background = exrBackground;
break;
case 'PNG':
newEnvMap = pngCubeRenderTarget ? pngCubeRenderTarget.texture : null;
newEnvMap = pngBackground;
background = pngBackground;
break;
......
......@@ -46,31 +46,27 @@
scene.add( group );
new HDRCubeTextureLoader()
.setDataType( THREE.UnsignedByteType )
.setDataType( THREE.FloatType )
.setPath( 'textures/cube/pisaHDR/' )
.load( [ 'px.hdr', 'nx.hdr', 'py.hdr', 'ny.hdr', 'pz.hdr', 'nz.hdr' ],
function ( hdrCubeMap ) {
const hdrCubeRenderTarget = pmremGenerator.fromCubemap( hdrCubeMap );
hdrCubeMap.dispose();
pmremGenerator.dispose();
function ( texture ) {
const geometry = new THREE.SphereGeometry( 80, 64, 32 );
const textureLoader = new THREE.TextureLoader();
const diffuse = textureLoader.load( "textures/carbon/Carbon.png" );
const diffuse = textureLoader.load( 'textures/carbon/Carbon.png' );
diffuse.encoding = THREE.sRGBEncoding;
diffuse.wrapS = THREE.RepeatWrapping;
diffuse.wrapT = THREE.RepeatWrapping;
diffuse.repeat.x = 10;
diffuse.repeat.y = 10;
const normalMap = textureLoader.load( "textures/carbon/Carbon_Normal.png" );
const normalMap = textureLoader.load( 'textures/carbon/Carbon_Normal.png' );
normalMap.wrapS = THREE.RepeatWrapping;
normalMap.wrapT = THREE.RepeatWrapping;
const normalMap2 = textureLoader.load( "textures/water/Water_1_M_Normal.jpg" );
const normalMap2 = textureLoader.load( 'textures/water/Water_1_M_Normal.jpg' );
const normalMap3 = new THREE.CanvasTexture( new FlakesTexture() );
normalMap3.wrapS = THREE.RepeatWrapping;
......@@ -79,9 +75,9 @@
normalMap3.repeat.y = 6;
normalMap3.anisotropy = 16;
const normalMap4 = textureLoader.load( "textures/golfball.jpg" );
const normalMap4 = textureLoader.load( 'textures/golfball.jpg' );
const clearcoatNormaMap = textureLoader.load( "textures/pbr/Scratched_gold/Scratched_gold_01_1K_Normal.png" );
const clearcoatNormaMap = textureLoader.load( 'textures/pbr/Scratched_gold/Scratched_gold_01_1K_Normal.png' );
// car paint
......@@ -151,8 +147,8 @@
//
scene.background = hdrCubeRenderTarget.texture;
scene.environment = hdrCubeRenderTarget.texture;
scene.background = texture;
scene.environment = texture;
}
......@@ -184,11 +180,6 @@
//
const pmremGenerator = new THREE.PMREMGenerator( renderer );
pmremGenerator.compileEquirectangularShader();
//
stats = new Stats();
container.appendChild( stats.dom );
......
......@@ -36,7 +36,6 @@
};
let camera, scene, renderer;
let gemBackMaterial, gemFrontMaterial;
let hdrCubeRenderTarget;
const objects = [];
......@@ -114,23 +113,17 @@
} );
new RGBELoader()
.setDataType( THREE.UnsignedByteType )
.setDataType( THREE.FloatType )
.setPath( 'textures/equirectangular/' )
.load( 'royal_esplanade_1k.hdr', function ( hdrEquirect ) {
.load( 'royal_esplanade_1k.hdr', function ( texture ) {
hdrCubeRenderTarget = pmremGenerator.fromEquirectangular( hdrEquirect );
pmremGenerator.dispose();
texture.mapping = THREE.EquirectangularReflectionMapping;
gemFrontMaterial.envMap = gemBackMaterial.envMap = hdrCubeRenderTarget.texture;
gemFrontMaterial.envMap = gemBackMaterial.envMap = texture;
gemFrontMaterial.needsUpdate = gemBackMaterial.needsUpdate = true;
hdrEquirect.dispose();
} );
const pmremGenerator = new THREE.PMREMGenerator( renderer );
pmremGenerator.compileEquirectangularShader();
// Lights
scene.add( new THREE.AmbientLight( 0x222222 ) );
......
......@@ -34,14 +34,15 @@
let camera, scene, renderer;
let hdrCubeRenderTarget;
let mesh;
const hdrEquirect = new RGBELoader()
.setDataType( THREE.UnsignedByteType )
.setDataType( THREE.FloatType )
.setPath( 'textures/equirectangular/' )
.load( 'royal_esplanade_1k.hdr', function () {
hdrEquirect.mapping = THREE.EquirectangularReflectionMapping;
init();
render();
......@@ -67,12 +68,7 @@
//
const pmremGenerator = new THREE.PMREMGenerator( renderer );
hdrCubeRenderTarget = pmremGenerator.fromEquirectangular( hdrEquirect );
hdrEquirect.dispose();
pmremGenerator.dispose();
scene.background = hdrCubeRenderTarget.texture;
scene.background = hdrEquirect;
//
......@@ -90,7 +86,7 @@
roughness: params.roughness,
reflectivity: params.reflectivity,
alphaMap: texture,
envMap: hdrCubeRenderTarget.texture,
envMap: hdrEquirect,
envMapIntensity: params.envMapIntensity,
transmission: params.transmission, // use material.transmission for glass materials
opacity: params.opacity,
......
......@@ -109,7 +109,7 @@
};
function loadEnvironment(name) {
function loadEnvironment( name ) {
if ( environments[ name ].texture !== undefined ) {
......@@ -121,18 +121,17 @@
const filename = environments[ name ].filename;
new RGBELoader()
.setDataType( THREE.UnsignedByteType )
.setPath( 'textures/equirectangular/' )
.load( filename, function ( hdrEquirect ) {
.setDataType( THREE.FloatType )
.setPath( 'textures/equirectangular/' )
.load( filename, function ( hdrEquirect ) {
const hdrCubeRenderTarget = pmremGenerator.fromEquirectangular( hdrEquirect );
hdrEquirect.dispose();
hdrEquirect.mapping = THREE.EquirectangularReflectionMapping;
scene.background = hdrCubeRenderTarget.texture;
scene.environment = hdrCubeRenderTarget.texture;
environments[ name ].texture = hdrCubeRenderTarget.texture;
scene.background = hdrEquirect;
scene.environment = hdrEquirect;
environments[ name ].texture = hdrEquirect;
} );
} );
}
......@@ -144,16 +143,13 @@
loadEnvironment( params.environment );
const gui = new GUI();
gui.add( params, 'environment', Object.keys( environments ) ).onChange( function( value ) {
gui.add( params, 'environment', Object.keys( environments ) ).onChange( function ( value ) {
loadEnvironment(value);
loadEnvironment( value );
} );
gui.open();
const pmremGenerator = new THREE.PMREMGenerator( renderer );
pmremGenerator.compileEquirectangularShader();
//
if ( statsEnabled ) {
......
......@@ -46,16 +46,12 @@
scene = new THREE.Scene();
let hdrCubeRenderTarget = null;
new RGBELoader()
.setDataType( THREE.UnsignedByteType )
.setDataType( THREE.FloatType )
.setPath( 'textures/equirectangular/' )
.load( 'pedestrian_overpass_1k.hdr', function ( hdrEquirect ) {
.load( 'pedestrian_overpass_1k.hdr', function ( texture ) {
hdrCubeRenderTarget = pmremGenerator.fromEquirectangular( hdrEquirect );
hdrEquirect.dispose();
pmremGenerator.dispose();
texture.mapping = THREE.EquirectangularReflectionMapping;
// Materials
......@@ -83,7 +79,7 @@
clearcoat: 1.0 - alpha,
clearcoatRoughness: 1.0 - beta,
reflectivity: 1.0 - gamma,
envMap: ( index % 2 ) == 1 ? hdrCubeRenderTarget.texture : null
envMap: ( index % 2 ) == 1 ? texture : null
} );
index ++;
......@@ -106,7 +102,7 @@
}
scene.background = hdrCubeRenderTarget.texture;
scene.background = texture;
} );
......@@ -129,14 +125,14 @@
}
addLabel( "+clearcoat", new THREE.Vector3( - 350, 0, 0 ) );
addLabel( "-clearcoat", new THREE.Vector3( 350, 0, 0 ) );
addLabel( '+clearcoat', new THREE.Vector3( - 350, 0, 0 ) );
addLabel( '-clearcoat', new THREE.Vector3( 350, 0, 0 ) );
addLabel( "+clearcoatRoughness", new THREE.Vector3( 0, - 300, 0 ) );
addLabel( "-clearcoatRoughness", new THREE.Vector3( 0, 300, 0 ) );
addLabel( '+clearcoatRoughness', new THREE.Vector3( 0, - 300, 0 ) );
addLabel( '-clearcoatRoughness', new THREE.Vector3( 0, 300, 0 ) );
addLabel( "+reflectivity", new THREE.Vector3( 0, 0, - 300 ) );
addLabel( "-reflectivity", new THREE.Vector3( 0, 0, 300 ) );
addLabel( '+reflectivity', new THREE.Vector3( 0, 0, - 300 ) );
addLabel( '-reflectivity', new THREE.Vector3( 0, 0, 300 ) );
particleLight = new THREE.Mesh( new THREE.SphereGeometry( 4, 8, 8 ), new THREE.MeshBasicMaterial( { color: 0xffffff } ) );
scene.add( particleLight );
......@@ -165,11 +161,6 @@
//
const pmremGenerator = new THREE.PMREMGenerator( renderer );
pmremGenerator.compileEquirectangularShader();
//
stats = new Stats();
container.appendChild( stats.dom );
......
......@@ -44,23 +44,19 @@
scene = new THREE.Scene();
let hdrCubeRenderTarget = null;
// Materials
let imgTexture = new THREE.TextureLoader().load( "textures/planets/moon_1024.jpg" );
let imgTexture = new THREE.TextureLoader().load( 'textures/planets/moon_1024.jpg' );
imgTexture.wrapS = imgTexture.wrapT = THREE.RepeatWrapping;
imgTexture.anisotropy = 16;
imgTexture = null;
new RGBELoader()
.setDataType( THREE.UnsignedByteType )
.setDataType( THREE.FloatType )
.setPath( 'textures/equirectangular/' )
.load( 'pedestrian_overpass_1k.hdr', function ( hdrEquirect ) {
.load( 'pedestrian_overpass_1k.hdr', function ( texture ) {
hdrCubeRenderTarget = pmremGenerator.fromEquirectangular( hdrEquirect );
hdrEquirect.dispose();
pmremGenerator.dispose();
texture.mapping = THREE.EquirectangularReflectionMapping;
const bumpScale = 1;
const cubeWidth = 400;
......@@ -88,7 +84,7 @@
color: diffuseColor,
metalness: beta,
roughness: 1.0 - alpha,
envMap: index % 2 === 0 ? null : hdrCubeRenderTarget.texture
envMap: index % 2 === 0 ? null : texture
} );
index ++;
......@@ -109,7 +105,7 @@
}
scene.background = hdrCubeRenderTarget.texture;
scene.background = texture;
} );
......@@ -132,14 +128,14 @@
}
addLabel( "+roughness", new THREE.Vector3( - 350, 0, 0 ) );
addLabel( "-roughness", new THREE.Vector3( 350, 0, 0 ) );
addLabel( '+roughness', new THREE.Vector3( - 350, 0, 0 ) );
addLabel( '-roughness', new THREE.Vector3( 350, 0, 0 ) );
addLabel( "-metalness", new THREE.Vector3( 0, - 300, 0 ) );
addLabel( "+metalness", new THREE.Vector3( 0, 300, 0 ) );
addLabel( '-metalness', new THREE.Vector3( 0, - 300, 0 ) );
addLabel( '+metalness', new THREE.Vector3( 0, 300, 0 ) );
addLabel( "-diffuse", new THREE.Vector3( 0, 0, - 300 ) );
addLabel( "+diffuse", new THREE.Vector3( 0, 0, 300 ) );
addLabel( '-diffuse', new THREE.Vector3( 0, 0, - 300 ) );
addLabel( '+diffuse', new THREE.Vector3( 0, 0, 300 ) );
particleLight = new THREE.Mesh( new THREE.SphereGeometry( 4, 8, 8 ), new THREE.MeshBasicMaterial( { color: 0xffffff } ) );
scene.add( particleLight );
......@@ -168,11 +164,6 @@
//
const pmremGenerator = new THREE.PMREMGenerator( renderer );
pmremGenerator.compileEquirectangularShader();
//
stats = new Stats();
container.appendChild( stats.dom );
......
......@@ -63,17 +63,14 @@
scene = new THREE.Scene();
new RGBELoader()
.setDataType( THREE.UnsignedByteType )
.setDataType( THREE.FloatType )
.setPath( 'textures/equirectangular/' )
.load( 'royal_esplanade_1k.hdr', function ( texture ) {
const envMap = pmremGenerator.fromEquirectangular( texture ).texture;
texture.mapping = THREE.EquirectangularReflectionMapping;
scene.background = envMap;
scene.environment = envMap;
texture.dispose();
pmremGenerator.dispose();
scene.background = texture;
scene.environment = texture;
// model
......@@ -120,9 +117,6 @@
lutPass = new LUTPass();
composer.addPass( lutPass );
const pmremGenerator = new THREE.PMREMGenerator( renderer );
pmremGenerator.compileEquirectangularShader();
const controls = new OrbitControls( camera, renderer.domElement );
controls.minDistance = 2;
controls.maxDistance = 10;
......
......@@ -84,11 +84,8 @@
controls.target.set( 0, 0, - 0.2 );
controls.update();
const pmremGenerator = new THREE.PMREMGenerator( renderer );
pmremGenerator.compileEquirectangularShader();
const rgbeLoader = new RGBELoader()
.setDataType( THREE.UnsignedByteType )
.setDataType( THREE.FloatType )
.setPath( 'textures/equirectangular/' );
const gltfLoader = new GLTFLoader().setPath( 'models/gltf/DamagedHelmet/glTF/' );
......@@ -100,13 +97,10 @@
// environment
const envMap = pmremGenerator.fromEquirectangular( texture ).texture;
scene.background = envMap;
scene.environment = envMap;
texture.mapping = THREE.EquirectangularReflectionMapping;
texture.dispose();
pmremGenerator.dispose();
scene.background = texture;
scene.environment = texture;
// model
......
......@@ -83,20 +83,16 @@
//
const pmremGenerator = new THREE.PMREMGenerator( renderer );
pmremGenerator.compileEquirectangularShader();
new RGBELoader()
.setDataType( THREE.UnsignedByteType )
.setPath( 'textures/equirectangular/' )
.load( 'royal_esplanade_1k.hdr', function ( texture ) {
defaultEnvironment = pmremGenerator.fromEquirectangular( texture ).texture;
texture.mapping = THREE.EquirectangularReflectionMapping;
scene.environment = defaultEnvironment;
defaultEnvironment = texture;
texture.dispose();
pmremGenerator.dispose();
scene.environment = defaultEnvironment;
} );
......
......@@ -23,7 +23,16 @@ class WebGLCubeRenderTarget extends WebGLRenderTarget {
options = options || {};
// By convention -- likely based on the RenderMan spec from the 1990's -- cube maps are specified by WebGL (and three.js)
// in a coordinate system in which positive-x is to the right when looking up the positive-z axis -- in other words,
// in a left-handed coordinate system. By continuing this convention, preexisting cube maps continued to render correctly.
// three.js uses a right-handed coordinate system. So environment maps used in three.js appear to have px and nx swapped
// and the flag isRenderTargetTexture controls this conversion. The flip is not required when using WebGLCubeRenderTarget.texture
// as a cube texture (this is detected when isRenderTargetTexture is set to true for cube textures).
this.texture = new CubeTexture( undefined, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding );
this.texture.isRenderTargetTexture = true;
this.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : false;
this.texture.minFilter = options.minFilter !== undefined ? options.minFilter : LinearFilter;
......
......@@ -24,6 +24,7 @@ class WebGLRenderTarget extends EventDispatcher {
this.viewport = new Vector4( 0, 0, width, height );
this.texture = new Texture( undefined, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding );
this.texture.isRenderTargetTexture = true;
this.texture.image = { width: width, height: height, depth: 1 };
......
......@@ -24,6 +24,7 @@ import { WebGLBufferRenderer } from './webgl/WebGLBufferRenderer.js';
import { WebGLCapabilities } from './webgl/WebGLCapabilities.js';
import { WebGLClipping } from './webgl/WebGLClipping.js';
import { WebGLCubeMaps } from './webgl/WebGLCubeMaps.js';
import { WebGLCubeUVMaps } from './webgl/WebGLCubeUVMaps.js';
import { WebGLExtensions } from './webgl/WebGLExtensions.js';
import { WebGLGeometries } from './webgl/WebGLGeometries.js';
import { WebGLIndexedBufferRenderer } from './webgl/WebGLIndexedBufferRenderer.js';
......@@ -266,7 +267,7 @@ function WebGLRenderer( parameters = {} ) {
}
let extensions, capabilities, state, info;
let properties, textures, cubemaps, attributes, geometries, objects;
let properties, textures, cubemaps, cubeuvmaps, attributes, geometries, objects;
let programCache, materials, renderLists, renderStates, clipping, shadowMap;
let background, morphtargets, bufferRenderer, indexedBufferRenderer;
......@@ -291,13 +292,14 @@ function WebGLRenderer( parameters = {} ) {
properties = new WebGLProperties();
textures = new WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info );
cubemaps = new WebGLCubeMaps( _this );
cubeuvmaps = new WebGLCubeUVMaps( _this );
attributes = new WebGLAttributes( _gl, capabilities );
bindingStates = new WebGLBindingStates( _gl, extensions, attributes, capabilities );
geometries = new WebGLGeometries( _gl, attributes, info, bindingStates );
objects = new WebGLObjects( _gl, geometries, attributes, info );
morphtargets = new WebGLMorphtargets( _gl );
clipping = new WebGLClipping( properties );
programCache = new WebGLPrograms( _this, cubemaps, extensions, capabilities, bindingStates, clipping );
programCache = new WebGLPrograms( _this, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping );
materials = new WebGLMaterials( properties );
renderLists = new WebGLRenderLists( properties );
renderStates = new WebGLRenderStates( extensions, capabilities );
......@@ -564,6 +566,7 @@ function WebGLRenderer( parameters = {} ) {
renderStates.dispose();
properties.dispose();
cubemaps.dispose();
cubeuvmaps.dispose();
objects.dispose();
bindingStates.dispose();
......@@ -1388,7 +1391,7 @@ function WebGLRenderer( parameters = {} ) {
materialProperties.environment = material.isMeshStandardMaterial ? scene.environment : null;
materialProperties.fog = scene.fog;
materialProperties.envMap = cubemaps.get( material.envMap || materialProperties.environment );
materialProperties.envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || materialProperties.environment );
if ( programs === undefined ) {
......@@ -1506,7 +1509,7 @@ function WebGLRenderer( parameters = {} ) {
const fog = scene.fog;
const environment = material.isMeshStandardMaterial ? scene.environment : null;
const encoding = ( _currentRenderTarget === null ) ? _this.outputEncoding : _currentRenderTarget.texture.encoding;
const envMap = cubemaps.get( material.envMap || environment );
const envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || environment );
const vertexAlphas = material.vertexColors === true && object.geometry && object.geometry.attributes.color && object.geometry.attributes.color.itemSize === 4;
const morphTargets = object.geometry && object.geometry.morphAttributes.position;
const morphNormals = object.geometry && object.geometry.morphAttributes.normal;
......
......@@ -102,7 +102,7 @@ function WebGLBackground( renderer, cubemaps, state, objects, premultipliedAlpha
}
boxMesh.material.uniforms.envMap.value = background;
boxMesh.material.uniforms.flipEnvMap.value = ( background.isCubeTexture && background._needsFlipEnvMap ) ? - 1 : 1;
boxMesh.material.uniforms.flipEnvMap.value = ( background.isCubeTexture && background.isRenderTargetTexture === false ) ? - 1 : 1;
if ( currentBackground !== background ||
currentBackgroundVersion !== background.version ||
......
......@@ -23,7 +23,7 @@ function WebGLCubeMaps( renderer ) {
function get( texture ) {
if ( texture && texture.isTexture ) {
if ( texture && texture.isTexture && texture.isRenderTargetTexture === false ) {
const mapping = texture.mapping;
......
import { CubeReflectionMapping, CubeRefractionMapping, EquirectangularReflectionMapping, EquirectangularRefractionMapping } from '../../constants.js';
import { PMREMGenerator } from '../../extras/PMREMGenerator.js';
function WebGLCubeUVMaps( renderer ) {
let cubeUVmaps = new WeakMap();
let pmremGenerator = null;
function get( texture ) {
if ( texture && texture.isTexture && texture.isRenderTargetTexture === false ) {
const mapping = texture.mapping;
const isEquirectMap = ( mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping );
const isCubeMap = ( mapping === CubeReflectionMapping || mapping === CubeRefractionMapping );
if ( isEquirectMap || isCubeMap ) {
// equirect/cube map to cubeUV conversion
if ( cubeUVmaps.has( texture ) ) {
return cubeUVmaps.get( texture ).texture;
} else {
const image = texture.image;
if ( ( isEquirectMap && image && image.height > 0 ) || ( isCubeMap && image && isCubeTextureComplete( image ) ) ) {
const currentRenderTarget = renderer.getRenderTarget();
if ( pmremGenerator === null ) pmremGenerator = new PMREMGenerator( renderer );
const renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular( texture ) : pmremGenerator.fromCubemap( texture );
cubeUVmaps.set( texture, renderTarget );
renderer.setRenderTarget( currentRenderTarget );
texture.addEventListener( 'dispose', onTextureDispose );
return renderTarget.texture;
} else {
// image not yet ready. try the conversion next frame
return null;
}
}
}
}
return texture;
}
function isCubeTextureComplete( image ) {
let count = 0;
const length = 6;
for ( let i = 0; i < length; i ++ ) {
if ( image[ i ] !== undefined ) count ++;
}
return count === length;
}
function onTextureDispose( event ) {
const texture = event.target;
texture.removeEventListener( 'dispose', onTextureDispose );
const cubemapUV = cubeUVmaps.get( texture );
if ( cubemapUV !== undefined ) {
cubemapUV.delete( texture );
cubemapUV.dispose();
}
}
function dispose() {
cubeUVmaps = new WeakMap();
if ( pmremGenerator !== null ) {
pmremGenerator.dispose();
pmremGenerator = null;
}
}
return {
get: get,
dispose: dispose
};
}
export { WebGLCubeUVMaps };
......@@ -145,7 +145,7 @@ function WebGLMaterials( properties ) {
uniforms.envMap.value = envMap;
uniforms.flipEnvMap.value = ( envMap.isCubeTexture && envMap._needsFlipEnvMap ) ? - 1 : 1;
uniforms.flipEnvMap.value = ( envMap.isCubeTexture && envMap.isRenderTargetTexture === false ) ? - 1 : 1;
uniforms.reflectivity.value = material.reflectivity;
uniforms.refractionRatio.value = material.refractionRatio;
......
......@@ -3,7 +3,7 @@ import { WebGLProgram } from './WebGLProgram.js';
import { ShaderLib } from '../shaders/ShaderLib.js';
import { UniformsUtils } from '../shaders/UniformsUtils.js';
function WebGLPrograms( renderer, cubemaps, extensions, capabilities, bindingStates, clipping ) {
function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping ) {
const programs = [];
......@@ -112,7 +112,7 @@ function WebGLPrograms( renderer, cubemaps, extensions, capabilities, bindingSta
const fog = scene.fog;
const environment = material.isMeshStandardMaterial ? scene.environment : null;
const envMap = cubemaps.get( material.envMap || environment );
const envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || environment );
const shaderID = shaderIDs[ material.type ];
......
......@@ -11,18 +11,6 @@ class CubeTexture extends Texture {
super( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );
// Why CubeTexture._needsFlipEnvMap is necessary:
//
// By convention -- likely based on the RenderMan spec from the 1990's -- cube maps are specified by WebGL (and three.js)
// in a coordinate system in which positive-x is to the right when looking up the positive-z axis -- in other words,
// in a left-handed coordinate system. By continuing this convention, preexisting cube maps continued to render correctly.
// three.js uses a right-handed coordinate system. So environment maps used in three.js appear to have px and nx swapped
// and the flag _needsFlipEnvMap controls this conversion. The flip is not required (and thus _needsFlipEnvMap is set to false)
// when using WebGLCubeRenderTarget.texture as a cube texture.
this._needsFlipEnvMap = true;
this.flipY = false;
}
......
......@@ -68,6 +68,8 @@ class Texture extends EventDispatcher {
this.version = 0;
this.onUpdate = null;
this.isRenderTargetTexture = false;
}
updateMatrix() {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册