I have created bottle in blender. If i test it on threejs editor it is giving right results.
But when I render it on my site it is giving
This as output. I am but new to threejs
import './style.css'
import * as THREE from 'three'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
const updateAllMaterials = () =>
{
scene.traverse((child) =>
{
if(child instanceof THREE.Mesh)
{
child.material.envMap = environmentMap
child.material.transparent = true
child.material.opacity = 0.1
child.material.envMapIntensity = 5
const material = new THREE.MeshPhysicalMaterial( {
transmission: 1, // use material.transmission for glass materials
opacity: 0.2,
color:"blue",
transparent: true
} );
child.material = material
}
})
}
// Canvas
const canvas = document.querySelector('canvas.webgl')
const gltfLoader = new GLTFLoader()
gltfLoader.load('/models/wine5.glb',(bottle)=>{
bottle.scene.scale.set(0.5,0.45,0.5)
bottle.scene.rotation.set(-0.5,1,0.3)
bottle.scene.position.set(-1,-1.5,2)
updateAllMaterials()
scene.add(bottle.scene)
})
// Scene
const scene = new THREE.Scene()
const axesHelper = new THREE.AxesHelper( 5 );
scene.add( axesHelper );
const directionalLights = new THREE.PointLight('#fff',4)
directionalLights.position.set(-0.4,2,5)
scene.add(directionalLights)
/**
* Sizes
*/
const sizes = {
width: window.innerWidth,
height: window.innerHeight
}
/**
* Camera
*/
// Base camera
const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height, 0.1, 100)
scene.add(camera)
// ENV MAPS
const singleTextureLoader = new THREE.TextureLoader()
singleTextureLoader.load('/BG/tree.jpg',(img)=>{
scene.background = img
})
/**
* Renderer
*/
const renderer = new THREE.WebGLRenderer({
canvas: canvas,
antialias: true
})
renderer.setSize(sizes.width, sizes.height)
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
renderer.physicallyCorrectLights = true
renderer.outputEncoding = THREE.sRGBEncoding
renderer.toneMapping = THREE.ACESFilmicToneMapping
renderer.toneMappingExposure = 1
renderer.depth = false
Your updateAllMaterials() is traversing an empty scene, thus not applying the material to anything. Just swap the calls like this:
scene.add(bottle.scene)
updateAllMaterials()
Also, inside the updateAllMaterials() function, you are changing some parameters of the child's material, and then you overwrite the material itself, losing all the changes.
It should be something like this:
const material = new THREE.MeshPhysicalMaterial({
transmission: 1,
opacity: 0.2,
color:"blue",
transparent: true,
envMap: environmentMap,
transparent: true,
opacity: 0.1,
envMapIntensity: 5
});
child.material = material
Related
How to prevent an object from being stretched after being rotated inside another object that has some scale?
In general, I want the child to behave as if the parent has a size of 1, 1, 1,
and I don't want to create a group for the parent and for the child.
A few letters for the system to accept the question
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
// Renderer
const renderer = new THREE.WebGLRenderer({
alpha: false,
antialias: true,
stencil: false,
depth: false
});
document.body.appendChild(renderer.domElement);
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera();
camera.position.z = 10;
new OrbitControls(camera, renderer.domElement)
// Parent
const parentGeometry = new THREE.BoxGeometry(1, 1, 1);
const parentMaterial = new THREE.MeshBasicMaterial({ color: "tomato" });
const parent = new THREE.Mesh(parentGeometry, parentMaterial);
parent.scale.set(3, 0.5, 3)
scene.add(parent);
// Child
const childGeometry = new THREE.BoxGeometry(1, 1, 1);
const childMaterial = new THREE.MeshBasicMaterial({ color: "lightblue" });
const child = new THREE.Mesh(childGeometry, childMaterial);
parent.add(child);
child.scale.x = 1 / parent.scale.x;
child.scale.y = 1 / parent.scale.y;
child.scale.z = 1 / parent.scale.z;
// ???
child.rotation.x = Math.PI / 4;
function resize() {
const width = document.documentElement.clientWidth;
const height = window.innerHeight;
camera.aspect = width / height;
camera.fov = 55
camera.updateProjectionMatrix();
renderer.setPixelRatio(Math.min(2, devicePixelRatio));
renderer.setSize(width, height);
}
window.addEventListener("resize", resize);
resize();
function tick(t) {
requestAnimationFrame(tick);
renderer.render(scene,camera);
}
requestAnimationFrame(tick);
I found that it seems to be solved by setting the blending attribute of material, but it still cannot be solved after trying.
Incorrect occlusion
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import {GLTFLoader} from "three/examples/jsm/loaders/GLTFLoader.js"
import {
CSS3DRenderer,
CSS3DObject
} from "three/examples/jsm/renderers/CSS3DRenderer.js"
import dat from "dat.gui"
function initThree() {
const scene = new THREE.Scene();
const scene2 = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
50,
window.innerWidth / window.innerHeight,
0.1,
10000
);
camera.position.set(0, 0, 2500);
scene.add(camera);
const renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true,
});
renderer.shadowMap.enabled = true;
renderer.setSize(window.innerWidth, window.innerHeight);
document.querySelector('#webgl').appendChild(renderer.domElement);
const labelRenderer = new CSS3DRenderer()
labelRenderer.setSize(window.innerWidth, window.innerHeight);
labelRenderer.domElement.style.position = 'absolute';
labelRenderer.domElement.style.top = 0;
document.body.appendChild(labelRenderer.domElement);
scene.add(new THREE.AxesHelper(1000))
const controls = new OrbitControls(camera, labelRenderer.domElement);
controls.enableDamping = true;
const clock = new THREE.Clock()
window.addEventListener("resize", () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
labelRenderer.setSize(window.innerWidth, window.innerHeight);
});
return {
scene,
scene2,
camera,
renderer,
labelRenderer,
controls,
clock,
}
}
const gltfLoader = new GLTFLoader()
const textureLoader = new THREE.TextureLoader()
const gui = new dat.GUI()
const {
scene,
scene2,
camera,
renderer,
labelRenderer,
controls,
clock
} = initThree();
const ambientLight = new THREE.AmbientLight("#ffffff", 1)
scene.add(ambientLight)
const position = new THREE.Vector3(0, 900, 300);
const rotation = new THREE.Euler(0, 0, 0);
const container = document.createElement('div');
container.style.width = '1000px';
container.style.height = '1000px';
container.style.opacity = '1';
container.style.background = '#1d2e2f';
const iframe = document.createElement('iframe');
iframe.src = "http://csyedu.top"
iframe.style.width = "1000px"
iframe.style.height = "1000px"
iframe.style.padding = 10 + 'px';
iframe.style.boxSizing = 'border-box';
iframe.style.opacity = '1';
container.appendChild(iframe);
const object = new CSS3DObject(container);
// copy monitor position and rotation
object.position.copy(position);
object.rotation.copy(rotation);
// Add to CSS scene
scene2.add(object);
// Create GL plane
const material = new THREE.MeshLambertMaterial();
material.side = THREE.DoubleSide;
material.opacity = 0;
material.transparent = true;
// NoBlending allows the GL plane to occlude the CSS plane
material.blending = THREE.NoBlending;
// Create plane geometry
const geometry = new THREE.PlaneGeometry(1000, 1000);
// Create the GL plane mesh
const mesh = new THREE.Mesh(geometry, material);
// Copy the position, rotation and scale of the CSS plane to the GL plane
mesh.position.copy(object.position);
mesh.rotation.copy(object.rotation);
mesh.scale.copy(object.scale);
// Add to gl scene
scene.add(mesh);
gltfLoader.load("./models/computer_setup.glb", model => {
const texture = textureLoader.load("./models/baked_computer.jpg");
texture.flipY = false;
texture.encoding = THREE.sRGBEncoding;
const material = new THREE.MeshBasicMaterial({
map: texture,
});
model.scene.traverse((child) => {
if (child instanceof THREE.Mesh) {
child.scale.set(900, 900, 900);
child.material.map = texture;
child.material = material;
}
});
scene.add(model.scene)
})
function render() {
const elapsedTime = clock.getElapsedTime();
controls.update();
renderer.render(scene, camera);
labelRenderer.render(scene2, camera)
requestAnimationFrame(render);
}
render();
The effect I want is that the 3D mesh can correctly occlude the CSS3DObject.
I runned over the same problem, I'm trying your code and works good on my project, I think you have a styling problem.
I have separated the WebGL and CSS3DRenderer on the html.
<body>
<div id="css"></div>
<div id="webgl"></div>
</body>
#css,
#webgl
{
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
}
If I only put the #css on absolute this is the result
If I put both in absolute it works fine.
I wish that'll help
I'm using threejs to provide a 3D animation...
this is my main.js file content:
import './style.css'
import {
AxesHelper,
BufferGeometry,
Float32BufferAttribute,
MathUtils,
PerspectiveCamera,
Points,
PointsMaterial,
Scene,
TextureLoader,
VertexColors,
WebGLRenderer,
} from "three";
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls.js';
const count = 100;
const distance = 2;
const textureLoader = new TextureLoader();
const circleTexture = textureLoader.load("ball.png");
const scene = new Scene();
scene.add(new AxesHelper());
const camera = new PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.01,1000);
camera.position.z = 2;
camera.position.y = 0.5;
camera.position.x = 0.5;
scene.add(camera);
const pts = new Float32Array(count * 3);
const colors = new Float32Array(count * 3);
for (let i = 0; i < pts.length; i++) {
pts[i] = MathUtils.randFloatSpread(distance * 2);
colors[i] = Math.random();
}
const geometry = new BufferGeometry();
geometry.setAttribute('position', new Float32BufferAttribute(pts,3));
geometry.setAttribute('colors', new Float32BufferAttribute(colors,3));
const pointMaterial = new PointsMaterial({
size: 0.1,
map : circleTexture,
alphaTest: 0.01,
transparent: true,
vertexColors : VertexColors,
});
const points = new Points(geometry, pointMaterial);
scene.add(points);
const renderer = new WebGLRenderer({
antialias: true, //removing all ugly pixels from cube's sides
alpha : true,
});
renderer.setClearColor(0x000000, 0);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(Math.min(window.devicePixelRatio,2));
document.body.appendChild(renderer.domElement);
const controls = new OrbitControls(camera, renderer.domElement);
function anime() {
renderer.render(scene, camera);
controls.update();
requestAnimationFrame(anime);
}
anime();
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix(); // mettre a jour la camera...
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(Math.min(window.devicePixelRatio,2));
});
in PointsMaterial() constructor , I want to assign a value to vertexColor to make a variety of colors for my objects (3D looking points...), but I got the following error on the console :
Uncaught SyntaxError: The requested module '/node_modules/.vite/deps/three.js?v=19235266' does not provide an export named 'VertexColors' (at main.js?t=1655672405709:13:5)
it seems like threejs doesn't contain this property or what ??!!!
Please i need help on three.js animation. trying to animate the ball randomly on the plane before stoping at specific or selected location on the plane. my code below please any help will be appreciates.
1: https://i.stack.imgur.com/3kXhW.png
Please i need help on three.js animation. trying to animate the ball randomly on the plane before stoping at specific or selected location on the plane. my code below please any help will be appreciates.
.
. .
import { OrbitControls } from "./libs/three128/OrbitControls.js";
import { GUI } from "./dat.gui.module.js";
class Game {
constructor() {
const container = document.createElement("div");
document.body.appendChild(container);
this.step = 0;
this.speed = 0.01;
this.camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
this.camera.position.set(-10, 150, 150);
this.scene = new THREE.Scene();
this.scene.background = new THREE.Color(0xaaaaaa);
const ambient = new THREE.HemisphereLight(0xffffff, 0xbbbbff, 0.3);
this.scene.add(ambient);
const light = new THREE.DirectionalLight();
light.position.set(0.2, 1, 1);
this.scene.add(light);
this.renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
this.renderer.setPixelRatio(window.devicePixelRatio);
this.renderer.setSize(window.innerWidth, window.innerHeight);
container.appendChild(this.renderer.domElement);
//Replace Box with Circle, Cone, Cylinder, Dodecahedron, Icosahedron, Octahedron, Plane, Sphere, Tetrahedron, Torus or TorusKnot
const planeGeometry = new THREE.BoxBufferGeometry(200, 200, 3);
const planeMaterial = new THREE.MeshStandardMaterial({
color: 0xff0000,
side: THREE.DoubleSide,
});
this.plane = new THREE.Mesh(planeGeometry, planeMaterial);
this.scene.add(this.plane);
const ballGeometry = new THREE.SphereGeometry(8, 100, 100);
const ballMaterial = new THREE.MeshStandardMaterial({
color: 0x0000ff,
wireframe: false,
});
this.ball = new THREE.Mesh(ballGeometry, ballMaterial);
this.scene.add(this.ball);
const controls = new OrbitControls(this.camera, this.renderer.domElement);
this.gridHelper = new THREE.GridHelper(200);
this.scene.add(this.gridHelper);
this.input();
this.renderer.setAnimationLoop(this.render.bind(this));
window.addEventListener("resize", this.resize.bind(this));
}
input() {
const gui = new GUI();
let ball = this.ball;
let plane = this.plane;
ball.position.set(0, 9.5, 0);
const options = {
ballColor: ball.material.color.getHex(),
planeColor: plane.material.color.getHex(),
positionX: ball.position.x,
positionZ: ball.position.z,
wireframe: false,
};
gui
.add(options, "positionX", -100, 100)
.name("X-coodinate")
.onChange(function (value) {
ball.position.x = value;
console.log(value);
});
gui
.add(options, "positionZ", -100, 100)
.name("Y-coodinate")
.onChange(function (value) {
ball.position.z = value;
console.log(value);
});
gui
.addColor(options, "ballColor")
.name("Ball-Color")
.onChange(function (value) {
ball.material.color.set(value);
});
gui
.addColor(options, "planeColor")
.name("Plane-Color")
.onChange(function (value) {
plane.material.color.set(value);
});
// gui.add(ball.material, "wireframe").name("Wireframe");
}
resize() {
this.camera.aspect = window.innerWidth / window.innerHeight;
this.camera.updateProjectionMatrix();
this.renderer.setSize(window.innerWidth, window.innerHeight);
}
render() {
this.plane.rotation.x = -0.5 * Math.PI;
this.renderer.render(this.scene, this.camera);
}
}
export { Game };
project picture.
smile on shirt has black background
smile with transparent true
GOAL: I would like users to be able to add images/colors with buttons
PROBLEM: but the png image texture(smiley face) loaded with textureLoader() has black background and lines crossing the image. :frowning:
MINOR PROBLEM:
(1) Are there any ways to match the background color of the image and the obj/gltf(shirt) that I load?
Here are my codes.
const colorSelection = {
"pink": "#ff2d55",
"purple": "#5856d6",
"blue": "#007aff",
"orange": "#ff9500",
}
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
const renderer = new THREE.WebGLRenderer({ antialias: true });
const loader = new THREE.OBJLoader();
const myCanvas = document.getElementById("container");
const controls = new THREE.OrbitControls(camera, renderer.domElement);
const axisHelper = new THREE.AxisHelper(5);
const hlight = new THREE.AmbientLight (0x404040);
const directionalLight = new THREE.DirectionalLight(0xffffff,0.4);
const geometry = new THREE.SphereGeometry(50,50,50);
const texture = new THREE.TextureLoader().load("assets/smile2.png");
const newMat = new THREE.MeshPhongMaterial({ map: texture });
myCanvas.appendChild( renderer.domElement );
renderer.setSize( 800, 800 );
renderer.setClearColor ("darkgrey", 1);
camera.position.set(200,300,200);
controls.addEventListener("change", animate);
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
};
// SCENES and LIGHTING
scene.add(axisHelper);
scene.add(hlight);
scene.add(directionalLight);
directionalLight.position.set(0,1155,325);
directionalLight.castShadow = true;
function changeTextureColor(color) {
loader.load("assets/standard-t-shirt/source/tshirt.obj", function(obj) {
obj.scale.set(0.4,0.4,0.4)
obj.position.set(0,-500,0)
obj.traverse((child) => {
if (child instanceof THREE.Mesh) {
child.material.emissive = new THREE.Color(colorSelection[color])
console.log(child.material)
}
})
console.log(obj.children)
obj.children[0].material = newMat
scene.add(obj)
})
}
document.querySelectorAll("button").forEach(colorBtn => colorBtn.addEventListener("click", function () {
console.log(this.id)
const userColor = this.id;
changeTextureColor(userColor);
}))
Thanks so much for reading!
You need the transparent: true setting when creating your material, like so:
const newMat = new THREE.MeshPhongMaterial({ map: texture, transparent: true });