Размышления в Трех Дж - PullRequest
       64

Размышления в Трех Дж

1 голос
/ 22 октября 2019

У меня плохая проблема, которую нужно решить в приложении, основанном на реакции, написанном машинописным шрифтом, который должен управлять трехмерными фигурами. Проблема в том, что отражения выглядят не очень хорошо. Я перепробовал все, что мог, чтобы улучшить код, но ничего не получилось.

Рабочий процесс заключается в создании держателя материала в блендере, его экспорте и применении к пустой фигуре, импортированной из другого файла gltf.

Для всех материалов, которые я пробовал (бумага, с обычной структурой карты), все работает отлично.

с простым материалом бумаги with simple paper material

Если материал является отражающим (шероховатость 0,2 и металличность 0,8), это результат:

с отражающим материалом with reflective material

AsВы можете видеть, что часть отраженной среды является совершенно неправильной, если вы считаете, что куб является заполнителем, поэтому:

одно из шести изображений карты куба one of the six images of the cube 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;
  }

и онre рендеринг сцены:

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

Может кто-нибудь помочь мне понять, как получить нормальное отражение карты куба, которая применяется к фону сцены?

Спасибо

Майкл Моретти

...