> For the complete documentation index, see [llms.txt](https://docs.decentraland.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.decentraland.org/creator/content-creator-es/scenes-sdk7/fundamentos-del-contenido-3d/materials.md).

# Materiales

Aprende cómo añadir materiales y texturas a entidades con formas primitivas.

## Materiales

Los materiales pueden aplicarse a entidades que usan formas primitivas (cubo, esfera, plano, etc.) añadiendo un `Material` componente. Este componente tiene varios campos que te permiten configurar las propiedades del material, añadir una textura, etc.

*glTF* modelos incluyen sus propios materiales, que se importan implícitamente en una escena junto con el modelo. Para modificar o sobrescribir estos materiales, usa el `GltfNodeModifiers` componente. Consulta [Modificar materiales glTF](#modify-gltf-materials) para más detalles.

Al importar un modelo 3D con sus propios materiales, ten en cuenta que no todos los shaders son compatibles con el motor de Decentraland. Solo se admiten materiales estándar y materiales PBR (renderizado basado en la física). Consulta [consideraciones sobre modelos 3D externos](https://github.com/decentraland/docs/blob/main/creator/3d-modeling/materials.md) para más detalles.

Hay diferentes tipos de materiales compatibles:

* PBR (Renderizado basado en la física): el tipo de material más común en Decentraland. Admite colores planos o texturas, y distintas propiedades como metallic, emissive, transparencia, etc. Lee más sobre [PBR](https://en.wikipedia.org/wiki/Physically_based_rendering).
* Materiales básicos: no responden a luces ni sombras, lo que los hace ideales para mostrar imágenes tipo billboard.

## Usa el Scene Editor en Creator Hub

La forma más sencilla de darle un Material a una entidad es usar el Scene Editor. Puedes añadir un **Material** componente a tu entidad y luego configurar todos los campos disponibles en la UI del Scene Editor. Consulta [Añadir componentes](/creator/content-creator-es/scene-editor/construir/components.md#add-components).

## Añadir un material

El siguiente ejemplo crea un material PBR y establece algunos de sus campos para darle un color rojo y propiedades metálicas. Este material se añade a una entidad que también tiene una forma de caja, por lo que coloreará la caja con este material.

```ts
//Crear entidad y asignar forma
const meshEntity = engine.addEntity()
Transform.create(meshEntity, {
	position: Vector3.create(4, 1, 4),
})
MeshRenderer.setBox(meshEntity)

//Crear material y configurar sus campos
Material.setPbrMaterial(meshEntity, {
	albedoColor: Color4.Red(),
	metallic: 0.8,
	roughness: 0.1,
})
```

Para cambiar el material de una entidad que ya tiene un `Material` componente, ejecuta `Material.setPbrMaterial()` o cualquiera de las otras funciones auxiliares y sobrescribirá el material original. No es necesario eliminar el original `Material` ni usar la sintaxis avanzada.

```ts
//Crear entidad y asignar forma
const meshEntity = engine.addEntity()
Transform.create(meshEntity, {
	position: Vector3.create(4, 1, 4),
})
MeshRenderer.setBox(meshEntity)

//Crear material y configurar sus campos
Material.setPbrMaterial(meshEntity, {
	albedoColor: Color4.Red(),
})

//Sobrescribir con un nuevo componente de material
Material.setPbrMaterial(meshEntity, {
	albedoColor: Color4.Blue(),
})
```

{% hint style="warning" %}
**📔 Nota**: El `Material` componente debe importarse mediante

> `import { Material } from "@dcl/sdk/ecs"`

Ver [Importaciones](/creator/content-creator-es/scenes-sdk7/primeros-pasos/coding-scenes.md#imports) para saber cómo manejarlos fácilmente.
{% endhint %}

## Colores del material

Dale a un material un color plano. En un Material PBR, estableces el `albedoColor` campo. Los colores albedo responden a la luz y pueden incluir matices.

Los valores de color son de tipo `Color4`, compuesto por *r*, *g* y *b* (rojo, verde y azul). Cada uno toma valores entre 0 y 1. Al asignarles valores diferentes, puedes componer cualquier color visible. Para negro, pon los tres en 0. Para blanco, ponlos todos en 1.

{% hint style="warning" %}
**📔 Nota**: Si estableces cualquier color en `albedoColor` un valor mayor que *1*1, aparecerá como *emisivo*, con más intensidad cuanto mayor sea el valor. Así que, por ejemplo, `{r: 15, g: 0, b: 0}` produce un resplandor rojo muy brillante.
{% endhint %}

Ver [tipos de color](/creator/content-creator-es/scenes-sdk7/fundamentos-del-contenido-3d/color-types.md) para más detalles sobre cómo establecer colores.

También puedes editar los siguientes campos en un Material PBR para ajustar cómo se percibe su color:

* *emissiveColor*: El color emitido por el material.
* *reflectivityColor*: También conocido como *Specular Color* en otra nomenclatura.

Para crear un material de color plano que no se vea afectado por la luz y las sombras del entorno, crea un material básico en lugar de un material PBR.

```ts
Material.setBasicMaterial(myEntity, {
	diffuseColor: Color4.Black(),
})
```

## Uso de texturas

Establece un archivo de imagen como textura en un material configurando el `texture` parámetro.

```ts
//Crear entidad y asignar forma
const meshEntity = engine.addEntity()
Transform.create(meshEntity, {
	position: Vector3.create(4, 1, 4),
})
MeshRenderer.setBox(meshEntity)

//Crear material y configurar sus campos
Material.setPbrMaterial(meshEntity, {
	texture: Material.Texture.Common({
		src: 'assets/materials/wood.png',
	}),
})
```

En el ejemplo anterior, la imagen del material está ubicada en una `assets/materials` carpeta, que se encuentra en el nivel raíz de la carpeta del proyecto de la escena.

{% hint style="info" %}
**💡 Consejo**: Te recomendamos mantener tus archivos de imagen de textura en alguna parte de la carpeta `/assets` dentro de tu escena.
{% endhint %}

Al crear una textura, también puedes pasar parámetros adicionales:

* `filterMode`: Determina cómo se estiran o comprimen los píxeles de la textura cuando se renderiza. Esto toma un valor del `TextureFilterMode` enum. Consulta [Escalado de textura](#texture-scaling).
* `wrapMode`: Determina cómo se mosaica una textura sobre un objeto. Esto toma un valor del `TextureWrapMode` enum. Consulta [Envoltura de textura](#texture-wrapping).

```ts
Material.setPbrMaterial(myEntity, {
	texture: Material.Texture.Common({
		src: 'assets/materials/wood.png',
		filterMode: TextureFilterMode.TFM_BILINEAR,
		wrapMode: TextureWrapMode.TWM_CLAMP,
	}),
})
```

Para crear una textura que no se vea afectada por la luz y las sombras del entorno, crea un material básico en lugar de un material PBR.

```ts
Material.setBasicMaterial(myEntity, {
	texture: Material.Texture.Common({
		src: 'assets/materials/wood.png',
	}),
})
```

### Texturas desde una URL externa

Puedes apuntar la textura de tu material a una URL externa en lugar de una ruta interna en el proyecto de la escena.

```ts
Material.setBasicMaterial(myEntity, {
	texture: Material.Texture.Common({
		src: 'https://wearable-api.decentraland.org/v2/collections/community_contest/wearables/cw_tuxedo_tshirt_upper_body/thumbnail',
	}),
})
```

La URL debe comenzar con `https`, `http` Las URLs no son compatibles.

### Envoltura de textura

Puedes establecer cómo se alinea una textura con una superficie. De forma predeterminada, la textura se estira para ocupar la superficie una vez, pero puedes escalarla y desplazarla.

Los siguientes campos están disponibles en todas las texturas:

* `offset`: Desplaza la textura para cambiar su alineación. El valor es un Vector2, donde ambos ejes van de 0 a 1, donde 1 es el ancho o la altura completos de la textura.
* `tiling`: Escala la textura. El valor predeterminado es el Vector2 `[1, 1]`, lo que hace que la imagen se repita una vez cubriendo toda la superficie.
* `TextureWrapMode`: Determina qué sucede si el mosaico de la imagen no cubre toda la superficie. Esta propiedad toma sus valores del `TextureWrapMode` enum, que permite los siguientes valores:
  * `TextureWrapMode.TWM_CLAMP`: La textura solo se muestra una vez en el tamaño especificado. El resto de la superficie del mesh queda transparente. El valor de `tiling` se ignora.
  * `TextureWrapMode.TWM_REPEAT`: La textura se repite tantas veces como quepa en el mesh, usando el tamaño especificado.
  * `TextureWrapMode.TWM_MIRROR`: Al igual que en wrap, la textura se repite tantas veces como quepa, pero la orientación de estas repeticiones se refleja en espejo.

```ts
Material.setPbrMaterial(myEntity, {
	texture: Material.Texture.Common({
		src: 'assets/materials/wood.png',
		wrapMode: TextureWrapMode.TWM_REPEAT,
		offset: Vector2.create(0, 0.2),
		tiling: Vector2.create(1, 1),
	}),
})
```

{% hint style="warning" %}
**📔 Nota**: El `offset` y `tiling` estas propiedades solo son compatibles con el cliente de escritorio DCL 2.0.
{% endhint %}

Usa esta función para cubrir una superficie grande con un patrón en mosaico. Por ejemplo, repite la siguiente imagen:

![](https://1216664193-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-e0324d6080a0e815b172eafd56b5ece426ca68ca%2Ftiles.png?alt=media\&token=33b26659-761d-4005-9c43-29ca542204d1)

```ts
Material.setPbrMaterial(myEntity, {
	texture: Material.Texture.Common({
		src: 'assets/materials/wood.png',
		wrapMode: TextureWrapMode.TWM_REPEAT,
		tiling: Vector2.create(8, 8),
	}),
})
```

![](https://1216664193-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-6e66e1936998029bf4cd65f497509ae21896809a%2Ftiles-in-scene.png?alt=media\&token=42961e2a-7050-457b-9e2b-768497de08b5)

En el ejemplo siguiente, la textura usa un *espejo* modo de envoltura, y cada repetición de la textura ocupa solo 1/4 de la superficie. Esto significa que veremos 4 copias de la imagen, reflejadas entre sí en ambos ejes.

```ts
Material.setPbrMaterial(myEntity, {
	texture: Material.Texture.Common({
		src: 'materials/atlas.png',
		wrapMode: TextureWrapMode.TWM_MIRROR,
		tiling: Vector2.create(0.25, 0.25),
	}),
})
```

### Tweens de textura

Haz que una textura se deslice suavemente usando un `Tween` componente, configurado con el `TextureMove` modo. El tween cambia gradualmente el valor de la `offset` o las `tiling` propiedades de una textura a lo largo de un período de tiempo, de manera fluida y optimizada.

{% hint style="warning" %}
**📔 Nota**: Esta función solo es compatible con el cliente de escritorio DCL 2.0.
{% endhint %}

Usa el `Tween` componente con la `setTextureMove` función para mover la textura entre dos posiciones.

```ts
Tween.setTextureMove(myEntity, Vector2.create(0, 0), Vector2.create(1, 0), 2000)
```

El tween de textura toma la siguiente información:

* `entity`: La entidad cuya textura se va a mover
* `start`: Un Vector2 para la posición inicial
* `end`: Un Vector2 para la posición final
* `duration`: Cuántos milisegundos tarda en moverse entre las dos posiciones

También está disponible este otro parámetro opcional:

* `movementType`: define si el movimiento estará en el `offset` o las `tiling` campo. Por defecto usa `offset`.
* `easingFunction`: La curva de la tasa de cambio a lo largo del tiempo, el valor predeterminado es `EasingFunction.EF_LINEAR`. Otros valores hacen que el cambio acelere o desacelere a distintas velocidades.

```ts
const myEntity = engine.addEntity()

MeshRenderer.setPlane(myEntity)

Transform.create(myEntity, {
	position: Vector3.create(4, 1, 4),
})

Material.setPbrMaterial(myEntity, {
	texture: Material.Texture.Common({
		src: 'materials/water.png',
		wrapMode: TextureWrapMode.TWM_REPEAT,
	}),
})

Tween.setTextureMove(myEntity, Vector2.create(0, 0), Vector2.create(0, 1), 1000)
```

El ejemplo anterior ejecuta un tween que dura 1 segundo y mueve la textura solo una vez. Para lograr un movimiento continuo, por ejemplo para simular la caída de una cascada, necesitas usar `setTextureMoveContinuous`.

```ts
const myEntity = engine.addEntity()

MeshRenderer.setPlane(myEntity)

Transform.create(myEntity, {
	position: Vector3.create(4, 1, 4),
})

Material.setPbrMaterial(myEntity, {
	texture: Material.Texture.Common({
		src: 'materials/water.png',
		wrapMode: TextureWrapMode.TWM_REPEAT,
	}),
})

Tween.setTextureMoveContinuous(myEntity, Vector2.create(0, 1), 1)
```

El ejemplo anterior usa `setTextureMoveContinuous`, con una dirección de `(0, 1)`, y una velocidad de 1 unidad por segundo.

El tween continuo de textura toma la siguiente información:

* `entity`: La entidad cuya textura se va a mover
* `direction`: Un Vector2 para el movimiento
* `speed`: Cuántas unidades por segundo se moverá la entidad

También están disponibles estos otros parámetros opcionales:

* `movementType`: define si el movimiento estará en el campo offset o en el campo tiling. Por defecto usa offset.
* `duration`: Cuántos milisegundos se mantendrá el movimiento. Después de este tiempo, el movimiento se detendrá.

**Secuencias complejas de tween**

También puedes hacer que los movimientos de textura sigan una secuencia compleja con tantos pasos como quieras. Usa el `campo sequence` para listar tantos tweens como quieras; se ejecutarán secuencialmente después del primer tween descrito en el `Tween` componente.

```ts
//(...)
Tween.setTextureMove(myEntity, Vector2.create(0, 0), Vector2.create(0, 1), 1000)

TweenSequence.create(myEntity, {
	sequence: [
		{
			mode: Tween.Mode.TextureMove({
				start: Vector2.create(0, 1),
				end: Vector2.create(1, 1),
			}),
			duration: 1000,
			easingFunction: EasingFunction.EF_LINEAR,
		},
		{
			mode: Tween.Mode.TextureMove({
				start: Vector2.create(1, 1),
				end: Vector2.create(1, 0),
			}),
			duration: 1000,
			easingFunction: EasingFunction.EF_LINEAR,
		},
		{
			mode: Tween.Mode.TextureMove({
				start: Vector2.create(1, 0),
				end: Vector2.create(0, 0),
			}),
			duration: 1000,
			easingFunction: EasingFunction.EF_LINEAR,
		},
	],
	loop: TweenLoop.TL_RESTART,
})
```

Ten en cuenta que, al definir un tween dentro de un TweenSequence, necesitas usar el formato más detallado de `Tween.Mode.TextureMove` para definir el tween.

### Texturas multicapa

Puedes usar varios archivos de imagen como capas para componer texturas más realistas, por ejemplo incluyendo una `bumpTexture` y una `emissiveTexture`.

```ts
Material.setPbrMaterial(myEntity, {
	texture: Material.Texture.Common({
		src: 'materials/wood.png',
	}),
	bumpTexture: Material.Texture.Common({
		src: 'materials/woodBump.png',
	}),
	emissiveTexture: Material.Texture.Common({
		src: 'materials/glow.png',
	}),
})
```

La `bumpTexture` puede simular relieves y arrugas en una superficie, modificando cómo se comportan las normales de la superficie en cada píxel.

![](https://1216664193-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-b8e239e871864457936864ad2e8021a22338b8ad%2Fwood-bump.png?alt=media\&token=30c048c4-50a0-42b8-8cb2-a3dd29c8c273)

La `emissiveTexture` puede acentuar el brillo en ciertas partes de un material para lograr efectos muy interesantes.

**Configurar UVs**

Otra alternativa para cambiar la escala o la alineación de una textura es configurar las propiedades *uv* en el [componente MeshRenderer](/creator/content-creator-es/scenes-sdk7/fundamentos-del-contenido-3d/shape-components.md).

Estableces *u* y *v* coordenadas en la imagen 2D de la textura para que correspondan a los vértices de la forma. Cuantos más vértices tenga la entidad, más *uv* coordenadas deben definirse en la textura; por ejemplo, un plano necesita tener 8 *uv* puntos definidos, 4 para cada una de sus dos caras.

```ts
const meshEntity = engine.addEntity()
Transform.create(meshEntity, {
	position: Vector3.create(4, 1, 4),
})
MeshRenderer.setPlane(
	meshEntity,
	[
		0, 0.75,

		0.25, 0.75,

		0.25, 1,

		0, 1,

		0, 0.75,

		0.25, 0.75,

		0.25, 1,

		0, 1,
	]
)

Material.setPbrMaterial(myEntity, {
	texture: Material.Texture.Common({
		src: 'materials/wood.png',
		wrapMode: TextureWrapMode.TWM_REPEAT,
	}),
})
```

El siguiente ejemplo incluye una función que simplifica la configuración de uvs. La función `setUVs` definida aquí recibe un número de filas y columnas como parámetros, y establece los uvs para que la imagen de la textura se repita un número específico de veces.

```ts
const meshEntity = engine.addEntity()
Transform.create(meshEntity, {
	position: Vector3.create(4, 1, 4),
})
MeshRenderer.setBox(meshEntity, setUVs(3, 3))

Material.setPbrMaterial(myEntity, {
	texture: Material.Texture.Common({
		src: 'materials/atlas.png',
		wrapMode: TextureWrapMode.TWM_REPEAT,
	}),
})

function setUVs(rows: number, cols: number) {
	return [
		// Lado norte del plano sin rotar
		0, // esquina inferior izquierda
		0,

		cols, // esquina inferior derecha
		0,

		cols, // esquina superior derecha
		rows,

		0, // esquina superior izquierda
		rows,

		// Lado sur del plano sin rotar
		cols, // esquina inferior derecha
		0,

		0, // esquina inferior izquierda
		0,

		0, // esquina superior izquierda
		rows,

		cols, // esquina superior derecha
		rows,
	]
}
```

Para establecer los UVs de una `caja` forma de mesh, se aplica la misma estructura. Cada una de las 6 caras del cubo toma 4 pares de coordenadas, uno para cada esquina. Los 48 valores se listan como un solo array.

{% hint style="warning" %}
**📔 Nota**: Las propiedades UV actualmente solo están disponibles en `plane` y en `caja` formas. Además, *uv* los valores afectan a todas las capas de textura por igual, ya que se establecen en la *forma*.
{% endhint %}

### Escalado de textura

Cuando las texturas se estiran o encogen a un tamaño diferente del de la imagen de textura original, esto a veces puede crear artefactos. En un entorno 3D, los efectos de la perspectiva provocan esto de forma natural. Existen varios [algoritmos de filtrado de texturas](https://en.wikipedia.org/wiki/Texture_filtering) que existen para compensarlo de distintas maneras.

La `Material` el objeto usa el *bilineal* algoritmo de forma predeterminada, pero te permite configurarlo para usar el *vecino más cercano* o *trilineal* algoritmos en su lugar estableciendo la `filterMode` propiedad de la textura. Esto toma un valor del `TextureFilterMode` enum:

* `TextureFilterMode.TFM_POINT`: Usa un algoritmo de "vecino más cercano". Esta configuración es ideal para gráficos estilo pixel art, ya que los contornos permanecerán nítidamente marcados al verse la textura más grande en pantalla, en lugar de verse borrosos.
* `TextureFilterMode.TFM_BILINEAR`: Usa un algoritmo bilineal para estimar el color de cada píxel.
* `TextureFilterMode.TFM_TRILINEAR`: Usa un algoritmo trilineal para estimar el color de cada píxel.

```ts
Material.setPbrMaterial(myEntity, {
	texture: Material.Texture.Common({
		src: 'materials/atlas.png',
		filterMode: TextureFilterMode.TFM_BILINEAR,
	}),
})
```

## Materiales sin iluminación

La mayoría de las veces querrás que los materiales de tu escena se vean afectados por las condiciones de iluminación, incluidas las sombras y los matices de los cambios de tono de las distintas horas del día. Pero en otros casos quizá quieras mostrar los colores en su estado puro. Esto es útil al reproducir videos, o también para marcadores abstractos que necesitan destacar y que están pensados para señalar pistas al jugador.

Para crear un material sin iluminación, usa `Material.setBasicMaterial`. Los materiales básicos no tienen todas las mismas propiedades que los materiales PBR; solo tienen las esenciales:

* `diffuseColor`: Color4 para el color
* `texture`: Texture
* `alphaTexture`: Textura separada para la capa de transparencia
* `alphaTest`: Umbral para lograr transparencia según el color de la textura
* `castShadows`: Si es falso, no se proyectan sombras sobre otras entidades de la escena.

```ts
Material.setBasicMaterial(screen, {
	diffuseColor: Color4.Red(),
})
```

## Retratos de Avatar

Para mostrar una imagen en miniatura de cualquier jugador, usa `Material.Texture.Avatar` al configurar la textura de tu material, pasando la dirección de un jugador existente. Esto crea una textura a partir de una imagen de 256x256 del jugador, mostrando cabeza y hombros. El jugador se muestra llevando el conjunto de wearables que el servidor actual registró por última vez.

```ts
Material.setPbrMaterial(myEntity, {
	texture: Material.Texture.Avatar({
		userId: '0x517....',
	}),
})
```

![](https://1216664193-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-76248b67a42c940111a0d827d74acde8d5093f73%2FavatarTexture.png?alt=media\&token=cc232037-1e1e-4107-8f92-17b77e4a6521)

Puedes obtener el retrato de cualquier jugador de Decentraland, incluso si no está conectado actualmente, e incluso si no tiene un nombre de Decentraland reclamado.

Las siguientes propiedades son compatibles dentro del objeto que pasas como argumento:

* `userId`: ID del usuario cuyo perfil quieres mostrar
* `filterMode`: Determina cómo se estiran o comprimen los píxeles de la textura cuando se renderiza. Esto toma un valor del `TextureFilterMode` enum. Consulta [Escalado de textura](#texture-scaling).
* `wrapMode`: Determina cómo se mosaica una textura sobre un objeto. Esto toma un valor del `TextureWrapMode` enum. Consulta [Envoltura de textura](#texture-wrapping).

## Materiales transparentes

Para hacer transparente un material con un color plano, simplemente define el color como un `Color4`, y establece el cuarto valor en algo entre *0* y *1*. Cuanto más cerca de *1*, más opaco será.

```typescript
let transparentRed = Color4.create(1, 0, 0, 0.5)

Material.setPbrMaterial(meshEntity, {
	albedoColor: transparentRed,
})
```

Si un material usa una textura .png que incluye transparencia, será opaco por defecto, pero puedes activar su transparencia configurando el `transparencyMode` a `MaterialTransparencyMode.MTM_ALPHA_BLEND`.

![](https://1216664193-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-7cf6142ee2bc727894e78f01d271556822ebe0fc%2Ftransparent-image.png?alt=media\&token=610b0414-bbdd-442a-ada9-7475df626999)

```typescript
Material.setPbrMaterial(floor, {
	texture: Material.Texture.Common({
		src: 'assets/scene/transparent-image.png',
	}),
	transparencyMode: MaterialTransparencyMode.MTM_ALPHA_BLEND,
})
```

La `transparencyMode` puede tener los siguientes valores:

* `MaterialTransparencyMode.MTM_OPAQUE`: Sin transparencia alguna
* `MaterialTransparencyMode.MTM_ALPHA_TEST`: Cada píxel es completamente opaco o completamente transparente, según un umbral.
* `MaterialTransparencyMode.MTM_ALPHA_BLEND`: Son posibles valores intermedios según el valor de cada píxel.
* `MaterialTransparencyMode.MTM_ALPHA_TEST_AND_ALPHA_BLEND`: Usa una combinación de ambos métodos.
* `MaterialTransparencyMode.MTM_AUTO`: Determina el método en función de la textura proporcionada.

Si configuras el `transparencyMode` a `MaterialTransparencyMode.MTM_ALPHA_TEST`, puedes ajustar finamente el umbral utilizado para determinar si cada píxel es transparente o no. Establece la `alphaTest` propiedad entre *0* y *1*. Por defecto, su valor es *0.5*.

```ts
// Usando alpha test
Material.setPbrMaterial(meshEntity1, {
	texture: Material.Texture.Common({
		src: 'images/myTexture.png',
	}),
	transparencyMode: MaterialTransparencyMode.MTM_ALPHA_TEST,
	alphaTest: 1,
})
```

Al usar un [material unlit](#unlit-materials), puedes añadir un `alphaTexture` para hacer que solo ciertas regiones del material sean transparentes, basándose en una textura.

{% hint style="warning" %}
**📔 Nota**: Debe ser una imagen de un solo canal. En esta imagen usa el color rojo o negro para determinar qué partes de la textura real deben ser transparentes.
{% endhint %}

![](https://1216664193-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-29eeafc704d19336cc3b0dc023c91e278b4bcd94%2Fcircular-video-screen.png?alt=media\&token=13d1560a-3d64-4a17-943c-25338f931f48)

```ts
// Usando alpha test
Material.setPbrMaterial(meshEntity1, {
	texture: Material.Texture.Common({
		src: 'images/myTexture.png',
	}),
	alphaTexture: Material.Texture.Common({
		src: 'assets/scene/circle_mask.png',
		wrapMode: TextureWrapMode.TWM_MIRROR,
	}),
})
```

Esto puede usarse de formas muy interesantes junto con videos. Consulta [video playing](/creator/content-creator-es/scenes-sdk7/media/video-playing.md).

## Video en reproducción

Para transmitir video desde una URL a un material, o reproducir un video desde un archivo almacenado en la escena, consulta [video playing](/creator/content-creator-es/scenes-sdk7/media/video-playing.md).

El video se usa como textura en un material; puedes establecer cualquiera de las otras propiedades de los materiales para alterar cómo se ve la pantalla del video.

## Sintaxis avanzada

La sintaxis completa para crear un `Materiales` componente, sin ningún helper para simplificarlo, se ve así:

```ts
Material.create(myEntity, {
	material: {
		$case: 'pbr',
		pbr: {
			texture: {
				tex: {
					$case: 'texture',
					texture: {
						src: 'images/scene-thumbnail.png',
					},
				},
			},
		},
	},
})

Material.create(myEntity, {
	material: {
		$case: 'pbr',
		pbr: {
			texture: {
				tex: {
					$case: 'avatarTexture',
					avatarTexture: {
						userId: '0x517....',
					},
				},
			},
		},
	},
})
```

Así es como el protocolo base interpreta los componentes Material. Las funciones auxiliares abstraen esto y exponen una sintaxis más amigable, pero entre bastidores generan esta sintaxis.

La `$case` los campos te permiten especificar uno de los tipos permitidos. Cada tipo admite un conjunto distinto de parámetros. Hay dos niveles de `$case` aquí:

* La `material` campo admite los valores `pbr` y `unlit`, para definir el tipo de material.
* La `tex` campo dentro de una textura admite los siguientes valores, para definir el tipo de textura:
  * `texture`
  * `avatarTexture`
  * `videoTexture`

Dependiendo del valor de `$case`, es válido definir el objeto para el tipo correspondiente, pasando cualquier propiedad relevante.

Para añadir un `Material` componente a una Entity que potencialmente ya tiene una instancia de este componente, usa `Material.createOrReplace()`. Las funciones auxiliares como `Material.setPbrMaterial()` se encargan de sobrescribir las instancias existentes del componente, pero ejecutar `Material.create()` en una Entity que ya tiene este componente devuelve un error.

## Modificar materiales glTF

Usa el `GltfNodeModifiers` componente para modificar los materiales de un *glTF* modelo. Este componente te permite sobrescribir los materiales de un *glTF* modelo con tus propios materiales. Puedes usar cualquiera de las propiedades del `Material` componente, incluidas texturas, texturas de video, materiales unlit, etc.

Hay dos maneras de usar el `GltfNodeModifiers` componente:

* Modifica el material de todo el modelo dejando la `path` propiedad como una cadena vacía.
* Modifica el material de un nodo específico del modelo (o de varios nodos) configurando la `path` propiedad con la ruta al nodo.

### Modifica el material de todo el modelo

El siguiente ejemplo muestra cómo modificar el material de un *glTF* modelo. En este caso, el material de todo el modelo se modifica para que sea rojo.

```ts
import { GltfNodeModifiers, GltfContainer, Transform } from '@dcl/sdk/ecs'

const myEntity = engine.addEntity()

GltfContainer.create(myEntity, {
	src: 'models/myModel.glb',
})

Transform.create(myEntity, {
	position: Vector3.create(4, 0, 4),
})

GltfNodeModifiers.create(myEntity, {
	modifiers: [
		{
			path: '',
			material: {
				material: {
					$case: 'pbr',
					pbr: {
						albedoColor: Color4.Red(),
					},
				},
			},
		},
	],
})
```

La `GltfNodeModifiers` el componente tiene las siguientes propiedades:

* `modifiers`: Un array de modificadores. Cada modificador tiene las siguientes propiedades:
  * `path`: La ruta al nodo del modelo que se va a modificar.
  * `material`: El material a usar.

La `path` La propiedad es una cadena que representa la ruta al nodo en el *glTF* modelo que se va a modificar. Si quieres modificar el material de todo el model, puedes usar una cadena vacía. Si quieres modificar el material de un nodo específico, puedes usar la ruta al nodo. La ruta debe apuntar a un nodo mesh, no a un nodo de vértice.

{% hint style="info" %}
**💡 Consejo**: Puedes usar la [aplicación Babylon Sandbox](https://sandbox.babylonjs.com/) para inspeccionar el *glTF* modelo y encontrar la ruta al nodo que quieres modificar.

Sin embargo, en algunos modelos, Babylon Sandbox puede listar rutas que pertenecen a vértices en lugar de meshes, lo cual no funcionará. Si intentas usar una ruta que no es válida, la consola de la escena mostrará un mensaje de error que incluye la lista completa de rutas válidas en ese modelo.
{% endhint %}

La `material` La propiedad es un objeto que representa el material a usar. Debe escribirse usando la [sintaxis avanzada](#advanced-syntax) para materiales, como se muestra en el ejemplo anterior. Funciones auxiliares como `Material.setPbrMaterial()` no pueden usarse aquí.

### Modifica el material de un nodo específico del modelo

El siguiente ejemplo muestra cómo modificar el material de un nodo específico en el *glTF* modelo. En este caso, el material de la cabeza se modifica para usar una textura alternativa.

```ts
import { GltfNodeModifiers, GltfContainer, Transform } from '@dcl/sdk/ecs'

const myEntity = engine.addEntity()

GltfContainer.create(myEntity, {
	src: 'models/myModel.glb',
})

Transform.create(myEntity, {
	position: Vector3.create(4, 0, 4),
})

GltfNodeModifiers.create(myEntity, {
	modifiers: [
		{
			path: 'M_Head_BaseMesh',
			material: {
				material: {
					$case: 'pbr',
					pbr: {
						texture: Material.Texture.Common({
							src: 'assets/scene/images/blinking-head.png',
						}),
					},
				},
			},
		},
	],
})
```

Un `GltfNodeModifiers` puede contener varios modificadores, cada uno modificando un nodo diferente del modelo. El siguiente ejemplo muestra cómo modificar el material de la cabeza y el cuerpo de un *glTF* modelo.

```ts
import { GltfNodeModifiers, GltfContainer, Transform } from '@dcl/sdk/ecs'

const myEntity = engine.addEntity()

GltfContainer.create(myEntity, {
	src: 'models/myModel.glb',
})

Transform.create(myEntity, {
	position: Vector3.create(4, 0, 4),
})

GltfNodeModifiers.create(myEntity, {
	modifiers: [
		{
			path: 'M_Head_BaseMesh',
			material: {
				material: {
					$case: 'pbr',
					pbr: {
						albedoColor: Color4.Red(),
					},
				},
			},
		},
		{
			path: 'M_Body_BaseMesh',
			material: {
				material: {
					$case: 'pbr',
					pbr: {
						albedoColor: Color4.Blue(),
					},
				},
			},
		},
	],
})
```

### Modificar campos de un material existente

El componente Material proporciona una interfaz simplificada para acceder y modificar las propiedades del componente Material. Elimina la necesidad de navegar por estructuras union profundamente anidadas (`PBR` frente a `Unlit`, `texture` frente a `avatarTexture` frente a `videoTexture`), haciendo que la manipulación de materiales sea más intuitiva y menos propensa a errores.

Los siguientes métodos permiten manipular fácilmente el `Material` componente:

* `Material.getFlat(entity: Entity): ReadonlyFlatMaterial`: Devuelve un **solo lectura** `FlatMaterial` objeto accessor que proporciona acceso directo de lectura a las propiedades del material. Devolverá un error si la Entity no tiene un `Material` componente. Para evitar esto, los siguientes métodos pueden usarse como alternativa.

```ts
const src = Material.getFlat(entity).texture.src
```

* `Material.getFlatOrNull(entity: Entity): ReadonlyFlatMaterial | null`: Devuelve un **solo lectura o null**, dependiendo de si la Entity tiene o no un `Material` componente.

```ts
const src = Material.getFlatOrNull(entity)?.texture.src
```

* `Material.getFlatMutable(entity: Entity): FlatMaterial`: Devuelve un **lectura y escritura** `FlatMaterial`objeto que permite modificar sus propiedades. Lanzará un error si la Entity llamada no tiene el `Material` componente.

```ts
const src = Material.getFlatMutable(entity).texture.src
```

* `Material.getFlatMutableOrNull(entity: Entity): FlatMaterial | null`: Devuelve un **lectura y escritura o null** `FlatMaterial` objeto que permite modificar sus propiedades. En caso de que la Entity no tenga un `componente Material`, devolverá `null`.

```ts
const flatMaterial = Material.getFlatMutableOrNull(entity)
if (flatMaterial) {
	flatMaterial.texture.src = myNewTextureFile
}
```

### Eliminar sombras de un modelo glTF

Para eliminar sombras de un *glTF* modelo, puedes establecer la `castShadows` propiedad en `false` en el `GltfNodeModifiers` objeto. Esto conserva el material original del modelo, pero evita que proyecte sombras. Esto es útil para modelos que no están pensados para proyectar sombras, como haces de luz.

```ts
import { GltfNodeModifiers } from '@dcl/sdk/ecs'

GltfNodeModifiers.create(myEntity, {
	modifiers: [
		{
			path: '',
			castShadows: false,
		},
	],
})
```

{% hint style="info" %}
**💡 Consejo**: Las texturas usadas en materiales también pueden aplicarse a efectos de partículas. Consulta [Particle System](/creator/content-creator-es/scenes-sdk7/fundamentos-del-contenido-3d/particle-system.md) para obtener detalles sobre el uso de texturas personalizadas y sprite sheets con partículas.
{% endhint %}

{% hint style="info" %}
**💡 Consejo**: Para ver ejemplos prácticos de materiales, consulta el [`52,-52-testing-gallery`](https://github.com/decentraland/sdk7-test-scenes/tree/main/scenes/52,-52-testing-gallery) escena de prueba, que muestra combinaciones de metallic/roughness/emissive/normal-map una al lado de la otra, [`74,-8-gltfnodemodifier`](https://github.com/decentraland/sdk7-test-scenes/tree/main/scenes/74,-8-gltfnodemodifier), que sobrescribe materiales PBR y unlit en nodos GLTF individuales, y [`0,3-texture-movement`](https://github.com/decentraland/sdk7-test-scenes/tree/main/scenes/0,3-texture-movement), que anima el desplazamiento y el mosaico de la textura.
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.decentraland.org/creator/content-creator-es/scenes-sdk7/fundamentos-del-contenido-3d/materials.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
