three.js docs mentions the order of textures is px, nx / py, ny / pz, nz. But I noticed the first value relates to the negative-x axis, not the positive one. This was very confusing and caused me to waste a lot of time trying to figure out what was wrong with my skybox (wrong handedness turns out). I created a https://jsfiddle.net/ebvwxzf2/79/ so you can test it out for yourself.
This is my attempt to illustrate what @nickyvanurk says:
https://codepen.io/boytchev/full/oNVmbOR
The cube in the center has 6 materials, one for each side, and px/nx/py/ny/pz/nz are consistent with the world axes. The background is a cube texture and py/ny/pz/nz are consistent, while px/nx are swapped.
Exactly, thank you very much.
Cube textures have px/nx flipped which is a convention in the library (you can read about the background of this in 3d - Why are the faces of a cubemap labelled px, nx, py, ny, pz, nz? - Stack Overflow).
When you use the sides of the cube map not with CubeTexture
, you have to apply the flip by yourself. So the multi-material mesh should be created like so:
var cube = new THREE.Mesh(
new THREE.BoxGeometry(1,1,1),
[
material(imageNX),
material(imagePX),
material(imagePY),
material(imageNY),
material(imagePZ),
material(imageNZ),
]
);
BTW: When assigning the same skybox (the instance of CubeTexture
) to Scene.background
and the envMap
property of a material, the result is as expected.
Thank you very much for this explanation! Now I know why my skybox, when rendered, appears to be rotated 180 degrees the wrong way. Which by convention is actually the correct way. Is there currently a way to rotate a skybox/CubeTexture when used as a scene.background by 180 degrees? Or is waiting for CubeTexture orientation · Issue #16328 · mrdoob/three.js · GitHub or creating a literal box with the sky texture + doubleside rendering the only options I have at this point?
Awesome. TIL
Just a bit of warning… if you’re building something that is Z up… and you’re trying to make the library accomodate it… There are hard ways, and slightly easier ways to achieve it.
My honest recommendation after being in this situation half a dozen times in my life…
A. convert your code to use Y up if possible.
B. If A isn’t an option… put all your stuff under a single Object3D with a rotation.x = -Math.PI*.5
and use lots of localToWorld and worldToLocal in your logic to make it work.
C. Continue down the path of trying to force threejs to work in a Z up scenario. This path ends in much frustration and gnashing of teeth. Because you will be fighting against… 1. every model importer/exporter that autoconverts to Y up.(like the gltf one)
2. All the controls types (orbitcontrols/flycontrols) etc.
3. All skybox/cubemap/equirectangular env map code. Lord knows if you can even work around this… decompressing images… rotating them. It’s a Complete nightmare. Then there are the many addons 3rd party stuff that have Y up baked in as assumptions. There is the global Up vector in threejs… which you’ll have to reset.
10 years ago, I was a Z-up zealot… since it of course makes perfect sense in a 3d world (it doesn’t)… and I learned the hard way to embrace the native up-ness of the platform… (which turns out to really just be a kinda small shift in perspective and not worth grinding your fingers to nubs to work around for a year only to end up with a pile of janky workarounds…)
(I just re-read the thread and realize that you’re probably not trying to force Z up, but my ptsd about it compelled me to vomit this warning tract.)
I had a good chuckle at your expense, as there’s obviously years of hair pulling trauma behind that post. This is a safe space
If you stare into the up vector long enough, the up vector stares back.