三个J的思考

时间:2019-10-22 05:43:35

标签: reactjs typescript three.js gltf

在应用程序中基于反应的,使用应管理3D形状的打字稿编写的应用中,我遇到了一个不好的问题。 问题在于反射看起来一点也不好。我尽力改善了代码,但没有成功。

工作流程是在搅拌机中创建材质支架,将其导出并应用于从另一个gltf导入的空形状。

对于我尝试过的所有材料(具有正常地图结构的纸张),一切正常。

使用简单的纸张材料 with simple paper material

如果材料具有反射性(粗糙度0.2和金属度0.8),则结果如下:

具有反光材料 with reflective material

如您所见,如果您认为多维数据集是一个占位符,那么反映出的环境部分是非常错误的:

立方体贴图的六个图像之一 one of the six images of the cube map

代码非常简单,在这里我创建多维数据集Map:

    const loader = new THREE.CubeTextureLoader();
    const path = `${this.props.baseUrl}backgrounds/${background.value}`;
    const ext = background.value === "test" ? "jpg" : "png";
    const bkcg = [
      `${path}/py.${ext}`,
      `${path}/nz.${ext}`,
      `${path}/px.${ext}`,
      `${path}/ny.${ext}`,
      `${path}/pz.${ext}`,
      `${path}/nx.${ext}`,
    ];

    // const loader = new THREE.TextureLoader();
    // const bkcg = `${this.props.baseUrl}backgrounds/test_texture.jpg`;

    loader.load(bkcg, async (t) => {
      t.minFilter = THREE.LinearFilter;
      t.magFilter = THREE.LinearFilter;
      t.encoding = THREE.sRGBEncoding;
      t.format = THREE.RGBFormat;
      this.setState({
        background: t,
        bckgLoaded: true,
      });  

在这里,我将材质分配给不同的网格:

  public editMeshes = (
    item: THREE.Mesh,
    isOrderPage: boolean,
    design: IDesign,
    materials: {[name: string]: THREE.MeshStandardMaterial | string},
    textures: ITextures,
    renderer: THREE.WebGLRenderer,
    scene: THREE.Scene,
  ) => {
    if (item.name === "Ground" || item.name === "X_Ground_Freigabe") {
      const color = isOrderPage ? new THREE.Color("#ffffff") : new THREE.Color("#aaaaaa"); // #8f8f8f
      const groundMaterial = new THREE.MeshBasicMaterial({ color });
      item.material = groundMaterial;
    } else {
      item.scale.x = item.scale.x + 0;
      item.scale.y = item.scale.y + 0;
      item.scale.z = item.scale.z + 0;  
      if (Object.keys(design).indexOf(item.name) !== -1 || Object.keys(materials).indexOf(item.name) !== -1) {
        if (Object.keys(design).indexOf(item.name) === -1 && Object.keys(materials).indexOf(item.name) !== -1) {
          if (item.material instanceof THREE.MeshStandardMaterial) {
            item.material.color = new THREE.Color(`${materials[item.name]}`);
          }
        } else {
          if (typeof(materials[item.name]) !== "string") {
            item.material = materials[item.name] as THREE.MeshStandardMaterial;
            if (item.material instanceof THREE.MeshStandardMaterial) {
              if (shinyMaterials.indexOf((item.material as THREE.MeshStandardMaterial).name) !== -1) {
                this.createCubeCamera(item, textures, scene, renderer);
                item.material.needsUpdate = true;
              } else {
                (item.material as THREE.MeshStandardMaterial).map = textures ? textures[item.name] : 
                  (item.material as THREE.MeshStandardMaterial).map;
                (item.material as THREE.MeshStandardMaterial).envMapIntensity = 4;
                (item.material as THREE.MeshStandardMaterial).needsUpdate = true;
                item.material.flatShading = false;    
              }
            } 
          }  
        }
      } else {
        if (shinyMaterials.indexOf((item.material as THREE.MeshStandardMaterial).name) !== -1) {
          this.createCubeCamera(item, textures, scene, renderer);
        }
      }
    }
  }
}

在这里,我为反射创建相机:

  public createCubeCamera = (
    item: THREE.Mesh, 
    textures: ITextures, 
    scene: THREE.Scene, 
    renderer: THREE.WebGLRenderer) => {
    const cubeCamera = new THREE.CubeCamera(0.001, 10000, 2048);
    scene.add(cubeCamera);
    cubeCamera.name = `cubeCamera_${item.name}`;
    cubeCamera.position.set(item.position.x, item.position.y, item.position.z);
    item.visible = false;
    cubeCamera.update(renderer, scene);
    item.visible = true;
    const renderCamera = cubeCamera.renderTarget.texture as THREE.CubeTexture; // scene.background as THREE.CubeTexture
    (item.material as THREE.MeshStandardMaterial).map = 
    textures ? textures[item.name] : (item.material as THREE.MeshStandardMaterial).map;
    (item.material as THREE.MeshStandardMaterial).envMap = renderCamera;
    (item.material as THREE.MeshStandardMaterial).envMapIntensity = 1;
    (item.material as THREE.MeshStandardMaterial).flatShading = false; 
    (item.material as THREE.MeshStandardMaterial).needsUpdate = true;
  }

在这里渲染场景:

    if (this.props.background) {
      scene.background = this.props.background;
      const camera = this.props.mainScene.cameras[0];
      scene.children[0].children.map((item: THREE.Object3D) => {
        if (item instanceof THREE.Light) {
          this.props.mockUtils.editLights(
            item as THREE.SpotLight | THREE.DirectionalLight, 
            this.props.scene.lights_intensity,
            scene,
            );
        } 

        if (item instanceof THREE.Mesh) {
          this.props.mockUtils.editMeshes(
            item,
            this.props.isOrderPage,
            this.props.design,
            this.props.materials,
            this.props.textures,
            // this.props.background,
            renderer,
            scene,
          );
        }
      });
      this.props.mockUtils.addAmbientLight(scene, this.props.scene.ambient_light);
      scene.children.map((obj: THREE.Object3D) => {
        if (obj instanceof THREE.CubeCamera) {
          obj.update(renderer, scene);
        }
      });
      renderer.render(scene, camera);
      if (this.design.current) {
        this.props.mockUtils.finish(
          renderer, 
          FinalImage, 
          id, 
          `${this.props.baseUrl}products/${this.props.scene.product_name}.jpg`,
          this.props.isOrderPage,
          this.props.scene.zoomFactor,
          this.design.current,
          this.assetsLoaderCallback,
        );
      }
    }
  }

有人可以帮助我了解如何接收应用于场景背景的立方体贴图的法线反射吗?

谢谢

迈克尔·莫雷蒂

0 个答案:

没有答案