I downloaded this project from codesandbox.io that shows an image on the side of a cube. THREE.js - CodeSandbox
When it’s downloaded and run locally, the cube is rendered, but the image is not added. After downloading, I run npm install
and npm run start
. There are warnings about gamma not being supported. I tried a few changes based and added postprocessing, but couldn’t get the image to show on the face of the cube. Are there some new ways to place an image on geometric objects?
I’ve updated the code and cleaned it up a bit so you can copy/paste it into one of the official examples e.g. webgl_geometry_cube
and run it locally. The code works with the latest official three.js
release r141
.
import * as THREE from 'three';
import { OrbitControls } from './jsm/controls/OrbitControls.js';
let camera;
let renderer;
let scene;
let mesh;
let controls;
function init() {
// Creating the scene
scene = new THREE.Scene();
scene.background = new THREE.Color("skyblue");
createCamera();
createLights();
createMeshes();
createRenderer();
createControls();
renderer.setAnimationLoop(() => {
update();
render();
});
}
function createCamera() {
const fov = 35;
const aspect = window.innerWidth / window.innerHeight;
const near = 0.1;
const far = 100;
camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.set(-2, 2, 10);
}
function createLights() {
const mainLight = new THREE.DirectionalLight(0xffffff, 5);
mainLight.position.set(10, 10, 10);
const hemisphereLight = new THREE.HemisphereLight(0xddeeff, 0x202020, 5);
scene.add(mainLight, hemisphereLight);
}
function createMeshes() {
const textureLoader = new THREE.TextureLoader();
const texture = textureLoader.load("./textures/uv_grid_opengl.jpg");
texture.encoding = THREE.sRGBEncoding;
const geometry = new THREE.BoxGeometry(2, 2, 2);
const material = new THREE.MeshStandardMaterial({ map: texture });
mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
}
function createRenderer() {
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.outputEncoding = THREE.sRGBEncoding;
renderer.physicallyCorrectLights = true;
document.body.appendChild(renderer.domElement);
}
function createControls() {
controls = new OrbitControls(camera, renderer.domElement);
}
function update() {
// mesh.rotation.x += 0.01;
// mesh.rotation.y += 0.01;
// mesh.rotation.z += 0.01;
}
function render() {
renderer.render(scene, camera);
}
init();
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
// Update camera frustum
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth , window.innerHeight);
}
window.addEventListener("resize", onWindowResize, false);
Thanks for looking at this.
I incorporated your changes but I’m still not seeing the image on the cube.
I get a little confused on importing three.js. I copied the orbitcontrol in examples from node_modules into /src. I think it is reading both three.js and orbitcontrol from /src.
I can build and I have pushed and deployed to netlify.
I can’t figure out why the image doesn’t show up on the cube??
Here’s the code: GitHub - rebeccapeltz/three-test: testing three.js
Here’s the deployed code: https://bright-mousse-6903a7.netlify.app/
I just got this to work by loading the image to the texture from a remote URL rather than from the local server - I think that parcel is not copying the local image over to the build output directory. I don’t get a 404, but the image you need in the inspector network tab when you load locally is not the image.
I’m not familiar with Parcel, sorry. I’ve just used the local server which is defined as a dev dependency of the three.js
npm package.
Do you recommend using the CDN’s over NPM?
IMO, using CDNs is fine when you learn three.js
or just want to hack around/ try out features. For all other cases, I recommend using the npm
package in combination with a built tool.
Hi all, @rebeccapeltz, @Mugen87 .
Just jumping in as I guess my answer can be helpful to others encountering the same issue with Parcel builder and using three js locally. I used to have the same problem that I solved doing the following.
This is a parcel specific problem as this bundler doesn’t serve static files by default. But textures files are static files.
Hence you need to add the npm / parcel plugin :
parcel-reporter-static-files-copy - npm or look for the older version if you use parcel 1.
Install it in your repo using : npm install -D parcel-reporter-static-files-copy
.
Then add a .parcelrc
file in the same folder as your package.json
and copy the following:
{
"extends": "@parcel/config-default",
"reporters": [
"...",
"parcel-reporter-static-files-copy"
]
}
Then in your package.json, add the following line to the three, just after devDependencies for example :
{
"dependencies": {
"three": "^0.148.0"
},
"devDependencies": {
"parcel": "^2.8.2",
"parcel-reporter-static-files-copy": "^1.5.0"
},
"staticFiles": {
"staticPath": "assets" // this must be your folder where the static files are stored. The files can be in subfolders of this folder as well.
}
}
Then when you reference a file that is located into /assets/textures
for example, you can address it directly using /textures like :
const texture = textureLoader.load('/textures/uv-test-col.png');
You do not need to add /assets
at the beginning as the files are directly served into the dist
folder (and the associated subfolder if so). See the screenshot below when parcel is running.
Ex here :
Hope this helps !