2017-11-10 19 views
1

とありがとうございます。どのようにgl.drawElementsが対応する頂点配列バッファを "見つけ"ますか?

私はWebglで非常に新しく、drawElementsメソッドと描画したい現在の頂点バッファの間のリンクを実際に理解していません。 drawArrayメソッド(バッファの作成、コンテキストへのバインド、データの埋め込み、対応する属性の指し示し、描画など)について、おおよそのことを理解しています。私は、インデックス配列と少ない頂点データと同じことをしようとする。しかし、私はこのタイプのエラーが発生します。

[.Offscreen-For-WebGL-0x7fae2b940800]GL ERROR :GL_INVALID_OPERATION : glDrawElements: bound to target 0x8893 : no buffer 

たぶん私のコードのヒントはあなたを助けることができます。

const cube = new Program(renderer.gl, vertex3d, fragment); // my webgl program 
    const cubeData = new Cube(); // Only array of vertices/indices 
    const cubeVertexPosition = new ArrayBuffer(renderer.gl, cubeData.vertices, 'STATIC_DRAW'); // ARRAY_BUFFER 
    const cubeVertexIndices = new IndexBuffer(renderer.gl, renderer.gl.UNSIGNED_SHORT, cubeData.indices, 'STATIC_DRAW'); // ELEMENT_ARRAY_BUFFER 
cubeVertexPosition.attribute('aPosition', 3, 'FLOAT', false); // define attribute corresponding in vertex shader 
    cubeVertexPosition.attributePointer(cube); // enableVertexAttribArray + vertexAttribPointer 
    [...] 
    cubeVertexIndices.draw('TRIANGLES', 0, 36); // drawElements with gl.UNSIGNED_SHORT type 

私はdrawArrayでそれを描くことに成功しています:)

([...]だけ制服のための変換行列れます)。

たぶん、あなたは私が、

おかげで多くのことを、この黒魔術を理解するのに役立つ可能性が心の中で急速にヒントがあります!

答えて

1

drawArray使用の頂点がcountパラメータのfirstパラメータから、彼らはバッファであるために描かれているところから、1つまたは複数のARRAY_BUFFER

drawElements使用する1つまたはいくつかのARRAY_BUFFERAND描画するARRAY_BUFFER頂点を指すインデックスを含むELEMENT_ARRAY_BUFFERdrawElementsoffsettypeUNSIGNED_BYTE(1バイトであることができるELEMENT_ARRAY_BUFFER(usualy FirstIndex*sizeof(type)を読み取るために開始するバイトオフセットを指定しながらcountパラメータ)、ELEMENT_ARRAY_BUFFER読まれるべきインデックスの数を指定し、UNSIGNED_SHORT(2バイト)またはUNSIGNED_INT(4バイト)

ELEMENT_ARRAY_BUFFER

[0][1][2][1][2][0][1][2][3][3][1][2][3][4][5][... 

ARRAY_BUFFER

| 0 | 1 | 2 | 3 | 4 | ... 
[x][y][z][x][y][z][x][y][z][x][y][z][x][y][z][... 

正常に動作させるには、offset + count*sizeof(type)は、バイト単位でELEMENT_ARRAY_BUFFERのサイズを超えてはなりません。また、ELEMENT_ARRAY_BUFFERの要素インデックスは、ARRAY_BUFFERに含まれる頂点の数より少なくする必要があります。

drawArrayと同様に、drawElementsは、現在バインドされているバッファを(属性ポインタを構成して)データソースとして使用します。 drawElementsとの違いは、あなたがそのように、ELEMENT_ARRAY_BUFFERターゲットを使用して、additionnal要素(インデックス)のバッファを指定しなければならないということである。

gl.bindBuffer(gl.ARRAY_BUFFER, myVerticesA); 
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, myIndicesA); 
// configure attributes pointers here 
gl.drawElements(gl.TRIANGLES, 12345, gl.UNSIGNED_SHORT, 0); 

drawElementsが保存されたインデックスに従ってARRAY_BUFFERバッファ(複数可)の属性を取るだろう「どのように」 ELEMENT_ARRAY_BUFFERでは、属性ポインタの設定方法に依存します。

、インターリーブ位置に次の頂点バッファを想定法線及びテクスチャ座標:

| p0 || n0 || t0 || p1 || n1 || t1 | 
[px][py][pz][nx][ny][nz][tu][tv][px][py][pz][nx][ny][nz][tu][tv][... 

我々は以下のように属性のポインタを定義:

let stride = 8*4; // 8*float (8 * 4 bytes) 
let offp = 0; // positions at beginning 
let offn = 3*4; // normals after 3*float position. 
let offt = 6*4; // tex coords after 3*float position + 3*float normal 
gl.vertexAttribPointer(0, 3, gl.FLOAT, false, stride, offp); 
gl.vertexAttribPointer(1, 3, gl.FLOAT, false, stride, offn); 
gl.vertexAttribPointer(2, 2, gl.FLOAT, false, stride, offt); 

要素(インデックスに)バッファ、GL意志を使用ポインタをELEMENT_ARRAY_BUFFERバッファに格納されたインデックスに従って移動するだけです。

// pseudo-code 
for(let i = start_elem; i < start_elem+count_elem; i++) { 

    let index = ELEMENT_ARRAY_BUFFER[i]; 

    attrib[0] = ARRAY_BUFFER[(index*stride)+offp]; 
    attrib[1] = ARRAY_BUFFER[(index*stride)+offn]; 
    attrib[2] = ARRAY_BUFFER[(index*stride)+offt]; 

} 
+0

感謝を読んでお勧めしたいです。それは私にはもう少し明白です。 2つの配列のあなたのスキーマは物事がどのようにリンクされているかを説明していますが、リンクは明白にはっきりしていません。どのARRAY_BUFFERがELEMENT_ARRAY_BUFFERにリンクされているかを指定する方法はありますか? –

+0

「リンク」は、 'drawElements'を呼び出すときにどのバッファがバインドされているかによって異なります。'ELEMENT_ARRAY_BUFFER'を' ELEMENT_ARRAY_BUFFER'で 'target'と呼ぶと、要素(インデックス)バッファがバインドされています。属性(頂点)バッファがバインドされている' ARRAY_BUFFER'で 'bindBuffer'を呼び出します。これはそれと同じくらい簡単です。この部分を指定するために私の答えを編集します。 – dest1

0

投稿したコードはWebGLではありません。あなたはコードから明らかないくつかのライブラリを使用しています。 ProgramIndexBufferArrayBufferのようなものは、使用しているライブラリの一部です。そのライブラリはどのようにしてそのライブラリに依存しますか?

一般的に、WebGLにはシェーダがあります。頂点シェーダは、gl_Positionを各頂点のクリップ空間座標に設定し、フラグメントシェーダのジョブはgl_FragColorを各ピクセルの色に設定します。

頂点シェーダは通常、属性からの位置に関するデータを取得します。アトリビュートは通常、バッファからデータを取得します。どのバッファにデータを取得するかを指定するには、最初にバッファをARRAY_BUFFERバインドポイントにバインドしてgl.bindBuffer(gl.ARRAY_BUFFER, someBuffer)とし、次にgl.vertexAttribPointerを呼び出して、WebGLにそのバッファからどのようにデータを取得するかを指示します(データのタイプ、頂点間でスキップするバイト数、開始するバッファの距離)を指定します。 gl.vertexAttribPointerは、指定された属性のすべての情報と、ARRAY_BUFFERバインドポイントにバインドされた現在のバッファへの参照を保存します。そのため、別のバッファをバインドして別の属性を設定することができます。

あなたはシェーダの属性に指定されているデータは、シェーダの各反復のために、バッファから1組の値を引かれますgl.drawArrays呼び出す

それはもう一つのバッファを取りgl.drawElementsについては、バウンドELEMENT_ARRAY_BUFFERに設定し、gl.drawElementsをcllすると、そのバッファのデータタイプ(gl.UNSIGNED_BYTEまたはgl.UNSIGNED_SHORT)が表示されます。次に、そのバッファの値を使用して属性バッファから値を取り出します。

gl.drawElementsは、単純に増加する値をバッファに入れると、正確にgl.drawArraysと同じです。あなたがINDEXDATAを供給し、この後者の場合には、それが連続である必要はありませんので、例

const offset = 0; 
const numVerts = 100; 

// process 100 vertices from the buffers pointed to by the attributes 
// in order 0 to 99 
gl.drawArrays(gl.POINTS, offset, numVerts) 

を効果的

// fill a buffer with numbers 0 to 99 (0 to numVerts) 
const numVerts = 100; 
const indexData = new Uint16Array(numVerts); 
for (let i = 0; i < numVerts; ++i) { 
    indexData[i] = i; 
} 
const indexBuffer = gl.createBuffer(); 
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer); 
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indexData, gl.STATIC_DRAW); 

// process 100 vertices from the buffers pointed to by the attributes 
// in order 0 to 99 
const offset = 0; 
gl.drawElements(gl.POINTS, numVerts, gl.UNSIGNED_SHORT, offset); 

もちろんのと同じです。

私はあなたの迅速な応答のためのいくつかの他のwebgl tutorials

+0

お返事ありがとうございました!ライブラリの外観コードと同じように申し訳ありません。何度も何度も書き直すことなく、私にリンクした同じチュートリアルを行うだけです。要点は、drawArrayメソッドを理解していて、それを前に正常に適用したことです。今私はdrawElementsメソッドに焦点を当てています。これは、配列バッファをインデックスバッファにバインドするためのプログラム的なメソッドを見つけられません。 –

関連する問題