Mapeado de texturas

ImprimirCitar
Método de definir el detalle superficial en un modelo gráfico o 3D generado por ordenador
1: Modelo 3D sin texturas
2: Mismo modelo con texturas
Mapping a dos dimensiones textura sobre un modelo 3D

Mapeo de texturas es un método para mapear una textura en un gráfico generado por computadora. La textura aquí puede ser detalle de alta frecuencia, textura superficial o color.

Historia

La técnica original fue iniciada por Edwin Catmull en 1974.

El mapeo de texturas originalmente se refería al mapeo difuso, un método que simplemente mapeaba píxeles de una textura a una superficie 3D ("envolviendo" la imagen alrededor del objeto). En las últimas décadas, el advenimiento del renderizado multipaso, multitexturizado, mipmaps y mapeos más complejos como el mapeo de altura, el mapeo de relieve, el mapeo normal, el mapeo de desplazamiento, el mapeo de reflexión, el mapeo especular, el mapeo de oclusión y muchas otras variaciones de la técnica. (controlado por un sistema de materiales) han hecho posible simular casi fotorrealismo en tiempo real al reducir enormemente la cantidad de polígonos y cálculos de iluminación necesarios para construir una escena 3D realista y funcional.

Ejemplos de multitextura:
1: esfera intextada, 2: Textura y mapas de parachoques, 3: Textura mapa solamente, 4: Opacity y textura mapas

Mapas de textura

Un mapa de texturas es una imagen aplicada (asignada) a la superficie de una forma o polígono. Puede ser una imagen de mapa de bits o una textura de procedimiento. Pueden almacenarse en formatos de archivo de imagen comunes, referenciados por formatos de modelos 3D o definiciones de materiales, y ensamblados en paquetes de recursos.

Pueden tener de 1 a 3 dimensiones, aunque las 2 dimensiones son las más comunes para las superficies visibles. Para su uso con hardware moderno, los datos del mapa de textura se pueden almacenar en ordenamientos swizzled o en mosaico para mejorar la coherencia de la memoria caché. Las API de renderizado normalmente administran los recursos del mapa de textura (que pueden estar ubicados en la memoria del dispositivo) como búferes o superficies, y pueden permitir 'renderizar a textura' para efectos adicionales como el procesamiento posterior o el mapeo del entorno.

Por lo general, contienen datos de color RGB (ya sea almacenados como color directo, formatos comprimidos o color indexado) y, a veces, un canal adicional para mezcla alfa (RGBA), especialmente para vallas publicitarias y texturas de superposición de calcomanías. Es posible usar el canal alfa (que puede ser conveniente para almacenar en formatos analizados por hardware) para otros usos, como la especularidad.

Se pueden combinar varios mapas (o canales) de textura para controlar la especularidad, las normales, el desplazamiento o la dispersión del subsuelo, p. para la reproducción de la piel.

Se pueden combinar varias imágenes de texturas en atlas de texturas o matrices de texturas para reducir los cambios de estado en el hardware moderno. (Pueden considerarse una evolución moderna de los gráficos de mapas de mosaicos). El hardware moderno a menudo admite texturas de mapas de cubos con múltiples caras para el mapeo de entornos.

Creación

Los mapas de textura se pueden adquirir mediante escaneo/fotografía digital, diseñarse en un software de manipulación de imágenes como GIMP, Photoshop o pintarse sobre superficies 3D directamente en una herramienta de pintura 3D como Mudbox o zbrush.

Aplicación de textura

Este proceso es similar a aplicar papel estampado a una caja blanca normal. A cada vértice de un polígono se le asigna una coordenada de textura (que en el caso 2d también se conoce como coordenadas UV). Esto se puede hacer mediante la asignación explícita de atributos de vértice, editados manualmente en un paquete de modelado 3D a través de herramientas de desenvolvimiento UV. También es posible asociar una transformación procesal del espacio 3d al espacio de textura con el material. Esto podría lograrse a través de una proyección plana o, alternativamente, un mapeo cilíndrico o esférico. Mapeos más complejos pueden considerar la distancia a lo largo de una superficie para minimizar la distorsión. Estas coordenadas se interpolan en las caras de los polígonos para muestrear el mapa de texturas durante el renderizado. Las texturas se pueden repetir o reflejar para extender un mapa de bits rectangular finito sobre un área más grande, o pueden tener una "inyección" mapeo de cada pieza de una superficie (que es importante para el mapeo de renderizado y el mapeo de luz, también conocido como horneado).

Espacio de textura

El mapeo de texturas mapea la superficie del modelo (o el espacio de la pantalla durante la rasterización) en espacio de textura; en este espacio, el mapa de textura es visible en su forma no distorsionada. Las herramientas de desenvolvimiento UV generalmente brindan una vista en el espacio de la textura para la edición manual de las coordenadas de la textura. Algunas técnicas de representación, como la dispersión del subsuelo, se pueden realizar aproximadamente mediante operaciones de espacio de textura.

Multitexturizado

Multitexturizado es el uso de más de una textura a la vez en un polígono. Por ejemplo, se puede usar una textura de mapa de luz para iluminar una superficie como alternativa a volver a calcular esa iluminación cada vez que se renderiza la superficie. Las microtexturas o texturas de detalle se utilizan para agregar detalles de mayor frecuencia, y los mapas de tierra pueden agregar erosión y variación; esto puede reducir en gran medida la periodicidad aparente de la repetición de texturas. Los gráficos modernos pueden utilizar más de 10 capas, que se combinan mediante sombreadores, para una mayor fidelidad. Otra técnica de texturas múltiples es el mapeo de relieve, que permite que una textura controle directamente la dirección de orientación de una superficie a efectos de sus cálculos de iluminación; puede dar una muy buena apariencia de una superficie compleja (como la corteza de un árbol o el concreto rugoso) que adquiere detalles de iluminación además de la coloración detallada habitual. El mapeo de relieve se ha vuelto popular en los videojuegos recientes, ya que el hardware de gráficos se ha vuelto lo suficientemente potente como para acomodarlo en tiempo real.

Filtrado de texturas

La forma en que las muestras (por ejemplo, cuando se ven como píxeles en la pantalla) se calculan a partir de los texels (píxeles de textura) se rige por el filtrado de texturas. El método más económico es usar la interpolación del vecino más cercano, pero la interpolación bilineal o la interpolación trilineal entre mipmaps son dos alternativas comúnmente utilizadas que reducen el aliasing o los jaggies. En el caso de que una coordenada de textura esté fuera de la textura, se sujeta o envuelve. El filtrado anisotrópico elimina mejor los artefactos direccionales al ver texturas desde ángulos de visión oblicuos.

Transmisión de texturas

La transmisión de texturas es un medio de usar flujos de datos para texturas, donde cada textura está disponible en dos o más resoluciones diferentes, para determinar qué textura debe cargarse en la memoria y usarse en función de la distancia de dibujo desde el espectador y la cantidad de memoria. está disponible para texturas. La transmisión de texturas permite que un motor de renderizado use texturas de baja resolución para objetos que se encuentran lejos de la cámara del espectador y las resuelva en texturas más detalladas, leídas desde una fuente de datos, a medida que el punto de vista se acerca a los objetos.

Hornear

Como optimización, es posible renderizar detalles de un modelo complejo de alta resolución o un proceso costoso (como la iluminación global) en una textura de superficie (posiblemente en un modelo de baja resolución). Hornear también se conoce como mapeo de renderizado. Esta técnica se usa más comúnmente para mapas de luz, pero también se puede usar para generar mapas normales y mapas de desplazamiento. Algunos juegos de computadora (por ejemplo, Messiah) han utilizado esta técnica. El motor de software original de Quake usaba horneado sobre la marcha para combinar mapas de luz y mapas de color ("almacenamiento en caché de superficie").

La cocción se puede utilizar como una forma de generación de nivel de detalle, donde una escena compleja con muchos elementos y materiales diferentes se puede aproximar mediante un elemento único con un único textura, que luego se reduce algorítmicamente para reducir el costo de renderizado y menos llamadas. También se utiliza para tomar modelos de gran detalle del software de escultura 3D y el escaneo de nubes de puntos y aproximarlos con mallas más adecuadas para el renderizado en tiempo real.

Algoritmos de rasterización

Varias técnicas han evolucionado en implementaciones de software y hardware. Cada uno ofrece diferentes ventajas y desventajas en precisión, versatilidad y rendimiento.

Asignación de texturas afines

Debido a que el mapeo de texturas affine no tiene en cuenta la información de profundidad sobre los vértices de un polígono, donde el polígono no es perpendicular al espectador, produce un defecto notable, especialmente cuando se rasteriza como triángulos.

Asignación de texturas afines interpola linealmente las coordenadas de textura en una superficie, por lo que es la forma más rápida de asignación de texturas. Algunos software y hardware (como la PlayStation original) proyectan vértices en el espacio 3D en la pantalla durante el renderizado e interpolan linealmente las coordenadas de la textura en el espacio de la pantalla entre ellos. Esto se puede hacer incrementando las coordenadas UV de puntos fijos o mediante un algoritmo de error incremental similar al algoritmo de línea de Bresenham.

A diferencia de los polígonos perpendiculares, esto conduce a una distorsión notable con transformaciones de perspectiva (ver figura: la textura de la casilla de verificación parece doblada), especialmente como elementos primitivos cerca de la cámara. Tal distorsión puede reducirse con la subdivisión del polígono en otros más pequeños.

Para el caso de objetos rectangulares, usar primitivas cuádruples puede parecer menos incorrecto que el mismo rectángulo dividido en triángulos, pero debido a que la interpolación de 4 puntos agrega complejidad a la rasterización, la mayoría de las primeras implementaciones preferían solo triángulos. Algún hardware, como el mapeo de texturas directo utilizado por Nvidia NV1, pudo ofrecer primitivas cuádruples eficientes. Con la corrección de perspectiva (ver más abajo) los triángulos se vuelven equivalentes y esta ventaja desaparece.

Para objetos rectangulares, especialmente cuando perpendicular a la vista, interpolar linealmente a través de un quad puede dar un resultado de afina superior frente al mismo rectángulo dividido en dos triángulos de afin.

Para objetos rectangulares que están en ángulo recto con respecto al espectador, como pisos y paredes, la perspectiva solo debe corregirse en una dirección a través de la pantalla, en lugar de ambas. El mapeo de perspectiva correcto se puede calcular en los bordes izquierdo y derecho del piso, y luego una interpolación lineal afín en ese tramo horizontal se verá correcta, porque cada píxel a lo largo de esa línea está a la misma distancia del espectador.

Corrección de la perspectiva

Perspectiva correcta cuentas de textura para los vértices' posiciones en el espacio 3D, en lugar de simplemente interpolar coordenadas en el espacio de la pantalla 2D. Esto logra el efecto visual correcto pero es más costoso de calcular.

Para realizar corrección de perspectiva de las coordenadas de textura u{displaystyle u} y v{displaystyle v}, con z{displaystyle z} siendo el componente de profundidad desde el punto de vista del espectador, podemos aprovechar el hecho de que los valores 1z{fnMicroc} {1}{z}}, uz{displaystyle {frac {f} {fn}}} {fnMicroc {fn}}} {f}}} {fn}}}}}}}, y vz{displaystyle {frac {f} {fn}}} {fnMicroc} {f}}} {f}} {f}}} son lineales en espacio de pantalla a través de la superficie siendo texturado. En contraste, el original z{displaystyle z}, u{displaystyle u} y v{displaystyle v}, antes de la división, no son lineales a través de la superficie en el espacio de la pantalla. Por lo tanto, podemos interponer linealmente estos reciprocales a través de la superficie, computando valores corregidos en cada pixel, para dar lugar a una perspectiva correcta cartografía de textura.

Para ello, calculamos primero las reciprocas en cada vértice de nuestra geometría (3 puntos para un triángulo). Para el vértice n{displaystyle n} tenemos unzn,vnzn,1zn{fnMicroc} {fn} {fn} {fn} {fn} {fn}} {fn}} {fn}} {fn}} {fn}}}} {fnfnfnfnfn} {fn} {fn} {fn} {fn}} {fn} {fn}} {fn}} {fn}} {fn}}} {fnfn} {1}{z_{n}}}. Entonces, interpolamos linealmente estos recíprocos entre los n{displaystyle n} vértices (p. ej., utilizando Coordenadas Baricéntricas), resultando en valores interpolados a través de la superficie. En un momento dado, esto produce la interpolación ui,vi{displaystyle U_{i},v_{i}, y zReciprocali=1zi{displaystyle zReciprocal_{i}={frac {1}{z_{i}}}. Note que esto ui,vi{displaystyle U_{i},v_{i} no se puede utilizar todavía como nuestras coordenadas de textura como nuestra división por z{displaystyle z} alteró su sistema de coordenadas.

Para corregir de nuevo u,v{displaystyle u,v} espacio primero calculamos el corregido z{displaystyle z} tomando de nuevo el recíproco zcorrect=1zReciprocali=11zi{displaystyle z_{correct}={frac {1} {fn} {fnMicroc}} {fnMicroc} {fnK}} {f}} {f}}} {fn}} {f}}}} {fn} {fnf}} {f}} {f} {f}}} {fnf}} {f}f}} {f}f}f}f}f} {f}f}f}f}f}f} {f} {f} {f} {f} {f} {f} {f}f}f}f}f}f}f}f}}f}f} {f} {f}f} {f}f}f}f} {f}f}fn}f}f}f}f}f}f}f}f}f}fn {1}{frac} {1}{z_{i}}}}. Entonces usamos esto para corregir nuestro ui,vi{displaystyle U_{i},v_{i}: ucorrect=ui⋅ ⋅ zi{displaystyle U_{correct}=u_{i}cdot z_{i} y vcorrect=vi⋅ ⋅ zi{displaystyle v_{correct}=v_{i}cdot z_{i}.

Esta corrección hace que en las partes del polígono que están más cerca del espectador, la diferencia de píxel a píxel entre las coordenadas de la textura sea menor (estirando más la textura) y en las partes más alejadas, esta diferencia sea mayor (comprimiendo la textura).

Cartografía de textura fina interpola directamente una coordenadas de textura uα α {displaystyle u_{alpha} {}}}} {fn}}} entre dos puntos finales u0{displaystyle u_{0} {}} {}displaystyle u_{0}}} {}}}} {}}} {}}}} {f}}}}} {f}} y u1{displaystyle u_{1} {}} {}displaystyle u_{1}}}} {}}} {}}}} {}}}}} {fn}}}} {f}}}:
uα α =()1− − α α )u0+α α u1{displaystyle u_{alpha}=(1-alpha)u_{0}+alpha U_{1} Donde 0≤ ≤ α α ≤ ≤ 1{displaystyle 0leq alpha leq 1}
Perspective correct mapping interpola después de dividir por profundidad z{displaystyle z_{} {}} {}displaystyle z_{}} {}}}} {}}}} {}}}} {}}}}}} {}}}}}, luego utiliza su reciprocal interpolado para recuperar la coordenadas correcta:
uα α =()1− − α α )u0z0+α α u1z1()1− − α α )1z0+α α 1z1{displaystyle u_{alpha }{}={frac {(1-alpha){frac {fn} {fn}}}\fnK}} {f}} {f}}} {f}}}} {\fn}}}}}}}}\\\\fn\fn\\\fnMicrosoft}} {fnMicroc {u_{1}{z_{1}}}{(1-alpha){frac {1}{z_{0}}+Alpha {fnMicroc {1}{z_{1}}}

El hardware de gráficos 3D suele admitir texturas de perspectiva correcta.

Han evolucionado varias técnicas para representar la geometría mapeada de textura en imágenes con diferentes compensaciones de calidad/precisión, que se pueden aplicar tanto al software como al hardware.

Los mapeadores de texturas de software clásicos generalmente solo hacían un mapeo simple con un efecto de iluminación como máximo (normalmente aplicado a través de una tabla de búsqueda), y la precisión de la perspectiva era aproximadamente 16 veces más costosa.

Rotación de cámara restringida

El motor Doom no permitió pisos rampados o paredes inclinadas. Esto requiere corrección de perspectiva sólo una vez por cada lapso horizontal o vertical, en lugar de per-pixel.

El motor Doom restringía el mundo a paredes verticales y suelos/techos horizontales, con una cámara que solo podía girar sobre el eje vertical. Esto significaba que las paredes tendrían una coordenada de profundidad constante a lo largo de una línea vertical y los pisos/techos tendrían una profundidad constante a lo largo de una línea horizontal. Después de realizar un cálculo de corrección de perspectiva para la profundidad, el resto de la línea podría usar un mapeo afín rápido. Algunos renderizadores posteriores de esta era simularon una pequeña cantidad de inclinación de la cámara con cizallamiento, lo que permitió la apariencia de una mayor libertad mientras usaban la misma técnica de renderizado.

Algunos motores podían renderizar mapas de altura con mapas de texturas (por ejemplo, Voxel Space de Nova Logic y el motor para Outcast) a través de algoritmos incrementales similares a los de Bresenham, produciendo la apariencia de un paisaje con mapas de texturas sin el uso de geometría tradicional. primitivos.

Subdivisión para corrección de perspectiva

Cada triángulo se puede subdividir en grupos de unos 16 píxeles para lograr dos objetivos. Primero, mantener la fábrica de aritmética ocupada en todo momento. Segundo, producir resultados aritméticos más rápidos.

Subdivisión del espacio mundial

Para el mapeo de texturas en perspectiva sin soporte de hardware, un triángulo se divide en triángulos más pequeños para renderizar y se usa un mapeo afín en ellos. La razón por la que esta técnica funciona es que la distorsión del mapeo afín se vuelve mucho menos perceptible en los polígonos más pequeños. La PlayStation de Sony hizo un uso extensivo de esto porque solo admitía el mapeo afín en el hardware, pero tenía un rendimiento triangular relativamente alto en comparación con sus pares.

Subdivisión del espacio de la pantalla

Screen space sub division techniques. Parte superior izquierda: Quake-like, superior derecha: bilinear, inferior izquierda: const-z

Los renderizadores de software generalmente prefieren la subdivisión de pantalla porque tiene menos sobrecarga. Además, intentan hacer una interpolación lineal a lo largo de una línea de píxeles para simplificar la configuración (en comparación con la interpolación afín 2d) y, por lo tanto, nuevamente la sobrecarga (también el mapeo de textura afín no encaja en la baja cantidad de registros de la CPU x86; el 68000 o cualquier RISC es mucho más adecuado).

Se adoptó un enfoque diferente para Quake, que calcularía las coordenadas correctas de la perspectiva solo una vez cada 16 píxeles de una línea de exploración y las interpolaría linealmente entre ellas, funcionando efectivamente a la velocidad de la interpolación lineal porque la perspectiva correcta el cálculo se ejecuta en paralelo en el coprocesador. Los polígonos se representan de forma independiente, por lo que es posible cambiar entre tramos y columnas o direcciones diagonales dependiendo de la orientación del polígono normal para lograr una z más constante, pero el esfuerzo parece no valer la pena.

Otras técnicas

Otra técnica consistía en aproximar la perspectiva con un cálculo más rápido, como un polinomio. Otra técnica más utiliza el valor 1/z de los dos últimos píxeles dibujados para extrapolar linealmente el siguiente valor. Luego, la división se realiza a partir de esos valores, de modo que solo se debe dividir un pequeño resto, pero la cantidad de contabilidad hace que este método sea demasiado lento en la mayoría de los sistemas.

Finalmente, el motor de compilación amplió el truco de distancia constante utilizado para Doom al encontrar la línea de distancia constante para polígonos arbitrarios y renderizar a lo largo de ella.

Implementaciones de hardware

El hardware de mapeo de texturas se desarrolló originalmente para la simulación (por ejemplo, como se implementó en los generadores de imágenes ESIG de Evans y Sutherland) y las estaciones de trabajo de gráficos profesionales como Silicon Graphics, las máquinas de efectos de video digital de transmisión como Ampex ADO y luego aparecieron en los gabinetes Arcade., consolas de videojuegos de consumo y tarjetas de video para PC a mediados de la década de 1990. En la simulación de vuelo, el mapeo de texturas proporcionó importantes señales de movimiento.

Las unidades de procesamiento de gráficos (GPU) modernas proporcionan unidades de funciones fijas especializadas denominadas muestradores de texturas, o unidades de mapeo de texturas, para realizar el mapeo de texturas, generalmente con filtrado trilineal o mejor filtrado anisotrópico de varias pulsaciones y hardware para decodificación de formatos específicos como DXTn. A partir de 2016, el hardware de mapeo de texturas es omnipresente ya que la mayoría de los SOC contienen una GPU adecuada.

Algunos hardware combinan el mapeo de texturas con la determinación de superficies ocultas en renderizado diferido basado en mosaicos o renderizado de línea de exploración; dichos sistemas solo obtienen los téxeles visibles a expensas de utilizar un mayor espacio de trabajo para los vértices transformados. La mayoría de los sistemas se han decidido por el enfoque de almacenamiento en búfer Z, que aún puede reducir la carga de trabajo del mapeo de texturas con la clasificación de adelante hacia atrás.

Entre el hardware de gráficos anterior, había dos paradigmas en competencia sobre cómo entregar una textura a la pantalla:

  • Cartografía de textura avanzada itera a través de cada texel en la textura, y decide dónde colocarlo en la pantalla.
  • Cartografía de textura inversa en su lugar itera a través de píxeles en la pantalla, y decide qué texel utilizar para cada uno.

El mapeo de textura inverso es el método que se ha vuelto estándar en el hardware moderno.

Mapeo de textura inversa

Con este método, un píxel de la pantalla se asigna a un punto de la textura. Cada vértice de una primitiva de representación se proyecta en un punto de la pantalla, y cada uno de estos puntos se asigna a una coordenada de texel u,v en la textura. Un rasterizador interpolará entre estos puntos para completar cada píxel cubierto por la primitiva.

La principal ventaja es que cada píxel cubierto por una primitiva se recorrerá exactamente una vez. Una vez que se transforman los vértices de una primitiva, la cantidad de trabajo restante se escala directamente con la cantidad de píxeles que cubre en la pantalla.

La principal desventaja frente al mapeo directo de texturas es que el patrón de acceso a la memoria en el espacio de la textura no será lineal si la textura está en ángulo con respecto a la pantalla. Esta desventaja a menudo se aborda mediante técnicas de almacenamiento en caché de texturas, como la disposición de memoria de textura swizzled.

La interpolación lineal se puede usar directamente para el mapeo de texturas afines simple y eficiente, pero también se puede adaptar para corregir la perspectiva.

Asignación de textura hacia adelante

El mapeo de textura hacia adelante asigna cada texel de la textura a un píxel en la pantalla. Después de transformar una primitiva rectangular en un lugar en la pantalla, un renderizador de mapeo de texturas hacia adelante itera a través de cada elemento de textura en la textura, salpicando cada uno en un píxel del búfer de cuadro.

Esto fue utilizado por algunos hardware, como el Sega Saturn y el NV1.

La principal ventaja es que se accederá a la textura en un orden lineal simple, lo que permite un almacenamiento en caché muy eficiente de los datos de la textura. Sin embargo, este beneficio también es su desventaja: a medida que una primitiva se hace más pequeña en la pantalla, aún tiene que iterar sobre cada texel en la textura, lo que hace que muchos píxeles se sobredibujen de manera redundante.

Este método también es adecuado para renderizar primitivos cuádruples en lugar de reducirlos a triángulos, lo que supuso una ventaja cuando la textura de perspectiva correcta no estaba disponible en el hardware. Esto se debe a que la distorsión afín de un cuádruple parece menos incorrecta que el mismo cuádruple dividido en dos triángulos (vea el mapeo de texturas afines arriba). El hardware NV1 también permitió un modo de interpolación cuadrática para proporcionar una aproximación aún mejor de la corrección de la perspectiva.

Las implementaciones de hardware existentes no proporcionaban un mapeo de coordenadas UV efectivo, lo que se convirtió en una técnica importante para el modelado 3D y ayudó a recortar la textura correctamente cuando la primitiva sobrepasó el borde de la pantalla. Estas deficiencias podrían haberse solucionado con un mayor desarrollo, pero desde entonces el diseño de la GPU se ha movido principalmente hacia el mapeo inverso.

Aplicaciones

Más allá del renderizado 3D, la disponibilidad de hardware de mapeo de texturas ha inspirado su uso para acelerar otras tareas:

Tomografía

Es posible usar hardware de mapeo de texturas para acelerar tanto la reconstrucción de conjuntos de datos de vóxeles a partir de escaneos tomográficos como para visualizar los resultados.

Interfaces de usuario

Muchas interfaces de usuario utilizan el mapeo de texturas para acelerar las transiciones animadas de los elementos de la pantalla, p. Exposé en Mac OS X.

Software

  • TexRecon — software de código abierto para la redacción de modelos 3D escritos en C++

Contenido relacionado

HexChat

Compacrón

Estudios de ciencia y tecnología

Los estudios de ciencia y tecnología son un campo interdisciplinario que examina la creación, el desarrollo y las consecuencias de la ciencia y la...
Más resultados...
Tamaño del texto:
Copiar