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);
}
);
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.
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);
You can do this economically and without creating a custom shader.
Create a second object that shares the geometry of the first, and assign 2 different materials with FrontSide and BackSide respectively. This will work for large models without a hit on performance, unless of course you are introducing a large bitmap for both sides of the object.