# Materials

## Materiais

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

*glTF* models incluem os seus próprios materiais, que são importados implicitamente para uma scene juntamente com o modelo. Para modificar ou substituir estes materiais, use o `GltfNodeModifiers` component. Veja [Modificar materiais glTF](#modify-gltf-materials) para mais detalhes.

Ao importar um modelo 3D com os seus próprios materiais, tenha em mente que nem todos os shaders são suportados pelo Decentraland engine. Apenas materiais standard 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 de material mais comum em Decentraland. Suporta cores simples ou textures, e diferentes propriedades como metallic, emissive, transparency, etc. Leia mais sobre [PBR](https://en.wikipedia.org/wiki/Physically_based_rendering).
* Materiais Basic: Não respondem a luz e sombras, o que os torna ideais para exibir imagens de billboard.

## Use o Scene Editor no Creator Hub

A forma mais simples de atribuir um Material a uma entity é usar o Scene Editor. Pode adicionar um **Material** component à sua entity e depois configurar todos os campos disponíveis na UI do Scene Editor. Veja [Add Components](/creator/content-creator-pt/scene-editor/construir/components.md#add-components).

## Adicionar um material

O exemplo seguinte cria um material PBR e define alguns dos seus campos para lhe dar uma cor vermelha e propriedades metálicas. Este material é adicionado a uma entity que também tem uma forma de caixa, por isso irá colorir a caixa com este material.

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

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

Para alterar o material de uma entity que já tem um `Material` component, execute `Material.setPbrMaterial()` ou qualquer uma das outras funções auxiliares e isto irá substituir o material original. Não é necessário remover o original `Material` nem usar a sintaxe avançada.

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

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

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

{% hint style="warning" %}
**📔 Nota**: O `Material` component deve ser importado através de

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

Veja [Imports](/creator/content-creator-pt/scenes-sdk7/comecar/coding-scenes.md#imports) para saber como lidar facilmente com estes casos.
{% endhint %}

## Cores de material

Dê a um material uma cor simples. Num material PBR, define o `albedoColor` campo. As cores de albedo respondem à luz e podem incluir sombras.

Os valores de cor são do tipo `Color4`, compostos por *r*, *g* e *b* valores (vermelho, verde e azul). Cada um destes aceita valores entre 0 e 1. Ao definir valores diferentes para estes, pode compor qualquer cor visível. Para preto, defina os três para 0. Para branco, defina todos para 1.

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

Veja [tipos de cor](/creator/content-creator-pt/scenes-sdk7/essenciais-de-conteudo-3d/color-types.md) para mais detalhes sobre como definir cores.

Também pode editar os seguintes campos num material PBR para afinar a forma como a sua cor é percecionada:

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

Para criar um material de cor simples que não seja afetado pela luz e sombras do ambiente, crie um basic material em vez de um material PBR.

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

## Usar textures

Defina um ficheiro de imagem como texture num material configurando o `texture` parâmetro.

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

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

No exemplo acima, a imagem do material está localizada numa `assets/materials` que se encontra ao nível da raiz da pasta do projeto da scene.

{% hint style="info" %}
**💡 Dica**: Recomendamos manter os ficheiros de imagem das suas textures algures em `/assets` dentro da tua scene.
{% endhint %}

Ao criar uma texture, também pode passar parâmetros adicionais:

* `filterMode`: Determina como os píxeis na texture são esticados ou comprimidos quando renderizados. Isto recebe um valor do `TextureFilterMode` enum. Veja [Texture Scaling](#texture-scaling).
* `wrapMode`: Determina como uma texture é repetida sobre um objeto. Isto recebe 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 texture que não seja afetada pela luz e sombras do ambiente, crie um basic material em vez de um material PBR.

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

### Textures de um URL externo

Pode apontar a texture do seu material para um URL externo em vez de um caminho interno no projeto da scene.

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

O URL deve começar com `https`, `http` URLs não são suportados.

### Envolvimento de texture

Pode definir como uma texture se alinha com uma superfície. Por predefinição, a texture é esticada para ocupar a superfície uma vez, mas pode escalá-la e deslocá-la.

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

* `offset`: Desloca a texture para alterar o seu alinhamento. O valor é um Vector2, em que ambos os eixos vão de 0 a 1, sendo 1 a largura ou altura total da texture.
* `tiling`: Escala a texture. O valor predefinido é o Vector 2 `[1, 1]`, que faz a imagem repetir uma vez cobrindo toda a superfície.
* `TextureWrapMode`: Determina o que acontece se o tiling da imagem não cobrir toda a superfície. Esta propriedade recebe os seus valores do `TextureWrapMode` enum, que permite os seguintes valores:
  * `TextureWrapMode.TWM_CLAMP`: A texture é exibida apenas uma vez no tamanho especificado. O resto da superfície da mesh fica transparente. O valor de `tiling` é ignorado.
  * `TextureWrapMode.TWM_REPEAT`: A texture é repetida tantas vezes quantas couberem na mesh, usando o tamanho especificado.
  * `TextureWrapMode.TWM_MIRROR`: Tal como em wrap, a texture é repetida tantas vezes quantas couberem, mas a orientação destas 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ó são suportadas no cliente desktop DCL 2.0.
{% endhint %}

Use esta funcionalidade para cobrir uma grande superfície com um padrão repetido. Por exemplo, repita a seguinte imagem:

![](/files/3050867e2ac5c8d33d325aa64095555f223d2148)

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

![](/files/82d20588e6e555f509d66f1066f3f60be420dd5b)

No exemplo abaixo, a texture usa um modo de envolvimento *mirror* e cada repetição da texture ocupa apenas 1/4 da superfície. Isto 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),
	}),
})
```

### Tweens de textura

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

{% hint style="warning" %}
**📔 Nota**: Texture Tweens é uma funcionalidade suportada apenas no cliente desktop DCL 2.0.
{% endhint %}

Use a `Tween` component com o `setTextureMove` função para mover a texture 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:

* `entity`: A entity para mover a textura de
* `start`: Um Vector2 para a posição inicial
* `end`: Um Vector2 para a posição final
* `duration`: Quantos milissegundos demora a mover entre as duas posições

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

* `movementType`: define se o movimento será no `offset` ou o `tiling` campo. Por defeito usa `offset`.
* `easingFunction`: A curva para a taxa de variação ao longo do tempo; o valor predefinido é `EasingFunction.EF_LINEAR`. Outros valores fazem a alteração acelerar e/ou desacelerar a ritmos diferentes.

```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 texture apenas uma vez. Para obter um movimento contínuo, por exemplo para simular a queda de uma cascata, precisa de 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:

* `entity`: A entity para mover a textura de
* `direction`: Um Vector2 para o movimento
* `speed`: Quantas unidades por segundo a entity se moverá

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

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

**Sequências de tween complexas**

Também pode fazer com que os movimentos da texture sigam uma sequência complexa com tantos passos quantos quiser. Use o `sequence` campo para listar tantos tweens quantos quiser; eles serão executados sequencialmente após o primeiro tween descrito no `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,
})
```

Nota que, ao definir um tween dentro de um TweenSequence, tens de usar o formato mais detalhado de `Tween.Mode.TextureMove` para definir o tween.

### Textures multicamada

Pode usar vários ficheiros de imagem como layers para compor textures mais realistas, por exemplo incluindo uma `bumpTexture` e uma `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 relevos e vincos numa superfície, modificando a forma como as normais da superfície se comportam em cada pixel.

![](/files/ec2b6be0ff14700aec5b02489994bf26cb3cc307)

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

**Definir UVs**

Outra alternativa para alterar a escala ou o alinhamento de uma texture é configurar propriedades *uv* no [componente MeshRenderer](/creator/content-creator-pt/scenes-sdk7/essenciais-de-conteudo-3d/shape-components.md).

Você define *u* e *v* coordenadas na imagem 2D da texture para corresponder aos vértices da forma. Quanto mais vértices a entity tiver, mais *uv* coordenadas precisam de ser definidas na texture; um plano, por exemplo, precisa de ter 8 *uv* pontos definidos, 4 para cada uma das 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 seguinte inclui uma função que simplifica a definição de uvs. A `setUVs` função definida aqui recebe como parâmetros um número de linhas e colunas, e define os uvs para que a imagem da texture 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 [
		// Face norte do plano não rotacionado
		0, //canto inferior esquerdo
		0,

		cols, //canto inferior direito
		0,

		cols, //canto superior direito
		rows,

		0, //canto superior esquerdo
		rows,

		// Face sul do 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 de uma `caixa` mesh shape, aplica-se a mesma estrutura. Cada uma das 6 faces do cubo recebe 4 pares de coordenadas, um para cada canto. Todos estes 48 valores são listados como um único array.

{% hint style="warning" %}
**📔 Nota**: As propriedades Uv estão atualmente disponíveis apenas em `plano` e em `caixa` shapes. Além disso, *uv* valores afetam todas as layers da texture da mesma forma, uma vez que são definidos no *shape*.
{% endhint %}

### Escala de texture

Quando as textures são esticadas ou reduzidas para um tamanho diferente do da imagem original da texture, isso pode às vezes criar artefactos. Num ambiente 3D, os efeitos da perspetiva causam isso naturalmente. Existem vários algoritmos de [filtragem de texture](https://en.wikipedia.org/wiki/Texture_filtering) que existem para compensar isto de diferentes formas.

O `Material` objeto usa o *bilinear* algoritmo por defeito, mas permite configurá-lo para usar os algoritmos *nearest neighbor* ou *trilinear* em vez disso, definindo o `samplingMode` propriedade da texture. Isto recebe um valor do `TextureFilterMode` enum:

* `TextureFilterMode.TFM_POINT`: Usa um algoritmo de "nearest neighbor". Esta definição é ideal para gráficos em estilo pixel art, uma vez que os contornos permanecem nitidamente definidos à medida que a texture é vista maior no ecrã, em vez de ficar desfocada.
* `TextureFilterMode.TFM_BILINEAR`: Usa um algoritmo bilinear para estimar a cor de cada píxel.
* `TextureFilterMode.TFM_TRILINEAR`: Usa um algoritmo trilinear para estimar a cor de cada píxel.

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

## Materiais Unlit

Na maioria das vezes vai querer que os materiais na sua scene sejam afetados pelas condições de iluminação, incluindo sombras e a tonalidade causada pelas mudanças de hora do dia. Mas, noutros casos, pode querer mostrar as cores no seu estado puro. Isto é útil ao reproduzir videos, ou também para marcadores abstratos que precisam de se destacar e que servem para assinalar hints ao player.

Para criar um material unlit, use `Material.setBasicMaterial`. Os materiais Basic não têm exatamente as mesmas propriedades que os materiais PBR; apenas têm as essenciais:

* `diffuseColor`: Color4 para a cor
* `texture`: Texture
* `alphaTexture`: Texture separada para a layer de transparência
* `alphaTest`: Limiar para obter transparência com base na cor da texture
* `castShadows`: Se false, não são projetadas sombras sobre outras entities na scene.

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

## Retratos de Avatar

Para exibir uma imagem miniatura de qualquer player, use `Material.Texture.Avatar` ao definir a texture do seu material, passando o endereço de um player existente. Isto cria uma texture a partir de uma imagem 256x256 do player, mostrando cabeça e ombros. O player é exibido com o conjunto de wearables que o server atual registou por último.

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

![](/files/57c77c2f79ab9caebef9133640e7b655bc654ec7)

Pode obter o retrato de qualquer player do Decentraland, mesmo que não esteja atualmente ligado, e mesmo que não tenha um Decentraland name reclamado.

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

* `userId`: ID do user cujo perfil quer exibir
* `filterMode`: Determina como os píxeis na texture são esticados ou comprimidos quando renderizados. Isto recebe um valor do `TextureFilterMode` enum. Veja [Texture Scaling](#texture-scaling).
* `wrapMode`: Determina como uma texture é repetida sobre um objeto. Isto recebe um valor do `TextureWrapMode` enum. Veja [Texture Wrapping](#texture-wrapping).

## Materiais transparentes

Para tornar transparente um material com uma cor simples, basta definir a cor como um `Color4`, e definir o 4.º valor para algo entre *0* e *1*. Quanto mais perto de *1*, mais opaco ficará.

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

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

Se um material usar uma texture .png que inclua transparência, ele será opaco por defeito, mas pode ativar a transparência definindo o `transparencyMode` a `MaterialTransparencyMode.MTM_ALPHA_BLEND`.

![](/files/bc3f4a41d5b764448bb1750e5335b8670be301fe)

```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 nenhuma
* `MaterialTransparencyMode.MTM_ALPHA_TEST`: Cada píxel é completamente opaco ou completamente transparente, com base num limiar.
* `MaterialTransparencyMode.MTM_ALPHA_BLEND`: São possíveis valores intermédios com base no valor de cada píxel.
* `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 texture fornecida.

Se definir o `transparencyMode` a `MaterialTransparencyMode.MTM_ALPHA_TEST`, pode afinar o limiar usado para determinar se cada píxel é transparente ou não. Defina a `alphaTest` propriedade entre *0* e *1*. Por defeito, o seu valor é *0.5*.

```ts
// Usar 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), pode adicionar um `alphaTexture` para tornar apenas certas regiões do material transparentes, com base numa texture.

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

![](/files/60327cfcf67be1e64f6a5e8774b0fe81d800f36d)

```ts
// Usar 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 formas muito interessantes em conjunto com videos. Veja [video playing](/creator/content-creator-pt/scenes-sdk7/media/video-playing.md).

## Video playing

Para fazer streaming de video de um URL para um material, ou reproduzir um video a partir de um ficheiro guardado na scene, veja [video playing](/creator/content-creator-pt/scenes-sdk7/media/video-playing.md).

O video é usado como texture num material, e pode definir quaisquer outras propriedades dos materiais para alterar o aspeto do ecrã do video.

## Sintaxe avançada

A sintaxe completa para criar um `Materiais` component, sem quaisquer auxiliares para o simplificar, é a seguinte:

```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 os components Materials. As funções auxiliares abstraem isto e expõem uma sintaxe mais amigável, mas por trás dos bastidores produzem esta sintaxe.

O `$case` campo permite-lhe especificar um dos tipos permitidos. Cada tipo suporta um conjunto diferente de parâmetros. No exemplo acima, o `caixa` tipo suporta um `uvs` field.

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

* `texture`
* `avatarTexture`

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

Para adicionar um `Material` component a uma entity que potencialmente já tem uma instância deste component, use `Material.createOrReplace()`. As funções auxiliares como `MeshRenderer.setPbrMaterial()` tratam de substituir instâncias existentes do component, mas executar `Material.create()` numa entity que já tem este component devolve um erro.

## Modificar materiais glTF

Use a `GltfNodeModifiers` component para modificar os materiais de um *glTF* model. Este component permite substituir os materiais de um *glTF* model pelos seus próprios materiais. Pode usar qualquer uma das propriedades do `Material` component, incluindo texture, video texture, materiais unlit, etc.

Existem duas formas de usar o `GltfNodeModifiers` component:

* Modifique o material de todo o model deixando a `path` propriedade como uma string vazia.
* Modifique o material de um node específico no model (ou de vários nodes) definindo a `path` propriedade como o caminho para o node.

### Modificar o material de todo o model

O exemplo seguinte mostra como modificar o material de um *glTF* model. Neste caso, o material de todo o model é modificado para 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` component tem as seguintes propriedades:

* `modifiers`: Um array de modifiers. Cada modifier tem as seguintes propriedades:
  * `path`: O caminho para o node no model a modificar.
  * `material`: O material a usar.

O `path` propriedade é uma string que representa o caminho para o node no *glTF* model a modificar. Se quiser modificar o material de todo o model, pode usar uma string vazia. Se quiser modificar o material de um node específico, pode usar o caminho para o node. O caminho deve apontar para um node de mesh, não para um vertex node.

{% hint style="info" %}
**💡 Dica**: Pode usar a [Babylon Sandbox app](https://sandbox.babylonjs.com/) para inspecionar o *glTF* model e encontrar o caminho para o node que quer modificar.

Em alguns models, contudo, o Babylon sandbox pode listar caminhos que pertencem a vértices em vez de meshes, o que não funcionará. Se tentar usar um caminho que não seja válido, a console da scene mostrará uma mensagem de erro que inclui a lista completa de caminhos válidos nesse model.
{% endhint %}

O `material` propriedade é um objeto que representa o material a usar. Precisa de ser escrito usando a [sintaxe avançada](#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 node específico no model

O exemplo seguinte mostra como modificar o material de um node específico no *glTF* model. Neste caso, o material da cabeça é modificado para usar uma texture 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 modifiers, cada um modificando um node diferente no model. O exemplo seguinte mostra como modificar o material da cabeça e do corpo de um *glTF* model.

```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 component Material fornece uma interface simplificada para aceder e modificar propriedades do component Material. Elimina a necessidade de navegar por estruturas union profundamente aninhadas (`PBR` vs `Unlit`, `texture` vs `avatarTexture` vs `videoTexture`), tornando a manipulação de materiais mais intuitiva e menos propensa a erros.

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

* `Material.getFlat(entity: Entity): ReadonlyFlatMaterial`: Devolve um objeto accessor FlatMaterial **só de leitura** `que fornece acesso direto de leitura às propriedades do material. Devolverá um erro se a entity não tiver um` component. Para evitar isso, os métodos seguintes podem ser usados como alternativa. `Material` const src = Material.getFlat(entity).texture.src

```ts
Material.getFlatOrNull(entity: Entity): ReadonlyFlatMaterial | null
```

* `só de leitura ou null`: Devolve um objeto accessor FlatMaterial **, dependendo de a entity ter ou não um**const src = Material.getFlatOrNull(entity).texture.src `Material` componente.

```ts
Material.getFlatMutable(entity: Entity): FlatMaterial
```

* `leitura e escrita`: Devolve um objeto accessor FlatMaterial **objeto que permite modificar as suas propriedades. Irá lançar um erro se a entity a que é chamado não tiver o** `que fornece acesso direto de leitura às propriedades do material. Devolverá um erro se a entity não tiver um`const src = Material.getFlatMutable(entity).texture.src `Material` componente.

```ts
Material.getFlatMutableOrNull(entity: Entity): FlatMaterial | null
```

* `leitura e escrita ou null`: Devolve um objeto accessor FlatMaterial **objeto que permite modificar as suas propriedades. Caso a entity não tenha um** `que fornece acesso direto de leitura às propriedades do material. Devolverá um erro se a entity não tiver um` Material component `, ele irá devolver`reutrn `null`.

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

### Remover sombras de um modelo glTF

Para remover sombras de um *glTF* model, pode definir o `castShadows` propriedade para `false` no `GltfNodeModifiers` object. Isto mantém o material original do model, mas impede-o de projetar sombras. Isto é útil para models que não se destinam a projetar sombras, como feixes de luz.

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

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

{% hint style="info" %}
**💡 Dica**: Textures usadas em materiais também podem ser aplicadas a efeitos de partículas. Veja [Particle System](particle-system.md) para detalhes sobre usar textures personalizadas e sprite sheets com particles.
{% endhint %}
```


---

# Agent Instructions: Querying This Documentation

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

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.decentraland.org/creator/content-creator-pt/scenes-sdk7/essenciais-de-conteudo-3d/materials.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
