BufferGeometry索引问题

时间:2014-09-20 09:43:01

标签: javascript opengl-es three.js buffer-geometry

我试图将我在openFrameworks中创建的代码移植到THREE.JS中。该代码使用perlin噪声生成景观。我这样做是为了首先创建一个静态索引数组,然后将顶点的位置放在一个方格网格中,每个方格网格都移位一个指定的距离。这使得阵列内的顶点的位置可以被移位(向上,向下,向左或向右),使得当相机移动时,可以更新景观并且基于相机移动的方向生成新的景观条带。

对于每个顶点,将6个索引添加到索引数组,该索引数组引用两个相邻的三角形。我不想浪费内存来存储每个三角形的每个顶点的副本。

例如,例如

v12  v11  v10
*----*----*
|\   |\   |
| \  | \  |
|  \ |  \ |
|   \|   \|
*----*----*
v02  v01  v00

所以,例如在顶点v00处,添加了索引{v00,v10,v11}和{v00,v11,v01}等。

在我的openFrameworks代码中,这一切都完美无缺!经过很多麻烦我终于在THREE.js中工作了,但是我注意到,一旦我增加了顶点的数量,一切都开始变得怪异 - 三角形连接(似乎)到处都是,一大块顶点开始被跳过。目前任何包括网格大小256 * 256在内的任何东西都可以正常工作,但是一旦我增加任何更高的值,我就会开始看到所有的文物。

我认为这可能是抵消问题,但我并不真正理解这意味着什么,或者如何用我的代码实现它。我已经看到其他人在按顺序(0,1,2,3,...)定义索引时成功使用它,而是为每个三角形使用3个单独的顶点(并为每个三角形添加每个三个顶点)序列)。我似乎无法让同样的事情发挥作用。

有什么想法吗?我已经在下面提供了我的代码以防它有所帮助。你可以看到我注释掉的部分。

var landscape = {     大小:0,     chunkSize:21845,     距离:0,     geometry:null,     mesh:null,     职位:null,     法线:null,     颜色:null,     indices:null,

generateVertex: function( r, c )
{
    var pos, color;

    // Set position
    pos = new THREE.Vector3();
    pos.x = this.distance * c;
    pos.z = this.distance * r;
    pos.y = -2 + 5*simplex.noise2D( 0.1*pos.x, 0.1*pos.z );

    // Set color
    color = new THREE.Color();
    color.setRGB( Math.random(1), 0, 0 );

    this.vertices.setXYZ( r * this.size + c, pos.x, pos.y, pos.z );
    this.colors.setXYZ( r * this.size + c, color.r, color.g, color.b );
},

generateIndices: function( i, r, c )
{
    this.indices[ i ] = ( r * this.size ) + c;
    this.indices[ i + 1 ] = ( ( r + 1 ) * this.size ) + c;
    this.indices[ i + 2 ] = ( ( r + 1 ) * this.size ) + ( c + 1 );

    this.indices[ i + 3 ] = ( r * this.size ) + c;
    this.indices[ i + 4 ] = ( ( r + 1 ) * this.size ) + ( c + 1 );
    this.indices[ i + 5 ] = ( r * this.size ) + ( c + 1 );

    /*this.indices[ i ] =  ( ( r * this.size ) + c ) % ( 3 * this.chunkSize );
    this.indices[ i + 1 ] = ( ( ( r + 1 ) * this.size ) + c ) % ( 3 * this.chunkSize );
    this.indices[ i + 2 ] = ( ( ( r + 1 ) * this.size ) + ( c + 1 ) ) % ( 3 * this.chunkSize );

    this.indices[ i + 3 ] = ( ( r * this.size ) + c ) % ( 3 * this.chunkSize );
    this.indices[ i + 4 ] = ( ( ( r + 1 ) * this.size ) + ( c + 1 ) ) % ( 3 * this.chunkSize );
    this.indices[ i + 5 ] = ( ( r * this.size ) + ( c + 1 ) ) % ( 3 * this.chunkSize ); */   
},

generatePoint: function( x, z )
{

},

generate: function( size, distance )
{        
    var sizeSquared, i;
    sizeSquared = size * size;
    i = 0;
    this.size = size;
    this.distance = distance;

    // Create buffer geometry
    this.geometry = new THREE.BufferGeometry();

    this.indices = new Uint16Array( 6*(size-1)*(size-1) );

    this.vertices = new THREE.BufferAttribute( new Float32Array( sizeSquared * 3 ), 3 );
    this.colors = new THREE.BufferAttribute( new Float32Array( sizeSquared * 3 ), 3 );

    // Generate points
    for( var r = 0; r < size; r = r + 1 )
    {
        for( var c = 0; c < size; c = c + 1 )
        {
            this.generateVertex( r, c );

            if( (r < size - 1) && (c < size - 1) )
            {
                this.generateIndices( i, r, c );
                i = i + 6;
            }
        }
    }

    // Set geometry
    this.geometry.addAttribute( 'index', new THREE.BufferAttribute( this.indices, 1 ) );
    this.geometry.addAttribute( 'position', this.vertices );
    this.geometry.addAttribute( 'color', this.colors );        

    //
    /*this.geometry.offsets = [];

    var triangles = 2 * ( size - 1 ) * ( size - 1 );
    var offsets = triangles / this.chunkSize;

    for( var j = 0; j < offsets; j = j + 1 )
    {
        var offset =
        {
            start: j * this.chunkSize * 3,
            index: j * this.chunkSize * 3,
            count: Math.min( triangles - ( j * this.chunkSize ), this.chunkSize ) * 3
        };

        this.geometry.offsets.push( offset );
    }*/

    var material = new THREE.MeshBasicMaterial( {vertexColors: THREE.VertexColors} );
    //var material = new THREE.LineBasicMaterial({ vertexColors: THREE.VertexColors });

    this.geometry.computeBoundingSphere();

    this.mesh = new THREE.Mesh( this.geometry, material );
    scene.add( this.mesh );

}

1 个答案:

答案 0 :(得分:3)

WebGL基于OpenGL ES 2.0,它不支持32位索引缓冲区,因此只要有超过256 * 256个顶点,索引缓冲区就无法再解决所有这些问题。

来自OpenGL ES 2.0 Standard(第2.8节顶点阵列):

  

支持使用ubyte和ushort索引的索引支持。支持   对于uint索引,OpenGL ES 2.0不需要。如果   实现支持uint索引,它将导出OES元素   index - uint extension。

假设这是问题,您可以通过获取并检查OES_element_index_uint extension来启用32位索引缓冲区。

var uintExt = gl.getExtension("OES_element_index_uint");
if (!uintExt) {
   alert("Sorry, this app needs 32bit indices and your device or browser doesn't appear to support them");
   return;
}

根据webglstats.com,93.5%的机器支持扩展。


您需要更改generate函数以创建32位数组:

this.indices = new Uint16Array( 6*(size-1)*(size-1) );

应该是:

this.indices = new Uint32Array( 6*(size-1)*(size-1) );

我在source of three.js's renderer内快速钻研,看起来它会检查索引数组的类型,如果使用gl.UNSIGNED_INT,它会将glDrawElements传递给Uint32Array }。