2012-01-16 2 views
5

Tengo una escena que se renderiza en textura a través de FBO y la muestro desde un sombreador de fragmentos, dibujando regiones de primitivas en lugar de dibujar un cuadrante de pantalla completa: Conservo recursos generando solo los fragmentos que necesitaré.La búsqueda de texturas en FBO renderizado está desactivada en medio píxel

Para probar esto, estoy emitiendo exactamente la misma geometría que mi textura-render, lo que significa que el patrón de rasterización producido debería ser exactamente el mismo: cuando mi fragmento sombreador busca su textura con la coordenada variable que se le dio debe coincidir perfectamente con los otros valores que se le dio.

Así es como yo estoy dando mi fragmento shader las coordenadas para auto-textura de la geometría con la textura de mi pantalla completa:

// Vertex shader 
uniform mat4 proj_modelview_mat; 
out vec2 f_sceneCoord; 
void main(void) { 
    gl_Position = proj_modelview_mat * vec4(in_pos,0.0,1.0); 
    f_sceneCoord = (gl_Position.xy + vec2(1,1)) * 0.5; 
} 

estoy trabajando en 2D, así que no me ocupo de la brecha perspectiva aquí. Acabo de establecer el valor de sceneCoord utilizando la posición del espacio de recorte reducida desde [-1,1] a [0,1].

uniform sampler2D scene; 
in vec2 f_sceneCoord; 
//in vec4 gl_FragCoord; 
in float f_alpha; 
out vec4 out_fragColor; 
void main (void) { 
    //vec4 color = texelFetch(scene,ivec2(gl_FragCoord.xy - vec2(0.5,0.5)),0); 
    vec4 color = texture(scene,f_sceneCoord); 
    if (color.a == f_alpha) { 
     out_fragColor = vec4(color.rgb,1); 
    } else 
     out_fragColor = vec4(1,0,0,1); 
} 

Aviso Escuché un fragmento rojo si mis alfa no coinciden. El procesamiento de texturas establece el valor alfa para cada objeto renderizado en un índice específico, de modo que sé qué coincide con qué.

Lo siento, no tengo una imagen para mostrar, pero está muy claro que mis píxeles están desactivados por (0.5,0.5): obtengo un borde rojo fino de un píxel alrededor de mis objetos, en sus lados inferior y izquierdo, que aparece y fuera. Es bastante "transitorio". El sorteo es que solo aparece en los lados inferior y izquierdo de los objetos.

Aviso Tengo una línea comentada que usa texelFetch: Este método funciona, y ya no aparece mi fragmento rojo. Sin embargo, me gustaría que funcione correctamente con texture y coordenadas de textura normalizadas porque creo que habrá más hardware que lo soporte. Tal vez la verdadera pregunta es, ¿es posible hacerlo bien sin enviar mi resolución de la vista a través de un uniforme? ¡Debe haber una manera de evitar eso!

Actualización: Intenté cambiar el acceso a la textura por medio píxel, un cuarto de píxel, una centésima de píxel, todo empeoró y produjo un borde sólido de valores incorrectos en todos los bordes: parece que mi gl_Position.xy+vec2(1,1))*0.5 truco establece los valores correctos, pero el muestreo se acaba un poco de alguna manera. Esto es bastante extraño ... ¿Ves los fragmentos rojos? Cuando los objetos están en movimiento, brillan dentro y fuera ligeramente. Significa que los valores alfa que establecí no coinciden perfectamente en esos píxeles.

transient red fragments indicate a texture sampling mis-match

No es crítico para que consiga una precisión de píxel perfecto para que la alfa-index-check para mi aplicación real, pero este comportamiento no es justo lo que esperaba.

Respuesta

4

Bueno, primero que considerar abandonar f_sceneCoord variable y sólo usar gl_FragCoord/screenSize como la textura de coordenadas (que ya tiene esto en su ejemplo, pero el -0.5 es basura), con screenSize ser un uniforme (tal vez pre-dividido). Esto debería funcionar casi exactamente, porque por defecto gl_FragCoord está en el centro de píxeles (es decir, i+0.5) y OpenGL devuelve valores de texel exactos cuando se muestrea la textura en el centro de texel ((i+0.5)/textureSize).

Esto todavía puede presentar desviaciones muy muy muy leves de los valores de texel exactos (si los hay) debido a la precisión finita y tal.Pero, de nuevo, es probable que desee utilizar un modo de filtrado de GL_NEAREST para tales correspondencias uno a uno de textura a pantalla, de todos modos. De hecho, su enfoque f_sceneCoord existente puede funcionar bien y son solo esos pequeños problemas de redondeo evitados por GL_NEAREST que crean sus artefactos. Pero, de nuevo, todavía no necesitas esa cosa f_sceneCoord.

EDITAR: En cuanto a la portabilidad de texelFetch. Esa función se introdujo con GLSL 1.30 (~ SM4/GL3/DX10-hardware, ~ GeForce 8), creo. Pero esta versión ya es requerida por la nueva sintaxis in/out que está usando (a diferencia de la antigua sintaxis varying/attribute). Entonces, si no los va a cambiar, asumir texelFetch como se indica no es ningún problema y también puede ser ligeramente más rápido que texture (que también requiere GLSL 1.30, en contraste con el antiguo texture2D), eludiendo completamente el filtrado.

+0

Gracias por la crianza de GL_NEAREST. Es probable que resuelva el problema porque puedo ver cómo el filtrado lineal con un error de precisión muy ligeramente diferente puede hacer que mi cheque falle. Voy a intentar esa primera oportunidad que tengo. Encuentro que mi solución 'f_sceneCoord' es más elegante que usar' FragCoord' y un tamaño de pantalla uniforme: funciona independientemente de que tenga que hacer un seguimiento de un tamaño de pantalla uniforme ... Menos complejidad siempre es buena. –

+0

¡Ojalá pudiera votar más de una vez! Tener un voto positivo y un aceptar. –

+0

Sí, intenté depurar con glslDevil y me requirió volver a la sintaxis 1.2, así que lo cambié todo de nuevo a 'variante/atributo' y 'textura2D' ... glslDevil todavía no me muestra ningún valor. De todos modos, eso no importa, lo que es bueno es 'GL_NEAREST' produce resultados perfectos. Resulta que en mi implementación real todavía necesitaré usar 'GL_LINEAR' de todos modos para que las cosas se vean sin problemas, pero estoy muy contento de haber llegado al fondo de esto. –

1

Si trabaja en perfecto X, Y [0,1] sin errores de redondeo, eso es genial ... Pero a veces, especialmente si trabaja con coords polares, puede considerar alinear los coords calculados con la textura 'rejilla' ...

que utilizo:

// align it to the nearest centered texel 
curPt -= mod(curPt, (0.5/vec2(imgW, imgH))); 

funciona de maravilla y ya no obtiene errores de redondeo al azar en los bordes de la pantalla ...

Cuestiones relacionadas