E N D
1. Gráficas Interactivas Isaac Rudomín (Instructor)
rudomin@itesm.mx
Erik Millán (asistente)
emillan@itesm.mx
2. Rasterización
Aliasing
Recorte
3. Rasterización Líneas
Triángulos
Polígonos
4. Rasterización: Que es? Como ir de los números reales de las coordenadas de los vértices de las primitivas a las coordenadas enteras de los pixeles en pantalla
Primitivas geométricas
Puntos: redondear locación del vértice en coordenadas de pantalla
Líneas: OK para puntos extremos, pero que hacemos en medio?
Polígonos: Como lleno área acotada por aristas?
5. Rasterizando líneas: metas Dibuja pixeles tan cerca como sea posible de la línea ideal
Usand el mínimu número de pixeles sin dejar huecos
Hacerlo eficientemente
Extras
Diferentes estilos de líneas
Anchura
Punteado
Estilos de uniones para líneas conectadas
Minimizar aliasing (“escalerillas”)
6. Dibujo de líneas mediante DDA DDA significa “Digital Differential Analyzer”, que es el nombre de unos plotters que existían antiguamente
Forma pendiente-intersección de la línea:
y = mx + b
m = dy/dx
b es donde la línea intersecta al eje Y
La idea básica del DDA: Si incrementamos la coordenada x por 1 pixel en cada paso, la pendiente de la línea nos dice cuanto incrementar y por paso
Es decir m = dy/dx, por lo que para
dx = 1, dy = m
Esto solo funciona si m <1— sino hay huecos
Solución: intercambia los ejes y avanza en dirección Y pues entonces dy = 1, obtenemos dx = 1/m
7. Dibujo de líneas mediante DDA DDA significa “Digital Differential Analyzer”, que es el nombre de unos plotters que existían antiguamente
Forma pendiente-intersección de la línea:
y = mx + b
m = dy/dx
b es donde la línea intersecta al eje Y
La idea básica del DDA: Si incrementamos la coordenada x por 1 pixel en cada paso, la pendiente de la línea nos dice cuanto incrementar y por paso
Es decir m = dy/dx, por lo que para
dx = 1, dy = m
Esto solo funciona si m <1— sino hay huecos
Solución: intercambia los ejes y avanza en dirección Y pues entonces dy = 1, obtenemos dx = 1/m
8. DDA: Algoritmo Dados puntos extremos (x0, y0), (x1, y1)
Coordenadas enteras: Redondea si los endpoints fueron originalmente de valor real
Supon (x0, y0) a la izquierda de (x1, y1): Intercambia en caso contrario
Entonces calculamos pendientes no negativas:
m = dy/dx = (y1 ¡ y0) / (x1 ¡ x0)
Itera
If m <= 1: Itera entero x de x0 a x1, incrementando por 1 cada paso
Inicializa real y = y0
Agregale m a y en cada paso y dibuja punto (x, round(y))
Si m > 1: Itera entero y desde y0 a y1, incrementando por 1
Inicializa real x = x0
Agregale 1/m a x en cada paso y dibuja punto (round(x), y)
9. DDA: Notas Pendientes negativas por simetría
Es decir, rota 90 grados a favor del reloj para iterar:
(x, y) ! (y, ¡x)
Trata como caso normal
Rota de vuelta para dibujar
DDA es lento
Cálculo de punto flotante y redondeo son relativamente caros
10. Algoritmo de punto medio Midpoint (Bresenham) para dibujar líneas Idea básica: Evita redondear, hacer todo con aritmética de enteros para velocidad
Supon pendiente entre 0 y 1
Otra vez usar simetría para líneas con otras pendientes
11. Dibujando líneas con punto medio: la ecuación La forma de pendiente-intersección de la ecuación de la línea es y = (dy/dx)x + b
Multiplicando por dx, queda:
F(x, y) = dy x - dx y + dx b = 0
F es:
Cero para puntos en la línea
Positiva para puntos bajo la línea (a la derecha si pendiente > 1)
Negativa para puntos sobre la línea (izquierda si pendiente > 1)
Ejemplos: (0, 1), (1, 0), etc.
12. Dibujando líneas con punto medio: la decisión Dadas nuestras suposiciones sobre la pendiente, después de dibujar (x, y) el siguiente pixel puede ser
o bién el superior U = (x + 1, y + 1)
o bién el inferior L = (x + 1, y)
13. Dibujando líneas con punto medio: la decisión Despues de dibujar (x, y), para escoger el siguiente pixel a dibujar consideramos el punto medio M = (x + 1, y + 0.5)
Si está en la línea, U y L son equidistantes de la línea
Si está bajo la línea, U es mas cercano a la línea que L
Si está sobre la línea, L es mas cercano que U.
14. Dibujando líneas con punto medio: la decisión entonces F es una función de decisión acerca de que pixel dibujar:
Si F (M ) = F (x + 1, y + 0.5 ) > 0 (M bajo la línea), escogemos U
Si F (M ) = F (x + 1, y + 0.5 ) <= 0 (M sobre o en la l[inea), escogemos L
15. Dibujando líneas con punto medio: implementación Por eficiencia: F no necesariamente debe ser evaluada por completo en cada paso
Si evaluamos por completo y obtenemos F(x + 1, y + 0.5)
Si escogemos L, el próximo punto medio, M0 está en F(x + 2, y + 0.5)
Si escogemos U, el próximo punto medio, M00 está en F(x + 2, y + 1.5)
16. Dibujando líneas con punto medio: implementación Por eficiencia: F no necesariamente debe ser evaluada por completo en cada paso
Si evaluamos por completo y obtenemos F(x + 1, y + 0.5)
Si escogemos L, el próximo punto medio, M0 está en F(x + 2, y + 0.5)
Si escogemos U, el próximo punto medio, M00 está en F(x + 2, y + 1.5)
17. Dibujando líneas con punto medio: implementación Por eficiencia: F no necesariamente debe ser evaluada por completo en cada paso
Si evaluamos por completo y obtenemos F(x + 1, y + 0.5)
Si escogemos L, el próximo punto medio, M0 está en F(x + 2, y + 0.5)
Si escogemos U, el próximo punto medio, M00 está en F(x + 2, y + 1.5)
18. Dibujando líneas con punto medio: implementación Expandiendo esto utilizando using F(x, y) = dy x - dx y + dx b :
FM = F(x + 1, y + 0.5) = dy(x + 1) - dx(y + 0.5) + dx b
FM0 = F(x + 2, y + 0.5) = dy(x + 2) - dx(y + 0.5) + dx b
FM00 = F(x + 2, y + 1.5) = dy(x + 2) - dx(y + 1.5) + dx b
Nota que FM0 ¡ FM = dy y FM00 ¡ FM = dy - dx
Asi que dependiendo si escogemos L o U, solo debemos agregar dy o dy - dx, respectivemente, al viejo valor de F para obtener el nuevo valor
19. Dibujando líneas con punto medio: algoritmo Para inicializar, calculamos F en el primer punto medio junto al punto extremo izquierdo:
F(x0 + 1, y0 + 0.5) = dy(x0 + 1) - dx(y0 + 0.5) + dx b
= dy x0 ¡- dx y0 + dx b + dy - 0.5 dx
= F(x0, y0) + dy - 0.5 dx
pero F(x0, y0) = 0 pues está sobre la línea, asi que la primera F =dy-0.5 dx
Solo importa el signo para la decisió, asi que para que sea un valor entero, multiplicamos por 2 y obtenemos 2F = 2 dy - dx
Para actualizar, se requiere conocer el valor actual para x y y y un valor parar F:
Si escojo L: F += 2dy y x++
Si escojo U: F += 2(dy - dx) y x++ , y++
20. Velocidad de dibujo de líneas 100,000 líneas al azar en ventana 500 x 500
DDA: 6.8 segundos
Midpoint: 2.5 segundos
OpenGL usando GL_LINES (en software): 1.6 segundos
21. Rasterizando Polígonos En gráficas interactivas, los polígonos dominan
Dos razonesTwo main reasons:
Mínimo denominador común
Pueden representar o aproximar cualquier superficie
Simplicidad matemática que permite algoritmos sencillos y regulares, que pueden ser implementados en hardware
22. Rasterizando Triángulos El triángulo es polígono mínimo
Todos los polígonos pueden descomponerse en triángulos
Convexos, concavos, complejos
Los triángulos son siempre:
Planos
Convexos
Que es ser convexo?
23. Formas Convexas Una forma bidimensional es convexa si y solo si cualquier segmento conectando dos puntos en la frontera está contenido por completo en la forma.
24. Formas Convexas Porque queremos formas convexas para rasterizar?
Una respuesta: porque cualquier línea de scan está garantizada a contener a lo mas un segmento o span de un triángulo
25. Decomponer Polis a Tris Cualquier polígono convexo se descompone trivialmente en triángulos
Los polígonos concavos o complejos también, aunque no es trivial
26. Rasterizar triángulos Caso especial de polígonos
Exactamente dos aristas activas en cualquier momento
Un método:
Llena tabla de la línea de scan entre vértice superior e inferior usando los algoritmos DDA o punto medio para seguir las aristas
Hacer travesía de la tabla línea de scan por línea de scan, llenando de izquierda a derecha
27. Rasterizar triángulos Hardware para gráficas interactivas usa comúnmente las técnicas de edge walking o edge equation
Hay otras técnicas:
Subdivisión recursiva de primitivas a micropolígonos (REYES, Renderman)
Subdivisión recursiva de pantalla (Warnock)
28. Subdivisión recursiva de triángulos
29. Subdivisión recursiva de pantalla
30. Seguimiento de aristas Basicamente:
Dibuja aristas verticalmente
LLena spans horizontales para cada línea de scan
Interpola colores a lo largo de las aristas
En cada línea de scan, interpola colores de arista a través del span
Notas:
Muy rápido
Tiene algunos problemas con casos especiales
Puede haber huecos entre aristas adyacentes
31. Ecuaciones de aristas (edge equations) Un edge equation es simplemente la ecuación de la línea que contiene esa arista
Edge equations definen dos medios espacios:
32. Edge Equations Un triángulo puede definirse como la intersección de tres medios espacios positivos:
33. Edge Equations Basta encenderlos pixeles para los cuales todas las edge equations evalúan a > 0:
34. Uso de Edge Equations Como hacer esto en hardware?
Como lo harías en software?
35. Uso de Edge Equations Que pixeles?: calcula caja acotante min,max (fácil)
Edge equations: calcúla a partir de vértices, con área positiva
Problemas numéricos (aquí lo dejamos)
36. Edge Equations: Código Basic amente:
Setup: calcular edge equations, bounding box
(loop externo) Para cada línea de scan en BB
(loop interno) …checa cada pixel en línea de scan, evaluando las ecuaciones y dibujando el pixel si las tres son positivas
37. Optimiza esto! findBoundingBox(&xmin, &xmax, &ymin, &ymax);
setupEdges (&a0,&b0,&c0,&a1,&b1,&c1,&a2,&b2,&c2);
/* Optimize this: */
for (int y = yMin; y <= yMax; y++) {
for (int x = xMin; x <= xMax; x++) {
float e0 = a0*x + b0*y + c0;
float e1 = a1*x + b1*y + c1;
float e2 = a2*x + b2*y + c2;
if (e0 > 0 && e1 > 0 && e2 > 0) setPixel(x,y);
}
}
38. Rasterización de polígonos Dado un conjunto de vértices, rellenar el interior
Básicamente:
Itera sobre líneas de scan entre vértice superior e inferior
Para cada línea de scan, encuentra todas las intersecciones con aristas de polígonos
Ordena intersecciones por valor en x y llena de pixeles entre pares de intersecciones non y par
39. Rasterización de polígonos: Notas Refinnamientos
Mantener paridad correcta descartando intersecciones con puntos extremos superiores de cualquier arista
Evita dibujar doblemente las fronteras de polígonos adyacentes (es malo si hay blending o XOR) siguiendo la regla de pertenencia izquierda-abajo:
Dibuja pixel en arista izquierda pero no en derecha
Descarta intersecciones con aristas horizontales
40. Rasterización de polígonos Básicamente: usar prueba de paridad
for each scanline
edgeCnt = 0;
for each pixel on scanline (l to r)
if (oldpixel->newpixel crosses edge)
edgeCnt ++;
// draw the pixel if edgeCnt odd
if (edgeCnt % 2)
setPixel(pixel);
41. Tabla de aristas activas Idea:
Aristas que intersectan una línea de scan, probablemente intersectan la próxima
Entre líneas de scan consecutivas, el órden de las intersecciones con aristas probablemente no cambie mucho
42. Tabla de aristas activas Algoritmo:
Sort de aristas por coordenada y mínima
Comenzando abajo, agrega aristas con Ymin= 0 a la tabla
Para cada línea de scan:
Sort de aristas en tabla por intersección x
Ve de izquierda a derecha, dibujando pixeles según regla de paridad
Incrementa línea de scan
Quita aristas con Ymax < Y
Agrega aristas con Ymin > Y
Recalcula intersecciones de aristas y vuelve a ordenar (como hacerlo eficientemente?)
Para cuando Y > Ymax para las últimas aristas
43. Aliasing y anti Aliasing
44. Aliasing y Antialiasing Aliasing: término de procesamiento de señales con significado preciso
Aliasing: término en gráficas computacionales para cualquier artefacto visual no deseado
Antialiasing: término en gráficas computacioneales para el combate a los artefactos no deseados
Veremos estos en órden
45. Procesamiento de señales Dispositivo Raster: muestras regulares de una función continua
Piensa en una función 1-D:
46. Procesamiento de señales Muestra de función 1-D:
47. Procesamiento de señales Muestra de función 1-D:
48. Procesamiento de señales Muestra de función 1-D:
Que notas?
49. Procesamiento de señales Muestra de función 1-D:
Que notas?
No es suave
50. Procesamiento de señales Muestra de función 1-D:
Que notas?
No es suave
Pierde información!
51. Procesamiento de señales Muestra de función 1-D:
Que notas?
No es suave
Pierde información!
Que podemos hacer?
Reconstrucción de mayor órden
Usar mas muestras
Cuantas muestras mas?
52. El teorema de muestreo Obviamente, entre mas muestras, mejor aproximamos la función inicial
El teorema:
Una función continua limitada en banda, puede ser completamente representada por un conjunto de muestras regulares, si estas ocurren a más del doble de la frecuencia, del componente de máxima frecuencia de la función.
53. El teorema de muestreo En otras palabras, para representar adecuadamente una función cuya máxima frecuencia es F, debemos muestrear a la frecuencia N = 2F.
N se llama límite de Nyquist.
54. El teorema de muestreo Ejemplo: sinusoidales
55. El teorema de muestreo Ejemplo: sinusoidales
56. Teoría de Fourier Los ejemplos usan sinusoidales, porque?
La teoría de Fourier nos permite descomponer cualquier señal en una suma de (posiblemente un número infinito de) ondas senoidales
57. Prefiltrado Elimina las altas frecuencias antes de muestrear
Convertir I(x) a F(u)
Applica filtro pasa bajos (e.g., multiplica F(u) por función caja)
Entonces muestrea. Resultado: no hay aliasing!
Entonces que problema hay?
Problema: los algoritmos de render generan directamente una función como muestras
e.g., Z-buffer, ray tracing
58. Supersampling La forma mas sencilla para reducir artefactos de aliasing es el supersampling
Incrementa la resolución de las muestras
Promedia
A veces se llama postfiltrado
Crea imagen virtual a mas alta resolución que la imagen final
Aplica filtro pasa bajos
Remuestrea imagen filtrada
59. Supersampling: Limitaciones Almacenamiento crece cuadráticamente
No elimina el aliasing, solo sube el límite de Nyquist
Peor caso … tablero de ajedrez recediendo al infinito
De todas maneras se utiliza. Como hacerlo bien?
60. Supersampling El proceso:
Crea imagen virtual a mas alta resolución que la imagen final (fácil)
Aplica filtro pasa bajos
Convierte a dominio de frecuencia
Multiplica por función caja
Caro!!! Pero recuerda que multiplicación en dominio de frecuencia equivale a convolución en el espacio, por lo que:
basta hacer la convolución de la imagen con la transformada de Fourier de la función caja
Remuestrea imagen filtrada
En la práctica si combinamos los pasos 2 y 3 solo debemos crear la imagen filtrada en los nuevos puntos muestra, es decir solo hay que hacer la convolución con el filtro en los nuevos puntos, lo cual involucra solo multiplicar y sumar valores
61. Supersampling:Convolución digital
62. Supersampling Para multiplicar por una función caja en la frecuencia, en el espacio debemos usar la función sinc que es (sin(x) / x)
Es dificil pues Sinc tiene soporte infinito y lóbulos negativos
Comunmente se usa
Sinc truncado
Caja (muy malo)
Triángulo
Gaussiano (bueno, entre mas ancho el filtro, mejor; usualmente 3x3, 5x5 o a lo mas 7x7)
63. Antialiasing en el dominio continuo A pesar de los problemas del prefiltrado, a veces se trata de aproximar el efecto de la convolución en el dominio continuo
64. Antialiasing en el dominio continuo
65. Antialiasing en el dominio continuo Lo bueno
Puedo evaluar de manera exacta la cobertura de poligono del kernel del filtro
Que implica?
Recorte
Determinar superficies visibles
Lo malo
Determinar cobertura es muy caro
La variación de intensidad puede no ser pareja
66. Algoritmo de Catmull Encuentra area de fragmentos
Multiplica por color de fragmentos
Suma para determinar color final del pixel
67. Algoritmo de Catmull Primer intento para filtrar en dominio continuo
Muy caro
Recorta poligonos a fragmentos
Ordena fragmentos de poligono por profundidad
Es un filtro de caja
68. El A-Buffer Idea: approximar filtrado continuo por muestreo a nivel subpixel
Sumar areas se vuelve sencillo
69. El A-Buffer Ventajas:
Incorporar a scanline renderer reduces costos de almacenamiento dramáticamente
Procesamiento por pixel depende solo del número de fragmentos visibles
Puede implementarse eficientemente con operaciones de lógicas de bits sobre máscaras a nivel subpixel
Desventajas
Básicamente sigue siendo supersampling
No es amigable para el hardware
70. Muestreo estadístico El muestreo irregular da ruido en vez de aliasing, lo que molesta menos al sistema visual.
Integrar el muestreo estadístico a
Ray tracing (sencillo)
Z-buffer (posible, ver REYES) o simular con jitter de imagen
A-buffer (no)
Como es bueno distribuir las muestras?
Poisson (agregar al azar hasta llenar; es uniforme)
Disco de Poisson (distancia minima; muy pareja)
Jittered (perturba malla regular al azar; granular)
71. Recorte
72. Recorte Hemos estado suponiendo que todas las primitivas (líneas, triángulos, polígonos), están completamente dentro del viewport
En general, esto no es cierto:
73. Recorte Se pueden calcular analíticamente las partes de las primitivas dentro del viewport
74. Porque recortar? Es mala idea rasterizar fuera de los límites del framebuffer
No queremos desperdiciar tiempo rasterizando pixeles fuera de la ventana
75. Recorte Método ingenuo:
for each line segment
for each edge of viewport
find intersection points
pick “nearest” point
if anything is left, draw it
Que es mas cercano?
Como optimizar?
76. Aceptación y Rechazo Trivial Si los dos extremos estan dentro aceptación trivial
Si los dos extremos están del mismo lado de la misma línea, rechazo trivial
77. Recorte de Líneas Cohen-Sutherland Divide plano de vista en regiones definidas por aristas
Asigna a cada región un código de 4 bits:
78. Recorte de Líneas Cohen-Sutherland Define bits con pruebas sencillas
x > xmax y < ymin etc.
Asigna un código a cada vértice de la línea
Si ambos códigos = 0, aceptación trivial
haz AND bit por bit de códigos de los vértices
Si resultado ? 0, rechazo trivial
79. Recorte de Líneas Cohen-Sutherland Si línea no puede ser aceptada o rechazada trivialmente, subdivide para poder descartar uno o ambos segmentos
Escoge arista que la línea cruza (como?)
Intersecta línea con arista (como?)
Descarta porción en lado incorrecto de arista y asignale código al nuevo vértice
Aplica pruebas de aceptación y rechazo trivial; repite si es necesario
80. Recorte de Líneas Cohen-Sutherland Pruebas de código e intersecciones son rápidas
Algunas líneas requieren varias iteraciones
Otros algoritmos son mas eficientes (checar):
Cyrus-Beck usa líneas paramétrica
Liang-Barsky optimiza esto para volumenes verticales
81. Recorte de Polígonos Recortar polígonos es mas complejo que recortar cada línea que lo forma
Entrada: polígono
Salida: polígono, o nada
Hay aceptación o rechazo trivial del polígono en vez de los segmentos que lo forman?
82. Que le pasa al triángulo al recortar? Cuantos lados tiene al final? Por que es dificil el recorte?
83. Caso dificil. Resultan varios polígonos: Por que es dificil el recorte??
84. Recorte Sutherland-Hodgman Basicamente:
Considera cada arista del viewport individualmente
Recorta el polígono contra la ecuación de esa arista
Al terminar con todas, hemos terminado
85. Sutherland-Hodgman Clipping
86. Sutherland-Hodgman Clipping
87. Sutherland-Hodgman Clipping
88. Sutherland-Hodgman Clipping
89. Sutherland-Hodgman Clipping
90. Sutherland-Hodgman Clipping
91. Sutherland-Hodgman Clipping
92. Sutherland-Hodgman Clipping
93. Sutherland-Hodgman Clipping
94. Sutherland-Hodgman Clipping Rutina básica:
Ve alrededor del polígonoun vértice a la vez
El vértice actual tiene una posición p
El vértice previo tuvo posición s, y se agrego a la salida si era apropiado
95. Sutherland-Hodgman Clipping Cuatro casos para arista de s a p:
96. Prueba punto plano Una prueba generalpara determinar si un punto p está dentro de un plano P, definido por q y n:
(p - q) • n < 0: p dentro P
(p - q) • n = 0: p sobre P
(p - q) • n > 0: p fuera de P
97. Intersección Línea-Plano Usar definición paramétrica de arista:
E(t) = s + t(p - s)
Si t = 0 entonces E(t) = s
Si t = 1 entonces E(t) = p
Si no, E(t) está entre s y p
98. Intersección Línea-Plano La arista intersecta al plano P donde E(t) está sobre P
q es un punto en P
n es normal a P
(E(t) - q) • n = 0
t = [(q - s) • n] / [(p - s) • n]
El punto de intersección i = E(t)
para este valor de t
99. Intersección Línea-Plano Note que la longitud de n no afecta el resultado:
t = [(q - s) • n] / [(p - s) • n]
Otra vez, oportunidad para optimizar
100. Recorte 3-D Antes de dibujar debemos recortar
Podemos transformar a coordenadas de pantalla primero y recortar en 2-D?
Corrección: no dibujar cosas atras del ojo
101. Recorte con perspectiva Problema: despues de multiplicar por matriz de perspectiva y hacer la división homogenea, un punto en (-8, -2, -10) se ve igual que uno en (8, 2, 10).
Solución A: recorta antes de multiplicar el punto por la matriz de proyección
I.e., recorta en coordenadas de cámara
Solución B: recorta despues de aplicar la matriz pero antes de dividir
I.e., recorta en coordenadas homogeneas de pantalla
102. Recorte con perspectiva Solución A:
103. Recap: Proyección de perspectiva El volumen de vista típico es un frustum o pirámide truncada
104. Proyección de Perspectiva El fustrum consiste de 6 planos
Sutherland-Hodgeman algorithm (recortar poligonos a una región plano por plano) generaliza a 3-D
Recorta poligonos contra los 6 planos del frustum
Cual es el problema?
Recortar un segmento contra un plano arbitrario es caro pues requiere productos punto
105. Proyección de Perspectiva De hecho, por simplicidad se prefiere utilizar un fustrum canónico:
106. Proyección de Perspectiva De hecho, por simplicidad se prefiere utilizar un frustum canónico:
107. Recorte con perspectiva Hay que refinar nuestro modelo de pipeline:
Note que esto nos obliga a separar las transformaciones de proyección de las de modelado y vista
108. Recorte en coordenadas homogeneas Otra opción es recortar directamente en coordenadas homogeneas.
Esto permite recortar después de la proyección de perspectiva:
Que ventaja tiene?
109. Recorte en coordenadas homogeneas Otras ventajas:
Podemos transformar la vista canónica para perspectiva en la vista canónica de proyecciones paralelas
Recortar en esta última
Permite implementar en hardware
Habrá primitivas con w ? 1
Por ejemplo, polígonos que resultan de subdividir splines
Si no se recorta en coordenadas homogeneas, hay que dividir dos veces en esas primitivas
110. Recorte en coordenadas homogeneas Pero como se recorta en coordenadas homogeneas?
Brevemente, así:
Recuerda que hemos aplicado una transformación a device coordinates
x, y ? [-1, 1]
z ? [0, 1]
Al recortar digamos al lado derecho de la pantalla (x = 1), recorta mejor a (x = w)