在three.js中Mipmap一个行星? [英] Mipmap a planet in three.js?

查看:120
本文介绍了在three.js中Mipmap一个行星?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我最近了解了 mipmapping 的定义,但我不确定如何在 Three.js 中正确使用该技术.

So I recently learned about the definition of mipmapping but im unsure of how to properly use that technique within three.js.

我看了一下这个例子:http://threejs.org/examples/webgl_materials_texture_manualmipmap.html

我也看到了这个:http://threejs.org/examples/#webgl_materials_texture_anisotropy

两者似乎都使用了 mipmapping.第一个例子有这部分代码:

Both seem to use mipmapping. The first example has this section of code:

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' );

以及二维上下文的使用.

and the usage of a 2d context.

无论如何,鉴于示例的性质,我仍然不知道如何对行星进行 mipmap.所以是的,我不确定如何正确映射球体.首先,我需要我的行星/球体由单独的部分组成,以便我可以将分解纹理的不同部分放在球体的每个部分上.然后我创建了 2 个尺寸变化的幂,然后呢?

Either way, given the nature of the examples, I am still unaware how to mipmap a planet. So yes, I am unsure how to mitmap a sphere properly. First I would need my planet / sphere to comprise of seperate sections so that I can put the different pieces of the broken up texture on each of those sections of the sphere. Then I create power of 2 size variations but what then?

所以我的问题是,当用于立方体、球体等时,three.js 中的 mipmapping 看起来如何?一个简化的演示将非常受欢迎,因为现有的示例(很少见)似乎都过于臃肿或没有记录.

So my question is, how does mipmapping in three.js look like when used for cubes , spheres etc? A simplified demo would be very appreciated as the existing examples (which are rare) all seem either too bloated or undocumented.

stackoverflow 中的另一个用户发布了这个:

Another user in stackoverflow posted this:

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 是如何工作的.

It seems the key to mipmaps is texture.mipmaps[]. Here the person only specified one image though. Shouldnt we serve various images and let the computer decide which is appropiate depending on how far you are? Not sure how this mipmapping works.

推荐答案

Mipmaping

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

Mipmapping

Mipmapping is a texture rendering technique that you apply on a per-texture basis. The basic gist of it is that when mipmapping is enabled, the GPU will use smaller versions of a texture to render a surface depending on how far away the surface is from the camera.

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

In order to use mipmapping, you need to have a set of mipmaps for your texture; the mipmaps are the smaller versions of your texture. You can provide these mipmaps yourself, and in olden days you might have had to, however with recent graphics APIs (OpenGL >= 3.0) they can be automatically generated. It is very unlikely you need to generate your own mipmaps if all you're doing is applying a basic texture map to the surface of a sphere.

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

Mipmapping does not have anything to do with the 3D shape of the object you are texturing. Whether you are applying the texture to a cube, sphere, or any other model, the steps you need to take as a programmer to enable mipmapping are going to be the same. You do not need to enable mipmapping to render textures, although it will probably make your textures look prettier.

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

By default in three.js you do not need to do anything to generate mipmaps for your textures. Referring to the three.js docs for Texture, there is a generateMipmaps property that controls the automatic generation of mipmaps, and defaults to true. This feature is implemented in the renderer here. This means the bare minimum you need to do to get a mipmapped texture is this:

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

还有一个 mipmaps 属性可以手动填充 mipmap 图像,如您提供的示例所示.奇怪的是,一个未公开的特性是如果这个数组不为空,它会禁用自动 mipmap 生成.您可以在此处查看其来源.

第一个示例中,在瓷砖地板上绘制了一幅画,mipmap() 函数在 HTML 画布上绘制 2D 纹理.它负责绘制您在地平面上看到的平铺纹理.然后将这些纹理作为 mipmap 加载到 mipmaps 数组中,这样它们就可以通过 Three.js 以 3D 形式呈现.

In the first example with the painting on the tiled floor, the mipmap() function draws a 2D texture on an HTML canvas. It is responsible for drawing the tiled texture you see on the ground plane. These textures are then loaded as mipmaps by putting them in the mipmaps array, so that they can then be rendered in 3D by three.js.

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 的边缘.

Did you notice how each successive mipmap is twice as small? The starting texture (which we have to put in mipmaps[0]) is 128x128, the second is 64x64, the third is 32x32, and so on. The colors (#0f0, #00f, #400, etc) are what cause the weird rainbow effect on the tiles. They are colored differently to illustrate the edges of the different mipmaps.

第二个示例用于展示一种称为各向异性过滤的效果,这是进一步的增强在 mipmapping 之上;它根据与相机的距离到相机的视角来选择要使用的纹理大小.当远离相机倾斜时,这可以使远处的纹理看起来更好.

The second example is used to show off an effect called anisotropic filtering, which is a further enhancement on top of mipmapping; it chooses the size of texture to use based on the distance from the camera and the viewing angle to the camera. This can make far-off textures look even nicer when they are tilted away from the camera.

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 );

您是否注意到左侧的 crate 纹理 (texture1) 比右侧的 (texture2) 更清晰且不那么模糊?

Did you notice how the crate texture on the left (texture1) is a lot sharper and less blurry than the one on the right (texture2)?

我在 plunker 中整理了一个更深入的示例,希望能做到更清楚在所有这些场景中发生了什么.一些注意事项:

I put together a more in-depth example in a plunker to hopefully make it a little clearer what is happening in all these scenarios. Some notes:

  • 当您向上倾斜相机时,左上角(无 mipmapping)具有非常明显的莫尔条纹.这就是我们需要 mipmapping 的原因!
  • 右上角(mipmapping)看起来更好,但在远处仍然模糊.这是为什么?
  • 左下角(彩色 mipmap)向我们展示了原因.模糊是由线性过滤器将所有 mipmap 插值在一起造成的.随着我们离相机越远,使用的图像越小,用颜色表示.
  • 右下角(各向异性过滤)应该看起来最好,无论距离多远,纹理都看起来很清晰.

这篇关于在three.js中Mipmap一个行星?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆