提交 89b9d21d 编写于 作者: A alteredq

Merged @MiiBond's single file DDS cube textures.

See #2670
...@@ -15981,10 +15981,22 @@ THREE.WebGLRenderer = function ( parameters ) { ...@@ -15981,10 +15981,22 @@ THREE.WebGLRenderer = function ( parameters ) {
this.deallocateTexture = function ( texture ) { this.deallocateTexture = function ( texture ) {
if ( ! texture.__webglInit ) return; // cube texture
texture.__webglInit = false; if ( texture.image && texture.image.__webglTextureCube ) {
_gl.deleteTexture( texture.__webglTexture );
_gl.deleteTexture( texture.image.__webglTextureCube );
// 2D texture
} else {
if ( ! texture.__webglInit ) return;
texture.__webglInit = false;
_gl.deleteTexture( texture.__webglTexture );
}
_this.info.memory.textures --; _this.info.memory.textures --;
...@@ -22316,6 +22328,8 @@ THREE.WebGLRenderer = function ( parameters ) { ...@@ -22316,6 +22328,8 @@ THREE.WebGLRenderer = function ( parameters ) {
texture.image.__webglTextureCube = _gl.createTexture(); texture.image.__webglTextureCube = _gl.createTexture();
_this.info.memory.textures ++;
} }
_gl.activeTexture( _gl.TEXTURE0 + slot ); _gl.activeTexture( _gl.TEXTURE0 + slot );
...@@ -22445,6 +22459,8 @@ THREE.WebGLRenderer = function ( parameters ) { ...@@ -22445,6 +22459,8 @@ THREE.WebGLRenderer = function ( parameters ) {
renderTarget.__webglTexture = _gl.createTexture(); renderTarget.__webglTexture = _gl.createTexture();
_this.info.memory.textures ++;
// Setup texture, create render and frame buffers // Setup texture, create render and frame buffers
var isTargetPowerOfTwo = isPowerOfTwo( renderTarget.width ) && isPowerOfTwo( renderTarget.height ), var isTargetPowerOfTwo = isPowerOfTwo( renderTarget.width ) && isPowerOfTwo( renderTarget.height ),
...@@ -24174,7 +24190,7 @@ THREE.ImageUtils = { ...@@ -24174,7 +24190,7 @@ THREE.ImageUtils = {
if ( images.loadCount === 6 ) { if ( images.loadCount === 6 ) {
texture.needsUpdate = true; texture.needsUpdate = true;
if ( onLoad ) onLoad(); if ( onLoad ) onLoad( texture );
} }
...@@ -24229,7 +24245,7 @@ THREE.ImageUtils = { ...@@ -24229,7 +24245,7 @@ THREE.ImageUtils = {
texture.format = dds.format; texture.format = dds.format;
texture.needsUpdate = true; texture.needsUpdate = true;
if ( onLoad ) onLoad(); if ( onLoad ) onLoad( texture );
} }
...@@ -24237,17 +24253,68 @@ THREE.ImageUtils = { ...@@ -24237,17 +24253,68 @@ THREE.ImageUtils = {
} }
for ( var i = 0, il = array.length; i < il; ++ i ) { // compressed cubemap textures as 6 separate DDS files
var cubeImage = {}; if ( array instanceof Array ) {
images[ i ] = cubeImage;
for ( var i = 0, il = array.length; i < il; ++ i ) {
var cubeImage = {};
images[ i ] = cubeImage;
var request = new XMLHttpRequest();
request.onload = generateCubeFaceCallback( request, cubeImage );
request.onerror = onError;
var url = array[ i ];
request.open( 'GET', url, true );
request.responseType = "arraybuffer";
request.send( null );
}
// compressed cubemap texture stored in a single DDS file
} else {
var url = array;
var request = new XMLHttpRequest(); var request = new XMLHttpRequest();
request.onload = generateCubeFaceCallback( request, cubeImage ); request.onload = function( ) {
request.onerror = onError;
var buffer = request.response;
var dds = THREE.ImageUtils.parseDDS( buffer, true );
if ( dds.isCubemap ) {
var faces = dds.mipmaps.length / dds.mipmapCount;
for ( var f = 0; f < faces; f ++ ) {
images[ f ] = { mipmaps : [] };
var url = array[ i ]; for ( var i = 0; i < dds.mipmapCount; i ++ ) {
images[ f ].mipmaps.push( dds.mipmaps[ f * dds.mipmapCount + i ] );
images[ f ].format = dds.format;
images[ f ].width = dds.width;
images[ f ].height = dds.height;
}
}
texture.format = dds.format;
texture.needsUpdate = true;
if ( onLoad ) onLoad( texture );
}
}
request.onerror = onError;
request.open( 'GET', url, true ); request.open( 'GET', url, true );
request.responseType = "arraybuffer"; request.responseType = "arraybuffer";
...@@ -24339,85 +24406,103 @@ THREE.ImageUtils = { ...@@ -24339,85 +24406,103 @@ THREE.ImageUtils = {
var off_pfFlags = 20; var off_pfFlags = 20;
var off_pfFourCC = 21; var off_pfFourCC = 21;
var off_caps = 27;
var off_caps2 = 28;
var off_caps3 = 29;
var off_caps4 = 30;
// Parse header // Parse header
var header = new Int32Array( buffer, 0, headerLengthInt ); var header = new Int32Array( buffer, 0, headerLengthInt );
if ( header[ off_magic ] !== DDS_MAGIC ) { if ( header[ off_magic ] !== DDS_MAGIC ) {
console.error( "ImageUtils.parseDDS(): Invalid magic number in DDS header" ); console.error( "ImageUtils.parseDDS(): Invalid magic number in DDS header" );
return dds; return dds;
} }
if ( ! header[ off_pfFlags ] & DDPF_FOURCC ) { if ( ! header[ off_pfFlags ] & DDPF_FOURCC ) {
console.error( "ImageUtils.parseDDS(): Unsupported format, must contain a FourCC code" ); console.error( "ImageUtils.parseDDS(): Unsupported format, must contain a FourCC code" );
return dds; return dds;
} }
var blockBytes; var blockBytes;
var fourCC = header[ off_pfFourCC ]; var fourCC = header[ off_pfFourCC ];
switch ( fourCC ) { switch ( fourCC ) {
case FOURCC_DXT1: case FOURCC_DXT1:
blockBytes = 8; blockBytes = 8;
dds.format = THREE.RGB_S3TC_DXT1_Format; dds.format = THREE.RGB_S3TC_DXT1_Format;
break; break;
case FOURCC_DXT3: case FOURCC_DXT3:
blockBytes = 16; blockBytes = 16;
dds.format = THREE.RGBA_S3TC_DXT3_Format; dds.format = THREE.RGBA_S3TC_DXT3_Format;
break; break;
case FOURCC_DXT5: case FOURCC_DXT5:
blockBytes = 16; blockBytes = 16;
dds.format = THREE.RGBA_S3TC_DXT5_Format; dds.format = THREE.RGBA_S3TC_DXT5_Format;
break; break;
default: default:
console.error( "ImageUtils.parseDDS(): Unsupported FourCC code: ", int32ToFourCC( fourCC ) ); console.error( "ImageUtils.parseDDS(): Unsupported FourCC code: ", int32ToFourCC( fourCC ) );
return dds; return dds;
} }
dds.mipmapCount = 1; dds.mipmapCount = 1;
if ( header[ off_flags ] & DDSD_MIPMAPCOUNT && loadMipmaps !== false ) { if ( header[ off_flags ] & DDSD_MIPMAPCOUNT && loadMipmaps !== false ) {
dds.mipmapCount = Math.max( 1, header[ off_mipmapCount ] );
dds.mipmapCount = Math.max( 1, header[ off_mipmapCount ] ); }
//TODO: Verify that all faces of the cubemap are present with DDSCAPS2_CUBEMAP_POSITIVEX, etc.
} dds.isCubemap = header[ off_caps2 ] & DDSCAPS2_CUBEMAP ? true : false;
dds.width = header[ off_width ]; dds.width = header[ off_width ];
dds.height = header[ off_height ]; dds.height = header[ off_height ];
var dataOffset = header[ off_size ] + 4; var dataOffset = header[ off_size ] + 4;
// Extract mipmaps buffers // Extract mipmaps buffers
var width = dds.width; var width = dds.width;
var height = dds.height; var height = dds.height;
for ( var i = 0; i < dds.mipmapCount; i ++ ) { var faces = dds.isCubemap ? 6 : 1;
for ( var face = 0; face < faces; face ++ ) {
for ( var i = 0; i < dds.mipmapCount; i ++ ) {
var dataLength = Math.max( 4, width ) / 4 * Math.max( 4, height ) / 4 * blockBytes; var dataLength = Math.max( 4, width ) / 4 * Math.max( 4, height ) / 4 * blockBytes;
var byteArray = new Uint8Array( buffer, dataOffset, dataLength ); var byteArray = new Uint8Array( buffer, dataOffset, dataLength );
var mipmap = { "data": byteArray, "width": width, "height": height }; var mipmap = { "data": byteArray, "width": width, "height": height };
dds.mipmaps.push( mipmap ); dds.mipmaps.push( mipmap );
dataOffset += dataLength; dataOffset += dataLength;
width = Math.max( width * 0.5, 1 );
height = Math.max( height * 0.5, 1 );
}
width = Math.max( width * 0.5, 1 ); width = dds.width;
height = Math.max( height * 0.5, 1 ); height = dds.height;
} }
...@@ -31196,7 +31281,7 @@ THREE.TubeGeometry = function( path, segments, radius, radiusSegments, closed, d ...@@ -31196,7 +31281,7 @@ THREE.TubeGeometry = function( path, segments, radius, radiusSegments, closed, d
a, b, c, d, a, b, c, d,
uva, uvb, uvc, uvd; uva, uvb, uvc, uvd;
var frames = new THREE.TubeGeometry.FrenetFrames(path, segments, closed), var frames = new THREE.TubeGeometry.FrenetFrames( this.path, this.segments, this.closed ),
tangents = frames.tangents, tangents = frames.tangents,
normals = frames.normals, normals = frames.normals,
binormals = frames.binormals; binormals = frames.binormals;
...@@ -31259,7 +31344,7 @@ THREE.TubeGeometry = function( path, segments, radius, radiusSegments, closed, d ...@@ -31259,7 +31344,7 @@ THREE.TubeGeometry = function( path, segments, radius, radiusSegments, closed, d
for ( j = 0; j < this.radiusSegments; j++ ) { for ( j = 0; j < this.radiusSegments; j++ ) {
ip = ( closed ) ? (i + 1) % this.segments : i + 1; ip = ( this.closed ) ? (i + 1) % this.segments : i + 1;
jp = (j + 1) % this.radiusSegments; jp = (j + 1) % this.radiusSegments;
a = this.grid[ i ][ j ]; // *** NOT NECESSARILY PLANAR ! *** a = this.grid[ i ][ j ]; // *** NOT NECESSARILY PLANAR ! ***
...@@ -31290,8 +31375,7 @@ THREE.TubeGeometry.prototype = Object.create( THREE.Geometry.prototype ); ...@@ -31290,8 +31375,7 @@ THREE.TubeGeometry.prototype = Object.create( THREE.Geometry.prototype );
// For computing of Frenet frames, exposing the tangents, normals and binormals the spline // For computing of Frenet frames, exposing the tangents, normals and binormals the spline
THREE.TubeGeometry.FrenetFrames = function(path, segments, closed) { THREE.TubeGeometry.FrenetFrames = function(path, segments, closed) {
var var tangent = new THREE.Vector3(),
tangent = new THREE.Vector3(),
normal = new THREE.Vector3(), normal = new THREE.Vector3(),
binormal = new THREE.Vector3(), binormal = new THREE.Vector3(),
......
此差异已折叠。
...@@ -82,12 +82,19 @@ ...@@ -82,12 +82,19 @@
var map4 = THREE.ImageUtils.loadCompressedTexture( 'textures/compressed/explosion_dxt5_mip.dds' ); var map4 = THREE.ImageUtils.loadCompressedTexture( 'textures/compressed/explosion_dxt5_mip.dds' );
map4.anisotropy = 4; map4.anisotropy = 4;
var material1 = new THREE.MeshBasicMaterial( { map: map1 } ); var cubemap = THREE.ImageUtils.loadCompressedTextureCube( 'textures/compressed/Mountains.dds', new THREE.CubeReflectionMapping, function( cubemap ) {
cubemap.magFilter = cubemap.minFilter = THREE.LinearFilter;
material1.needsUpdate = true;
} );
var material1 = new THREE.MeshBasicMaterial( { map: map1, envMap: cubemap } );
var material2 = new THREE.MeshBasicMaterial( { map: map2 } ); var material2 = new THREE.MeshBasicMaterial( { map: map2 } );
var material3 = new THREE.MeshBasicMaterial( { map: map3, alphaTest: 0.5, side: THREE.DoubleSide } ); var material3 = new THREE.MeshBasicMaterial( { map: map3, alphaTest: 0.5, side: THREE.DoubleSide } );
var material4 = new THREE.MeshBasicMaterial( { map: map4, side: THREE.DoubleSide, blending: THREE.AdditiveBlending, depthTest: false, transparent: true } ); var material4 = new THREE.MeshBasicMaterial( { map: map4, side: THREE.DoubleSide, blending: THREE.AdditiveBlending, depthTest: false, transparent: true } );
var mesh = new THREE.Mesh( geometry, material1 ); var mesh = new THREE.Mesh( new THREE.TorusGeometry( 100, 50, 32, 16 ), material1 );
mesh.position.x = -200; mesh.position.x = -200;
mesh.position.y = -200; mesh.position.y = -200;
scene.add( mesh ); scene.add( mesh );
......
...@@ -103,7 +103,7 @@ THREE.ImageUtils = { ...@@ -103,7 +103,7 @@ THREE.ImageUtils = {
if ( images.loadCount === 6 ) { if ( images.loadCount === 6 ) {
texture.needsUpdate = true; texture.needsUpdate = true;
if ( onLoad ) onLoad(); if ( onLoad ) onLoad( texture );
} }
...@@ -158,7 +158,7 @@ THREE.ImageUtils = { ...@@ -158,7 +158,7 @@ THREE.ImageUtils = {
texture.format = dds.format; texture.format = dds.format;
texture.needsUpdate = true; texture.needsUpdate = true;
if ( onLoad ) onLoad(); if ( onLoad ) onLoad( texture );
} }
...@@ -166,17 +166,68 @@ THREE.ImageUtils = { ...@@ -166,17 +166,68 @@ THREE.ImageUtils = {
} }
for ( var i = 0, il = array.length; i < il; ++ i ) { // compressed cubemap textures as 6 separate DDS files
var cubeImage = {}; if ( array instanceof Array ) {
images[ i ] = cubeImage;
for ( var i = 0, il = array.length; i < il; ++ i ) {
var cubeImage = {};
images[ i ] = cubeImage;
var request = new XMLHttpRequest();
request.onload = generateCubeFaceCallback( request, cubeImage );
request.onerror = onError;
var url = array[ i ];
request.open( 'GET', url, true );
request.responseType = "arraybuffer";
request.send( null );
}
// compressed cubemap texture stored in a single DDS file
} else {
var url = array;
var request = new XMLHttpRequest(); var request = new XMLHttpRequest();
request.onload = generateCubeFaceCallback( request, cubeImage ); request.onload = function( ) {
request.onerror = onError;
var buffer = request.response;
var dds = THREE.ImageUtils.parseDDS( buffer, true );
if ( dds.isCubemap ) {
var faces = dds.mipmaps.length / dds.mipmapCount;
for ( var f = 0; f < faces; f ++ ) {
images[ f ] = { mipmaps : [] };
for ( var i = 0; i < dds.mipmapCount; i ++ ) {
images[ f ].mipmaps.push( dds.mipmaps[ f * dds.mipmapCount + i ] );
images[ f ].format = dds.format;
images[ f ].width = dds.width;
images[ f ].height = dds.height;
}
var url = array[ i ]; }
texture.format = dds.format;
texture.needsUpdate = true;
if ( onLoad ) onLoad( texture );
}
}
request.onerror = onError;
request.open( 'GET', url, true ); request.open( 'GET', url, true );
request.responseType = "arraybuffer"; request.responseType = "arraybuffer";
...@@ -268,85 +319,103 @@ THREE.ImageUtils = { ...@@ -268,85 +319,103 @@ THREE.ImageUtils = {
var off_pfFlags = 20; var off_pfFlags = 20;
var off_pfFourCC = 21; var off_pfFourCC = 21;
var off_caps = 27;
var off_caps2 = 28;
var off_caps3 = 29;
var off_caps4 = 30;
// Parse header // Parse header
var header = new Int32Array( buffer, 0, headerLengthInt ); var header = new Int32Array( buffer, 0, headerLengthInt );
if ( header[ off_magic ] !== DDS_MAGIC ) { if ( header[ off_magic ] !== DDS_MAGIC ) {
console.error( "ImageUtils.parseDDS(): Invalid magic number in DDS header" ); console.error( "ImageUtils.parseDDS(): Invalid magic number in DDS header" );
return dds; return dds;
} }
if ( ! header[ off_pfFlags ] & DDPF_FOURCC ) { if ( ! header[ off_pfFlags ] & DDPF_FOURCC ) {
console.error( "ImageUtils.parseDDS(): Unsupported format, must contain a FourCC code" ); console.error( "ImageUtils.parseDDS(): Unsupported format, must contain a FourCC code" );
return dds; return dds;
} }
var blockBytes; var blockBytes;
var fourCC = header[ off_pfFourCC ]; var fourCC = header[ off_pfFourCC ];
switch ( fourCC ) { switch ( fourCC ) {
case FOURCC_DXT1: case FOURCC_DXT1:
blockBytes = 8; blockBytes = 8;
dds.format = THREE.RGB_S3TC_DXT1_Format; dds.format = THREE.RGB_S3TC_DXT1_Format;
break; break;
case FOURCC_DXT3: case FOURCC_DXT3:
blockBytes = 16; blockBytes = 16;
dds.format = THREE.RGBA_S3TC_DXT3_Format; dds.format = THREE.RGBA_S3TC_DXT3_Format;
break; break;
case FOURCC_DXT5: case FOURCC_DXT5:
blockBytes = 16; blockBytes = 16;
dds.format = THREE.RGBA_S3TC_DXT5_Format; dds.format = THREE.RGBA_S3TC_DXT5_Format;
break; break;
default: default:
console.error( "ImageUtils.parseDDS(): Unsupported FourCC code: ", int32ToFourCC( fourCC ) ); console.error( "ImageUtils.parseDDS(): Unsupported FourCC code: ", int32ToFourCC( fourCC ) );
return dds; return dds;
} }
dds.mipmapCount = 1; dds.mipmapCount = 1;
if ( header[ off_flags ] & DDSD_MIPMAPCOUNT && loadMipmaps !== false ) { if ( header[ off_flags ] & DDSD_MIPMAPCOUNT && loadMipmaps !== false ) {
dds.mipmapCount = Math.max( 1, header[ off_mipmapCount ] );
}
dds.mipmapCount = Math.max( 1, header[ off_mipmapCount ] ); //TODO: Verify that all faces of the cubemap are present with DDSCAPS2_CUBEMAP_POSITIVEX, etc.
} dds.isCubemap = header[ off_caps2 ] & DDSCAPS2_CUBEMAP ? true : false;
dds.width = header[ off_width ]; dds.width = header[ off_width ];
dds.height = header[ off_height ]; dds.height = header[ off_height ];
var dataOffset = header[ off_size ] + 4; var dataOffset = header[ off_size ] + 4;
// Extract mipmaps buffers // Extract mipmaps buffers
var width = dds.width; var width = dds.width;
var height = dds.height; var height = dds.height;
for ( var i = 0; i < dds.mipmapCount; i ++ ) { var faces = dds.isCubemap ? 6 : 1;
var dataLength = Math.max( 4, width ) / 4 * Math.max( 4, height ) / 4 * blockBytes; for ( var face = 0; face < faces; face ++ ) {
var byteArray = new Uint8Array( buffer, dataOffset, dataLength );
var mipmap = { "data": byteArray, "width": width, "height": height }; for ( var i = 0; i < dds.mipmapCount; i ++ ) {
dds.mipmaps.push( mipmap );
dataOffset += dataLength; var dataLength = Math.max( 4, width ) / 4 * Math.max( 4, height ) / 4 * blockBytes;
var byteArray = new Uint8Array( buffer, dataOffset, dataLength );
var mipmap = { "data": byteArray, "width": width, "height": height };
dds.mipmaps.push( mipmap );
dataOffset += dataLength;
width = Math.max( width * 0.5, 1 );
height = Math.max( height * 0.5, 1 );
}
width = Math.max( width * 0.5, 1 ); width = dds.width;
height = Math.max( height * 0.5, 1 ); height = dds.height;
} }
......
...@@ -44,7 +44,7 @@ THREE.TubeGeometry = function( path, segments, radius, radiusSegments, closed, d ...@@ -44,7 +44,7 @@ THREE.TubeGeometry = function( path, segments, radius, radiusSegments, closed, d
a, b, c, d, a, b, c, d,
uva, uvb, uvc, uvd; uva, uvb, uvc, uvd;
var frames = new THREE.TubeGeometry.FrenetFrames(path, segments, closed), var frames = new THREE.TubeGeometry.FrenetFrames( this.path, this.segments, this.closed ),
tangents = frames.tangents, tangents = frames.tangents,
normals = frames.normals, normals = frames.normals,
binormals = frames.binormals; binormals = frames.binormals;
...@@ -107,7 +107,7 @@ THREE.TubeGeometry = function( path, segments, radius, radiusSegments, closed, d ...@@ -107,7 +107,7 @@ THREE.TubeGeometry = function( path, segments, radius, radiusSegments, closed, d
for ( j = 0; j < this.radiusSegments; j++ ) { for ( j = 0; j < this.radiusSegments; j++ ) {
ip = ( closed ) ? (i + 1) % this.segments : i + 1; ip = ( this.closed ) ? (i + 1) % this.segments : i + 1;
jp = (j + 1) % this.radiusSegments; jp = (j + 1) % this.radiusSegments;
a = this.grid[ i ][ j ]; // *** NOT NECESSARILY PLANAR ! *** a = this.grid[ i ][ j ]; // *** NOT NECESSARILY PLANAR ! ***
...@@ -138,8 +138,7 @@ THREE.TubeGeometry.prototype = Object.create( THREE.Geometry.prototype ); ...@@ -138,8 +138,7 @@ THREE.TubeGeometry.prototype = Object.create( THREE.Geometry.prototype );
// For computing of Frenet frames, exposing the tangents, normals and binormals the spline // For computing of Frenet frames, exposing the tangents, normals and binormals the spline
THREE.TubeGeometry.FrenetFrames = function(path, segments, closed) { THREE.TubeGeometry.FrenetFrames = function(path, segments, closed) {
var var tangent = new THREE.Vector3(),
tangent = new THREE.Vector3(),
normal = new THREE.Vector3(), normal = new THREE.Vector3(),
binormal = new THREE.Vector3(), binormal = new THREE.Vector3(),
......
...@@ -355,10 +355,22 @@ THREE.WebGLRenderer = function ( parameters ) { ...@@ -355,10 +355,22 @@ THREE.WebGLRenderer = function ( parameters ) {
this.deallocateTexture = function ( texture ) { this.deallocateTexture = function ( texture ) {
if ( ! texture.__webglInit ) return; // cube texture
texture.__webglInit = false; if ( texture.image && texture.image.__webglTextureCube ) {
_gl.deleteTexture( texture.__webglTexture );
_gl.deleteTexture( texture.image.__webglTextureCube );
// 2D texture
} else {
if ( ! texture.__webglInit ) return;
texture.__webglInit = false;
_gl.deleteTexture( texture.__webglTexture );
}
_this.info.memory.textures --; _this.info.memory.textures --;
...@@ -6690,6 +6702,8 @@ THREE.WebGLRenderer = function ( parameters ) { ...@@ -6690,6 +6702,8 @@ THREE.WebGLRenderer = function ( parameters ) {
texture.image.__webglTextureCube = _gl.createTexture(); texture.image.__webglTextureCube = _gl.createTexture();
_this.info.memory.textures ++;
} }
_gl.activeTexture( _gl.TEXTURE0 + slot ); _gl.activeTexture( _gl.TEXTURE0 + slot );
...@@ -6819,6 +6833,8 @@ THREE.WebGLRenderer = function ( parameters ) { ...@@ -6819,6 +6833,8 @@ THREE.WebGLRenderer = function ( parameters ) {
renderTarget.__webglTexture = _gl.createTexture(); renderTarget.__webglTexture = _gl.createTexture();
_this.info.memory.textures ++;
// Setup texture, create render and frame buffers // Setup texture, create render and frame buffers
var isTargetPowerOfTwo = isPowerOfTwo( renderTarget.width ) && isPowerOfTwo( renderTarget.height ), var isTargetPowerOfTwo = isPowerOfTwo( renderTarget.width ) && isPowerOfTwo( renderTarget.height ),
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册