2016-07-23 11 views
1

1回の描画呼び出しで10万以上のキューブ(同じVAOのインデックス付きジオメトリを使用して36個の頂点で作成)をレンダリングしたいのですが可能ですか?1回のドローコールで何千ものプリミティブを描画する

ジオメトリデータ(頂点データ)はすべてキューブなので、すべて同じです。投影とカメラビューも同じで、ユニフォームと同じように頂点シェーダに渡されます。それが重要な場合

#version 330 core 

in vec3 position; 
in vec4 vColor; 

out vec4 fColor; 
out vec3 fTexcoord; 

// Model 
uniform mat4 model; 

// View or a.k.a camera matrix 
uniform mat4 camera_view; 

// Projection 
uniform mat4 projection; 

void main() { 
    gl_Position = projection * camera_view * model * vec4(position, 1.0f); 
    fColor = vColor; 
    fTexcoord = normalize(position); 
} 


Render.cpp

for (auto chunk : world->chunks) { 
    for (auto cube : chunk.blocks) { 
     glBindTexture(GL_TEXTURE_CUBE_MAP, textures[cube.texture]); 

     // Model - transform_z * transform_y * transform_x * transform_translation * transform_scaling 
     model = Mat4<GLfloat>(); 
     model = model.translate(cube.position); 
     model = model.scale(cube.scale); 
     model = model * transformation_matrix_x(cube.theta_x); 
     model = model * transformation_matrix_y(cube.theta_y); 
     model = model * transformation_matrix_z(cube.theta_z); 
     glUniformMatrix4fv(gl_model, 1, GL_TRUE, model.data()); 
     // One draw call per cube is not scalable 
     glDrawElements(GL_TRIANGLES, cube.indices.size(), GL_UNSIGNED_INT, 0); 
    } 
    // A draw call like this would be nice since they share so much data. 
    // glDrawLotsOfElements(GL_TRIANGLES, cube.indices.size() * numCubes, GL_UNSIGNED_INT, 0); 
} 

頂点シェーダは、キューブの数は、動的です。

+0

https://www.opengl.org/sdk/docs/man/html/glDrawElementsInstanced.xhtmlを参照してください。 インスタンス化されたレンダリングと呼ばれ、ジオメトリの1セットを取り、それを複数回描画します。 –

+0

キューブ間で異なるのはモデル行列だけなので、どのようにして36個の頂点(キューブ)の各セットが1つのモデル行列などでセットアップされるように設定することができますか? – Entalpi

+0

マトリックスが各フレームで変化しているのか、それとも初期化時にマトリックスを設定していますか?初期化だけの場合は、頂点のすべての位置を事前に計算し、頂点シェーダで – wasthishelpful

答えて

0

パーティクルをレンダリングする前に、インスタンス化されたレンダリングを使用していましたので、正しい方向に向けることができるかどうかを確認します。

ゲームループの前に、シーンをレンダリングする関数を呼び出します。機能であなたのセットアップすることができ、このようなモデル行列、あなたは世界で異なる位置に、各キューブを持つことができますので、:

//matrices for the cubes 
//set amount by the number of cubes you want to draw 
glm::mat4* modelMatrices; 
modelMatrices = new glm::mat4[amount]; 

あなたは、あなたが各キューブに異なる位置を与えるループに入ります

for (GLuint i = 0; i < amount; i++) 
{ //use a function like rand() to get the x,y,z values different 
    glm::mat4 model; 
    model = glm::translate(model, glm::vec3(x, y, z)); 
    modelMatrices[i] = model; 
} 

これは、モデル行列(mat4)を属性としてGPU側に送信する必要があるため、バッファを埋めるときに少し違って見えるので、そのために4つの頂点属性ポインタが必要です。忘れないでください

 glVertexAttribDivisor(1, 1); 
     glVertexAttribDivisor(2, 1); 
     glVertexAttribDivisor(3, 1); 
     glVertexAttribDivisor(4, 1); 

と最後

glDrawArraysInstanced(GL_POINTS, 0, 1, amount); //replace to specify for a cube 

に続いて、あなたが実際にキューブをレンダリングglDrawArraysInstanced 1より多くの時間を使用する必要があります。

GPU側では、以前に送信したものと通常のモデルの行列を置き換えるだけで済みます。

関連する問題