2012-05-26 17 views
9

enter image description herepíxeles en Direct2D

se supone que las líneas de color gris oscuro a ser de color negro y 1 píxel de ancho:

pRT->DrawLine(Point2F(100, 120), Point2F(300, 120), blackbrush, 1); 

Las líneas de color gris claro se supone que son negro y 0,5 píxel de ancho:

pRT->DrawLine(Point2F(120, 130), Point2F(280, 130), blackbrush, 0.5); 

En cambio, ambos tienen 2 píxeles de ancho. Si solicito 2 píxeles de ancho, la línea es negra, pero naturalmente de 2 píxeles de ancho.

El objetivo de renderizado tiene el mismo tamaño que el área de cliente de la ventana. Me gustaría la precisión de píxeles como en GDI, una coordenada = un píxel y colores puros ...

Gracias.

Respuesta

13

Direct2D está prestando correctamente. Cuando le da una coordenada de píxel como (100, 120), que se refiere a la esquina superior e izquierda del elemento de píxel que se extiende desde las coordenadas de píxel (100, 120) a (101, 121) (arriba/izquierda son inclusivas, derecha/abajo son exclusivos). Como se trata de una línea horizontal recta, está obteniendo efectivamente un rectángulo relleno de (99.5, 119.5) - (300.5, 120.5). Dado que los bordes de este derrame en píxeles adyacentes, es por eso que está obteniendo líneas de "2 píxeles de ancho" con el brillo "incorrecto". Debe pensar en términos de las coordenadas de píxeles (puntos sin área) y los elementos de píxeles (puntos físicos en la pantalla con un área de 1x1, o simplemente 1 por supuesto).

Si desea dibujar una línea recta que cubra los píxeles (100, 120) a (300, 120), debe usar la sugerencia de SemMike de usar un renderizado con alias (¡lo cual es ideal para líneas rectas!) O puede usar desplazamientos de medio píxel (porque strokeWidth = 1; para otros Anchos de trazo, ajustar por trazo Anchura/2). Dibujar desde (100.5, 120.5) - (299.5, 120.5) con un ancho de trazo de 1.0 obtendrá lo que está buscando. Ese trazo se extiende alrededor de las coordenadas de píxeles que especifique, por lo que obtendrá el "rectángulo relleno" sobre los elementos de píxeles (100, 120) - (300, 121). Y de nuevo, ese es un rango exclusivo, por lo que 'y = 121' no está realmente lleno, tampoco x = 300.

Si se está preguntando por qué esto no sucede con algo como GDI, es porque no hace una representación antialias, por lo que todo siempre se ajusta a elementos de píxeles. Si se pregunta por qué esto no sucede con WPF al usar Shapes, es porque usa el redondeo de diseño (UseLayoutRounding) y el ajuste de píxeles. Direct2D no proporciona esos servicios porque es una API de nivel relativamente bajo.

+0

Gracias por la explicación, tiene sentido. ¿Extrañé esto en los documentos de MSDN en Direct2D en alguna parte o no está allí y se suponía que debía saberlo? "Dibujar desde (100.5, 120.5) - (299.5, 120.5) con un ancho de trazo de 1.0 obtendrá lo que está buscando" Si lo entiendo correctamente, eso sería (100.5, 120.5) - (300.5, 120.5) . De lo contrario, se omite el último píxel de la línea. Por cierto, "sugerencia de SemMike": el mismo tipo, estaba respondiendo mi propia pregunta ... – SemMike

+0

Si usa 299.5 o 300.5 depende de si desea una línea de 200px de ancho o una de 201px. Y esto probablemente no esté en los documentos porque es bastante estándar para las modernas API de gráficos en 2D, pero también es un poco obvio y avanzado, y a menudo las personas que están trabajando en cosas avanzadas olvidan lo que no sabían antes de serlo. eso avanzado. Me parece útil pensar en ello como una hoja de papel cuadriculado. Donde las líneas horizontales y verticales se cruzan son las coordenadas de píxel entero, y los cuadrados entre ellas son los elementos de píxel "físicos". –

5

Puedes jugar con pRenderTarget->DrawLine(Point2F(100-0.5, 120-0.5), Point2F(300-0.5, 120-0.5), blackbrush, 1), pero se vuelve rápidamente difícil. La más sencilla es:

pRenderTarget->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED); 

espero que ayude a alguien ...

+0

No recomendaría evitar la imagen mental correcta. En el momento en que necesite antialias o dibuje una forma que no sea una línea alineada con el eje, su código (escrito en una suposición mental incorrecta) lo confundirá. Esto es estándar, lo mismo para GDI + también. – jnm2

+0

Excepto en DX11, las coordenadas de texel están orientadas al punto medio, por lo que no es tan "estándar" como lo era antes. –