Saya punya beberapa kode yang loop melalui satu set objek dan membuat instance dari objek-objek itu. Daftar objek yang perlu dirender disimpan sebagai std :: map>, di mana objek class MeshResource berisi simpul dan indeks dengan data aktual, dan objek classMeshRenderer menentukan titik di ruang mesh yang akan menjadi diberikan pada.
Kode rendering saya adalah sebagai berikut:
glDisable(GL_BLEND);
glEnable(GL_CULL_FACE);
glDepthMask(GL_TRUE);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
for (std::map<MeshResource*, std::vector<MeshRenderer*> >::iterator it = renderables.begin(); it != renderables.end(); it++)
{
it->first->setupBeforeRendering();
cout << "<";
for (unsigned long i =0; i < it->second.size(); i++)
{
//Pass in an identity matrix to the vertex shader- used here only for debugging purposes; the real code correctly inputs any matrix.
uniformizeModelMatrix(Matrix4::IDENTITY);
/**
* StartHere fix rendering problem.
* Ruled out:
* Vertex buffers correctly.
* Index buffers correctly.
* Matrices correct?
*/
it->first->render();
}
it->first->cleanupAfterRendering();
}
geometryPassShader->disable();
glDepthMask(GL_FALSE);
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
Fungsi di MeshResource yang menangani pengaturan seragam adalah sebagai berikut:
void MeshResource::setupBeforeRendering()
{
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glEnableVertexAttribArray(3);
glEnableVertexAttribArray(4);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iboID);
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0); // Vertex position
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*) 12); // Vertex normal
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*) 24); // UV layer 0
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*) 32); // Vertex color
glVertexAttribPointer(4, 1, GL_UNSIGNED_SHORT, GL_FALSE, sizeof(Vertex), (const GLvoid*) 44); //Material index
}
Kode yang membuat objek adalah ini:
void MeshResource::render()
{
glDrawElements(GL_TRIANGLES, geometry->numIndices, GL_UNSIGNED_SHORT, 0);
}
Dan kode yang dibersihkan adalah ini:
void MeshResource::cleanupAfterRendering()
{
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
glDisableVertexAttribArray(3);
glDisableVertexAttribArray(4);
}
Hasil akhir dari ini adalah saya mendapatkan layar hitam, meskipun akhir dari pipa rendering saya setelah kode rendering (pada dasarnya hanya menggambar sumbu dan garis pada layar) bekerja dengan baik, jadi saya cukup yakin itu bukan masalah dengan lewat seragam. Namun, jika saya mengubah kode sedikit sehingga kode rendering memanggil pengaturan segera sebelum rendering, seperti:
void MeshResource::render()
{
setupBeforeRendering();
glDrawElements(GL_TRIANGLES, geometry->numIndices, GL_UNSIGNED_SHORT, 0);
}
Program bekerja seperti yang diinginkan. Saya tidak ingin harus melakukan ini, karena tujuan saya adalah mengatur vertex, material, dll. Data sekali per jenis objek dan kemudian membuat setiap instance hanya memperbarui informasi transformasi.
UniformizeModelMatrix berfungsi sebagai berikut:
void RenderManager::uniformizeModelMatrix(Matrix4 matrix)
{
glBindBuffer(GL_UNIFORM_BUFFER, globalMatrixUBOID);
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(Matrix4), matrix.ptr());
glBindBuffer(GL_UNIFORM_BUFFER, 0);
}
offsetof
ketika menentukan atribut vertexJawaban:
Pertama-tama, OpenGL penuh dengan hal-hal aneh sehingga bug driver, betapapun tidak mungkin, masih merupakan opsi - pertimbangkan untuk menguji aplikasi pada pengaturan yang berbeda (nVidia vs AMD, driver yang lebih tua) dan modifikasi kode kecil lainnya. Misalnya, Anda bisa mulai dengan menghapus "glBindBuffer (GL_UNIFORM_BUFFER, 0);" baris - tampaknya tidak melakukan apa pun yang berguna.
Karena semuanya di sini tampaknya benar, masalahnya kemungkinan besar tidak ada di sini. Ada dua opsi: gDEBugger dan melangkah melalui kode di C ++ debugger. Tampaknya ada sesuatu yang diatur ulang sebelum menggambar. Di gDEBugger, ada fitur "riwayat panggilan" yang dapat membantu Anda melihat panggilan yang dibuat sebelum panggilan undian dan dalam urutan apa.
Ngomong-ngomong, saya sangat menyarankan Anda untuk membungkus setiap panggilan yang mengembalikan kesalahan dengan makro yang memeriksa semua kemungkinan kesalahan dan melemparkannya. Itu harus menjadi makro untuk mendukung debugging yang diperluas (mencetak file, baris dan baris kode yang salah itu sendiri) yang dapat dinonaktifkan dalam rilis rilis. Jika beberapa aturan rahasia dilanggar, pengaturan seperti itu harus segera memperingatkan Anda tentang hal itu.
sumber
Saya cukup yakin bahwa atribut harus mengikat ke buffer saat ini sehingga tidak ada alasan untuk mengulang bisnis ini dengan atribut setiap frame kecuali Anda membangun kembali buffer setiap waktu ....
Jadi, Anda mungkin harus melakukannya dengan satu atau lain cara - baik biarkan saja atau bangun semuanya dalam setiap frame.
sumber
TL; DR: Bug driver.
Dalam tes saya pada hari ini (Oktober 2016) buffer seragam tidak didukung dengan baik oleh sebagian besar pengemudi di luar sana.
Beberapa tidak menghormati
glUniformBlockBinding
beberapa tidak memperbarui data seragam (glBufferSubData
danglBufferData
) dengan benar, di mana shader / GPU cache salinan internal kata buffer tidak dijaga koheren.Cara saya memahaminya (dan cara Nvidia juga memahaminya)
glBindBufferBase
atauglBindBufferRange
.glUniformBlockBinding(shader_id, shader_ubo_index, global_ubo_index);
pengaturan ini adalah per program shader , tidak dibagi secara global.Catatan: global_ubo_index BUKAN nama objek buffer seragam tetapi indeks ke tabel global itu.
"Kompleksitas" ini (yang merupakan fitur hebat untuk berbagi UBO di antara shader yang berbeda, seperti nilai pencahayaan) tampaknya menjadi penyebab sebagian besar driver OpenGL salah. Agar adil, kata-kata dalam dokumentasi OpenGL bukanlah yang paling jelas.
Saya harus menggunakan kembali seragam tua sederhana untuk pengemudi lain.
Kedua tangkapan layar menggunakan objek buffer seragam, dua driver berbeda:
sumber