首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在three.js的一颗行星?

在three.js的一颗行星?
EN

Stack Overflow用户
提问于 2015-12-02 10:56:34
回答 1查看 4.9K关注 0票数 4

因此,我最近了解了mipmapping的定义,但不确定如何在three.js中正确使用该技术。

我看了一下这个例子:manualmipmap.html

我也看到了这个:各向异性

两者似乎都使用mipmapping。第一个示例包含以下代码:

代码语言:javascript
复制
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 );

不清楚的是:

代码语言:javascript
复制
textureCanvas1.mipmaps[ 1 ] = mipmap( 64, '#0f0' );

以及2d上下文的使用。

不管怎样,考虑到例子的性质,我仍然不知道如何绘制行星地图。所以是的,我不知道如何正确地映射一个球体。首先,我需要我的行星/球体由独立的部分组成,这样我就可以将破碎的纹理的不同片段放在球体的每一段上。然后我创造了两种大小变化的力量,然后呢?

所以我的问题是,当用于立方体、球体等时,three.js中的mipmapping是什么样子的?一个简化的演示将是非常感谢的,因为现有的例子(这是罕见的)似乎都过于臃肿或无记录。

编辑:堆栈溢出中的另一个用户发布了以下内容:

代码语言:javascript
复制
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是如何工作的。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-12-06 10:51:46

Mipmapping映射

Mipmapping是一种纹理绘制技术,您可以在每个纹理的基础上应用它.它的基本要点是,当启用mipmapping时,GPU将使用较小版本的纹理渲染一个表面,具体取决于该表面离摄像机有多远。

为了使用mipmap,您需要为您的纹理提供一组mipmap;mipmap是纹理的较小版本。您可以自己提供这些mipmap,在过去的日子里,您可能不得不这样做,但是使用最近的图形API (OpenGL >= 3.0),它们可以自动生成。--如果您所做的只是将基本的纹理映射应用到球体表面,则不太可能需要生成自己的mipmap

混合映射与正在纹理的对象的3D形状没有任何关系。无论是将纹理应用到多维数据集、球体或任何其他模型,作为程序员,启用mipmapping所需的步骤都是相同的。您不需要启用mipmapping来呈现纹理,尽管它可能会使您的纹理看起来更漂亮。

这在Three.js中是如何影响您的?

默认情况下,in three.js不需要为纹理生成mipmap。参考three.js 纹理文档,有一个generateMipmaps属性控制mipmap的自动生成,默认为true。此特性在呈现器这里中实现。这意味着获得mipmapped纹理所需的最小值如下:

代码语言:javascript
复制
var texture1 = THREE.ImageUtils.loadTexture("surface.png");
// our mipmaps will generate automatically now!

还有一个mipmaps属性可以用mipmap图像手动填充,如您提供的示例所示。奇怪的是,一个无文档的特性是,如果这个数组不是空的,它将禁用自动生成mipmap。您可以看到该这里的源代码。

示例故障

在平铺地板上画的第一个例子中,mipmap()函数在HTML上绘制2D纹理。它负责绘制你在地面上看到的瓷砖纹理。然后将这些纹理作为mipmap加载到mipmaps数组中,这样three.js就可以在3D中呈现它们。

代码语言:javascript
复制
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之上的一种进一步增强,它根据相机与摄像机的视角之间的距离来选择纹理大小。这可以使远离纹理看起来更好,当他们倾斜远离相机。

代码语言:javascript
复制
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插值在一起造成的。当我们离相机更远时,用颜色来表示较小的图像。
  • 右下角(各向异性滤波)应该看起来最好,使纹理看起来清晰,不管它们有多远。
票数 18
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34040978

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档