> 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-ko/sdk7/3d/materials.md).

# 재질

단순한 형태의 엔티티에 재질과 텍스처를 추가하는 방법을 알아봅니다.

## 재질

기본 도형(큐브, 구체, 평면 등)을 사용하는 엔티티에는 다음을 추가하여 재질을 적용할 수 있습니다. `재질` 컴포넌트입니다. 이 컴포넌트에는 재질의 속성을 구성하고, 텍스처를 추가하는 등 여러 필드가 있습니다.

*glTF* 모델에는 모델과 함께 씬에 암묵적으로 가져와지는 자체 재질이 포함되어 있습니다. 이러한 재질을 수정하거나 덮어쓰려면 다음을 사용하세요. `GltfNodeModifiers` 컴포넌트입니다. 참조: [glTF 재질 수정](#modify-gltf-materials) 를 참조하세요.

자체 재질이 있는 3D 모델을 가져올 때는 모든 셰이더가 Decentraland 엔진에서 지원되는 것은 아니라는 점에 유의하세요. 표준 재질과 PBR(물리 기반 렌더링) 재질만 지원됩니다. 참조: [외부 3D 모델 고려 사항](https://github.com/decentraland/docs/blob/main/creator/3d-modeling/materials.md) 를 참조하세요.

지원되는 재질에는 여러 유형이 있습니다:

* PBR(물리 기반 렌더링): Decentraland에서 가장 일반적인 재질 유형입니다. 단색 또는 텍스처를 지원하며, 금속성, 발광, 투명도 등 다양한 속성을 지원합니다. 자세한 내용: [PBR](https://en.wikipedia.org/wiki/Physically_based_rendering).
* 기본 재질: 빛과 그림자에 반응하지 않으므로 빌보드 이미지를 표시하는 데 이상적입니다.

## Creator Hub의 씬 에디터 사용

엔티티에 재질을 부여하는 가장 쉬운 방법은 씬 에디터를 사용하는 것입니다. 엔티티에 다음을 추가할 수 있습니다. **재질** 컴포넌트를 엔티티에 추가한 다음, 씬 에디터 UI에서 사용할 수 있는 모든 필드를 구성할 수 있습니다. 참조: [컴포넌트 추가](/creator/content-creator-ko/scene-editor/build/components.md#add-components).

## 재질 추가

다음 예제는 PBR 재질을 생성하고, 일부 필드를 설정하여 빨간색과 금속성 속성을 부여합니다. 이 재질은 box shape도 가진 엔티티에 추가되므로, 이 재질로 상자를 색칠합니다.

```ts
//엔티티 생성 및 형태 할당
const meshEntity = engine.addEntity()
Transform.create(meshEntity, {
	position: Vector3.create(4, 1, 4),
})
MeshRenderer.setBox(meshEntity)

//새 재질 컴포넌트로 덮어쓰기
Material.setPbrMaterial(meshEntity, {
	albedoColor: Color4.Red(),
	metallic: 0.8,
	roughness: 0.1,
})
```

이미 다음을 가진 엔티티의 재질을 변경하려면 `재질` 컴포넌트를 가진 엔티티에서 다음을 실행하세요 `Material.setPbrMaterial()` 또는 다른 헬퍼 함수 중 아무거나 사용하면 원래 재질을 덮어씁니다. 원래 `재질` 또는 고급 구문을 사용할 필요는 없습니다.

```ts
//엔티티 생성 및 형태 할당
const meshEntity = engine.addEntity()
Transform.create(meshEntity, {
	position: Vector3.create(4, 1, 4),
})
MeshRenderer.setBox(meshEntity)

//새 재질 컴포넌트로 덮어쓰기
Material.setPbrMaterial(meshEntity, {
	albedoColor: Color4.Red(),
})

//새 재질 컴포넌트로 덮어쓰기
Material.setPbrMaterial(meshEntity, {
	albedoColor: Color4.Blue(),
})
```

{% hint style="warning" %}
**📔 참고**: 다음은 `재질` 컴포넌트는 다음을 통해 가져와야 합니다

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

참조 [가져오기](/creator/content-creator-ko/sdk7/getting-started/coding-scenes.md#imports) 이를 쉽게 처리하는 방법에 대해.
{% endhint %}

## 재질 색상

재질에 단색을 지정합니다. PBR 재질에서는 `albedoColor` 필드를 설정합니다. 알베도 색상은 빛에 반응하며 음영을 포함할 수 있습니다.

색상 값의 타입은 `Color4`, 다음으로 구성됩니다 *r*, *g* 및 *b* 값(빨강, 초록, 파랑)으로 구성됩니다. 각 값은 0과 1 사이의 값을 가집니다. 서로 다른 값을 설정하여 보이는 모든 색을 만들 수 있습니다. 검정은 세 값을 모두 0으로 설정하고, 흰색은 모두 1로 설정합니다.

{% hint style="warning" %}
**📔 참고**: ...의 색상을 설정하면 `albedoColor` 보다 큰 값으로 *1*, 발광으로 표시되며 *발광*, 값이 높을수록 더 강하게 나타납니다. 예를 들어, `{r: 15, g: 0, b: 0}` 매우 밝은 빨간 발광을 만듭니다.
{% endhint %}

참조 [색상 유형](/creator/content-creator-ko/sdk7/3d/color-types.md) 색상 설정 방법에 대한 자세한 내용.

PBR 재질에서 색상이 어떻게 인식되는지 미세 조정하기 위해 다음 필드도 편집할 수 있습니다:

* *emissiveColor*: 재질에서 방출되는 색상입니다.
* *reflectivityColor*: 즉 *스페큘러 색상* 다른 명칭으로는.

환경의 빛과 그림자에 영향을 받지 않는 단색 재질을 만들려면 PBR 재질 대신 기본 재질을 만드세요.

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

## 텍스처 사용

이미지 파일을 재질의 텍스처로 설정하려면 다음을 설정합니다 `texture` 매개변수.

```ts
//엔티티 생성 및 형태 할당
const meshEntity = engine.addEntity()
Transform.create(meshEntity, {
	position: Vector3.create(4, 1, 4),
})
MeshRenderer.setBox(meshEntity)

//새 재질 컴포넌트로 덮어쓰기
Material.setPbrMaterial(meshEntity, {
	texture: Material.Texture.Common({
		src: 'assets/materials/wood.png',
	}),
})
```

위 예제에서 재질의 이미지는 다음에 위치합니다 `assets/materials` 폴더이며, 이는 씬 프로젝트 폴더의 루트 수준에 있습니다.

{% hint style="info" %}
**💡 팁**: 텍스처 이미지 파일은 씬 내부의 `/assets` 폴더에 보관하는 것을 권장합니다.
{% endhint %}

텍스처를 만들 때 추가 매개변수도 전달할 수 있습니다:

* `filterMode`: 렌더링될 때 텍스처의 픽셀이 늘어나거나 압축되는 방식을 결정합니다. 이 값은 `TextureFilterMode` 열거형에서 가져옵니다. 참조: [텍스처 스케일링](#texture-scaling).
* `wrapMode`: 텍스처가 오브젝트에 타일링되는 방식을 결정합니다. 이 값은 `TextureWrapMode` 열거형에서 가져옵니다. 참조: [텍스처 래핑](#texture-wrapping).

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

환경의 빛과 그림자에 영향을 받지 않는 텍스처를 만들려면 PBR 재질 대신 기본 재질을 만드세요.

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

### 외부 URL의 텍스처

텍스처를 씬 프로젝트 내부 경로 대신 외부 URL로 지정할 수 있습니다.

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

URL은 다음으로 시작해야 합니다 `https`, `http` URL은 지원되지 않습니다.

### 텍스처 래핑

텍스처가 표면에 어떻게 맞춰지는지 설정할 수 있습니다. 기본적으로 텍스처는 표면을 한 번 덮도록 늘어나지만, 크기를 조정하거나 오프셋할 수 있습니다.

다음 필드는 모든 텍스처에서 사용할 수 있습니다:

* `offset`: 텍스처의 정렬을 바꾸기 위해 이동시킵니다. 값은 Vector2이며, 두 축 모두 0에서 1까지의 범위를 가집니다. 여기서 1은 텍스처의 전체 너비 또는 높이를 의미합니다.
* `tiling`: 텍스처의 크기를 조정합니다. 기본값은 Vector 2 `[1, 1]`, 이는 이미지가 표면 전체를 덮도록 한 번 반복되게 합니다.
* `TextureWrapMode`: 이미지 타일링이 표면 전체를 덮지 못할 때 어떤 일이 일어나는지 결정합니다. 이 속성은 `TextureWrapMode` 열거형의 값을 사용하며, 다음 값을 허용합니다:
  * `TextureWrapMode.TWM_CLAMP`: 텍스처는 지정한 크기로 한 번만 표시됩니다. 메쉬 표면의 나머지 부분은 투명하게 남습니다. 값은 `tiling` 무시됩니다.
  * `TextureWrapMode.TWM_REPEAT`: 텍스처는 지정한 크기만큼 메쉬에 맞는 횟수만큼 반복됩니다.
  * `TextureWrapMode.TWM_MIRROR`: 래핑처럼 텍스처는 맞는 횟수만큼 반복되지만, 이 반복들의 방향은 반전됩니다.

```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" %}
**📔 참고**: 다음은 `offset` 및 `tiling` 속성은 DCL 2.0 데스크톱 클라이언트에서만 지원됩니다.
{% endhint %}

이 기능을 사용해 넓은 표면을 타일 패턴으로 덮을 수 있습니다. 예를 들어, 다음 이미지를 반복하세요:

![](https://3980763956-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://3980763956-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)

아래 예제에서 텍스처는 *미러* 래핑 모드를 사용하며, 텍스처의 각 반복은 표면의 1/4만 차지합니다. 즉, 이미지 4개가 서로에 대해 양쪽 축에서 반전된 형태로 보입니다.

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

### 텍스처 트윈

텍스처를 부드럽게 이동시키려면 `트윈` 컴포넌트를 `TextureMove` 모드로 설정합니다. 트윈은 점진적으로 `offset` 또는 `tiling` 텍스처의 속성을 일정 기간에 걸쳐 부드럽고 최적화된 방식으로 변경합니다.

{% hint style="warning" %}
**📔 참고**: 텍스처 트윈은 DCL 2.0 데스크톱 클라이언트에서만 지원되는 기능입니다.
{% endhint %}

다음을 사용하세요 `트윈` 컴포넌트를 `setTextureMove` 함수로 텍스처를 두 위치 사이에서 이동시킵니다.

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

텍스처 트윈에는 다음 정보가 필요합니다:

* `엔티티`: 텍스처를 이동시킬 엔티티
* `시작`: 시작 위치를 위한 Vector2
* `종료`: 종료 위치를 위한 Vector2
* `지속 시간`: 두 위치 사이를 이동하는 데 걸리는 밀리초 수

다음 추가 선택 매개변수도 사용할 수 있습니다:

* `movementType`: 이동이 다음에서 이루어질지를 정의합니다 `offset` 또는 `tiling` 필드입니다. 기본적으로는 `offset`.
* `easingFunction`: 시간에 따른 변화율 곡선이며, 기본값은 `EasingFunction.EF_LINEAR`. 다른 값은 변화가 서로 다른 속도로 가속 및/또는 감속되게 합니다.

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

위 예제는 1초 동안 지속되는 트윈을 실행하며, 텍스처를 한 번만 이동합니다. 연속적인 움직임을 구현하려면, 예를 들어 폭포가 떨어지는 모습을 시뮬레이션하려면 다음을 사용해야 합니다 `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)
```

위 예제는 `setTextureMoveContinuous`, 방향은 `(0, 1)`이며, 초당 1단위의 속도로 사용합니다.

연속 텍스처 트윈에는 다음 정보가 필요합니다:

* `엔티티`: 텍스처를 이동시킬 엔티티
* `방향`: 이동을 위한 Vector2
* `속도`: 엔티티가 초당 몇 단위로 이동하는지

다음 추가 선택 매개변수도 사용할 수 있습니다:

* `movementType`: 이동이 offset 또는 tiling 필드에서 이루어질지 정의합니다. 기본값은 offset입니다.
* `지속 시간`: 이동을 유지할 밀리초 수입니다. 이 시간이 지나면 이동이 멈춥니다.

**복잡한 트윈 시퀀스**

텍스처 이동을 원하는 만큼 많은 단계로 이루어진 복잡한 시퀀스로 만들 수도 있습니다. 다음을 사용하세요 `시퀀스` 필드에 원하는 만큼 트윈을 나열할 수 있으며, 처음에 설명된 트윈 이후 순차적으로 실행됩니다 `트윈` 컴포넌트.

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

TweenSequence 안에서 트윈을 정의할 때는 더 장황한 형식의 `Tween.Mode.TextureMove` 를 사용해 트윈을 정의해야 합니다.

### 다층 텍스처

여러 이미지 파일을 레이어로 사용하여 더 사실적인 텍스처를 구성할 수 있습니다. 예를 들어 `bumpTexture` 와 `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',
	}),
})
```

다음 `bumpTexture` 표면의 각 픽셀에서 법선이 동작하는 방식을 수정하여 표면의 돌기와 주름을 시뮬레이션할 수 있습니다.

![](https://3980763956-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)

다음 `emissiveTexture` 재질의 특정 부분에서 발광을 강조해 매우 흥미로운 효과를 낼 수 있습니다.

**UV 설정**

텍스처의 크기나 정렬을 바꾸는 또 다른 방법은 *uv* 속성을 [MeshRenderer 컴포넌트에](/creator/content-creator-ko/sdk7/3d/shape-components.md).

다음을 설정하는 것입니다 *u* 및 *v* 텍스처의 2D 이미지의 좌표를 도형의 정점에 대응시키는 것입니다. 엔티티의 정점 수가 많을수록 더 많은 *uv* 좌표를 텍스처에 정의해야 하며, 예를 들어 평면에는 8개의 *uv* 점이 정의되어야 합니다. 두 면 각각에 4개씩입니다.

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

다음 예제에는 UV 설정을 간소화하는 함수가 포함되어 있습니다. 여기서 정의된 `setUVs` 함수는 행과 열의 개수를 매개변수로 받아, 텍스처 이미지가 특정 횟수만큼 반복되도록 UV를 설정합니다.

```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 [
		//회전되지 않은 평면의 북쪽 면
		0, //왼쪽 아래 모서리
		0,

		cols, //오른쪽 아래 모서리
		0,

		cols, //오른쪽 위 모서리
		rows,

		0, //왼쪽 위 모서리
		rows,

		//회전되지 않은 평면의 남쪽 면
		cols, // 오른쪽 아래 모서리
		0,

		0, // 왼쪽 아래 모서리
		0,

		0, // 왼쪽 위 모서리
		rows,

		cols, // 오른쪽 위 모서리
		rows,
	]
}
```

다음은 `상자` 메쉬 형태의 UV를 설정할 때도 동일한 구조가 적용됩니다. 큐브의 6개 면 각각은 각 모서리마다 4쌍의 좌표를 사용합니다. 이 48개 값은 모두 하나의 배열로 나열됩니다.

{% hint style="warning" %}
**📔 참고**: UV 속성은 현재 `평면` 과 `상자` 도형에서만 사용할 수 있습니다. 또한, *uv* 값은 *도형*.
{% endhint %}

### 텍스처 스케일링

텍스처가 원본 이미지와 다른 크기로 늘어나거나 줄어들면 때때로 아티팩트가 생길 수 있습니다. 3D 환경에서는 원근 효과가 이를 자연스럽게 유발합니다. 이를 보정하는 다양한 [텍스처 필터링](https://en.wikipedia.org/wiki/Texture_filtering) 알고리즘이 서로 다른 방식으로 존재합니다.

다음 `재질` 오브젝트는 기본적으로 *bilinear* 알고리즘을 사용하지만, 설정을 통해 *nearest neighbor* 또는 *trilinear* 알고리즘 대신 사용하도록 `filterMode` 텍스처의 속성을 설정합니다. 이 값은 `TextureFilterMode` 열거형의 값을 사용합니다:

* `TextureFilterMode.TFM_POINT`"nearest neighbor" 알고리즘을 사용합니다. 이 설정은 픽셀 아트 스타일 그래픽에 이상적이며, 화면에서 텍스처가 더 크게 보일 때 흐려지지 않고 윤곽이 선명하게 유지됩니다.
* `TextureFilterMode.TFM_BILINEAR`: 각 픽셀의 색을 추정하기 위해 bilinear 알고리즘을 사용합니다.
* `TextureFilterMode.TFM_TRILINEAR`: 각 픽셀의 색을 추정하기 위해 trilinear 알고리즘을 사용합니다.

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

## 조명이 비치지 않는 재질

대부분의 경우 씬의 재질이 그림자를 포함한 조명 조건의 영향을 받고, 하루 중 시간대 변화에 따라 색조가 바뀌기를 원할 것입니다. 하지만 경우에 따라 색상을 순수한 상태로 표시하고 싶을 수 있습니다. 이는 비디오를 재생할 때 유용하며, 플레이어에게 힌트를 전달하기 위해 눈에 띄어야 하는 추상적인 마커에도 유용합니다.

조명이 비치지 않는 재질을 만들려면 `Material.setBasicMaterial`. 기본 재질은 PBR 재질과 동일한 모든 속성을 갖지 않으며, 필수 항목만 있습니다:

* `diffuseColor`: 색상을 위한 Color4
* `texture`: 텍스처
* `alphaTexture`: 투명도 레이어를 위한 별도 텍스처
* `alphaTest`: 텍스처 색상을 기반으로 투명도를 얻기 위한 임계값
* `castShadows`: false이면 씬의 다른 엔티티에 그림자가 투영되지 않습니다.

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

## 아바타 초상화

모든 플레이어의 썸네일 이미지를 표시하려면 `Material.Texture.Avatar` 를 사용하세요. 재질의 텍스처를 설정할 때 기존 플레이어의 주소를 전달합니다. 이렇게 하면 플레이어의 256x256 이미지에서 텍스처가 생성되며, 머리와 어깨가 표시됩니다. 플레이어는 현재 서버가 마지막으로 기록한 착용 아이템을 착용한 상태로 표시됩니다.

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

![](https://3980763956-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)

현재 연결되어 있지 않더라도, 그리고 Decentraland 이름을 등록하지 않았더라도 모든 Decentraland 플레이어의 초상화를 가져올 수 있습니다.

다음 속성은 인수로 전달하는 객체에서 지원됩니다:

* `userId`: 표시하려는 프로필의 사용자 ID
* `filterMode`: 렌더링될 때 텍스처의 픽셀이 늘어나거나 압축되는 방식을 결정합니다. 이 값은 `TextureFilterMode` 열거형에서 가져옵니다. 참조: [텍스처 스케일링](#texture-scaling).
* `wrapMode`: 텍스처가 오브젝트에 타일링되는 방식을 결정합니다. 이 값은 `TextureWrapMode` 열거형에서 가져옵니다. 참조: [텍스처 래핑](#texture-wrapping).

## 투명 재질

단색 재질을 투명하게 만들려면, 색상을 단순히 다음과 같이 정의하면 됩니다 `Color4`그리고 4번째 값을 다음 사이의 값으로 설정하고 *0* 및 *1*. 에 가까울수록 *1*, 더 불투명해집니다.

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

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

재질이 투명도를 포함하는 .png 텍스처를 사용하면 기본적으로 불투명하지만, 다음을 설정하여 투명도를 활성화할 수 있습니다: `transparencyMode` 을(를) 다음으로 `MaterialTransparencyMode.MTM_ALPHA_BLEND`.

![](https://3980763956-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,
})
```

다음 `transparencyMode` 다음 값을 가질 수 있습니다:

* `MaterialTransparencyMode.MTM_OPAQUE`: 전혀 투명하지 않음
* `MaterialTransparencyMode.MTM_ALPHA_TEST`: 각 픽셀은 임계값에 따라 완전히 불투명하거나 완전히 투명합니다.
* `MaterialTransparencyMode.MTM_ALPHA_BLEND`: 각 픽셀 값에 따라 중간 값이 가능합니다.
* `MaterialTransparencyMode.MTM_ALPHA_TEST_AND_ALPHA_BLEND`: 두 방법을 조합하여 사용합니다.
* `MaterialTransparencyMode.MTM_AUTO`: 제공된 텍스처를 기반으로 방법을 결정합니다.

다음을 설정하면 `transparencyMode` 을(를) 다음으로 `MaterialTransparencyMode.MTM_ALPHA_TEST`, 각 픽셀이 투명한지 여부를 결정하는 데 사용되는 임계값을 세밀하게 조정할 수 있습니다. 다음을 설정하세요: `alphaTest` 속성을 다음 사이로 *0* 및 *1*. 기본값은 *0.5*.

```ts
// 알파 테스트 사용
Material.setPbrMaterial(meshEntity1, {
	texture: Material.Texture.Common({
		src: 'images/myTexture.png',
	}),
	transparencyMode: MaterialTransparencyMode.MTM_ALPHA_TEST,
	alphaTest: 1,
})
```

을 사용하는 경우 [언릿 재질](#unlit-materials), 다음을 추가하여 `alphaTexture` 텍스처를 기반으로 재질의 특정 영역만 투명하게 만들 수 있습니다.

{% hint style="warning" %}
**📔 참고**: 이것은 반드시 단일 채널 이미지여야 합니다. 이 이미지에서는 빨간색 또는 검은색을 사용하여 실제 텍스처의 어떤 부분을 투명하게 할지 결정합니다.
{% endhint %}

![](https://3980763956-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
// 알파 테스트 사용
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,
	}),
})
```

이는 비디오와 함께 매우 흥미로운 방식으로 사용할 수 있습니다. 다음을 참조하세요: [비디오 재생](/creator/content-creator-ko/sdk7/media/video-playing.md).

## 비디오 재생

URL에서 재질로 비디오를 스트리밍하거나, 씬에 저장된 파일에서 비디오를 재생하려면 다음을 참조하세요: [비디오 재생](/creator/content-creator-ko/sdk7/media/video-playing.md).

비디오는 재질의 텍스처로 사용되며, 재질의 다른 속성들을 설정해 비디오 화면의 모양을 바꿀 수 있습니다.

## 고급 구문

를 생성하기 위한 전체 구문은 `재질` 를 단순화하는 도우미 없이 보면 다음과 같습니다:

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

이것이 기본 프로토콜이 Materials 컴포넌트를 해석하는 방식입니다. 도우미 함수는 이를 추상화하여 더 친숙한 구문을 제공하지만, 내부적으로는 이 구문을 출력합니다.

다음 `$case` 필드에서는 허용된 유형 중 하나를 지정할 수 있습니다. 각 유형은 서로 다른 매개변수 집합을 지원합니다. 여기에는 두 단계의 `$case` 가 있습니다:

* 다음 `material` 필드는 다음 값을 지원합니다: `pbr` 및 `unlit`, 재질의 종류를 정의합니다.
* 다음 `tex` 텍스처 안의 필드는 텍스처의 종류를 정의하기 위해 다음 값을 지원합니다:
  * `texture`
  * `avatarTexture`
  * `videoTexture`

값에 따라 `$case`, 해당 종류에 대한 객체를 관련 속성과 함께 정의하는 것이 유효합니다.

을 추가하려면 `재질` 이 컴포넌트의 인스턴스가 이미 있을 수 있는 엔티티에 컴포넌트를 추가하려면 다음을 사용하세요: `Material.createOrReplace()`. 다음과 같은 도우미 함수는 `Material.setPbrMaterial()` 기존 컴포넌트 인스턴스의 덮어쓰기를 처리하지만, 다음을 실행하면 `Material.create()` 이 컴포넌트가 이미 있는 엔티티에 대해 실행하면 오류가 반환됩니다.

## glTF 재질 수정

다음을 사용하세요 `GltfNodeModifiers` 의 재질을 수정하기 위한 컴포넌트 *glTF* 모델. 이 컴포넌트는 다음의 재질을 사용자 지정 재질로 덮어쓸 수 있게 해줍니다: *glTF* 모델의 재질을 사용자 지정 재질로 바꿀 수 있습니다. 다음의 속성 중 어떤 것이든 사용할 수 있습니다: `재질` 컴포넌트의 속성들을 사용할 수 있습니다. 여기에는 텍스처, 비디오 텍스처, 언릿 재질 등이 포함됩니다.

를 사용하는 방법은 두 가지가 있습니다: `GltfNodeModifiers` 컴포넌트:

* 전체 모델의 재질을 수정하려면 다음을 비워 둡니다 `path` 속성을 빈 문자열로 둡니다.
* 모델의 특정 노드(또는 여러 노드)의 재질을 수정하려면 다음을 설정합니다: `path` 속성에 해당 노드의 경로를 지정합니다.

### 전체 모델의 재질 수정

다음 예제는 다음의 재질을 수정하는 방법을 보여줍니다: *glTF* 모델. 이 경우 전체 모델의 재질이 빨간색으로 수정됩니다.

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

다음 `GltfNodeModifiers` 컴포넌트에는 다음 속성이 있습니다:

* `modifiers`: 수정자 배열입니다. 각 수정자는 다음 속성을 가집니다:
  * `path`: 수정할 모델 내 노드의 경로입니다.
  * `material`: 사용할 재질입니다.

다음 `path` 속성은 다음의 노드 경로를 나타내는 문자열입니다: *glTF* 수정할 모델입니다. 전체 모델의 재질을 수정하려면 빈 문자열을 사용할 수 있습니다. 특정 노드의 재질을 수정하려면 해당 노드의 경로를 사용할 수 있습니다. 경로는 정점 노드가 아니라 메쉬 노드를 가리켜야 합니다.

{% hint style="info" %}
**💡 팁**: 다음을 사용할 수 있습니다: [Babylon Sandbox 앱](https://sandbox.babylonjs.com/) 를 검사하여 *glTF* 모델을 보고 수정하려는 노드의 경로를 찾을 수 있습니다.

그러나 일부 모델에서는 Babylon sandbox가 메쉬가 아니라 정점에 속한 경로를 나열할 수 있으며, 이는 작동하지 않습니다. 유효하지 않은 경로를 사용하려고 하면 씬의 콘솔에 해당 모델의 유효한 경로 전체 목록이 포함된 오류 메시지가 표시됩니다.
{% endhint %}

다음 `material` 속성은 사용할 재질을 나타내는 객체입니다. 다음을 사용하여 작성해야 합니다: [고급 구문](#advanced-syntax) 위 예제에서 보이듯이 재질에 대한 것입니다. 다음과 같은 도우미 함수는 `Material.setPbrMaterial()` 여기서는 사용할 수 없습니다.

### 모델의 특정 노드의 재질 수정

다음 예제는 다음의 특정 노드의 재질을 수정하는 방법을 보여줍니다: *glTF* 모델. 이 경우 머리의 재질이 대체 텍스처를 사용하도록 수정됩니다.

```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` 여러 수정자를 포함할 수 있으며, 각 수정자는 모델의 서로 다른 노드를 수정합니다. 다음 예제는 다음의 머리와 몸체의 재질을 수정하는 방법을 보여줍니다: *glTF* 모델.

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

### 기존 재질의 필드 수정

Material 컴포넌트는 Material 컴포넌트 속성에 접근하고 수정하기 위한 단순화된 인터페이스를 제공합니다. 깊게 중첩된 유니온 구조를 탐색할 필요를 없애며(`PBR` vs `Unlit`, `texture` vs `avatarTexture` vs `videoTexture`) 재질 조작을 더 직관적이고 오류가 적게 만들어 줍니다.

다음 메서드들은 다음을 쉽게 조작할 수 있게 해줍니다: `재질` 컴포넌트:

* `Material.getFlat(entity: Entity): ReadonlyFlatMaterial`: 다음을 반환합니다: **읽기 전용** `FlatMaterial` 재질 속성에 직접 읽기 접근을 제공하는 접근자 객체입니다. 엔티티에 다음이 없으면 오류를 반환합니다: `재질` 컴포넌트. 이를 피하기 위해 다음 메서드들을 대안으로 사용할 수 있습니다.

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

* `Material.getFlatOrNull(entity: Entity): ReadonlyFlatMaterial | null`: 다음을 반환합니다: **읽기 전용 또는 null**, 엔티티에 다음이 있는지 여부에 따라 `재질` 컴포넌트.

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

* `Material.getFlatMutable(entity: Entity): FlatMaterial`: 다음을 반환합니다: **읽기/쓰기** `FlatMaterial`속성을 수정할 수 있는 객체입니다. 호출된 엔티티에 다음이 없으면 오류를 발생시킵니다: `재질` 컴포넌트.

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

* `Material.getFlatMutableOrNull(entity: Entity): FlatMaterial | null`: 다음을 반환합니다: **읽기/쓰기 또는 null** `FlatMaterial` 속성을 수정할 수 있는 객체입니다. 엔티티에 다음이 없는 경우 `Material 컴포넌트`다음 `null`.

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

### glTF 모델에서 그림자 제거

에서 그림자를 제거하려면 *glTF* 모델에서 다음을 설정할 수 있습니다: `castShadows` 속성을 다음으로 설정하세요: `false` 에서 `GltfNodeModifiers` 객체. 이렇게 하면 모델의 원래 재질은 유지되지만 그림자를 드리우지 않게 됩니다. 이는 광선처럼 그림자를 드리우도록 설계되지 않은 모델에 유용합니다.

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

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

{% hint style="info" %}
**💡 팁**: 재질에 사용된 텍스처는 파티클 효과에도 적용할 수 있습니다. 다음을 참조하세요: [Particle System](/creator/content-creator-ko/sdk7/3d/particle-system.md) 파티클과 함께 사용자 지정 텍스처와 스프라이트 시트를 사용하는 방법에 대한 자세한 내용은
{% endhint %}

{% hint style="info" %}
**💡 팁**: 재질의 작동 예제는 다음을 참조하세요: [`52,-52-testing-gallery`](https://github.com/decentraland/sdk7-test-scenes/tree/main/scenes/52,-52-testing-gallery) 테스트 씬으로, PBR 금속성/거칠기/발광/노멀 맵 조합을 나란히 비교해 봅니다, [`74,-8-gltfnodemodifier`](https://github.com/decentraland/sdk7-test-scenes/tree/main/scenes/74,-8-gltfnodemodifier)개별 GLTF 노드에서 PBR 및 언릿 재질을 덮어쓰며, 그리고 [`0,3-texture-movement`](https://github.com/decentraland/sdk7-test-scenes/tree/main/scenes/0,3-texture-movement)텍스처 오프셋과 타일링을 애니메이션합니다.
{% 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-ko/sdk7/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.
