본문 바로가기

Dev/graphics

[playcanvas] Material with texture in glTF (engine only)

playcanvas engine only

1. Make Material with texture in glTF 

  public loadWheel(entityName: string, folderName: any, partName: any, materialAsset: boolean) {
    const targetEntity = this.app.root.findByName(entityName);
    const part = new pc.Entity();
    part.addComponent('model');
    part.name = partName;
    const wheelUrl = `${ environment.apiUrl }/assets/products/${ folderName }/${ partName }/${ partName }.gltf`;
    const duplicatedPart = this.isDuplicate(part.name);
    let that = this;
    // If there is wheel, remove from asset list.
    if (duplicatedPart !== undefined) { // Duplicated!
      const url = `${environment.apiUrl}/assets/products/${folderName}/${duplicatedPart}/${duplicatedPart}.gltf`;
      this.app.assets.remove(this.app.assets.getByUrl(url));
    }
    this.app.assets.loadFromUrl(wheelUrl, 'json', (err, asset) => {
      let json = asset.resource;
      let glTF = JSON.parse(json);
      const loadGltf = window['loadGltf'];

      loadGltf(glTF, that.app.graphicsDevice, (model, textures, animationClips) => {
        if (duplicatedPart !== undefined) {
          const dpEntity = targetEntity.findByName(duplicatedPart);
          dpEntity.destroy();
        }
        part.model.model = model;

        if (materialAsset === true) {
          let diffuseImage = new Image();
          diffuseImage.crossOrigin = 'use-credentials';
          diffuseImage.src = `${environment.apiUrl}/assets/products/${folderName}/texture/${partName}_Diffuse.png`;

          let normalImage = new Image();
          normalImage.crossOrigin = 'use-credentials';
          normalImage.src = `${environment.apiUrl}/assets/products/${folderName}/texture/${partName}_Normal.png`;
          let that2 = this;


          diffuseImage.onload = () => {
            let normalTexture = new pc.Texture(that2.app.graphicsDevice, {
              format: pc.PIXELFORMAT_R8_G8_B8,
              autoMipmap: true,
            });
            normalTexture.setSource(normalImage);
            // normalImage.onload = () => {
            let diffuseTexture = new pc.Texture(that2.app.graphicsDevice, {
              format: pc.PIXELFORMAT_R8_G8_B8,
              autoMipmap: true,
            });
            diffuseTexture.setSource(diffuseImage);

            const material = new pc.StandardMaterial();

            material.normalMap = normalTexture;
            material.diffuseMap = diffuseTexture;
            console.log(material);
            material.bumpiness = 2;
            material.update();

            part.model.meshInstances[0].material = material; // gltf, json

          };
        }


      }, {
        basePath: `${environment.apiUrl}/assets/products/${folderName}/${partName}/`
      });
    });
    targetEntity.addChild(part);
  }

texture랑 material을 완전 코드 베이스로 만들어 봤다.

하지만 이렇게 할일은 거의 없다. Material을 Editor 으로 JSON으로 다운 받아서 사용하면 되기때문이다.

도대체 언제 누가 왜? Material과 Texture를 이렇게 만들어서 사용할까? 

일단 저장용ㅇ

2. Downloaded Material with texture in glTF 

modelLoadGLTF(entityName, carBaseUrl, materialAsset) {
    const basePath = carBaseUrl.split('/');
    const part = new pc.Entity();
    part.name = basePath[6];
    let tha = this;
    this.app.assets.loadFromUrl(carBaseUrl, 'json', function (err, asset) {
      let json = asset.resource;
      let gltf = JSON.parse(json);
      const loadGltf = window['loadGltf'];

      loadGltf(gltf, tha.app.graphicsDevice, (model, textures, animationClips) => {
        // add the loaded scene to the hierarchy
        part.addComponent('model');
        part.model.model = model; // Check again!
        if (materialAsset !== undefined) {
          if (part.name === 'wheel19') {
            let diffuseImage = new Image();
            diffuseImage.crossOrigin = 'use-credentials';
            diffuseImage.src = `${environment.apiUrl}/assets/products/dl3/texture/wheel19_Diffuse.png`;

            let normalImage = new Image();
            normalImage.crossOrigin = 'use-credentials';
            normalImage.src = `${environment.apiUrl}/assets/products/dl3/texture/wheel19_Normal.png`;

            diffuseImage.onload = () => {
              let diffuseTexture = new pc.Texture(tha.app.graphicsDevice, {
                format: pc.PIXELFORMAT_R8_G8_B8,
                autoMipmap: true,
              });
              diffuseTexture.setSource(diffuseImage);
              materialAsset.resource.diffuseMap = diffuseTexture;

              let normalTexture = new pc.Texture(tha.app.graphicsDevice, {
                format: pc.PIXELFORMAT_R8_G8_B8,
                autoMipmap: true,
              });
              normalTexture.setSource(normalImage);
              materialAsset.resource.normalMap = normalTexture;
              materialAsset.resource.bumpiness = 2;
              materialAsset.resource.update();
              part.model.model.meshInstances[0].material = materialAsset.resource;
            };

          } else {
            part.model.model.meshInstances[0].material = materialAsset.resource;
          }
        }

      }, {
        // basePath: `${environment.apiUrl}/${basePath[3]}/${basePath[4]}/${basePath[5]}/${basePath[6]}/`
        basePath: `${environment.apiUrl}/${basePath[3]}/${basePath[4]}/${basePath[5]}/${basePath[6]}/`
      });
    });
    const targetEntity = this.app.root.findByName(entityName);
    targetEntity.addChild(part);
  }

 

3. assets.loadFromUrl material with texture  이거 버그 고처짐

아직 머지는 안됐지만 https://github.com/playcanvas/engine/pull/1692#pullrequestreview-288433123 

 

AssetsRegistry.loadFromUrl material now will load textures too by Maksims · Pull Request #1692 · playcanvas/engine

Fixes #1096 Now textures are loaded too, when loading material asset from url. I confirm I have signed the Contributor License Agreement.

github.com

이제 코드가 더 간단해짐

  modelLoadGLTF(entityName, carBaseUrl, materialAsset) {
    const basePath = carBaseUrl.split('/');
    const part = new pc.Entity();
    part.name = basePath[6];
    let tha = this;
    this.app.assets.loadFromUrl(carBaseUrl, 'json', (err, asset) => {
      let json = asset.resource;
      let gltf = JSON.parse(json);
      const loadGltf = window['loadGltf'];

      loadGltf(gltf, tha.app.graphicsDevice, (model, textures, animationClips) => {
        // add the loaded scene to the hierarchy
        part.addComponent('model');
        part.model.model = model; // Check again!
        if (materialAsset !== undefined) {
            part.model.model.meshInstances[0].material = materialAsset.resource;
        }
      }, {
        basePath: `${environment.apiUrl}/${basePath[3]}/${basePath[4]}/${basePath[5]}/${basePath[6]}/`
      });
    });
    const targetEntity = this.app.root.findByName(entityName);
    targetEntity.addChild(part);
  }

크~