Javascript Mipmap一颗行星在三个.js中?
因此,我最近了解了mipmapping的定义,但我不确定如何在three.js中正确使用该技术 我看了一下这个例子: 我也看到了: 两者似乎都使用mipmapping。第一个示例包含以下代码部分:Javascript Mipmap一颗行星在三个.js中?,javascript,three.js,Javascript,Three.js,因此,我最近了解了mipmapping的定义,但我不确定如何在three.js中正确使用该技术 我看了一下这个例子: 我也看到了: 两者似乎都使用mipmapping。第一个示例包含以下代码部分: function mipmap( size, color ) { var imageCanvas = document.createElement( "canvas" ), context = imageCanvas.getContext(
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上下文的使用
不管怎样,考虑到这些例子的性质,我仍然不知道如何绘制行星地图。所以,是的,我不确定如何正确地映射球体。首先,我需要我的行星/球体由不同的部分组成,这样我可以在球体的每个部分上放置不同的破碎纹理。然后我创造了两种尺寸变化的力量,但接下来呢
所以我的问题是,three.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的关键是纹理。mipmaps[]。但在这里,此人只指定了一个图像。难道我们不应该提供各种各样的图像,让计算机根据你的距离来决定哪一种是合适的吗?不确定这个映射是如何工作的 Mipmapping
Mipmapping是一种基于每个纹理应用的纹理渲染技术。它的基本要点是,当启用mipmapping时,GPU将使用较小版本的纹理来渲染曲面,具体取决于曲面与摄影机的距离
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 );
为了使用mipmapping,您需要为您的纹理设置一组mipmapps;mipmap是纹理的较小版本。您可以自己提供这些mipmap,在过去您可能不得不这样做,但是使用最新的图形API(OpenGL>=3.0),它们可以自动生成如果您所做的只是将基本纹理贴图应用于球体表面,则不太可能需要生成自己的mipmap
Mipmapping与正在纹理的对象的三维形状没有任何关系。无论您是将纹理应用于立方体、球体还是任何其他模型,作为程序员启用mipmapping所需的步骤都是相同的。您不需要启用mipmapping来渲染纹理,尽管它可能会使纹理看起来更漂亮
在Three.js中,这对您有何影响
默认情况下,在three.js中,无需执行任何操作即可为纹理生成mipmap。参考的three.js文档,有一个属性控制mipmap的自动生成,默认为true。此功能在渲染器中实现。这意味着,要获得mipmapped纹理,您至少需要执行以下操作:
var texture1 = THREE.ImageUtils.loadTexture("surface.png");
// our mipmaps will generate automatically now!
还有一个属性可以手动填充mipmap图像,如您提供的示例所示。奇怪的是,一个未记录的特性是,如果这个数组不是空的,它将禁用自动mipmap生成。你可以看到它的来源
示例分解
在“在平铺地板上绘制”的中,函数mipmap()
在HTML画布上绘制2D纹理。它负责绘制您在地平面上看到的平铺纹理。然后,通过将这些纹理放入mipmaps
数组中,将其加载为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的边缘
好处:各向异性
用于显示一种称为各向异性过滤的效果,这是在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
)更清晰、更模糊
结果
我在一篇文章中放了一个更深入的例子,希望能让大家更清楚地了解在所有这些场景中发生了什么。一些注意事项:
- 当您向上倾斜相机时,左上角(无mipmapping)有一个非常明显的莫尔图案。这就是为什么我们需要mipmapping李>
- 右上角(mipmapping)看起来更好,但在远处仍然模糊。为什么呢
- 左下角(彩色mipmap)显示了原因。模糊是由线性滤波器将所有mipmap插值在一起造成的。当我们离相机越来越远时,就会使用更小的图像,用颜色表示
- 右下角(各向异性过滤)应该看起来最好,使纹理无论距离有多远都看起来清晰