Different Materials on Plane side A and side B

Hey,
I’m pretty new to threejs and have been googling my way through but can’t seem to find a solution to my seemingly easy problem:

How can I add a material A to side A of a plane and material B to side B of the same plane?

At the moment I get a plane which is (depending on my settings THREE.DoubleSide/FrontSide/BackSide) either transparent from side B or has the same material on both sides. I created a plane in Blender, exported the file as GLTF from threejs/editor and imported it via GLTF-Loader like this:

assetLoader.load(
  monkeyUrl.href,
  function (gltf) {
    const model = gltf.scene;

    //SIDE A MATERIAL
    const frontCard = model.getObjectByName("Front_Card");
    const materialFrontCardFront = new THREE.MeshPhongMaterial({
      side: THREE.FrontSide,
    });
    frontCard.material.color.setHex(0xff0000);
    frontCard.material = materialFrontCardFront;
   


    //SIDE B MATERIAL
    const materialFrontCardBack = new THREE.MeshPhongMaterial({
      side: THREE.BackSide,
    });
    frontCard.material.color.setHex(0xbb0000);
 frontCard.material = materialFrontCardBack;

    scene.add(model);
  },
  undefined,
  function (error) {
    console.error(error);
  }
);

Thanks for the help!

three docs examples might have something. Otherwise poke around in Unity forms and also use the search term cg shader
https://en.wikibooks.org/wiki/Cg_Programming/Unity/Two-Sided_Surfaces

Youll be doing the same routine if you need to write a custom two pass shader

Base idea if I recall is, if you can get the function to know which direction the normal of the face is pointing you swap which texture it needs to render.

There are many approaches (with a second pair of triangles, with a twin-plane, with a flat box, with a custom shader…)

Here is the case with a flat box:

var plane = new THREE.Mesh(
       new THREE.BoxGeometry( 3, 2, 0 ),
       [  null,  null, null, null,
          new THREE.MeshLambertMaterial( {color: 'crimson'}),
          new THREE.MeshLambertMaterial( {color: 'yellow'}),
      ]
  );	
1 Like

I vote for this :slight_smile:

import {mergeGeometries} from "three/addons/utils/BufferGeometryUtils.js";
...
let plane = new THREE.Mesh(
  mergeGeometries(
    [
      new THREE.PlaneGeometry(3, 2),
      new THREE.PlaneGeometry(3, 2).rotateY(Math.PI)
    ],
    true // allow groups
  ),
  [
    new THREE.MeshBasicMaterial({ color: "red" }),
    new THREE.MeshBasicMaterial({ color: "blue" })
  ]
);
scene.add(plane);
2 Likes

For a more complex object, it should be possible to clone geometry, flip the normals and use mergeGeometries like in the example