Tengo algunos problemas para representar un montón de valores en un rendertarget. Los valores nunca terminan en el rango exacto que quiero. Básicamente, utilizo un quad de pantalla completa y un sombreador de píxeles para representar mi textura de renderizado y luego intento usar las coordenadas de textura como base para algunos cálculos en el sombreador. Las coordenadas de textura del rango cuádruple van desde (0,0) en la esquina superior izquierda hasta (1,1) en la esquina inferior derecha ... el problema es que, después de la interpolación, estos valores no llegan al sombreador de píxeles como tal .
Un ejemplo: renderizo a una textura 4x4 y el sombreador en este caso simplemente muestra las coordenadas de textura (u, v) en los canales rojo y verde:
return float4(texCoord.rg, 0, 1);
Lo que quiero obtener es una textura donde el píxel en la parte superior izquierda es RGB (0,0,0) y, por lo tanto, negro, el píxel en la parte superior derecha es RGB (255,0,0) y, por lo tanto, un brillo rojo y el píxel en la parte inferior izquierda es RGB (0,255,0), un verde brillante.
Sin embargo, en cambio obtengo esto aquí a la derecha:
(representación cuádruple recta, sin corrección)
El píxel superior izquierdo es negro, pero solo obtengo un rojo relativamente oscuro y un verde oscuro en las otras esquinas. Sus valores RGB son (191,0,0) y (0,191,0). Sospecho fuertemente que tiene que ver con las ubicaciones de muestreo del quad: el píxel superior izquierdo muestrea correctamente la esquina superior izquierda del quad y obtiene (0,0) como coordenadas UV, pero los otros píxeles de la esquina no toman muestras Las otras esquinas del patio. He ilustrado esto en la imagen izquierda con el cuadro azul que representa el quad y los puntos blancos las coordenadas de muestreo superiores.
Ahora sé sobre el desplazamiento de medio píxel que debe aplicar a sus coordenadas al representar quads alineados con la pantalla en Direct3D9. Veamos qué tipo de resultado obtengo de esto:
(quad renderizado con el desplazamiento de medio píxel de DX9)
El rojo y el verde se han vuelto más brillantes pero aún no son correctos: 223 es el máximo que obtengo en el canal de color rojo o verde. Pero ahora, ya ni siquiera tengo negro puro, ¡sino un gris oscuro amarillento con RGB (32,32,0)!
Lo que realmente necesito sería este tipo de renderizado:
(renderizado objetivo, tamaño cuádruple reducido)
Parece que tengo que mover el borde derecho e inferior de mi quad exactamente un píxel hacia arriba y hacia la izquierda, en comparación con la primera figura. Entonces, la columna derecha y la fila inferior de píxeles deberían obtener correctamente las coordenadas UV directamente desde el borde del quad:
VertexPositionTexture[] quad = new VertexPositionTexture[]
{
new VertexPositionTexture(new Vector3(-1.0f, 1.0f, 1f), new Vector2(0,0)),
new VertexPositionTexture(new Vector3(1.0f - pixelSize.X, 1.0f, 1f), new Vector2(1,0)),
new VertexPositionTexture(new Vector3(-1.0f, -1.0f + pixelSize.Y, 1f), new Vector2(0,1)),
new VertexPositionTexture(new Vector3(1.0f - pixelSize.X, -1.0f + pixelSize.Y, 1f), new Vector2(1,1)),
};
Sin embargo, esto no funcionó del todo y causó que los píxeles inferiores y derechos no se representaran en absoluto. Supongo que los centros de estos píxeles ya no están cubiertos por el quad y, por lo tanto, el sombreador no los procesará. Si cambio el cálculo de pixelSize en una pequeña cantidad para hacer que el quad sea un poco más grande, funciona un poco ... al menos en una textura 4x4. No funciona en texturas más pequeñas y me temo que distorsiona sutilmente la distribución uniforme de los valores uv en texturas más grandes también:
Vector2 pixelSize = new Vector2((2f / textureWidth) - 0.001f, (2f / textureHeight) - 0.001f);
(Modifiqué el cálculo de pixelSize en 0.001f - para texturas más pequeñas, por ejemplo, tablas de búsqueda 1D, esto no funciona y tengo que aumentarlo a 0.01f o algo más grande)
Por supuesto, este es un ejemplo trivial y podría hacer este cálculo mucho más fácilmente en la CPU sin tener que preocuparme por mapear los rayos UV a los centros de píxeles ... aún así, tiene que haber una manera de representar un completo, completo [0, 1] rango a píxeles en un rendertarget?