فهرست منبع

WebGLRenderer: Convert to power of two textures that require it instead of giving wrap/minFilter warnings.

Mr.doob 9 سال پیش
والد
کامیت
ff3465c7f0
2فایلهای تغییر یافته به همراه46 افزوده شده و 4 حذف شده
  1. 6 0
      src/math/Math.js
  2. 40 4
      src/renderers/WebGLRenderer.js

+ 6 - 0
src/math/Math.js

@@ -152,6 +152,12 @@ THREE.Math = {
 
 	},
 
+	nearestPowerOfTwo: function ( value ) {
+
+		return Math.pow( 2, Math.round( Math.log( value ) / Math.LN2 ) );
+
+	},
+
 	nextPowerOfTwo: function ( value ) {
 
 		value --;

+ 40 - 4
src/renderers/WebGLRenderer.js

@@ -1168,7 +1168,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 		if ( renderTarget ) {
 
 			var texture = renderTarget.texture;
-			var isTargetPowerOfTwo = THREE.Math.isPowerOfTwo( renderTarget.width ) && THREE.Math.isPowerOfTwo( renderTarget.height );
+			var isTargetPowerOfTwo = isPowerOfTwo( renderTarget );
 			if ( texture.generateMipmaps && isTargetPowerOfTwo && texture.minFilter !== THREE.NearestFilter && texture.minFilter !== THREE.LinearFilter ) {
 
 				 updateRenderTargetMipmap( renderTarget );
@@ -2724,8 +2724,14 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		texture.image = clampToMaxSize( texture.image, capabilities.maxTextureSize );
 
+		if ( textureNeedsPowerOfTwo( texture ) && isPowerOfTwo( texture.image ) === false ) {
+
+			texture.image = makePowerOfTwo( texture.image );
+
+		}
+
 		var image = texture.image,
-		isImagePowerOfTwo = THREE.Math.isPowerOfTwo( image.width ) && THREE.Math.isPowerOfTwo( image.height ),
+		isImagePowerOfTwo = isPowerOfTwo( image ), // TODO: Always true at this step?
 		glFormat = paramThreeToGL( texture.format ),
 		glType = paramThreeToGL( texture.type );
 
@@ -2875,6 +2881,36 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 	}
 
+	function isPowerOfTwo( image ) {
+
+		return THREE.Math.isPowerOfTwo( image.width ) && THREE.Math.isPowerOfTwo( image.height );
+
+	}
+
+	function textureNeedsPowerOfTwo( texture ) {
+
+		if ( texture.wrapS !== THREE.ClampToEdgeWrapping || texture.wrapT !== THREE.ClampToEdgeWrapping ) return true;
+		if ( texture.minFilter !== THREE.NearestFilter && texture.minFilter !== THREE.LinearFilter ) return true;
+
+		return false;
+
+	}
+
+	function makePowerOfTwo( image ) {
+
+		var canvas = document.createElement( 'canvas' );
+		canvas.width = THREE.Math.nearestPowerOfTwo( image.width );
+		canvas.height = THREE.Math.nearestPowerOfTwo( image.height );
+
+		var context = canvas.getContext( '2d' );
+		context.drawImage( image, 0, 0, canvas.width, canvas.height );
+
+		console.warn( 'THREE.WebGLRenderer: image is not power of two (' + image.width + 'x' + image.height + '). Resized to ' + canvas.width + 'x' + canvas.height, image );
+
+		return canvas;
+
+	}
+
 	function setCubeTexture ( texture, slot ) {
 
 		var textureProperties = properties.get( texture );
@@ -2918,7 +2954,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 				}
 
 				var image = cubeImage[ 0 ],
-				isImagePowerOfTwo = THREE.Math.isPowerOfTwo( image.width ) && THREE.Math.isPowerOfTwo( image.height ),
+				isImagePowerOfTwo = isPowerOfTwo( image ),
 				glFormat = paramThreeToGL( texture.format ),
 				glType = paramThreeToGL( texture.type );
 
@@ -3056,7 +3092,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 			// Setup texture, create render and frame buffers
 
-			var isTargetPowerOfTwo = THREE.Math.isPowerOfTwo( renderTarget.width ) && THREE.Math.isPowerOfTwo( renderTarget.height ),
+			var isTargetPowerOfTwo = isPowerOfTwo( renderTarget ),
 				glFormat = paramThreeToGL( renderTarget.texture.format ),
 				glType = paramThreeToGL( renderTarget.texture.type );