OpenGL Obyek Obyek Cepat Kesalahan


8

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);
}

Saya memiliki pengaturan yang hampir sama untuk rendering model saya. Kecuali panggilan render saya mengikat buffer dan menetapkan pointer atribut setiap kali. Apakah Anda mengalami masalah kinerja dengan ini? Ini berjalan sangat cepat untuk saya.
MichaelHouse

Saya belum mengalami masalah kinerja kecuali saya memiliki ratusan objek yang sama di layar, tapi tetap saja, saya tidak dapat menemukan apa yang salah di sini, dan akan bagus untuk mengetahui mengapa kode tidak berfungsi seperti yang diharapkan.
HJ Media Studios

1
Kami hanya perlu mendapatkan perhatian dari @NicolBolas dialah ahli OpenGL residen.
MichaelHouse

Mungkin ide yang baik untuk digunakan offsetofketika menentukan atribut vertex
JBeurer

Jawaban:


2

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.


5
Saya akan menghindari tautan ke situs Gremedy. Versi gDEBugger itu kuno dan tidak didukung dan sangat buggy. developer.amd.com/tools/heterogeneous-computing/amd-gdebugger adalah versi terbaru yang didukung AMD, dengan dukungan Windows dan Linux (sayangnya tidak ada OS X). Ada juga beberapa alat debugging / perf GL lainnya yang fantastis di situs AMD, belum lagi alat yang ditawarkan NVIDIA dan Intel.
Sean Middleditch

0

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.


0

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 glUniformBlockBindingbeberapa tidak memperbarui data seragam ( glBufferSubDatadan glBufferData) dengan benar, di mana shader / GPU cache salinan internal kata buffer tidak dijaga koheren.


Cara saya memahaminya (dan cara Nvidia juga memahaminya)

  • Bind / Petakan Objek Penyangga Seragam Anda ke tabel global yang dibagikan oleh semua shader di dalam driver OpenGL / GPU menggunakan glBindBufferBaseatau glBindBufferRange.
  • Memetakan akses penyangga seragam shader ke entri ke tabel global menggunakan 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:

Bug Penyangga Seragam


Driver apa yang Anda uji? Platform apa?
akaltar
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.