# Materials

## Materials

Materiais podem ser aplicados a entidades que usam formas primitivas (cubo, esfera, plano, etc) adicionando um `Material` componente. Este componente possui vários campos que permitem configurar as propriedades do material, adicionar uma textura, etc.

*arquivo glTF* modelos incluem seus próprios materiais que são implicitamente importados para uma cena junto com o modelo. Para modificar ou sobrescrever esses materiais, use o `GltfNodeModifiers` componente. Veja [Modify glTF materials](#modify-gltf-materials) para mais detalhes.

Ao importar um modelo 3D com seus próprios materiais, tenha em mente que nem todos os shaders são suportados pelo engine do Decentraland. Apenas materiais padrão e materiais PBR (physically based rendering) são suportados. Veja [considerações sobre modelos 3D externos](https://github.com/decentraland/docs-creator/blob/main/creator/3d-modeling/materials/README.md) para mais detalhes.

Existem diferentes tipos de materiais suportados:

* PBR (Physically Based Rendering): O tipo mais comum de material no Decentraland. Ele suporta cores sólidas ou texturas, e diferentes propriedades como metallic, emissive, transparency, etc. Leia mais sobre [PBR](https://en.wikipedia.org/wiki/Physically_based_rendering).
* Materiais básicos: Eles não respondem a luzes e sombras, o que os torna ideais para exibir imagens em billboard.

## Use o Scene Editor no Creator Hub

A maneira mais fácil de dar um Material a uma entidade é usar o Scene Editor. Você pode adicionar um **Material** componente à sua entidade e então configurar todos os campos disponíveis na UI do Scene Editor. Veja [Add Components](https://github.com/decentraland/docs/blob/main/creator/sdk7/scene-editor/build/components.md#add-components).

## Adicionar um material

O exemplo a seguir cria um material PBR e define alguns de seus campos para dar-lhe uma cor vermelha e propriedades metálicas. Este material é adicionado a uma entidade que também tem uma forma de caixa, então ele colorirá a caixa com este material.

```ts
//Criar entidade e atribuir forma
const meshEntity = engine.addEntity()
Transform.create(meshEntity, {
	position: Vector3.create(4, 1, 4),
})
MeshRenderer.setBox(meshEntity)

//Criar material e configurar seus campos
Material.setPbrMaterial(meshEntity, {
	albedoColor: Color4.Red(),
	metallic: 0.8,
	roughness: 0.1,
})
```

Para mudar o material de uma entidade que já possui um `Material` componente, execute `Material.setPbrMaterial()` ou qualquer uma das outras funções auxiliares e isso sobrescreverá o material original. Não há necessidade de remover o `Material` original ou de usar a sintaxe avançada.

```ts
//Criar entidade e atribuir forma
const meshEntity = engine.addEntity()
Transform.create(meshEntity, {
	position: Vector3.create(4, 1, 4),
})
MeshRenderer.setBox(meshEntity)

//Criar material e configurar seus campos
Material.setPbrMaterial(meshEntity, {
	albedoColor: Color4.Red(),
})

//Sobrescrever com novo componente de material
Material.setPbrMaterial(meshEntity, {
	albedoColor: Color4.Blue(),
})
```

{% hint style="warning" %}
**📔 Nota**: O `Material` componente deve ser importado via

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

Veja [Imports](https://github.com/decentraland/docs/blob/main/creator/sdk7/sdk7/getting-started/coding-scenes.md#imports) para como lidar com estes facilmente.
{% endhint %}

## Cores do Material

Dê a um material uma cor sólida. Em um Material PBR, você define o `albedoColor` campo. Cores de albedo respondem à luz e podem incluir sombreamentos.

Valores de cor são do tipo `Color4`, composto de *r*, *g* e *b* valores (red, green, and blue). Cada um deles assume valores entre 0 e 1. Definindo valores diferentes para esses, você pode compor qualquer cor visível. Para preto, defina todos os três para 0. Para branco, defina todos para 1.

{% hint style="warning" %}
**📔 Nota**: Se você definir qualquer cor em `albedoColor` para um valor maior que *1*, ela aparecerá como *emissive*, com maior intensidade quanto maior o valor. Então por exemplo, `{r: 15, g: 0, b: 0}` produz um brilho vermelho muito intenso.
{% endhint %}

Veja [tipos de cor](https://github.com/decentraland/docs/blob/main/creator/sdk7/sdk7/3d-essentials/color-types.md) para mais detalhes sobre como definir cores.

Você também pode editar os seguintes campos em um Material PBR para ajustar como sua cor é percebida:

* *emissiveColor*: A cor emitida pelo material.
* *reflectivityColor*: Também conhecido como *Specular Color* em outra nomenclatura.

Para criar um material de cor sólida que não seja afetado pela luz e sombras do ambiente, crie um material básico em vez de um material PBR.

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

## Usando texturas

Defina um arquivo de imagem como textura em um material definindo o `textura` parâmetro.

```ts
//Criar entidade e atribuir forma
const meshEntity = engine.addEntity()
Transform.create(meshEntity, {
	position: Vector3.create(4, 1, 4),
})
MeshRenderer.setBox(meshEntity)

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

No exemplo acima, a imagem para o material está localizada em um `assets/materials` diretório, que está localizado no nível raiz da pasta do projeto da cena.

{% hint style="info" %}
**💡 Tip**: Recomendamos manter seus arquivos de imagem de textura em algum lugar dentro de `/assets` pasta dentro da sua cena.
{% endhint %}

Ao criar uma textura, você também pode passar parâmetros adicionais:

* `filterMode`: Determina como os pixels na textura são esticados ou comprimidos quando renderizados. Isso assume um valor do `TextureFilterMode` enum. Veja [Escalonamento de Textura](#texture-scaling).
* `wrapMode`: Determina como uma textura é repetida sobre um objeto. Isso assume um valor do `TextureWrapMode` enum. Veja [Texture Wrapping](#texture-wrapping).

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

Para criar uma textura que não seja afetada por luz e sombras do ambiente, crie um material básico em vez de um material PBR.

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

### Texturas a partir de uma URL externa

Você pode apontar a textura do seu material para uma URL externa em vez de um caminho interno no projeto da cena.

```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',
	}),
})
```

A URL deve começar com `https`, `http` URLs não são suportadas. O site onde a imagem está hospedada também deve possuir [políticas CORS (Cross Origin Resource Sharing)](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing) que permitam acessá-la externamente.

### Texture wrapping

Você pode definir como uma textura se alinha com uma superfície. Por padrão, a textura é esticada para ocupar a superfície uma vez, mas você pode escalá-la e deslocá-la.

Os seguintes campos estão disponíveis em todas as texturas:

* `offset`: Desloca a textura para alterar seu alinhamento. O valor é um Vector2, onde ambos os eixos vão de 0 a 1, sendo 1 a largura ou altura completa da textura.
* `tiling`: Escala a textura. O valor padrão é o Vector2 `[1, 1]`, que faz a imagem repetir uma vez cobrindo toda a superfície.
* `TextureWrapMode`: Determina o que acontece se a repetição da imagem não cobrir toda a superfície. Esta propriedade assume seus valores do `TextureWrapMode` enum, que permite os seguintes valores:
  * `TextureWrapMode.TWM_CLAMP`: A textura é exibida apenas uma vez no tamanho especificado. O restante da superfície da malha fica transparente. O valor de `tiling` é ignorado.
  * `TextureWrapMode.TWM_REPEAT`: A textura é repetida quantas vezes couber na malha, usando o tamanho especificado.
  * `TextureWrapMode.TWM_MIRROR`: Como em wrap, a textura é repetida quantas vezes couber, mas a orientação dessas repetições é espelhada.

```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**: O `offset` e `tiling` propriedades são suportadas apenas no cliente desktop DCL 2.0.
{% endhint %}

Use este recurso para cobrir uma superfície grande com um padrão em ladrilho. Por exemplo, repita a seguinte imagem:

![](https://2402076176-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-e0324d6080a0e815b172eafd56b5ece426ca68ca%2Ftiles.png?alt=media)

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

![](https://2402076176-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-6e66e1936998029bf4cd65f497509ae21896809a%2Ftiles-in-scene.png?alt=media)

No exemplo abaixo, a textura usa um *mirror* modo de wrap, e cada repetição da textura ocupa apenas 1/4 da superfície. Isso significa que veremos 4 cópias da imagem, espelhadas entre si em ambos os eixos.

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

### Tween de textura

Faça uma textura deslizar suavemente usando um `Tween` componente, configurado com o `TextureMove` modo. O tween gradualmente altera o valor das `offset` ou o `tiling` propriedades de uma textura ao longo de um período de tempo, de forma suave e otimizada.

{% hint style="warning" %}
**📔 Nota**: Texture Tweens são um recurso suportado apenas no cliente desktop DCL 2.0.
{% endhint %}

Use o `Tween` componente com o `setTextureMove` função para mover a textura entre duas posições.

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

O tween de textura recebe as seguintes informações:

* `entidade`: A entidade cuja textura será movimentada
* `start`: Um Vector2 para a posição inicial
* `end`: Um Vector2 para a posição final
* `duration`: Quantos milissegundos leva para se mover entre as duas posições

Este outro parâmetro opcional também está disponível:

* `movementType`: define se o movimento será no campo `offset` ou o `tiling` . Por padrão usa-se `offset`.
* `easingFunction`: A curva para a taxa de mudança ao longo do tempo, o valor padrão é `EasingFunction.EF_LINEAR`. Outros valores fazem a mudança acelerar e/ou desacelerar em diferentes taxas.

```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)
```

O exemplo acima executa um tween que dura 1 segundo e move a textura apenas uma vez. Para alcançar um movimento contínuo, por exemplo para simular a queda de uma cascata, você precisa 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)
```

O exemplo acima usa `setTextureMoveContinuous`, com uma direção de `(0, 1)`, e uma velocidade de 1 unidade por segundo.

O tween contínuo de textura recebe as seguintes informações:

* `entidade`: A entidade cuja textura será movimentada
* `campo`: Um Vector2 para o movimento
* `Altere a velocidade com que uma animação é reproduzida alterando a propriedade`: Quantas unidades por segundo a entidade irá mover

Estes outros parâmetros opcionais também estão disponíveis:

* `movementType`: define se o movimento será no campo offset ou tiling. Por padrão usa offset.
* `duration`: Quantos milissegundos sustentar o movimento. Após esse tempo, o movimento irá parar.

**Sequências complexas de tween**

Você também pode fazer os movimentos da textura seguirem uma sequência complexa com quantos passos desejar. Use o `sequence` campo para listar quantos tweens quiser; eles serão executados sequencialmente após o primeiro tween descrito no `Tween` component.

```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,
})
```

Note que ao definir um tween dentro de um TweenSequence, você precisa usar o formato mais verboso de `Tween.Mode.TextureMove` para definir o tween.

### Texturas em múltiplas camadas

Você pode usar vários arquivos de imagem como camadas para compor texturas mais realistas, por exemplo incluindo uma `bumpTexture` e um `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',
	}),
})
```

O `bumpTexture` pode simular saliências e rugas em uma superfície, modificando como as normals da superfície se comportam em cada pixel.

![](https://2402076176-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-b8e239e871864457936864ad2e8021a22338b8ad%2Fwood-bump.png?alt=media)

O `emissiveTexture` pode acentuar o brilho em certas partes de um material, para alcançar efeitos muito interessantes.

**Definir UVs**

Outra alternativa para mudar a escala ou alinhamento de uma textura é configurar as *uv* propriedades no [componente MeshRenderer](https://github.com/decentraland/docs/blob/main/creator/sdk7/sdk7/3d-essentials/shape-components.md).

Você define as coordenadas *u* e *v* na imagem 2D da textura para corresponder aos vértices da forma. Quanto mais vértices a entidade tiver, mais *uv* coordenadas precisam ser definidas na textura; um plano por exemplo precisa ter 8 *uv* pontos definidos, 4 para cada uma de suas duas faces.

```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,
	}),
})
```

O exemplo a seguir inclui uma função que simplifica a definição de uvs. A `setUVs` função definida aqui recebe um número de linhas e colunas como parâmetros, e define os uvs para que a imagem de textura seja repetida um número específico de vezes.

```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 de plano não rotacionado
		0, // canto inferior esquerdo
		0,

		cols, // canto inferior direito
		0,

		cols, // canto superior direito
		rows,

		0, // canto superior esquerdo
		rows,

		// Lado sul de plano não rotacionado
		cols, // canto inferior direito
		0,

		0, // canto inferior esquerdo
		0,

		0, // canto superior esquerdo
		rows,

		cols, // canto superior direito
		rows,
	]
}
```

Para definir os UVs para uma `box` forma de malha, a mesma estrutura se aplica. Cada uma das 6 faces do cubo necessita de 4 pares de coordenadas, um para cada canto. Todos esses 48 valores são listados como um único array.

{% hint style="warning" %}
**📔 Nota**: Propriedades Uv atualmente estão disponíveis apenas em `plane` e em `box` formas. Além disso, *uv* valores afetam igualmente todas as camadas de textura, já que são definidos na *shape*.
{% endhint %}

### Escalonamento de textura

Quando texturas são esticadas ou reduzidas para um tamanho diferente da imagem de textura original, isso às vezes pode criar artefatos. Em um ambiente 3D, os efeitos de perspectiva causam isso naturalmente. Existem vários [algoritmos de texture filtering](https://en.wikipedia.org/wiki/Texture_filtering) que existem para compensar isso de maneiras diferentes.

O `Material` o objeto usa o algoritmo *bilinear* por padrão, mas permite configurá-lo para usar os algoritmos *nearest neighbor* ou *trilinear* em vez disso, definindo a propriedade `samplingMode` da textura. Isso assume um valor do `TextureFilterMode` enum:

* `TextureFilterMode.TFM_POINT`: Usa um algoritmo "nearest neighbor". Esta configuração é ideal para gráficos no estilo pixel art, pois os contornos permanecerão nitidamente marcados quando a textura for mostrada maior na tela em vez de serem borrados.
* `TextureFilterMode.TFM_BILINEAR`: Usa um algoritmo bilinear para estimar a cor de cada pixel.
* `TextureFilterMode.TFM_TRILINEAR`: Usa um algoritmo trilinear para estimar a cor de cada pixel.

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

## Materiais Unlit

Na maioria das vezes você vai querer que os materiais na sua cena sejam afetados pelas condições de iluminação, incluindo sombras e serem tinturados pelas mudanças de tonalidade em diferentes horas do dia. Mas em outros casos você pode querer mostrar as cores em seu estado puro. Isso é útil ao reproduzir vídeos, ou também para marcadores abstratos que precisam se destacar, que são destinados a sinalizar dicas ao jogador.

Para criar um material unlit, use `Material.setBasicMaterial`. Materiais básicos não têm todas as mesmas propriedades que materiais PBR, eles apenas têm o essencial:

* `diffuseColor`: Color4 para a cor
* `textura`: Texture
* `alphaTexture`: Textura separada para a camada de transparência
* `alphaTest`: Limiar para obter transparência com base na cor da textura
* `castShadows`: Se falso, nenhuma sombra é projetada sobre outras entidades na cena.

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

## Retratos de Avatar

Para exibir uma imagem em miniatura de qualquer jogador, use `Material.Texture.Avatar` ao definir a textura do seu material, passando o endereço de um player existente. Isso cria uma textura a partir de uma imagem 256x256 do jogador, mostrando cabeça e ombros. O jogador é exibido usando o conjunto de wearables que o servidor atual registrou por último.

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

![](https://2402076176-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-76248b67a42c940111a0d827d74acde8d5093f73%2FavatarTexture.png?alt=media)

Você pode buscar o retrato de qualquer jogador do Decentraland, mesmo que ele não esteja atualmente conectado, e mesmo que ele não tenha um NAME reivindicado no Decentraland.

As seguintes propriedades são suportadas dentro do objeto que você passa como argumento:

* `userId`: ID do usuário cujo perfil você deseja exibir
* `filterMode`: Determina como os pixels na textura são esticados ou comprimidos quando renderizados. Isso assume um valor do `TextureFilterMode` enum. Veja [Escalonamento de Textura](#texture-scaling).
* `wrapMode`: Determina como uma textura é repetida sobre um objeto. Isso assume um valor do `TextureWrapMode` enum. Veja [Texture Wrapping](#texture-wrapping).

## Materiais transparentes

Para tornar um material de cor sólida transparente, simplesmente defina a cor como um `Color4`, e defina o 4º valor para algo entre *0* e *1*. Quanto mais próximo de *1*, mais opaco ele será.

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

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

Se um material usa uma textura .png que inclui transparência, ele será opaco por padrão, mas você pode ativar sua transparência definindo o `transparencyMode` para `MaterialTransparencyMode.MTM_ALPHA_BLEND`.

![](https://2402076176-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-7cf6142ee2bc727894e78f01d271556822ebe0fc%2Ftransparent-image.png?alt=media)

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

O `transparencyMode` pode ter os seguintes valores:

* `MaterialTransparencyMode.MTM_OPAQUE`: Sem transparência alguma
* `MaterialTransparencyMode.MTM_ALPHA_TEST`: Cada pixel é completamente opaco ou completamente transparente, com base em um limiar.
* `MaterialTransparencyMode.MTM_ALPHA_BLEND`: Valores intermediários são possíveis com base no valor de cada pixel.
* `MaterialTransparencyMode.MTM_ALPHA_TEST_AND_ALPHA_BLEND`: Usa uma combinação de ambos os métodos.
* `MaterialTransparencyMode.MTM_AUTO`: Determina o método com base na textura fornecida.

Se você definir o `transparencyMode` para `MaterialTransparencyMode.MTM_ALPHA_TEST`, você pode ajustar finamente o limiar usado para determinar se cada pixel é transparente ou não. Defina a propriedade `alphaTest` entre *0* e *1*. Por padrão seu valor é *0.5*.

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

Ao usar um [material unlit](#unlit-materials), você pode adicionar um `alphaTexture` para tornar apenas certas regiões do material transparentes, com base em uma textura.

{% hint style="warning" %}
**📔 Nota**: Isso deve ser uma imagem de canal único. Nesta imagem use a cor vermelha ou preta para determinar quais partes da textura real devem ser transparentes.
{% endhint %}

![](https://2402076176-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-29eeafc704d19336cc3b0dc023c91e278b4bcd94%2Fcircular-video-screen.png?alt=media)

```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,
	}),
})
```

Isto pode ser usado de maneiras muito interessantes junto com vídeos. Veja [reprodução de vídeo](https://github.com/decentraland/docs/blob/main/creator/sdk7/sdk7/media/video-playing.md).

## Reprodução de vídeo

Para transmitir vídeo de uma URL para um material, ou reproduzir um vídeo de um arquivo armazenado na cena, veja [reprodução de vídeo](https://github.com/decentraland/docs/blob/main/creator/sdk7/sdk7/media/video-playing.md).

O vídeo é usado como uma textura em um material; você pode definir qualquer uma das outras propriedades dos materiais para alterar como a tela de vídeo aparece.

## para manter o ângulo da câmera fixo.

A sintaxe completa para criar um `Materials` componente, sem quaisquer helpers para simplificá-la, se parece com isto:

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

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

É assim que o protocolo base interpreta componentes Materials. As funções auxiliares abstraem isso e expõem uma sintaxe mais amigável, mas por trás dos panos elas produzem esta sintaxe.

O `$case` o campo permite que você especifique um dos tipos permitidos. Cada tipo suporta um conjunto diferente de parâmetros. No exemplo acima, o `box` tipo suporta um `uvs` campo.

Os valores suportados para `$case` são os seguintes:

* `textura`
* `avatarTexture`

Dependendo do valor de `$case`é válido definir o objeto para a forma correspondente, passando quaisquer propriedades relevantes.

Para adicionar um `Material` componente a uma entidade que potencialmente já tenha uma instância deste componente, use `Material.createOrReplace()`. As funções auxiliares como `MeshRenderer.setPbrMaterial()` lidam com a sobrescrição de instâncias existentes do componente, mas executar `Material.create()` em uma entidade que já possui este componente retorna um erro.

## Modify glTF materials

Use o `GltfNodeModifiers` componente para modificar os materiais de um *arquivo glTF* modelo. Este componente permite que você sobrescreva os materiais de um *arquivo glTF* modelo com seus próprios materiais. Você pode usar qualquer uma das propriedades do `Material` componente, incluindo textura, vídeo como textura, materiais unlit, etc.

Existem duas maneiras de usar o `GltfNodeModifiers` componente:

* Modifique o material de todo o modelo deixando a propriedade `path` como uma string vazia.
* Modifique o material de um nó específico no modelo (ou vários nós) definindo a propriedade `path` para o caminho do nó.

### Modificar o material de todo o modelo

O exemplo a seguir mostra como modificar o material de um *arquivo glTF* modelo. Neste caso, o material de todo o modelo é modificado para ficar vermelho.

```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(),
					},
				},
			},
		},
	],
})
```

O `GltfNodeModifiers` componente possui as seguintes propriedades:

* `modifiers`: Um array de modificadores. Cada modificador tem as seguintes propriedades:
  * `path`: O caminho para o nó no modelo a ser modificado.
  * `material`: O material a ser usado.

O `path` property é uma string que representa o caminho para o nó no *arquivo glTF* modelo a ser modificado. Se você quiser modificar o material de todo o modelo, você pode usar uma string vazia. Se você quiser modificar o material de um nó específico, você pode usar o caminho para o nó. O caminho deve apontar para um nó de mesh, não para um nó de vértice.

{% hint style="info" %}
**💡 Tip**: Você pode usar o [Babylon Sandbox app](https://sandbox.babylonjs.com/) para inspecionar o *arquivo glTF* modelo e encontrar o caminho para o nó que você deseja modificar.

Em alguns modelos, no entanto, o Babylon sandbox pode listar caminhos que pertencem a vértices em vez de meshes, o que não funcionará. Se você tentar usar um caminho que não seja válido, o console da cena exibirá uma mensagem de erro que inclui a lista completa de caminhos válidos naquele modelo.
{% endhint %}

O `material` property é um objeto que representa o material a ser usado. Ele precisa ser escrito usando a [advanced syntax](#advanced-syntax) para materiais, como mostrado no exemplo acima. Funções auxiliares como `Material.setPbrMaterial()` não podem ser usadas aqui.

### Modificar o material de um nó específico no modelo

O exemplo a seguir mostra como modificar o material de um nó específico no *arquivo glTF* modelo. Neste caso, o material da cabeça é modificado para usar uma 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',
						}),
					},
				},
			},
		},
	],
})
```

A `GltfNodeModifiers` pode conter vários modificadores, cada um modificando um nó diferente no modelo. O exemplo a seguir mostra como modificar o material da cabeça e do corpo de um *arquivo 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 um material existente

O componente Material fornece uma interface simplificada para acessar e modificar propriedades do componente Material. Ele elimina a necessidade de navegar por estruturas de união profundamente aninhadas (`PBR` vs `Unlit`, `textura` vs `avatarTexture` vs `videoTexture`), tornando a manipulação de material mais intuitiva e menos propensa a erros.

Os seguintes métodos permitem manipulação fácil do `Material` componente:

* `Material.getFlat(entity: Entity): ReadonlyFlatMaterial`: Retorna um **apenas leitura** `FlatMaterial` objeto accessor que fornece acesso direto de leitura às propriedades do material. Retornará um erro se a entidade não tiver um `Material` componente. Para evitar isso, os próximos métodos podem ser usados como alternativa.

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

* `Material.getFlatOrNull(entity: Entity): ReadonlyFlatMaterial | null`: Retorna um **apenas leitura ou null**, dependendo se a entidade tem ou não um `Material` component.

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

* `Material.getFlatMutable(entity: Entity): FlatMaterial`: Retorna um **leitura & escrita** `FlatMaterial`objeto que permite modificar suas propriedades. Ele lançará um erro se a entidade chamada não tiver o `Material` component.

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

* `Material.getFlatMutableOrNull(entity: Entity): FlatMaterial | null`: Retorna um **leitura & escrita ou null** `FlatMaterial` objeto que permite modificar suas propriedades. Caso a entidade não possua um `Material component`, ele retornará `null`.

```ts
Material.getFlatMutableOrNull(entity).texture.src = myNewTextureFile
```

### Remover sombras de um modelo glTF

Para remover sombras de um *arquivo glTF* modelo, você pode definir o `castShadows` propriedade para `false` mais próximo no `GltfNodeModifiers` objeto. Isso preserva o material original do modelo, mas impede que ele projete sombras. Isso é útil para modelos que não devem projetar sombras, como feixes de luz.

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

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