본문 바로가기

Graphics/playcanvas

[playcanvas] Asset 로드에 대한 모든것

플레이캔버스에서 Asset을 로드하며서 알게된 것들

플레이캔버스 상에서는 material도 texture도 json model도 모두 Asset입니다.

Asset 과 Asset.resource는 다르다

일반적으로 Material를 입힐땐, Asset.resource를 사용하지만, 큐브맵이나 2D 이미지를 적용할때는 Asset 자체를 사용한다.

Asset은 에셋 타입이고 Asset.resource는 그 해당 리소스의 타입을 따라간다. 예를들어 아래 코드처럼 Asset.resource가 texture타입이면 Asset.resource 도 텍스쳐 타입이된다.

Asset은 load하지 않아도 사용할수 있고, Asset.resource는 load해야 사용할수 있다.

// 에셋 생성 코드 
const asset = new pc.Asset('shadow', 'texutre', { 
    url: 'assets/common/shadow/shadow_alpha.png' 
}); 

console.log(asset);
console.log(asset.resource);

Asset과 AssetRegistry는 다르다

Asset은 실제 에셋이고, AssetRegistry는 내가 로드한 에셋들의 메타정보들이 등록되어있다.

Asset을 사용하기 위해 일반적으로 .add()와 .load()같이사용하지만, AssetRegistry에 add하는 것은 필수는 아니다.

// 에셋 생성 후 에셋레지스트리에 저장과 로드
const asset = new pc.Asset('shadow', 'texutre', { 
    url: 'assets/common/shadow/shadow_alpha.png' 
}); 

app.assets.add(asset);
app.assets.load(asset);

* 만약 entity를 destroy() 한다면, 엔티티에서 사용했던 Asset들도 AssetRegistry에서 remove()해줘야 한다.

비동기로 로드한 Asset을 사용하는 방법

기본적으로 플레이 캔버스에서 Asset을 비동기로 로드하기 때문에, 리스너를 달아서 기다렸다가, 로드가 완료되면 완료된 에셋을 사용한다.

// 에셋 생성 후 에셋레지스트리에 저장과 로드
const asset = new pc.Asset('shadow', 'texutre', { 
    url: 'assets/common/shadow/shadow_alpha.png' 
}); 

app.assets.add(asset); 
app.assets.load(asset); 

app.assets.on('load', ()=> { 
    console.log(asset) // 여기서 사용 
});

이 과정을 간단히 할수 있는 함수가 존재한다 .loadFromUrl 은 Asset Registry에 add를 자동으로 해주고, load한 Asset을 콜백으로 방아 처리할수 있다.

const that = this; // .bind 해서 사용가능
app.assets.loadFromUrl('assets/common/shadow/19352261/Shadow_plane.json', 'material', function(err, asset) {
    that.shadow.model.material = asset.resource; 
}); 

this.models.addChild(this.shadow);

응용 1: 특정 Asset 리스트만 add 후 완료됨 체크하기

const materialAssetManifest = [
	{ 
    	type: 'material', 
        url: 'assets/재질이름1.json' 
    }, 
    { 
    	type: 'material', 
        url: 'assets/재질이름2.json' 
    }, 
    { 
    	type: 'material', 
        url: 'assets/재질이름3.json' 
    }, 
]; 

let assetsToLoad = materialAssetManifest.length;
materialAssetManifest.forEach((entry) => {
	app.assets.loadFromUrl(entry.url, entry.type, (err, asset) => {
    	if (!err && asset) {
        	assetsToLoad--;
            entry[asset] = asset;
            if (assetsToLoad === 0) {
            	console.log(app.assets._assets, materialAssetManifest, 'Product material Assets are Loaded.');
                console.log(app.assets); 
                // 버튼 클릭했을때, assetsToLoad === 0 이면, 로드완료 
            } 
        } 
    }); 
});

응용 2 : 특정 Asset 만 load 하기

assets.once() 를 사용했다.

const entity = new pc.Entity();

const asset = new pc.Asset('test', 'json', {
	url: modelUrl, 
}); 

this.app.assets.once('load:' + asset.id, () => {
	console.log(asset); 
}); 

this.app.assets.load(asset);

번외

플레이캔버스 Asset을 불러와 Material을 생성하지않고, 텍스쳐를 포함한 Material를 만들수도 있다.

이때는 .onload를 사용하지만 이것은 플캔 메서드가 아닌, js 함수일뿐이다.

let image = new Image();
image.crossOrigin = 'use-credentials';
image.src = 'path'
image.onload = () => {
	let texture = new pc.Texture(app.graphicsDevice, { 
    	format: pc.PIXELFORMAT_R8_G8_B8,
        autoMipmap: true, 
    }); 
    texture.setSource(image); 
    
    const materia = new pc.StandardMaterial();
    material.opacityMap = texture;
    material.blendType = pc.BLEND-NORMAL;
    material.opacityMapChannel = 'r'; 
    material.diffuse.r = 0; 
    material.diffuse.g = 0; 
    material.diffuse.b = 0;
    material.update(); 
    entity.mode.model.meshInstances[0].material = material; 
}

'Graphics > playcanvas' 카테고리의 다른 글

[playcanvas] Asset 로드에 대한 모든것  (0) 2020.01.07
[playcanvas] Delete all child entities  (0) 2019.12.26
[playcanvas] loadFromUrl 에 대한 고찰  (0) 2019.12.03
[playcanvas] Anchor 와 pivot  (0) 2019.12.02
[playcanvas engine] 기초  (0) 2019.11.18
[Playcanvas] 레이어  (0) 2019.10.30