1. 程式人生 > >Opengl-例項化(不知道為啥叫例項化,感覺應該叫一次批量渲染)

Opengl-例項化(不知道為啥叫例項化,感覺應該叫一次批量渲染)

核心:glDrawArraysInstanced
和以往的不同就是這句Draw的時候改成這個API

補充:glVertexAttribDivisor
這個函式告訴了OpenGL該什麼時候更新頂點屬性的內容至新一組資料。它的第一個引數是需要的頂點屬性,第二個引數是屬性除數(Attribute Divisor)。預設情況下,屬性除數是0,告訴OpenGL我們需要在頂點著色器的每次迭代時更新頂點屬性。將它設定為1時,我們告訴OpenGL我們希望在渲染一個新例項的時候更新頂點屬性。而設定為2時,我們希望每2個例項更新一次屬性,以此類推。

程式碼

   unsigned int amount = 10000
; glm::mat4* modelMatrices; modelMatrices = new glm::mat4[amount]; srand(glfwGetTime()); // initialize random seed float radius = 150.0; float offset = 25.0f; for (unsigned int i = 0; i < amount; i++) { glm::mat4 model; // 1. translation: displace along circle with 'radius' in range [-offset, offset]
float angle = (float)i / (float)amount * 360.0f; float displacement = (rand() % (int)(2 * offset * 100)) / 100.0f - offset; float x = sin(angle) * radius + displacement; displacement = (rand() % (int)(2 * offset * 100)) / 100.0f - offset; float y = displacement * 0.4f; // keep height of asteroid field smaller compared to width of x and z
displacement = (rand() % (int)(2 * offset * 100)) / 100.0f - offset; float z = cos(angle) * radius + displacement; model = glm::translate(model, glm::vec3(x, y, z)); // 2. scale: Scale between 0.05 and 0.25f float scale = (rand() % 20) / 100.0f + 0.05; model = glm::scale(model, glm::vec3(scale)); // 3. rotation: add random rotation around a (semi)randomly picked rotation axis vector float rotAngle = (rand() % 360); model = glm::rotate(model, rotAngle, glm::vec3(0.4f, 0.6f, 0.8f)); // 4. now add to list of matrices modelMatrices[i] = model; } // configure instanced array // ------------------------- unsigned int buffer; glGenBuffers(1, &buffer); glBindBuffer(GL_ARRAY_BUFFER, buffer); glBufferData(GL_ARRAY_BUFFER, amount * sizeof(glm::mat4), &modelMatrices[0], GL_STATIC_DRAW); // set transformation matrices as an instance vertex attribute (with divisor 1) // note: we're cheating a little by taking the, now publicly declared, VAO of the model's mesh(es) and adding new vertexAttribPointers // normally you'd want to do this in a more organized fashion, but for learning purposes this will do. // ----------------------------------------------------------------------------------------------------------------------------------- for (unsigned int i = 0; i < rock.meshes.size(); i++) { unsigned int VAO = rock.meshes[i].VAO; glBindVertexArray(VAO); // set attribute pointers for matrix (4 times vec4) glEnableVertexAttribArray(3); glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)0); glEnableVertexAttribArray(4); glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(sizeof(glm::vec4))); glEnableVertexAttribArray(5); glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(2 * sizeof(glm::vec4))); glEnableVertexAttribArray(6); glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(3 * sizeof(glm::vec4))); glVertexAttribDivisor(3, 1); glVertexAttribDivisor(4, 1); glVertexAttribDivisor(5, 1); glVertexAttribDivisor(6, 1); glBindVertexArray(0); } while (!glfwWindowShouldClose(window)) { [...] for (unsigned int i = 0; i < rock.meshes.size(); i++) { glBindVertexArray(rock.meshes[i].VAO); glDrawElementsInstanced(GL_TRIANGLES, rock.meshes[i].indices.size(), GL_UNSIGNED_INT, 0, amount); glBindVertexArray(0); } }

這裡寫圖片描述