|
@@ -13,36 +13,51 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
|
|
_min = new THREE.Vector3(),
|
|
_min = new THREE.Vector3(),
|
|
_max = new THREE.Vector3(),
|
|
_max = new THREE.Vector3(),
|
|
|
|
|
|
- _matrixPosition = new THREE.Vector3(),
|
|
|
|
|
|
+ _lookTarget = new THREE.Vector3(),
|
|
|
|
+ _lightPositionWorld = new THREE.Vector3(),
|
|
|
|
|
|
_renderList = [];
|
|
_renderList = [];
|
|
|
|
|
|
|
|
+ var _depthMaterial, _depthMaterialMorph, _depthMaterialSkin, _depthMaterialMorphSkin,
|
|
|
|
+ _distanceMaterial, _distanceMaterialMorph, _distanceMaterialSkin, _distanceMaterialMorphSkin;
|
|
|
|
+
|
|
|
|
+ var cubeDirections = [ new THREE.Vector3( 1, 0, 0 ), new THREE.Vector3( - 1, 0, 0 ), new THREE.Vector3( 0, 0, 1 ),
|
|
|
|
+ new THREE.Vector3( 0, 0, - 1 ), new THREE.Vector3( 0, 1, 0 ), new THREE.Vector3( 0, - 1, 0 ) ];
|
|
|
|
+
|
|
|
|
+ var cubeUps = [ new THREE.Vector3( 0, 1, 0 ), new THREE.Vector3( 0, 1, 0 ), new THREE.Vector3( 0, 1, 0 ),
|
|
|
|
+ new THREE.Vector3( 0, 1, 0 ), new THREE.Vector3( 0, 0, 1 ), new THREE.Vector3( 0, 0, - 1 ) ];
|
|
|
|
+
|
|
|
|
+ var cube2DViewPorts = [ new THREE.Vector4(), new THREE.Vector4(), new THREE.Vector4(),
|
|
|
|
+ new THREE.Vector4(), new THREE.Vector4(), new THREE.Vector4() ];
|
|
|
|
+
|
|
|
|
+ var _vector4 = new THREE.Vector4();
|
|
|
|
+
|
|
// init
|
|
// init
|
|
|
|
|
|
var depthShader = THREE.ShaderLib[ "depthRGBA" ];
|
|
var depthShader = THREE.ShaderLib[ "depthRGBA" ];
|
|
var depthUniforms = THREE.UniformsUtils.clone( depthShader.uniforms );
|
|
var depthUniforms = THREE.UniformsUtils.clone( depthShader.uniforms );
|
|
|
|
|
|
- var _depthMaterial = new THREE.ShaderMaterial( {
|
|
|
|
|
|
+ _depthMaterial = new THREE.ShaderMaterial( {
|
|
uniforms: depthUniforms,
|
|
uniforms: depthUniforms,
|
|
vertexShader: depthShader.vertexShader,
|
|
vertexShader: depthShader.vertexShader,
|
|
fragmentShader: depthShader.fragmentShader
|
|
fragmentShader: depthShader.fragmentShader
|
|
} );
|
|
} );
|
|
|
|
|
|
- var _depthMaterialMorph = new THREE.ShaderMaterial( {
|
|
|
|
|
|
+ _depthMaterialMorph = new THREE.ShaderMaterial( {
|
|
uniforms: depthUniforms,
|
|
uniforms: depthUniforms,
|
|
vertexShader: depthShader.vertexShader,
|
|
vertexShader: depthShader.vertexShader,
|
|
fragmentShader: depthShader.fragmentShader,
|
|
fragmentShader: depthShader.fragmentShader,
|
|
morphTargets: true
|
|
morphTargets: true
|
|
} );
|
|
} );
|
|
|
|
|
|
- var _depthMaterialSkin = new THREE.ShaderMaterial( {
|
|
|
|
|
|
+ _depthMaterialSkin = new THREE.ShaderMaterial( {
|
|
uniforms: depthUniforms,
|
|
uniforms: depthUniforms,
|
|
vertexShader: depthShader.vertexShader,
|
|
vertexShader: depthShader.vertexShader,
|
|
fragmentShader: depthShader.fragmentShader,
|
|
fragmentShader: depthShader.fragmentShader,
|
|
skinning: true
|
|
skinning: true
|
|
} );
|
|
} );
|
|
|
|
|
|
- var _depthMaterialMorphSkin = new THREE.ShaderMaterial( {
|
|
|
|
|
|
+ _depthMaterialMorphSkin = new THREE.ShaderMaterial( {
|
|
uniforms: depthUniforms,
|
|
uniforms: depthUniforms,
|
|
vertexShader: depthShader.vertexShader,
|
|
vertexShader: depthShader.vertexShader,
|
|
fragmentShader: depthShader.fragmentShader,
|
|
fragmentShader: depthShader.fragmentShader,
|
|
@@ -55,6 +70,43 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
|
|
_depthMaterialSkin._shadowPass = true;
|
|
_depthMaterialSkin._shadowPass = true;
|
|
_depthMaterialMorphSkin._shadowPass = true;
|
|
_depthMaterialMorphSkin._shadowPass = true;
|
|
|
|
|
|
|
|
+
|
|
|
|
+ var distanceShader = THREE.ShaderLib[ "distanceRGBA" ];
|
|
|
|
+ var distanceUniforms = THREE.UniformsUtils.clone( distanceShader.uniforms );
|
|
|
|
+
|
|
|
|
+ _distanceMaterial = new THREE.ShaderMaterial( {
|
|
|
|
+ uniforms: distanceUniforms,
|
|
|
|
+ vertexShader: distanceShader.vertexShader,
|
|
|
|
+ fragmentShader: distanceShader.fragmentShader
|
|
|
|
+ } );
|
|
|
|
+
|
|
|
|
+ _distanceMaterialMorph = new THREE.ShaderMaterial( {
|
|
|
|
+ uniforms: distanceUniforms,
|
|
|
|
+ vertexShader: distanceShader.vertexShader,
|
|
|
|
+ fragmentShader: distanceShader.fragmentShader,
|
|
|
|
+ morphTargets: true
|
|
|
|
+ } );
|
|
|
|
+
|
|
|
|
+ _distanceMaterialSkin = new THREE.ShaderMaterial( {
|
|
|
|
+ uniforms: distanceUniforms,
|
|
|
|
+ vertexShader: distanceShader.vertexShader,
|
|
|
|
+ fragmentShader: distanceShader.fragmentShader,
|
|
|
|
+ skinning: true
|
|
|
|
+ } );
|
|
|
|
+
|
|
|
|
+ _distanceMaterialMorphSkin = new THREE.ShaderMaterial( {
|
|
|
|
+ uniforms: distanceUniforms,
|
|
|
|
+ vertexShader: distanceShader.vertexShader,
|
|
|
|
+ fragmentShader: distanceShader.fragmentShader,
|
|
|
|
+ morphTargets: true,
|
|
|
|
+ skinning: true
|
|
|
|
+ } );
|
|
|
|
+
|
|
|
|
+ _distanceMaterial._shadowPass = true;
|
|
|
|
+ _distanceMaterialMorph._shadowPass = true;
|
|
|
|
+ _distanceMaterialSkin._shadowPass = true;
|
|
|
|
+ _distanceMaterialMorphSkin._shadowPass = true;
|
|
|
|
+
|
|
//
|
|
//
|
|
|
|
|
|
var scope = this;
|
|
var scope = this;
|
|
@@ -69,6 +121,8 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
|
|
|
|
|
|
this.render = function ( scene ) {
|
|
this.render = function ( scene ) {
|
|
|
|
|
|
|
|
+ var faceCount, isPointLight;
|
|
|
|
+
|
|
if ( scope.enabled === false ) return;
|
|
if ( scope.enabled === false ) return;
|
|
if ( scope.autoUpdate === false && scope.needsUpdate === false ) return;
|
|
if ( scope.autoUpdate === false && scope.needsUpdate === false ) return;
|
|
|
|
|
|
@@ -98,13 +152,58 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
|
|
|
|
|
|
var light = _lights[ i ];
|
|
var light = _lights[ i ];
|
|
|
|
|
|
|
|
+ if ( light instanceof THREE.PointLight ) {
|
|
|
|
+
|
|
|
|
+ faceCount = 6;
|
|
|
|
+ isPointLight = true;
|
|
|
|
+
|
|
|
|
+ var vpWidth = light.shadowMapWidth / 4.0;
|
|
|
|
+ var vpHeight = light.shadowMapHeight / 2.0;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ *
|
|
|
|
+ * These viewports map a cube-map onto a 2D texture with the
|
|
|
|
+ * following orientation:
|
|
|
|
+ *
|
|
|
|
+ * xzXZ
|
|
|
|
+ * y Y
|
|
|
|
+ *
|
|
|
|
+ * Y - Positive y direction
|
|
|
|
+ * y - Negative y direction
|
|
|
|
+ * X - Positive x direction
|
|
|
|
+ * x - Negative x direction
|
|
|
|
+ * Z - Positive z direction
|
|
|
|
+ * z - Negative z direction
|
|
|
|
+ *
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+ // positive X
|
|
|
|
+ cube2DViewPorts[ 0 ].set( vpWidth * 2, vpHeight, vpWidth, vpHeight );
|
|
|
|
+ // negative X
|
|
|
|
+ cube2DViewPorts[ 1 ].set( 0, vpHeight, vpWidth, vpHeight );
|
|
|
|
+ // positive Z
|
|
|
|
+ cube2DViewPorts[ 2 ].set( vpWidth * 3, vpHeight, vpWidth, vpHeight );
|
|
|
|
+ // negative Z
|
|
|
|
+ cube2DViewPorts[ 3 ].set( vpWidth, vpHeight, vpWidth, vpHeight );
|
|
|
|
+ // positive Y
|
|
|
|
+ cube2DViewPorts[ 4 ].set( vpWidth * 3, 0, vpWidth, vpHeight );
|
|
|
|
+ // negative Y
|
|
|
|
+ cube2DViewPorts[ 5 ].set( vpWidth, 0, vpWidth, vpHeight );
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ faceCount = 1;
|
|
|
|
+ isPointLight = false;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
if ( ! light.castShadow ) continue;
|
|
if ( ! light.castShadow ) continue;
|
|
|
|
|
|
if ( ! light.shadowMap ) {
|
|
if ( ! light.shadowMap ) {
|
|
|
|
|
|
var shadowFilter = THREE.LinearFilter;
|
|
var shadowFilter = THREE.LinearFilter;
|
|
|
|
|
|
- if ( scope.type === THREE.PCFSoftShadowMap ) {
|
|
|
|
|
|
+ if ( scope.type === THREE.PCFSoftShadowMap) {
|
|
|
|
|
|
shadowFilter = THREE.NearestFilter;
|
|
shadowFilter = THREE.NearestFilter;
|
|
|
|
|
|
@@ -131,8 +230,7 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
|
|
|
|
|
|
} else {
|
|
} else {
|
|
|
|
|
|
- console.error( "THREE.ShadowMapPlugin: Unsupported light type for shadow", light );
|
|
|
|
- continue;
|
|
|
|
|
|
+ light.shadowCamera = new THREE.PerspectiveCamera( light.shadowCameraFov, 1.0, light.shadowCameraNear, light.shadowCameraFar );
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
@@ -153,78 +251,99 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
|
|
var shadowMatrix = light.shadowMatrix;
|
|
var shadowMatrix = light.shadowMatrix;
|
|
var shadowCamera = light.shadowCamera;
|
|
var shadowCamera = light.shadowCamera;
|
|
|
|
|
|
- //
|
|
|
|
|
|
+ _lightPositionWorld.setFromMatrixPosition( light.matrixWorld );
|
|
|
|
+ shadowCamera.position.copy( _lightPositionWorld );
|
|
|
|
|
|
- shadowCamera.position.setFromMatrixPosition( light.matrixWorld );
|
|
|
|
- _matrixPosition.setFromMatrixPosition( light.target.matrixWorld );
|
|
|
|
- shadowCamera.lookAt( _matrixPosition );
|
|
|
|
- shadowCamera.updateMatrixWorld();
|
|
|
|
|
|
+ // save the existing viewport so it can be restored later
|
|
|
|
+ _renderer.getViewport( _vector4 );
|
|
|
|
|
|
- shadowCamera.matrixWorldInverse.getInverse( shadowCamera.matrixWorld );
|
|
|
|
|
|
+ _renderer.setRenderTarget( shadowMap );
|
|
|
|
+ _renderer.clear();
|
|
|
|
|
|
- //
|
|
|
|
|
|
+ // render shadow map for each cube face (if omni-directional) or
|
|
|
|
+ // run a single pass if not
|
|
|
|
|
|
- if ( light.cameraHelper ) light.cameraHelper.visible = light.shadowCameraVisible;
|
|
|
|
- if ( light.shadowCameraVisible ) light.cameraHelper.update();
|
|
|
|
|
|
+ for ( var face = 0; face < faceCount; face ++ ) {
|
|
|
|
|
|
- // compute shadow matrix
|
|
|
|
|
|
+ if ( isPointLight ) {
|
|
|
|
|
|
- shadowMatrix.set(
|
|
|
|
- 0.5, 0.0, 0.0, 0.5,
|
|
|
|
- 0.0, 0.5, 0.0, 0.5,
|
|
|
|
- 0.0, 0.0, 0.5, 0.5,
|
|
|
|
- 0.0, 0.0, 0.0, 1.0
|
|
|
|
- );
|
|
|
|
|
|
+ _lookTarget.copy( shadowCamera.position );
|
|
|
|
+ _lookTarget.add( cubeDirections[ face ] );
|
|
|
|
+ shadowCamera.up.copy( cubeUps[ face ] );
|
|
|
|
+ shadowCamera.lookAt( _lookTarget );
|
|
|
|
+ var vpDimensions = cube2DViewPorts[ face ];
|
|
|
|
+ _renderer.setViewport( vpDimensions.x, vpDimensions.y, vpDimensions.z, vpDimensions.w );
|
|
|
|
|
|
- shadowMatrix.multiply( shadowCamera.projectionMatrix );
|
|
|
|
- shadowMatrix.multiply( shadowCamera.matrixWorldInverse );
|
|
|
|
|
|
+ } else {
|
|
|
|
|
|
- // update camera matrices and frustum
|
|
|
|
|
|
+ _lookTarget.setFromMatrixPosition( light.target.matrixWorld );
|
|
|
|
+ shadowCamera.lookAt( _lookTarget );
|
|
|
|
|
|
- _projScreenMatrix.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse );
|
|
|
|
- _frustum.setFromMatrix( _projScreenMatrix );
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- // render shadow map
|
|
|
|
|
|
+ shadowCamera.updateMatrixWorld();
|
|
|
|
+ shadowCamera.matrixWorldInverse.getInverse( shadowCamera.matrixWorld );
|
|
|
|
|
|
- _renderer.setRenderTarget( shadowMap );
|
|
|
|
- _renderer.clear();
|
|
|
|
|
|
+ if ( light.cameraHelper ) light.cameraHelper.visible = light.shadowCameraVisible;
|
|
|
|
+ if ( light.shadowCameraVisible ) light.cameraHelper.update();
|
|
|
|
|
|
- // set object matrices & frustum culling
|
|
|
|
|
|
+ // compute shadow matrix
|
|
|
|
|
|
- _renderList.length = 0;
|
|
|
|
|
|
+ shadowMatrix.set(
|
|
|
|
+ 0.5, 0.0, 0.0, 0.5,
|
|
|
|
+ 0.0, 0.5, 0.0, 0.5,
|
|
|
|
+ 0.0, 0.0, 0.5, 0.5,
|
|
|
|
+ 0.0, 0.0, 0.0, 1.0
|
|
|
|
+ );
|
|
|
|
|
|
- projectObject( scene, shadowCamera );
|
|
|
|
|
|
+ shadowMatrix.multiply( shadowCamera.projectionMatrix );
|
|
|
|
+ shadowMatrix.multiply( shadowCamera.matrixWorldInverse );
|
|
|
|
|
|
|
|
+ // update camera matrices and frustum
|
|
|
|
|
|
- // render regular objects
|
|
|
|
|
|
+ _projScreenMatrix.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse );
|
|
|
|
+ _frustum.setFromMatrix( _projScreenMatrix );
|
|
|
|
|
|
- for ( var j = 0, jl = _renderList.length; j < jl; j ++ ) {
|
|
|
|
|
|
+ // set object matrices & frustum culling
|
|
|
|
|
|
- var object = _renderList[ j ];
|
|
|
|
- var geometry = _objects.update( object );
|
|
|
|
- var material = object.material;
|
|
|
|
|
|
+ _renderList.length = 0;
|
|
|
|
+
|
|
|
|
+ projectObject( scene, shadowCamera );
|
|
|
|
+
|
|
|
|
+ // render shadow map
|
|
|
|
+ // render regular objects
|
|
|
|
+
|
|
|
|
+ for ( var j = 0, jl = _renderList.length; j < jl; j ++ ) {
|
|
|
|
|
|
- if ( material instanceof THREE.MeshFaceMaterial ) {
|
|
|
|
|
|
+ var object = _renderList[ j ];
|
|
|
|
+ var geometry = _objects.update( object );
|
|
|
|
+ var material = object.material;
|
|
|
|
|
|
- var groups = geometry.groups;
|
|
|
|
- var materials = material.materials;
|
|
|
|
|
|
+ if ( material instanceof THREE.MeshFaceMaterial ) {
|
|
|
|
|
|
- for ( var k = 0, kl = groups.length; k < kl; k ++ ) {
|
|
|
|
|
|
+ var groups = geometry.groups;
|
|
|
|
+ var materials = material.materials;
|
|
|
|
|
|
- var group = groups[ k ];
|
|
|
|
- var groupMaterial = materials[ group.materialIndex ];
|
|
|
|
|
|
+ for ( var k = 0, kl = groups.length; k < kl; k ++ ) {
|
|
|
|
|
|
- if ( groupMaterial.visible === true ) {
|
|
|
|
|
|
+ var group = groups[ k ];
|
|
|
|
+ var groupMaterial = materials[ group.materialIndex ];
|
|
|
|
|
|
- _renderer.renderBufferDirect( shadowCamera, _lights, null, geometry, getDepthMaterial( object, groupMaterial ), object, group );
|
|
|
|
|
|
+ if ( groupMaterial.visible === true ) {
|
|
|
|
+
|
|
|
|
+ var depthMaterial = getDepthMaterial( object, groupMaterial, isPointLight, _lightPositionWorld );
|
|
|
|
+ _renderer.renderBufferDirect( shadowCamera, _lights, null, geometry, depthMaterial, object, group );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ } else {
|
|
|
|
|
|
- } else {
|
|
|
|
|
|
+ var depthMaterial = getDepthMaterial( object, material, isPointLight, _lightPositionWorld );
|
|
|
|
+ _renderer.renderBufferDirect( shadowCamera, _lights, null, geometry, depthMaterial, object, null );
|
|
|
|
|
|
- _renderer.renderBufferDirect( shadowCamera, _lights, null, geometry, getDepthMaterial( object, material ), object, null );
|
|
|
|
|
|
+ }
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
@@ -246,44 +365,78 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ _renderer.setViewport( _vector4.x, _vector4.y, _vector4.z, _vector4.w );
|
|
|
|
+
|
|
_renderer.resetGLState();
|
|
_renderer.resetGLState();
|
|
|
|
|
|
scope.needsUpdate = false;
|
|
scope.needsUpdate = false;
|
|
|
|
|
|
};
|
|
};
|
|
|
|
|
|
- function getDepthMaterial( object, material ) {
|
|
|
|
|
|
+ function getDepthMaterial( object, material, isPointLight, lightPositionWorld ) {
|
|
|
|
|
|
var geometry = object.geometry;
|
|
var geometry = object.geometry;
|
|
|
|
|
|
var useMorphing = geometry.morphTargets !== undefined && geometry.morphTargets.length > 0 && material.morphTargets;
|
|
var useMorphing = geometry.morphTargets !== undefined && geometry.morphTargets.length > 0 && material.morphTargets;
|
|
var useSkinning = object instanceof THREE.SkinnedMesh && material.skinning;
|
|
var useSkinning = object instanceof THREE.SkinnedMesh && material.skinning;
|
|
|
|
|
|
- var depthMaterial;
|
|
|
|
|
|
+ var newMaterial;
|
|
|
|
+
|
|
|
|
+ var depthMaterial = _depthMaterial;
|
|
|
|
+ var depthMaterialMorph = _depthMaterialMorph;
|
|
|
|
+ var depthMaterialSkin = _depthMaterialSkin;
|
|
|
|
+ var depthMaterialMorphSkin = _depthMaterialMorphSkin;
|
|
|
|
|
|
- if ( object.customDepthMaterial ) {
|
|
|
|
|
|
+ if ( isPointLight ) {
|
|
|
|
+
|
|
|
|
+ depthMaterial = _distanceMaterial;
|
|
|
|
+ depthMaterialMorph = _distanceMaterialMorph;
|
|
|
|
+ depthMaterialSkin = _distanceMaterialSkin;
|
|
|
|
+ depthMaterialMorphSkin = _distanceMaterialMorphSkin;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
|
|
- depthMaterial = object.customDepthMaterial;
|
|
|
|
|
|
+ if ( object.customDepthMaterial || object.customDistanceMaterial ) {
|
|
|
|
+
|
|
|
|
+ if ( isPointLight ) {
|
|
|
|
+
|
|
|
|
+ newMaterial = object.customDistanceMaterial;
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ newMaterial = object.customDepthMaterial;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
|
|
} else if ( useSkinning ) {
|
|
} else if ( useSkinning ) {
|
|
|
|
|
|
- depthMaterial = useMorphing ? _depthMaterialMorphSkin : _depthMaterialSkin;
|
|
|
|
|
|
+ newMaterial = useMorphing ? depthMaterialMorphSkin : depthMaterialSkin;
|
|
|
|
|
|
} else if ( useMorphing ) {
|
|
} else if ( useMorphing ) {
|
|
|
|
|
|
- depthMaterial = _depthMaterialMorph;
|
|
|
|
|
|
+ newMaterial = depthMaterialMorph;
|
|
|
|
|
|
} else {
|
|
} else {
|
|
|
|
|
|
- depthMaterial = _depthMaterial;
|
|
|
|
|
|
+ newMaterial = depthMaterial;
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- depthMaterial.visible = material.visible;
|
|
|
|
- depthMaterial.wireframe = material.wireframe;
|
|
|
|
- depthMaterial.wireframeLinewidth = material.wireframeLinewidth;
|
|
|
|
|
|
+ newMaterial.visible = material.visible;
|
|
|
|
+ newMaterial.wireframe = material.wireframe;
|
|
|
|
+ newMaterial.wireframeLinewidth = material.wireframeLinewidth;
|
|
|
|
+
|
|
|
|
+ if ( isPointLight ) {
|
|
|
|
+
|
|
|
|
+ if ( newMaterial.uniforms.lightPos ) {
|
|
|
|
+
|
|
|
|
+ newMaterial.uniforms.lightPos.value.copy( lightPositionWorld );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
|
|
- return depthMaterial;
|
|
|
|
|
|
+ return newMaterial;
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|