当前位置:  开发笔记 > 编程语言 > 正文

在three.js中映射一颗行星?

如何解决《在three.js中映射一颗行星?》经验,为你挑选了1个好方法。

所以我最近了解了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;
};

似乎mipmap的关键是texture.mipmaps [].这里的人只指定了一个图像.我们不应该提供各种图像,让计算机根据你的距离决定哪个适合?不确定这个mipmapping是如何工作的.



1> 小智..:
纹理映射

Mipmapping是一种纹理渲染技术,可以在每个纹理的基础上应用.它的基本要点是,当启用mipmapping时,GPU将使用较小版本的纹理来渲染表面,具体取决于表面距相机的距离.

要使用mipmapping,您需要为纹理设置一组mipmap; mipmap是纹理的较小版本.您可以自己提供这些mipmap,并且在过去可能不得不提供这些mipmap,但是使用最近的图形API(OpenGL> = 3.0),它们可以自动生成.如果您所做的只是将基本纹理贴图应用于球体表面,则您不太可能需要生成自己的mipmap.

Mipmapping与您正在纹理化的对象的3D形状没有任何关系.无论是将纹理应用于立方体,球体还是任何其他模型,作为程序员启用mipmapping所需的步骤都将是相同的.您不需要启用mipmapping来渲染纹理,尽管它可能会使您的纹理看起来更漂亮.

这会如何影响你在Three.js

默认情况下,在three.js中,您不需要做任何事情来为纹理生成mipmap.参考Texture的three.js文档,有一个generateMipmaps控制mipmap 自动生成的属性,默认为true.此功能在此处的渲染器中实现.这意味着获得mipmap纹理所需的最低限度是:

var texture1 = THREE.ImageUtils.loadTexture("surface.png");
// our mipmaps will generate automatically now!

还有一个mipmaps属性可以手动填充mipmap图像,如您提供的示例.奇怪的是,一个未记录的功能是,如果此数组不为空,则禁用自动生成mipmap.你可以在这里看到它的来源.

示例细分

在第一个在拼贴地板上绘画的示例中,该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的边缘.

额外奖励:各向异性

的第二个例子是用来炫耀称为各向异性滤波的效果,这是上纹理映射的顶部的进一步增强; 它选择纹理的大小使用基于从照相机的距离视角到相机.这可以使远距离纹理在远离相机时更加美观.

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中放了一个更深入的例子,希望能让所有这些场景中发生的事情变得更加清晰.一些说明:

向上倾斜相机时,左上角(无mipmapping)具有非常明显的莫尔图案.这就是我们需要mipmapping的原因!

右上角(mipmapping)看起来更好,但在远处仍然模糊.这是为什么?

左下角(彩色mipmap)向我们展示了原因.模糊是由线性滤波器一起插入的所有mipmap引起的.随着我们越来越远离相机,使用较小的图像,用颜色表示.

右下角(各向异性过滤)应该看起来最好,使纹理看起来很清晰,无论它们有多远.

推荐阅读
勤奋的瞌睡猪_715
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有