2
0
Эх сурвалжийг харах

Don't treat render targets like textures. (#8658)

* Don't treat render targets like textures.

Expect Texture instances from now on. Added backwards compatibility
measures to ensure that render targets can still act as textures for the
time being. A deprecation warning will be given. Resolves #8615.

* Added comments to clear up RT-Cube detection.

* Revised the previously added comments.

* Added a TODO note.

Forgot to include this one in the last commit.

* Documentation: updated WebGLRenderTarget.

* Docs: added more Texture info to WebGLRenderTarget.

Also removed an unnecessary html line break.

* Docs: added a notification to ShaderMaterial.

WebGLRenderTarget and WebGLRenderTargetCube must not be used as
uniforms. Their texture instance must be used instead.

* Docs: revised a notification in ShaderMaterial.
Raoul v. R 9 жил өмнө
parent
commit
cd5b6bdd3f

+ 1 - 8
docs/api/materials/ShaderMaterial.html

@@ -22,6 +22,7 @@
 		<ul>
 			<li>A *ShaderMaterial* will only be rendered properly by [page:WebGLRenderer], since the GLSL code in the *vertexShader* and *fragmentShader* properties must be compiled and run on the GPU using WebGL.</li>
 			<li>As of THREE r72, directly assigning attributes in a *ShaderMaterial* is no longer supported. A [page:BufferGeometry] instance (instead of a [page:Geometry] instance) must be used instead, using [page:BufferAttribute] instances to define custom attributes.</li>
+			<li>As of THREE r77, [page:WebGLRenderTarget] or [page:WebGLRenderTargetCube] instances are no longer supposed to be used as uniforms. Their [page:Texture texture] property must be used instead.</li>
 		</ul>
 		</div>
 
@@ -261,18 +262,10 @@
 					<td>sampler2D</td>
 					<td>[page:Texture THREE.Texture]</td>
 				</tr>
-				<tr>
-					<td>sampler2D</td>
-					<td>[page:WebGLRenderTarget THREE.WebGLRenderTarget]</td>
-				</tr>
 				<tr>
 					<td>samplerCube</td>
 					<td>[page:CubeTexture THREE.CubeTexture]</tr>
 				</tr>
-				<tr>
-					<td>samplerCube</td>
-					<td>[page:WebGLRenderTargetCube THREE.WebGLRenderTargetCube]</td>
-				</tr>
 
 			</tbody>
 		</table>

+ 49 - 38
docs/api/renderers/WebGLRenderTarget.html

@@ -17,90 +17,101 @@
 
 
 		<h3>[name]([page:Number width], [page:Number height], [page:Object options])</h3>
+
 		<div>
 		width -- The width of the renderTarget. <br />
-		height -- The height of the renderTarget. <br />
-		options -- The options sets the properties of the render target.
-		</div>
-		<div>
-		Creates a new renderTarget with a certain width and height.
+		height -- The height of the renderTarget.
 		</div>
 
-		<h2>Properties</h2>
+		<div>options is an optional object that holds texture parameters for an auto-generated target texture and depthBuffer/stencilBuffer booleans. For an explanation of the texture parameters see [page:Texture Texture].</div>
 
-		<h3>[property:number wrapS]</h3>
 		<div>
-		The default is THREE.ClampToEdgeWrapping, where the edge is clamped to the outer edge texels. The other two choices are THREE.RepeatWrapping and THREE.MirroredRepeatWrapping.
+		wrapS — [page:Number] default is *THREE.ClampToEdgeWrapping*. <br />
+		wrapT — [page:Number] default is *THREE.ClampToEdgeWrapping*. <br />
+		magFilter — [page:Number], default is *THREE.LinearFilter*. <br />
+		minFilter — [page:Number], default is *THREE.LinearFilter*. <br />
+		format — [page:Number], default is *THREE.RGBAFormat*. <br />
+		type — [page:Number], default is *THREE.UnsignedByteType*. <br />
+		anisotropy — [page:Number], default is *1*. <br />
+		encoding — [page:Number], default is *THREE.LinearEncoding*. <br />
+		depthBuffer — [page:Boolean], default is *true*. Set this to false if you don't need it. <br />
+		stencilBuffer — [page:Boolean], default is *true*. Set this to false if you don't need it.
 		</div>
 
-		<h3>[property:number wrapT]</h3>
 		<div>
-		The default is THREE.ClampToEdgeWrapping, where the edge is clamped to the outer edge texels. The other two choices are THREE.RepeatWrapping and THREE.MirroredRepeatWrapping.
+		Creates a new render target with a certain width and height.
 		</div>
-		
-		<h3>[property:number magFilter]</h3>
+
+		<h2>Properties</h2>
+
+		<h3>[property:number uuid]</h3>
 		<div>
-		How the texture is sampled when a texel covers more than one pixel. The default is THREE.LinearFilter, which takes the four closest texels and bilinearly interpolates among them. The other option is THREE.NearestFilter, which uses the value of the closest texel.
+		A unique number for this render target instance.
 		</div>
 
-		<h3>[property:number minFilter]</h3>
+		<h3>[property:number width]</h3>
 		<div>
-		How the texture is sampled when a texel covers less than one pixel. The default is THREE.LinearMipMapLinearFilter, which uses mipmapping and a trilinear filter. Other choices are THREE.NearestFilter, THREE.NearestMipMapNearestFilter, THREE.NearestMipMapLinearFilter, THREE.LinearFilter, and THREE.LinearMipMapNearestFilter. These vary whether the nearest texel or nearest four texels are retrieved on the nearest mipmap or nearest two mipmaps. Interpolation occurs among the samples retrieved.
+		The width of the render target.
 		</div>
-		
-		<h3>[property:number anisotropy]</h3>
+
+		<h3>[property:number height]</h3>
 		<div>
-		The number of samples taken along the axis through the pixel that has the highest density of texels. By default, this value is 1. A higher value gives a less blurry result than a basic mipmap, at the cost of more texture samples being used. Use renderer.getMaxAnisotropy() to find the maximum valid anisotropy value for the GPU; this value is usually a power of 2.
+		The height of the render target.
 		</div>
 		
-		<h3>[property:Vector2 repeat]</h3>
+		<h3>[property:Vector4 scissor]</h3>
 		<div>
-		How many times the texture is repeated across the surface, in each direction U and V.
+		A rectangular area inside the render target's viewport. Fragments that are outside the area will be discarded.
 		</div>
 
-		<h3>[property:Vector2 offset]</h3>
+		<h3>[property:boolean scissorTest]</h3>
 		<div>
-		How much a single repetition of the texture is offset from the beginning, in each direction U and V. Typical range is 0.0 to 1.0.
+		Indicates whether the scissor test is active or not.
 		</div>
-		
-		<h3>[property:number format]</h3>
+
+		<h3>[property:Vector4 viewport]</h3>
 		<div>
-		The default is THREE.RGBAFormat for the texture. Other formats are: THREE.AlphaFormat, THREE.RGBFormat, THREE.LuminanceFormat, and THREE.LuminanceAlphaFormat. There are also compressed texture formats, if the S3TC extension is supported: THREE.RGB_S3TC_DXT1_Format, THREE.RGBA_S3TC_DXT1_Format, THREE.RGBA_S3TC_DXT3_Format, and THREE.RGBA_S3TC_DXT5_Format.
+		The viewport of this render target.
 		</div>
 
-		<h3>[property:number type]</h3>
+		<h3>[property:Texture texture]</h3>
 		<div>
-		The default is THREE.UnsignedByteType. Other valid types (as WebGL allows) are THREE.ByteType, THREE.ShortType, THREE.UnsignedShortType, THREE.IntType, THREE.UnsignedIntType, THREE.HalfFloatType, THREE.FloatType, THREE.UnsignedShort4444Type, THREE.UnsignedShort5551Type, and THREE.UnsignedShort565Type.
+		This texture instance holds the rendered pixels. Use it as input for further processing.
 		</div>
-		
+
 		<h3>[property:boolean depthBuffer]</h3>
 		<div>
 		Renders to the depth buffer. Default is true.
 		</div>
-		
+
 		<h3>[property:boolean stencilBuffer]</h3>
 		<div>
 		Renders to the stencil buffer. Default is true.
 		</div>
 
-		<h3>[property:boolean generateMipmaps]</h3>
+		<h3>[property:DepthTexture depthTexture]</h3>
 		<div>
-		Whether to generate mipmaps (if possible) for a texture. True by default.
+		If set, the scene depth will be rendered to this texture. Default is null.
 		</div>
 
-		
+
 		<h2>Methods</h2>
-		
+
 		<h3>[method:null setSize]( [page:Number width], [page:Number height] )</h3>
 		<div>
-		Sets the size of the renderTarget.
+		Sets the size of the render target.
 		</div>
-		
-		<h3>[method:RenderTarget clone]()</h3>
+
+		<h3>[method:WebGLRenderTarget clone]()</h3>
 		<div>
-		Creates a copy of the render target.
+		Creates a copy of this render target.
 		</div>
-		
+
+		<h3>[method:WebGLRenderTarget copy]( [page:WebGLRenderTarget source] )</h3>
+		<div>
+		Adopts the settings of the given render target.
+		</div>
+
 		<h3>[method:null dispose]()</h3>
 		<div>
 		Dispatches a dispose event.

+ 93 - 31
src/renderers/WebGLRenderer.js

@@ -2068,6 +2068,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		if ( uvScaleMap !== undefined ) {
 
+			// backwards compatibility
 			if ( uvScaleMap instanceof THREE.WebGLRenderTarget ) {
 
 				uvScaleMap = uvScaleMap.texture;
@@ -2082,7 +2083,12 @@ THREE.WebGLRenderer = function ( parameters ) {
 		}
 
 		uniforms.envMap.value = material.envMap;
-		uniforms.flipEnvMap.value = ( material.envMap instanceof THREE.WebGLRenderTargetCube ) ? 1 : - 1;
+
+		// don't flip CubeTexture envMaps, flip everything else:
+		//  WebGLRenderTargetCube will be flipped for backwards compatibility
+		//  WebGLRenderTargetCube.texture will be flipped because it's a Texture and NOT a CubeTexture
+		// this check must be handled differently, or removed entirely, if WebGLRenderTargetCube uses a CubeTexture in the future
+		uniforms.flipEnvMap.value = ( ! ( material.envMap instanceof THREE.CubeTexture ) ) ? 1 : - 1;
 
 		uniforms.reflectivity.value = material.reflectivity;
 		uniforms.refractionRatio.value = material.refractionRatio;
@@ -2309,6 +2315,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 		color,
 		intensity,
 		distance,
+		shadowMap,
 
 		viewMatrix = camera.matrixWorldInverse,
 
@@ -2325,6 +2332,8 @@ THREE.WebGLRenderer = function ( parameters ) {
 			intensity = light.intensity;
 			distance = light.distance;
 
+			shadowMap = ( light.shadow && light.shadow.map ) ? light.shadow.map.texture : null;
+
 			if ( light instanceof THREE.AmbientLight ) {
 
 				r += color.r * intensity;
@@ -2351,7 +2360,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 				}
 
-				_lights.directionalShadowMap[ directionalLength ] = light.shadow.map;
+				_lights.directionalShadowMap[ directionalLength ] = shadowMap;
 				_lights.directionalShadowMatrix[ directionalLength ] = light.shadow.matrix;
 				_lights.directional[ directionalLength ++ ] = uniforms;
 
@@ -2384,7 +2393,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 				}
 
-				_lights.spotShadowMap[ spotLength ] = light.shadow.map;
+				_lights.spotShadowMap[ spotLength ] = shadowMap;
 				_lights.spotShadowMatrix[ spotLength ] = light.shadow.matrix;
 				_lights.spot[ spotLength ++ ] = uniforms;
 
@@ -2409,7 +2418,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 				}
 
-				_lights.pointShadowMap[ pointLength ] = light.shadow.map;
+				_lights.pointShadowMap[ pointLength ] = shadowMap;
 
 				if ( _lights.pointShadowMatrix[ pointLength ] === undefined ) {
 
@@ -2794,8 +2803,6 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 	function setTexture2D( texture, slot ) {
 
-		if ( texture instanceof THREE.WebGLRenderTarget ) texture = texture.texture;
-
 		var textureProperties = properties.get( texture );
 
 		if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
@@ -2889,7 +2896,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 	}
 
-	function setCubeTexture ( texture, slot ) {
+	function setTextureCube ( texture, slot ) {
 
 		var textureProperties = properties.get( texture );
 
@@ -2968,7 +2975,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 								} else {
 
-									console.warn( "THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setCubeTexture()" );
+									console.warn( "THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()" );
 
 								}
 
@@ -3005,47 +3012,102 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 	}
 
-	function setCubeTextureDynamic ( texture, slot ) {
+	function setTextureCubeDynamic ( texture, slot ) {
 
 		state.activeTexture( _gl.TEXTURE0 + slot );
 		state.bindTexture( _gl.TEXTURE_CUBE_MAP, properties.get( texture ).__webglTexture );
 
 	}
 
-	var setTextureWarned = false;
-	this.setTexture = function( texture, slot ) {
+	this.allocTextureUnit = allocTextureUnit;
 
-		if ( ! setTextureWarned ) {
+	//this.setTexture2D = setTexture2D;
+	this.setTexture2D = ( function() {
 
-			console.warn( "THREE.WebGLRenderer: .setTexture is deprecated, " +
-				"use setTexture2D instead." );
-			setTextureWarned = true;
+		var warned = false;
 
-		}
+		// backwards compatibility: peel texture.texture
+		return function( texture, slot ) {
 
-		setTexture2D( texture, slot );
+			if ( texture instanceof THREE.WebGLRenderTarget ) {
 
-	};
+				if ( ! warned ) {
 
-	this.allocTextureUnit = allocTextureUnit;
-	this.setTexture2D = setTexture2D;
-	this.setTextureCube = function( texture, slot ) {
+					console.warn( "THREE.WebGLRenderer.setTexture2D: don't use render targets as textures. Use their .texture property instead." );
+					warned = true;
 
-		if ( texture instanceof THREE.CubeTexture ||
-			 ( Array.isArray( texture.image ) && texture.image.length === 6 ) ) {
+				}
 
-			// CompressedTexture can have Array in image :/
+				texture = texture.texture;
 
-			setCubeTexture( texture, slot );
+			}
 
-		} else {
-			// assumed: texture instanceof THREE.WebGLRenderTargetCube
+			setTexture2D( texture, slot );
 
-			setCubeTextureDynamic( texture.texture, slot );
+		};
 
-		}
+	}() );
 
-	};
+	this.setTexture = ( function() {
+
+		var warned = false;
+
+		return function( texture, slot ) {
+
+			if ( ! warned ) {
+
+				console.warn( "THREE.WebGLRenderer: .setTexture is deprecated, use setTexture2D instead." );
+				warned = true;
+
+			}
+
+			_this.setTexture2D( texture, slot );
+
+		};
+
+	}() );
+
+	this.setTextureCube = ( function() {
+
+		var warned = false;
+
+		return function( texture, slot ) {
+
+			// backwards compatibility: peel texture.texture
+			if ( texture instanceof THREE.WebGLRenderTargetCube ) {
+
+				if ( ! warned ) {
+
+					console.warn( "THREE.WebGLRenderer.setTextureCube: don't use cube render targets as textures. Use their .texture property instead." );
+					warned = true;
+
+				}
+
+				texture = texture.texture;
+
+			}
+
+			// currently relying on the fact that WebGLRenderTargetCube.texture is a Texture and NOT a CubeTexture
+			// TODO: unify these code paths
+			if ( texture instanceof THREE.CubeTexture ||
+				 ( Array.isArray( texture.image ) && texture.image.length === 6 ) ) {
+
+				// CompressedTexture can have Array in image :/
+
+				// this function alone should take care of cube textures
+				setTextureCube( texture, slot );
+
+			} else {
+
+				// assumed: texture property of THREE.WebGLRenderTargetCube
+
+				setTextureCubeDynamic( texture, slot );
+
+			}
+
+		};
+
+	}() );
 
 	// Render targets
 
@@ -3110,7 +3172,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 			renderTarget.depthTexture.needsUpdate = true;
 		}
 
-		_this.setTexture( renderTarget.depthTexture, 0 );
+		_this.setTexture2D( renderTarget.depthTexture, 0 );
 
 		var webglDepthTexture = properties.get( renderTarget.depthTexture ).__webglTexture;
 		_gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 );

+ 4 - 1
src/renderers/webgl/WebGLPrograms.js

@@ -81,6 +81,7 @@ THREE.WebGLPrograms = function ( renderer, capabilities ) {
 
 		} else if ( map instanceof THREE.WebGLRenderTarget ) {
 
+			console.warn( "THREE.WebGLPrograms.getTextureEncodingFromMap: don't use render targets as textures. Use their .texture property instead." );
 			encoding = map.texture.encoding;
 
 		}
@@ -118,13 +119,15 @@ THREE.WebGLPrograms = function ( renderer, capabilities ) {
 
 		}
 
+		var currentRenderTarget = renderer.getCurrentRenderTarget();
+
 		var parameters = {
 
 			shaderID: shaderID,
 
 			precision: precision,
 			supportsVertexTextures: capabilities.vertexTextures,
-			outputEncoding: getTextureEncodingFromMap( renderer.getCurrentRenderTarget(), renderer.gammaOutput ),
+			outputEncoding: getTextureEncodingFromMap( ( ! currentRenderTarget ) ? null : currentRenderTarget.texture, renderer.gammaOutput ),
 			map: !! material.map,
 			mapEncoding: getTextureEncodingFromMap( material.map, renderer.gammaInput ),
 			envMap: !! material.envMap,