0

"I'm new to Three.js and have created a .gltf file using Blender. However, I'm facing an issue where the backside of my object appears lighter than expected.

Here's my current view: https://i.sstatic.net/jtI4aCSF.jpg
I'm trying to achieve a look similar to this: https://i.sstatic.net/pL5L8cfg.gif

In this GIF, the object's backside wireframe appears lighter. How can I achieve this effect in my code ?

I can't figure out what’s causing this difference. Any insights or suggestions would be greatly appreciated. Thank you!"


  private initThree(): void {
    const canvas = this.canvas.nativeElement;
    this.scene = new THREE.Scene();
    this.scene.background = new THREE.Color(0xffffff);

    const aspectRatio = canvas.clientWidth / canvas.clientHeight;
    this.camera = new THREE.PerspectiveCamera(1, aspectRatio, 0.0001, 500); // FOV, aspect ratio, near, far

    this.renderer = new THREE.WebGLRenderer({ canvas, antialias: true });
    this.renderer.setSize(canvas.clientWidth, canvas.clientHeight);
    this.renderer.setPixelRatio(window.devicePixelRatio);
    this.controls = new ArcballControls(this.camera, this.renderer.domElement);
    this.controls.rotateSpeed = 0.7;
  }

  public shapeObject(modelPath: string, isInclusionObject: boolean = false): void {
    this.controls.reset();
    if (!isInclusionObject) this.clearScene();
    this.loaderGLTF.load(modelPath, (gltf) => {
      const model = gltf.scene;
      const box = new THREE.Box3().setFromObject(model);
      const center = box.getCenter(new THREE.Vector3());
      model.position.sub(center);
      const axesHelper = new THREE.AxesHelper(1);
      this.scene.add(axesHelper);
      if (isInclusionObject) {
        this.addInclusionModel(model, 0xff0000);
      } else {
        this.addShapeModel(model, 0x4080ff);
      }

      this.scene.add(model);
    },
      (xhr) => console.log(`${(xhr.loaded / xhr.total) * 100}% loaded`),
      (error) => console.error('An error occurred while loading the GLTF model:', error));
  }

  private addInclusionModel(model: THREE.Object3D, wireframeColor: number | string): void {
    this.camera.position.set(0, 0, 3.5);
    const targetDimensions = new THREE.Vector2(0.05, 0.05);
    const box = new THREE.Box3().setFromObject(model);
    const size = new THREE.Vector3();
    box.getSize(size);
    const scaleFactor = Math.min(
      targetDimensions.x / size.x,
      targetDimensions.y / size.y
    );
    model.scale.set(scaleFactor, scaleFactor, scaleFactor);
    model.position.set(0.18, 0, 0);

    model.traverse((child) => {
      if ((child as THREE.Mesh).isMesh) {
        const mesh = child as THREE.Mesh;
        const materials = Array.isArray(mesh.material) ? mesh.material : [mesh.material];

        materials.forEach((mat) => {
          const backWireframeMaterial = new THREE.LineBasicMaterial({ color: wireframeColor });
          const backWireframeGeometry = new THREE.EdgesGeometry(mesh.geometry);
          const backWireframe = new THREE.LineSegments(backWireframeGeometry, backWireframeMaterial);
          mesh.add(backWireframe);
        });
      }
    });
    this.activeInclusion++;
    this.addGuiControls(model, this.activeInclusion);
    this.inclusionIds.push(model.id);
    this.objectCounter++;
    this.sceneObjects.push({ id: this.objectCounter, name: `Inclusion ${this.objectCounter}`, object: model });
    this.inclusionStack.push(model);
    this.activeInclusion = this.sceneObjects.length;
    this.wireframeStates[this.objectCounter] = false;
    this.wireframeEnabled = false;
  }

  private addShapeModel(model: THREE.Object3D, wireframeColor: number | string): void {
    const targetDimensions = new THREE.Vector2(0.30, 0.30);
    const box = new THREE.Box3().setFromObject(model);
    const size = new THREE.Vector3();
    box.getSize(size);
    const scaleFactor = Math.min(
      targetDimensions.x / size.x,
      targetDimensions.y / size.y
    );
    model.scale.set(scaleFactor, scaleFactor, scaleFactor);
    box.setFromObject(model);
    box.getSize(size);
    const center = box.getCenter(new THREE.Vector3());
    //model.position.set(-center.x, -center.y, 0);
    model.position.set(-center.x, -0.05, 0);

    model.traverse((child) => {
      if ((child as THREE.Mesh).isMesh) {
        const mesh = child as THREE.Mesh;
        const materials = Array.isArray(mesh.material) ? mesh.material : [mesh.material];
        materials.forEach((mat) => {
          if ((mat as THREE.MeshStandardMaterial).wireframe !== undefined) {
            (mat as THREE.MeshStandardMaterial).wireframe = true;
            const wireframeMaterial = new THREE.LineBasicMaterial({ color: wireframeColor });
            const wireframeGeometry = new THREE.EdgesGeometry(mesh.geometry);
            const wireframe = new THREE.LineSegments(wireframeGeometry, wireframeMaterial);
            mesh.add(wireframe);
          }
        });
      }
    });
    this.isShapeAdded = true;
  }

1 Answer 1

0

I found my solution by using vertex shader and fragment shader

private shapeObject(modelPath: string, isInclusionObject: boolean = false): void {
  this.controls.reset();
  this.camera.position.set(0, 0, 3.5);
  if(!isInclusionObject) this.clearScene();
  this.loaderGLTF.load(modelPath, (gltf) => {
        const model = gltf.scene;
        const box = new THREE.Box3().setFromObject(model);
        const center = box.getCenter(new THREE.Vector3());
        model.position.sub(center);
        const axesHelper = new THREE.AxesHelper(0);
        this.scene.add(axesHelper);
        if (isInclusionObject) {
              this.addInclusionModel(model, 0xff0000);
        } else {
              this.addShapeModel(model, 'vec3(0.25,0.50,1.00)', 'vec3(0.95,0.95,0.95)');
        }
        this.scene.add(model);
  },
        (xhr) => console.log(`${(xhr.loaded / xhr.total) * 100}% loaded`),
        (error) => console.error('An error occurred while loading the GLTF model:', error));
}

private addShapeModel(model: THREE.Object3D, outSideColor: any, insideColor: any): void {
  const targetDimensions = new THREE.Vector2(0.30, 0.30);
  const box = new THREE.Box3().setFromObject(model);
  const size = new THREE.Vector3();
  box.getSize(size);
  const scaleFactor = Math.min(
        targetDimensions.x / size.x,
        targetDimensions.y / size.y
  );
  model.scale.set(scaleFactor, scaleFactor, scaleFactor);
  box.setFromObject(model);
  box.getSize(size);
  const center = box.getCenter(new THREE.Vector3());
  //model.position.set(-center.x, -center.y, 0);
  model.position.set(-center.x, -0.05, 0);

  var vertexShader = `
  varying vec3 vNormal;
  void main() {
    vNormal = normalize(normalMatrix * normal);
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
  }
`;

  var fragmentShader = `
  varying vec3 vNormal;
  void main() {
    float intensity = dot(vNormal, vec3(0.0, 0.0, 1.0)); // Light direction
    vec3 color = mix(${insideColor}, ${outSideColor}, step(0.0, intensity));
    gl_FragColor = vec4(color, 0.5);
  }
`;
  model.traverse((child) => {
        if ((child as THREE.Mesh).isMesh) {
              const mesh = child as THREE.Mesh;
              const material = new THREE.ShaderMaterial({
                    vertexShader: vertexShader,
                    fragmentShader: fragmentShader,
                    side: THREE.DoubleSide,
                    transparent: true,
                    opacity: 0.5
              });
              mesh.material = material;
              const materials = Array.isArray(mesh.material) ? mesh.material : [mesh.material];
              materials.forEach((mat) => {
                    if ((mat as THREE.MeshStandardMaterial).wireframe !== undefined) {
                          (mat as THREE.MeshStandardMaterial).wireframe = true;
                    }
              });
        }
  });
  this.isShapeAdded = true;
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.