Uma abordagem possível poderia ser o uso da consulta de oclusão de hardware.
Você pode usar os fatos de que, por especificação, o Teste de Estêncil é executado antes do teste de profundidade, e apenas os fragmentos que passam no teste de profundidade são contados pela Consulta de Oclusão.
Um exemplo simples (não testado) seria como:
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);
Observe que a chamada para obter o número de amostras chamará forçosamente a liberação do pipeline e aguardará a conclusão da consulta. Se você precisar de uma abordagem mais assíncrona, poderá consultar se a consulta de oclusão foi feita ou não usando:
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?