Apakah mungkin untuk mengetahui berapa banyak fragmen yang berhasil melalui uji stensil?

11

Saya memiliki aplikasi OpenGL yang menggunakan tes stensil cukup luas untuk membuat bentuk tidak teratur (sedikit seperti CSG 2-D sederhana ). Jika saya bisa mengetahui berapa banyak fragmen yang lulus uji stensil dan benar-benar diberikan, ini akan sangat membantu dalam menyederhanakan beberapa perhitungan di telepon. Secara khusus, ini akan memungkinkan saya untuk menentukan area bentuk yang diberikan secara gratis daripada harus memperkirakannya dengan simulasi Monte Carlo nanti.

Saya tahu bahwa ada konsep serupa untuk primitif yang dipancarkan dari geometri shader, yang disebut umpan balik transform . Saya ingin tahu apakah ada konsep serupa untuk fragmen dan uji stensil.

Martin Ender
sumber
Solusi kasar adalah dengan hanya melukis satu warna kontras ke yang lain melalui stensil, simpan buffer itu, dan hitung jumlah piksel yang diubah.
TheBuzzSaw
Hmm, spesifikasinya mengatakan query occulsion menghitung jumlah fragmen yang lulus uji kedalaman , tapi dari atas kepala saya, saya tidak yakin bagaimana itu berinteraksi dengan tes stensil sekarang.
Chris mengatakan Reinstate Monica
@ChristianRau Tampaknya hanya fragmen yang lolos tes kedalaman yang akan dihitung, tetapi uji stensil, buang, dan alfa diabaikan.
Maurice Laveaux
2
@ChristianRau dan Maurice, spesifikasi ARB_occlusion_query yang asli secara eksplisit mengatakan menghitung sampel yang melewati kedua tes kedalaman dan stensil. Lihat juga pertanyaan StackOverflow ini .
Nathan Reed
@NathanReed Kedengarannya Anda akan menulis jawaban.
Chris berkata Reinstate Monica

Jawaban:

10

Salah satu pendekatan yang mungkin adalah penggunaan Query Occlusion Perangkat Keras.

Anda dapat menggunakan fakta bahwa, berdasarkan spesifikasi, Uji Stensil dieksekusi sebelum uji kedalaman, dan hanya fragmen yang lolos uji kedalaman yang dihitung oleh Query Occlusion.

Contoh sederhana (tidak diuji) akan seperti:

    GLuint samples_query = 0;
    GLuint samples_passed = 0;
    glGenQueries(1, &samples_query);
    // Initialize your buffers and textures ...
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_STENCIL_TEST);

    // Set up the values on the stencil buffer ...

    // Now we count the fragments that pass the stencil test
    glDepthFunc(GL_ALWAYS); // Set up the depth test to always pass
    glBeginQuery(GL_SAMPLES_PASSED, samples_query);
    // Render your meshes here
    glEndQuery(GL_SAMPLES_PASSED);
    glGetQueryObjectuiv(samples_query, GL_QUERY_RESULT, &samples_passed);
    // samples_passed holds the number of fragments that passed the stencil test (if any)

    // Release your resources ...
    glDeleteQueries(1, &samples_query);

Perhatikan bahwa panggilan untuk mendapatkan jumlah sampel akan memanggil secara paksa flush dari pipeline dan menunggu pertanyaan selesai. Jika Anda memerlukan pendekatan yang lebih asinkron, Anda dapat menanyakan apakah permintaan oklusi selesai atau tidak dengan menggunakan:

    GLuint query_done = 0;
    glGetQueryObjectuiv(samples_query, GL_QUERY_RESULT_AVAILABLE, &query_done);
    if (query_done != 0)
        // Your query result is ready
    else
        // Maybe check the next frame?
Matteo Bertello
sumber
2

Jika yang Anda minati adalah area, Anda dapat memperkecil ukuran buffer stensil hingga Anda mencapai satu piksel dan menyimpulkan area itu dari warnanya.

Langkah-langkahnya adalah:

  • Salin stensil ke tekstur, menggunakan format dengan ketepatan yang cukup.
  • Memuat shader yang menghasilkan warna yang sebanding dengan jumlah texel dengan warna yang diberikan.
  • Lakukan ping-pong di antara framebuffer untuk memperkecil ukurannya hingga mencapai satu piksel.
  • Warna piksel adalah persentase viewport yang dicakup oleh area: cukup gandakan dengan area viewport.
Julien Guertault
sumber