È possibile scoprire quanti frammenti hanno superato il test dello stencil?


11

Ho un'applicazione OpenGL che utilizza test di stencil abbastanza ampiamente per il rendering di forme irregolari (un po 'come un semplice CSG 2-D ). Se potessi scoprire quanti frammenti hanno superato il test dello stencil e sono stati effettivamente resi, questo sarebbe molto utile nel semplificare alcuni calcoli lungo la linea. In particolare, mi consentirebbe di determinare gratuitamente l'area della forma renderizzata invece di doverla approssimare con una simulazione Monte Carlo in seguito.

So che esiste un concetto simile per i primitivi emessi dallo shader della geometria, chiamato feedback di trasformazione . Vorrei sapere se esiste un concetto simile per i frammenti e il test dello stencil.


Una soluzione rozza sarebbe quella di dipingere un colore contrastante su un altro attraverso lo stencil, salvare quel buffer fuori e contare il numero di pixel che sono stati modificati.
TheBuzzSaw

Hmm, la specifica dice che le domande di occlusione contano il numero di frammenti che superano il test di profondità , ma dalla parte superiore della mia testa non sono sicuro di come questo interagisca con il test di stencil in questo momento.
Chris dice di reintegrare Monica il

@ChristianRau Sembra che verranno conteggiati solo i frammenti che superano i test di profondità, ma i test di stencil, scarto e alfa vengono ignorati.
Maurice Laveaux,

2
@ChristianRau e Maurice, la specifica originale ARB_occlusion_query afferma esplicitamente che conta i campioni che superano sia i test di profondità che quelli di stencil. Vedi anche questa domanda StackOverflow .
Nathan Reed,

@NathanReed Sembra che stai per scrivere una risposta.
Chris dice di reintegrare Monica il

Risposte:


10

Un possibile approccio potrebbe essere l'uso di Hardware Occlusion Query.

È possibile utilizzare i fatti che, per specifica, lo Stencil Test viene eseguito prima del test di profondità e solo i frammenti che superano il test di profondità vengono conteggiati dalla Query Occlusione.

Un semplice esempio (non testato) sarebbe come:

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

Si noti che la chiamata per ottenere il numero di campioni chiamerà forzatamente il flush della pipeline e attenderà il completamento della query. Se è necessario un approccio più asincrono, è possibile eseguire una query se la query di occlusione viene eseguita o meno utilizzando:

    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?

2

Se quello che ti interessa è l'area, puoi ridimensionare il buffer dello stencil fino a raggiungere un pixel e dedurre quell'area dal suo colore.

I passaggi sarebbero:

  • Copia lo stencil su una trama, usando un formato con sufficiente precisione.
  • Carica uno shader che genera un colore proporzionale al numero di texel con un determinato colore.
  • Ping-pong tra i framebuffer per ridurre le dimensioni della metà fino a raggiungere un pixel.
  • Il colore del pixel è la percentuale della finestra coperta dall'area: basta moltiplicarla per l'area della finestra.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.