所以我最近了解了mipmapping的定义,但我不确定如何在three.js中正确使用该技术。
我看了一下这个例子: http://threejs.org/examples/webgl_materials_texture_manualmipmap.html
我也看到了这个: http://threejs.org/examples/#webgl_materials_texture_anisotropy
两者似乎都使用mipmapping。第一个例子有这部分代码:
function mipmap( size, color ) {
var imageCanvas = document.createElement( "canvas" ),
context = imageCanvas.getContext( "2d" );
imageCanvas.width = imageCanvas.height = size;
context.fillStyle = "#444";
context.fillRect( 0, 0, size, size );
context.fillStyle = color;
context.fillRect( 0, 0, size / 2, size / 2 );
context.fillRect( size / 2, size / 2, size / 2, size / 2 );
return imageCanvas;
}
var canvas = mipmap( 128, '#f00' );
var textureCanvas1 = new THREE.CanvasTexture( canvas );
textureCanvas1.mipmaps[ 0 ] = canvas;
textureCanvas1.mipmaps[ 1 ] = mipmap( 64, '#0f0' );
textureCanvas1.mipmaps[ 2 ] = mipmap( 32, '#00f' );
textureCanvas1.mipmaps[ 3 ] = mipmap( 16, '#400' );
textureCanvas1.mipmaps[ 4 ] = mipmap( 8, '#040' );
textureCanvas1.mipmaps[ 5 ] = mipmap( 4, '#004' );
textureCanvas1.mipmaps[ 6 ] = mipmap( 2, '#044' );
textureCanvas1.mipmaps[ 7 ] = mipmap( 1, '#404' );
textureCanvas1.repeat.set( 1000, 1000 );
textureCanvas1.wrapS = THREE.RepeatWrapping;
textureCanvas1.wrapT = THREE.RepeatWrapping;
var textureCanvas2 = textureCanvas1.clone();
textureCanvas2.magFilter = THREE.NearestFilter;
textureCanvas2.minFilter = THREE.NearestMipMapNearestFilter;
materialCanvas1 = new THREE.MeshBasicMaterial( { map: textureCanvas1 } );
materialCanvas2 = new THREE.MeshBasicMaterial( { color: 0xffccaa, map: textureCanvas2 } );
var geometry = new THREE.PlaneBufferGeometry( 100, 100 );
var meshCanvas1 = new THREE.Mesh( geometry, materialCanvas1 );
meshCanvas1.rotation.x = -Math.PI / 2;
meshCanvas1.scale.set(1000, 1000, 1000);
var meshCanvas2 = new THREE.Mesh( geometry, materialCanvas2 );
meshCanvas2.rotation.x = -Math.PI / 2;
meshCanvas2.scale.set( 1000, 1000, 1000 );
不清楚是:
textureCanvas1.mipmaps[ 1 ] = mipmap( 64, '#0f0' );
以及使用2d上下文。
无论哪种方式,考虑到示例的性质,我仍然不知道如何对行星进行mipmap。所以,是的,我不确定如何正确地对一个球体进行mitmap。首先,我需要我的行星/球体由单独的部分组成,这样我就可以在球体的每个部分上放置不同的碎片纹理。那么我创造了2种尺寸变化的力量,但那又是什么呢?
所以我的问题是,当用于立方体,球体等时,三个.js中的mipmapping怎么样?一个简化的演示将非常受欢迎,因为现有的例子(很少见)似乎都太过臃肿或没有文档。
编辑:stackoverflow中的另一个用户发布了这个:
var texture = THREE.ImageUtils.loadTexture( 'images/512.png', undefined, function() {
texture.repeat.set( 1, 1 );
texture.mipmaps[ 0 ] = texture.image;
texture.generateMipmaps = true;
texture.needsUpdate = true;
};
mipmaps的关键似乎是texture.mipmaps []。这里的人只指定了一个图像。我们不应该提供各种图像,让计算机根据你的距离决定哪个适合?不确定这个mipmapping是如何工作的。
答案 0 :(得分:14)
Mipmapping是一种纹理渲染技术,可以在每个纹理的基础上应用。它的基本要点是,当启用mipmapping时,GPU将使用较小版本的纹理来渲染表面,具体取决于表面离相机的距离。
为了使用mipmapping,您需要为纹理设置一组mipmap; mipmap是纹理的较小版本。您可以自己提供这些mipmap,并且在过去您可能不得不这样做,但是使用最近的图形API(OpenGL> = 3.0),它们可以自动生成。 如果您所做的只是将基本纹理贴图应用于球体表面,则您不太可能需要生成自己的mipmap 。
Mipmapping与您正在纹理化的对象的3D形状没有任何关系。无论是将纹理应用于立方体,球体还是任何其他模型,作为程序员启用mipmapping所需的步骤都将是相同的。您不需要启用mipmapping来渲染纹理,尽管它可能会使您的纹理看起来更漂亮。
默认情况下,在three.js中你不需要为纹理生成mipmap 。参考Texture的three.js文档,有一个generateMipmaps
属性可控制mipmap的自动生成,默认为true。此功能在渲染器here中实现。这意味着获得mipmap纹理所需的最低限度是:
var texture1 = THREE.ImageUtils.loadTexture("surface.png");
// our mipmaps will generate automatically now!
还有一个mipmaps
属性,可以使用mipmap图像手动填充,如您提供的示例所示。奇怪的是,一个未记录的功能是,如果此数组不为空,则禁用自动生成mipmap。您可以看到here的来源。
在瓷砖地板上绘画的first example中,mipmap()
函数在HTML画布上绘制2D纹理。它负责绘制您在地平面上看到的平铺纹理。然后将这些纹理作为mipmap加载,方法是将它们放在mipmaps
数组中,这样它们就可以通过three.js以3D形式呈现。
var canvas = mipmap( 128, '#f00' );
var textureCanvas1 = new THREE.CanvasTexture( canvas );
// manually set up some mipmaps
textureCanvas1.mipmaps[ 0 ] = canvas;
textureCanvas1.mipmaps[ 1 ] = mipmap( 64, '#0f0' );
textureCanvas1.mipmaps[ 2 ] = mipmap( 32, '#00f' );
textureCanvas1.mipmaps[ 3 ] = mipmap( 16, '#400' );
textureCanvas1.mipmaps[ 4 ] = mipmap( 8, '#040' );
textureCanvas1.mipmaps[ 5 ] = mipmap( 4, '#004' );
textureCanvas1.mipmaps[ 6 ] = mipmap( 2, '#044' );
textureCanvas1.mipmaps[ 7 ] = mipmap( 1, '#404' );
您是否注意到每个连续的mipmap如何小两倍?起始纹理(我们必须放在mipmaps[0]
中)是128x128,第二个是64x64,第三个是32x32,依此类推。颜色(#0f0
,#00f
,#400
等)是导致瓷砖上奇怪的彩虹效果的原因。它们的颜色不同,以说明不同mipmap的边缘。
second example用于展示一种称为各向异性过滤的效果,这是在mipmapping之上的进一步增强;它根据摄像机的距离和选择要使用的纹理大小。这可以使远距离纹理在远离相机时更加美观。
var maxAnisotropy = renderer.getMaxAnisotropy();
var texture1 = THREE.ImageUtils.loadTexture( "textures/crate.gif" );
// no need to generate mipmaps here, we get them automatically!
texture1.anisotropy = maxAnisotropy;
texture1.wrapS = texture1.wrapT = THREE.RepeatWrapping;
texture1.repeat.set( 512, 512 );
您是否注意到左侧(texture1
)的条板纹理比右侧(texture2
)更清晰,更模糊?
我在plunker中汇总了一个更深入的示例,希望能让所有这些场景中发生的事情变得更加清晰。一些说明: