提交 4d8781a1 编写于 作者: M Mugen87

PMREMGenerator: Refactor code.

上级 38bf141e
......@@ -62,14 +62,7 @@ var ENCODINGS = {
};
var _flatCamera = new OrthographicCamera();
var _blurMaterial = _getBlurShader( MAX_SAMPLES );
var _equirectShader = null;
var _cubemapShader = null;
var { _lodPlanes, _sizeLods, _sigmas } = _createPlanes();
var _pingPongRenderTarget = null;
var _renderer = null;
var _oldTarget = null;
// Golden Ratio
......@@ -91,8 +84,14 @@ var _axisDirections = [
function PMREMGenerator( renderer ) {
_renderer = renderer;
_compileMaterial( _blurMaterial );
this._renderer = renderer;
this._pingPongRenderTarget = null;
this._blurMaterial = _getBlurShader( MAX_SAMPLES );
this._equirectShader = null;
this._cubemapShader = null;
this._compileMaterial( this._blurMaterial );
}
......@@ -109,16 +108,17 @@ PMREMGenerator.prototype = {
*/
fromScene: function ( scene, sigma = 0, near = 0.1, far = 100 ) {
_oldTarget = _renderer.getRenderTarget();
var cubeUVRenderTarget = _allocateTargets();
_sceneToCubeUV( scene, near, far, cubeUVRenderTarget );
_oldTarget = this._renderer.getRenderTarget();
var cubeUVRenderTarget = this._allocateTargets();
this._sceneToCubeUV( scene, near, far, cubeUVRenderTarget );
if ( sigma > 0 ) {
_blur( cubeUVRenderTarget, 0, 0, sigma );
this._blur( cubeUVRenderTarget, 0, 0, sigma );
}
_applyPMREM( cubeUVRenderTarget );
_cleanup( cubeUVRenderTarget );
this._applyPMREM( cubeUVRenderTarget );
this._cleanup( cubeUVRenderTarget );
return cubeUVRenderTarget;
......@@ -146,11 +146,11 @@ PMREMGenerator.prototype = {
*/
fromCubemap: function ( cubemap ) {
_oldTarget = _renderer.getRenderTarget();
var cubeUVRenderTarget = _allocateTargets( cubemap );
_textureToCubeUV( cubemap, cubeUVRenderTarget );
_applyPMREM( cubeUVRenderTarget );
_cleanup( cubeUVRenderTarget );
_oldTarget = this._renderer.getRenderTarget();
var cubeUVRenderTarget = this._allocateTargets( cubemap );
this._textureToCubeUV( cubemap, cubeUVRenderTarget );
this._applyPMREM( cubeUVRenderTarget );
this._cleanup( cubeUVRenderTarget );
return cubeUVRenderTarget;
......@@ -162,10 +162,10 @@ PMREMGenerator.prototype = {
*/
compileCubemapShader: function () {
if ( _cubemapShader == null ) {
if ( this._cubemapShader === null ) {
_cubemapShader = _getCubemapShader();
_compileMaterial( _cubemapShader );
this._cubemapShader = _getCubemapShader();
this._compileMaterial( this._cubemapShader );
}
......@@ -177,10 +177,10 @@ PMREMGenerator.prototype = {
*/
compileEquirectangularShader: function () {
if ( _equirectShader == null ) {
if ( this._equirectShader === null ) {
_equirectShader = _getEquirectShader();
_compileMaterial( _equirectShader );
this._equirectShader = _getEquirectShader();
this._compileMaterial( this._equirectShader );
}
......@@ -193,10 +193,10 @@ PMREMGenerator.prototype = {
*/
dispose: function () {
_blurMaterial.dispose();
this._blurMaterial.dispose();
if ( _cubemapShader != null ) _cubemapShader.dispose();
if ( _equirectShader != null ) _equirectShader.dispose();
if ( this._cubemapShader !== null ) this._cubemapShader.dispose();
if ( this._equirectShader !== null ) this._equirectShader.dispose();
for ( var i = 0; i < _lodPlanes.length; i ++ ) {
......@@ -206,82 +206,19 @@ PMREMGenerator.prototype = {
},
};
function _createPlanes() {
var _lodPlanes = [];
var _sizeLods = [];
var _sigmas = [];
var lod = LOD_MAX;
for ( var i = 0; i < TOTAL_LODS; i ++ ) {
var sizeLod = Math.pow( 2, lod );
_sizeLods.push( sizeLod );
var sigma = 1.0 / sizeLod;
if ( i > LOD_MAX - LOD_MIN ) {
sigma = EXTRA_LOD_SIGMA[ i - LOD_MAX + LOD_MIN - 1 ];
} else if ( i == 0 ) {
sigma = 0;
}
_sigmas.push( sigma );
var texelSize = 1.0 / ( sizeLod - 1 );
var min = - texelSize / 2;
var max = 1 + texelSize / 2;
var uv1 = [ min, min, max, min, max, max, min, min, max, max, min, max ];
var cubeFaces = 6;
var vertices = 6;
var positionSize = 3;
var uvSize = 2;
var faceIndexSize = 1;
var position = new Float32Array( positionSize * vertices * cubeFaces );
var uv = new Float32Array( uvSize * vertices * cubeFaces );
var faceIndex = new Float32Array( faceIndexSize * vertices * cubeFaces );
for ( var face = 0; face < cubeFaces; face ++ ) {
var x = ( face % 3 ) * 2 / 3 - 1;
var y = face > 2 ? 0 : - 1;
var coordinates = [
x, y, 0,
x + 2 / 3, y, 0,
x + 2 / 3, y + 1, 0,
x, y, 0,
x + 2 / 3, y + 1, 0,
x, y + 1, 0
];
position.set( coordinates, positionSize * vertices * face );
uv.set( uv1, uvSize * vertices * face );
var fill = [ face, face, face, face, face, face ];
faceIndex.set( fill, faceIndexSize * vertices * face );
}
var planes = new BufferGeometry();
planes.setAttribute( 'position', new BufferAttribute( position, positionSize ) );
planes.setAttribute( 'uv', new BufferAttribute( uv, uvSize ) );
planes.setAttribute( 'faceIndex', new BufferAttribute( faceIndex, faceIndexSize ) );
_lodPlanes.push( planes );
if ( lod > LOD_MIN ) {
lod --;
// private interface
}
_cleanup: function ( outputTarget ) {
}
return { _lodPlanes, _sizeLods, _sigmas };
this._pingPongRenderTarget.dispose();
this._renderer.setRenderTarget( _oldTarget );
outputTarget.scissorTest = false;
// reset viewport and scissor
outputTarget.setSize( outputTarget.width, outputTarget.height );
}
},
function _allocateTargets( equirectangular ) {
_allocateTargets: function ( equirectangular ) {
var params = {
magFilter: NearestFilter,
......@@ -295,38 +232,37 @@ function _allocateTargets( equirectangular ) {
};
var cubeUVRenderTarget = _createRenderTarget( params );
cubeUVRenderTarget.depthBuffer = equirectangular ? false : true;
_pingPongRenderTarget = _createRenderTarget( params );
this._pingPongRenderTarget = _createRenderTarget( params );
return cubeUVRenderTarget;
}
},
function _cleanup( outputTarget ) {
_compileMaterial: function ( material ) {
_pingPongRenderTarget.dispose();
_renderer.setRenderTarget( _oldTarget );
outputTarget.scissorTest = false;
// reset viewport and scissor
outputTarget.setSize( outputTarget.width, outputTarget.height );
var tmpScene = new Scene();
tmpScene.add( new Mesh( _lodPlanes[ 0 ], material ) );
this._renderer.compile( tmpScene, _flatCamera );
}
},
function _sceneToCubeUV( scene, near, far, cubeUVRenderTarget ) {
_sceneToCubeUV: function ( scene, near, far, cubeUVRenderTarget ) {
var fov = 90;
var aspect = 1;
var cubeCamera = new PerspectiveCamera( fov, aspect, near, far );
var upSign = [ 1, 1, 1, 1, - 1, 1 ];
var forwardSign = [ 1, 1, - 1, - 1, - 1, 1 ];
var renderer = this._renderer;
var outputEncoding = _renderer.outputEncoding;
var toneMapping = _renderer.toneMapping;
var toneMappingExposure = _renderer.toneMappingExposure;
var clearColor = _renderer.getClearColor();
var clearAlpha = _renderer.getClearAlpha();
var outputEncoding = renderer.outputEncoding;
var toneMapping = renderer.toneMapping;
var toneMappingExposure = renderer.toneMappingExposure;
var clearColor = renderer.getClearColor();
var clearAlpha = renderer.getClearAlpha();
_renderer.toneMapping = LinearToneMapping;
_renderer.toneMappingExposure = 1.0;
_renderer.outputEncoding = LinearEncoding;
renderer.toneMapping = LinearToneMapping;
renderer.toneMappingExposure = 1.0;
renderer.outputEncoding = LinearEncoding;
scene.scale.z *= - 1;
var background = scene.background;
......@@ -338,7 +274,7 @@ function _sceneToCubeUV( scene, near, far, cubeUVRenderTarget ) {
var fExp = Math.min( Math.max( Math.ceil( Math.log2( maxComponent ) ), - 128.0 ), 127.0 );
background = background.multiplyScalar( Math.pow( 2.0, - fExp ) );
var alpha = ( fExp + 128.0 ) / 255.0;
_renderer.setClearColor( background, alpha );
renderer.setClearColor( background, alpha );
scene.background = null;
}
......@@ -364,40 +300,43 @@ function _sceneToCubeUV( scene, near, far, cubeUVRenderTarget ) {
}
_setViewport( cubeUVRenderTarget,
col * SIZE_MAX, i > 2 ? SIZE_MAX : 0, SIZE_MAX, SIZE_MAX );
_renderer.setRenderTarget( cubeUVRenderTarget );
_renderer.render( scene, cubeCamera );
renderer.setRenderTarget( cubeUVRenderTarget );
renderer.render( scene, cubeCamera );
}
_renderer.toneMapping = toneMapping;
_renderer.toneMappingExposure = toneMappingExposure;
_renderer.outputEncoding = outputEncoding;
_renderer.setClearColor( clearColor, clearAlpha );
renderer.toneMapping = toneMapping;
renderer.toneMappingExposure = toneMappingExposure;
renderer.outputEncoding = outputEncoding;
renderer.setClearColor( clearColor, clearAlpha );
scene.scale.z *= - 1;
}
},
function _textureToCubeUV( texture, cubeUVRenderTarget ) {
_textureToCubeUV: function ( texture, cubeUVRenderTarget ) {
var scene = new Scene();
var renderer = this._renderer;
if ( texture.isCubeTexture ) {
if ( _cubemapShader == null ) {
if ( this._cubemapShader == null ) {
_cubemapShader = _getCubemapShader();
this._cubemapShader = _getCubemapShader();
}
} else {
if ( _equirectShader == null ) {
if ( this._equirectShader == null ) {
_equirectShader = _getEquirectShader();
this._equirectShader = _getEquirectShader();
}
}
var material = texture.isCubeTexture ? _cubemapShader : _equirectShader;
var material = texture.isCubeTexture ? this._cubemapShader : this._equirectShader;
scene.add( new Mesh( _lodPlanes[ 0 ], material ) );
var uniforms = material.uniforms;
......@@ -411,40 +350,16 @@ function _textureToCubeUV( texture, cubeUVRenderTarget ) {
uniforms[ 'outputEncoding' ].value = ENCODINGS[ texture.encoding ];
_setViewport( cubeUVRenderTarget, 0, 0, 3 * SIZE_MAX, 2 * SIZE_MAX );
_renderer.setRenderTarget( cubeUVRenderTarget );
_renderer.render( scene, _flatCamera );
renderer.setRenderTarget( cubeUVRenderTarget );
renderer.render( scene, _flatCamera );
}
function _compileMaterial( material ) {
var tmpScene = new Scene();
tmpScene.add( new Mesh( _lodPlanes[ 0 ], material ) );
_renderer.compile( tmpScene, _flatCamera );
}
function _createRenderTarget( params ) {
var cubeUVRenderTarget = new WebGLRenderTarget( 3 * SIZE_MAX, 3 * SIZE_MAX, params );
cubeUVRenderTarget.texture.mapping = CubeUVReflectionMapping;
cubeUVRenderTarget.texture.name = 'PMREM.cubeUv';
cubeUVRenderTarget.scissorTest = true;
return cubeUVRenderTarget;
}
function _setViewport( target, x, y, width, height ) {
target.viewport.set( x, y, width, height );
target.scissor.set( x, y, width, height );
}
},
function _applyPMREM( cubeUVRenderTarget ) {
_applyPMREM: function ( cubeUVRenderTarget ) {
var autoClear = _renderer.autoClear;
_renderer.autoClear = false;
var renderer = this._renderer;
var autoClear = renderer.autoClear;
renderer.autoClear = false;
for ( var i = 1; i < TOTAL_LODS; i ++ ) {
......@@ -453,34 +368,36 @@ function _applyPMREM( cubeUVRenderTarget ) {
_sigmas[ i - 1 ] * _sigmas[ i - 1 ] );
var poleAxis =
_axisDirections[ ( i - 1 ) % _axisDirections.length ];
_blur( cubeUVRenderTarget, i - 1, i, sigma, poleAxis );
this._blur( cubeUVRenderTarget, i - 1, i, sigma, poleAxis );
}
_renderer.autoClear = autoClear;
renderer.autoClear = autoClear;
}
},
/**
/**
* This is a two-pass Gaussian blur for a cubemap. Normally this is done
* vertically and horizontally, but this breaks down on a cube. Here we apply
* the blur latitudinally (around the poles), and then longitudinally (towards
* the poles) to approximate the orthogonally-separable blur. It is least
* accurate at the poles, but still does a decent job.
*/
function _blur( cubeUVRenderTarget, lodIn, lodOut, sigma, poleAxis ) {
_blur: function ( cubeUVRenderTarget, lodIn, lodOut, sigma, poleAxis ) {
var pingPongRenderTarget = this._pingPongRenderTarget;
_halfBlur(
this._halfBlur(
cubeUVRenderTarget,
_pingPongRenderTarget,
pingPongRenderTarget,
lodIn,
lodOut,
sigma,
'latitudinal',
poleAxis );
_halfBlur(
_pingPongRenderTarget,
this._halfBlur(
pingPongRenderTarget,
cubeUVRenderTarget,
lodOut,
lodOut,
......@@ -488,9 +405,12 @@ function _blur( cubeUVRenderTarget, lodIn, lodOut, sigma, poleAxis ) {
'longitudinal',
poleAxis );
}
},
_halfBlur: function ( targetIn, targetOut, lodIn, lodOut, sigmaRadians, direction, poleAxis ) {
function _halfBlur( targetIn, targetOut, lodIn, lodOut, sigmaRadians, direction, poleAxis ) {
var renderer = this._renderer;
var blurMaterial = this._blurMaterial;
if ( direction !== 'latitudinal' && direction !== 'longitudinal' ) {
......@@ -503,8 +423,8 @@ function _halfBlur( targetIn, targetOut, lodIn, lodOut, sigmaRadians, direction,
var STANDARD_DEVIATIONS = 3;
var blurScene = new Scene();
blurScene.add( new Mesh( _lodPlanes[ lodOut ], _blurMaterial ) );
var blurUniforms = _blurMaterial.uniforms;
blurScene.add( new Mesh( _lodPlanes[ lodOut ], blurMaterial ) );
var blurUniforms = blurMaterial.uniforms;
var pixels = _sizeLods[ lodIn ] - 1;
var radiansPerPixel = isFinite( sigmaRadians ) ? Math.PI / ( 2 * pixels ) : 2 * Math.PI / ( 2 * MAX_SAMPLES - 1 );
......@@ -567,8 +487,101 @@ function _halfBlur( targetIn, targetOut, lodIn, lodOut, sigmaRadians, direction,
( lodOut > LOD_MAX - LOD_MIN ? lodOut - LOD_MAX + LOD_MIN : 0 );
_setViewport( targetOut, x, y, 3 * outputSize, 2 * outputSize );
_renderer.setRenderTarget( targetOut );
_renderer.render( blurScene, _flatCamera );
renderer.setRenderTarget( targetOut );
renderer.render( blurScene, _flatCamera );
}
};
function _createPlanes() {
var _lodPlanes = [];
var _sizeLods = [];
var _sigmas = [];
var lod = LOD_MAX;
for ( var i = 0; i < TOTAL_LODS; i ++ ) {
var sizeLod = Math.pow( 2, lod );
_sizeLods.push( sizeLod );
var sigma = 1.0 / sizeLod;
if ( i > LOD_MAX - LOD_MIN ) {
sigma = EXTRA_LOD_SIGMA[ i - LOD_MAX + LOD_MIN - 1 ];
} else if ( i == 0 ) {
sigma = 0;
}
_sigmas.push( sigma );
var texelSize = 1.0 / ( sizeLod - 1 );
var min = - texelSize / 2;
var max = 1 + texelSize / 2;
var uv1 = [ min, min, max, min, max, max, min, min, max, max, min, max ];
var cubeFaces = 6;
var vertices = 6;
var positionSize = 3;
var uvSize = 2;
var faceIndexSize = 1;
var position = new Float32Array( positionSize * vertices * cubeFaces );
var uv = new Float32Array( uvSize * vertices * cubeFaces );
var faceIndex = new Float32Array( faceIndexSize * vertices * cubeFaces );
for ( var face = 0; face < cubeFaces; face ++ ) {
var x = ( face % 3 ) * 2 / 3 - 1;
var y = face > 2 ? 0 : - 1;
var coordinates = [
x, y, 0,
x + 2 / 3, y, 0,
x + 2 / 3, y + 1, 0,
x, y, 0,
x + 2 / 3, y + 1, 0,
x, y + 1, 0
];
position.set( coordinates, positionSize * vertices * face );
uv.set( uv1, uvSize * vertices * face );
var fill = [ face, face, face, face, face, face ];
faceIndex.set( fill, faceIndexSize * vertices * face );
}
var planes = new BufferGeometry();
planes.setAttribute( 'position', new BufferAttribute( position, positionSize ) );
planes.setAttribute( 'uv', new BufferAttribute( uv, uvSize ) );
planes.setAttribute( 'faceIndex', new BufferAttribute( faceIndex, faceIndexSize ) );
_lodPlanes.push( planes );
if ( lod > LOD_MIN ) {
lod --;
}
}
return { _lodPlanes, _sizeLods, _sigmas };
}
function _createRenderTarget( params ) {
var cubeUVRenderTarget = new WebGLRenderTarget( 3 * SIZE_MAX, 3 * SIZE_MAX, params );
cubeUVRenderTarget.texture.mapping = CubeUVReflectionMapping;
cubeUVRenderTarget.texture.name = 'PMREM.cubeUv';
cubeUVRenderTarget.scissorTest = true;
return cubeUVRenderTarget;
}
function _setViewport( target, x, y, width, height ) {
target.viewport.set( x, y, width, height );
target.scissor.set( x, y, width, height );
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册