Im trying to implement post-processing effects in Three.js through this example here:
https://threejs.org/docs/#manual/en/introduction/How-to-use-post-processing
With the following code:
import * as THREE from 'three';
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js';
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js';
import { GlitchPass } from 'three/examples/jsm/postprocessing/GlitchPass.js';
var scene, camera, renderer, box, composer;
init();
function init() {
scene = new THREE.Scene();
scene.background = new THREE.Color("#333333");
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshStandardMaterial({ color: new THREE.Color('skyblue') });
box = new THREE.Mesh(geometry, material);
scene.add(box);
const light = new THREE.DirectionalLight();
light.position.set(0, 1, 2);
scene.add(light);
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 3;
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement);
// add EFFECT
composer = new EffectComposer(renderer);
composer.addPass(new RenderPass(scene, camera));
const filmPass = new FilmPass(0.35, 0.025, 648, false,);
filmPass.renderToScreen = true;
composer.addPass(filmPass);
window.addEventListener('resize', onResize, false);
update();
}
function update() {
requestAnimationFrame(update);
box.rotation.y += 0.01;
composer.render(scene, camera);
}
function onResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
composer.setSize(window.innerWidth, window.innerHeight);
}
This gives me error that it cant find /node_modules/three/examples/jsm/postprocessing/
This is indead true. The file does not exist anymore for some reason in my version of three
I found this:
https://www.npmjs.com/package/postprocessing
and did try to install and use that instead but without success:
npm install three postprocessing
And the following code:
import * as THREE from 'three';
import { BloomEffect, EffectComposer, EffectPass, RenderPass } from "postprocessing";
var scene, camera, renderer, box, composer;
init();
function init() {
scene = new THREE.Scene();
scene.background = new THREE.Color("#333333");
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshStandardMaterial({ color: new THREE.Color('skyblue') });
box = new THREE.Mesh(geometry, material);
scene.add(box);
const light = new THREE.DirectionalLight();
light.position.set(0, 1, 2);
scene.add(light);
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 3;
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement);
// add EFFECT
composer = new EffectComposer(renderer);
composer.addPass(new RenderPass(scene, camera));
// const filmPass = new BloomEffect());
// filmPass.renderToScreen = true;
composer.addPass(new BloomEffect());
window.addEventListener('resize', onResize, false);
update();
}
function update() {
requestAnimationFrame(update);
box.rotation.y += 0.01;
composer.render(scene, camera);
}
function onResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
composer.setSize(window.innerWidth, window.innerHeight);
}
This render my scene all black.
What am I doing wrong? How do I implement EffectComposer in Three.js
Related
I am creating a basic scene on threejs and making the canvas responsive to create a full screen experience. The mesh that is inside the scene doesn't resize correctly. It is supposed to be a cube but becomes a rectangle if resized.
const scene = new THREE.Scene();
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({ color: 0xff0000 });
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
const sizes = {
width: window.innerWidth,
height: window.innerHeight
}
//responsive canvas
const canvas = document.querySelector('.webgl');
window.addEventListener('resize', () => {
sizes.width = window.innerWidth;
sizes.height = window.innerHeight;
camera.aspect = sizes.width / sizes.height;
camera.updateProjectionMatrix();
renderer.setSize(sizes.width, sizes.height);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
});
const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height);
camera.position.z = 3
scene.add(camera)
const renderer = new THREE.WebGLRenderer({
canvas: canvas
});
renderer.setSize(sizes.width, sizes.height);
renderer.render(scene, camera);
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<canvas class="webgl"></canvas>
This is the expected result:
but on window resize, the cube gets a weird scale:
Since there is no animation loop in your scene, you need to call renderer.render on resize manually:
const scene = new THREE.Scene();
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({ color: 0xff0000 });
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
const sizes = {
width: window.innerWidth,
height: window.innerHeight
}
//responsive canvas
const canvas = document.querySelector('.webgl');
window.addEventListener('resize', () => {
sizes.width = window.innerWidth;
sizes.height = window.innerHeight;
camera.aspect = sizes.width / sizes.height;
camera.updateProjectionMatrix();
renderer.setSize(sizes.width, sizes.height);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
renderer.render(scene, camera); // -> Also needed
});
const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height);
camera.position.z = 3
scene.add(camera)
const renderer = new THREE.WebGLRenderer({
canvas: canvas
});
renderer.setSize(sizes.width, sizes.height);
renderer.render(scene, camera);
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<canvas class="webgl"></canvas>
An example with an animation loop:
const scene = new THREE.Scene();
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({ color: 0xff0000 });
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
const sizes = {
width: window.innerWidth,
height: window.innerHeight
}
//responsive canvas
const canvas = document.querySelector('.webgl');
window.addEventListener('resize', () => {
sizes.width = window.innerWidth;
sizes.height = window.innerHeight;
camera.aspect = sizes.width / sizes.height;
camera.updateProjectionMatrix();
renderer.setSize(sizes.width, sizes.height);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
// renderer.render(scene, camera); // -> Not needed since it is called in animate()
});
const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height);
camera.position.z = 3
scene.add(camera)
const renderer = new THREE.WebGLRenderer({
canvas: canvas
});
renderer.setSize(sizes.width, sizes.height);
function animate(time) {
time *= 0.001; // seconds
mesh.rotation.x = time * 0.5;
mesh.rotation.y = time * 1;
renderer.render(scene, camera); // Is called continuously here
requestAnimationFrame(animate);
}
requestAnimationFrame(animate);
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<canvas class="webgl"></canvas>
I am trying to create something like on this photo
So, how to remove that strange lines from the model
http://weblife.su/WineBazar/1/
You can see those lines while rorating the model.
What is the problem? I need to use opacity, to get result like on that scrinshot.
At least, can I hide the background for user, but reflectivity and metalness will be on my model?
My threeJs script is here
Thank you for the help!
<script type="module">
import * as THREE from 'https://threejs.org/build/three.module.js';
import { OrbitControls } from 'https://threejs.org/examples/jsm/controls/OrbitControls.js';
import { GLTFLoader } from 'https://threejs.org/examples/jsm/loaders/GLTFLoader.js';
import { RGBELoader } from 'https://threejs.org/examples/jsm/loaders/RGBELoader.js';
import { RoughnessMipmapper } from 'https://threejs.org/examples/jsm/utils/RoughnessMipmapper.js';
var container, controls;
var camera, scene, renderer;
init();
render();
function init() {
container = document.createElement('div');
document.body.appendChild(container);
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.25, 20);
camera.position.set(-1.8, 0.6, 2.7);
scene = new THREE.Scene();
new RGBELoader()
.setDataType(THREE.UnsignedByteType)
.setPath('https://threejs.org/examples/textures/equirectangular/')
.load('royal_esplanade_1k.hdr', function(texture) {
var envMap = pmremGenerator.fromEquirectangular(texture).texture;
scene.background = envMap;
scene.environment = envMap;
texture.dispose();
pmremGenerator.dispose();
render();
// model
// use of RoughnessMipmapper is optional
var roughnessMipmapper = new RoughnessMipmapper(renderer);
var loader = new GLTFLoader()
loader.load('http://weblife.su/WineBazar/1/ws_r_2-5.glb', function(gltf) {
gltf.scene.traverse(function(child) {
if (child.isMesh) {
child.material.color.setHex(0x9ed7f5);
child.material.emissive.setHex(0x062f61);
child.material.transparent = true;
child.material.opacity = 0.5;
child.material.needsUpdate = true;
child.material.reflectivity = 0.8;
child.material.roughness = 0.2;
child.material.metalness = 0.5;
child.depthWrite = true;
}
});
scene.add(gltf.scene);
roughnessMipmapper.dispose();
render();
});
});
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.toneMappingExposure = 1;
renderer.outputEncoding = THREE.sRGBEncoding;
container.appendChild(renderer.domElement);
var pmremGenerator = new THREE.PMREMGenerator(renderer);
pmremGenerator.compileEquirectangularShader();
controls = new OrbitControls(camera, renderer.domElement);
controls.addEventListener('change', render); // use if there is no animation loop
controls.minDistance = 2;
controls.maxDistance = 32;
controls.target.set(0, 0, -0.2);
controls.update();
window.addEventListener('resize', onWindowResize, false);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
render();
}
//
function render() {
renderer.render(scene, camera);
}
</script>
Looks like self-transparency artifacts. You should always set depthWrite to false if you encounter such rendering problems. But even this setting might not help to remove all glitches since correctly rendering transparency is very tricky. You would need a special Order-independent transparency algorithm like depth-peeling which is not supported by three.js.
https://en.wikipedia.org/wiki/Order-independent_transparency
Related issue at GitHub: https://github.com/mrdoob/three.js/issues/9977
I'm creating an HTML file integrating ThreeJs, basically I have created 4 Spheres, 1 of them projects the light, other 3 spheres turn in a wall. When the Spheres is behind the wall they should not reflect the light, what I supposed to do to solve this?
I've already try changing the materials of the Spheres which turns around the wall to Lambert and Phong, setting up castShadow to true, and recieveShadow to False
(function onLoad() {
var camera, scene, renderer, orbitControls;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(0, 30, -100);
scene = new THREE.Scene();
scene.background = new THREE.Color(0xffffff);
scene.add(camera);
orbitControls = new THREE.OrbitControls(camera);
escena = scene;
esferaLuz = new THREE.SphereBufferGeometry(0.5, 16, 16);
luzUno = new THREE.SpotLight(0xFFFFFF, 1);
luzUno.angle = Math.PI / 12;
luzUno.penumbra = 0.05;
luzUno.decay = 2;
luzUno.position.set(-30, 40, -5);
mtLuzUno = new THREE.MeshBasicMaterial({color: 0xFFFFFF});
mallaLuzUno = new THREE.Mesh(esferaLuz, mtLuzUno);
luzUno.add(mallaLuzUno);
escena.add(luzUno);
luzUno.castShadow = true;
luzUno.shadow.mapSize.width = 1024;
luzUno.shadow.mapSize.height = 1024;
luzUno.shadow.camera.near = 10;
luzUno.shadow.camera.far = 200;
luzMap = new THREE.SpotLightHelper(luzUno);
escena.add(luzMap);
sombraMap = new THREE.CameraHelper(luzUno.shadow.camera);
escena.add(sombraMap);
var luzAmbiente = new THREE.AmbientLight( 0xffffff, 0.1 );
escena.add(luzAmbiente);
geometriaPlana = new THREE.CubeGeometry(100, 100, 2, 2);
mtPlano = new THREE.MeshLambertMaterial({color: 0x000000});
mtPlano.transparent = false;
mtPlano.depthWrite = true;
mallaPlano = new THREE.Mesh(geometriaPlana, mtPlano);
mallaPlano.rotation.x = -0.5*Math.PI;
mallaPlano.position.x = 15;
mallaPlano.position.y = 0;
mallaPlano.position.z = 0;
mallaPlano.receiveShadow = true;
escena.add(mallaPlano);
objEsfera = new THREE.SphereGeometry(5, 100, 100);
mtObjEsfera = new THREE.MeshPhongMaterial({color: 0xFFFFFF, specular:0xFFFFFF, shininess: 1024});
mallaObjEsfera3 = new THREE.Mesh(objEsfera, mtObjEsfera);
mallaObjEsfera3.position.set(20, 0, 0);
mallaObjEsfera3.castShadow = true;
mallaObjEsfera3.receiveShadow = false;
escena.add(mallaObjEsfera3);
objEsfera = new THREE.SphereGeometry(5, 100, 100);
mtObjEsfera = new THREE.MeshPhongMaterial({color: 0xF90E0E, specular:0xF90E0E, shininess: 512});
mallaObjEsfera2 = new THREE.Mesh(objEsfera, mtObjEsfera);
mallaObjEsfera2.position.set(5, 0, 0);
mallaObjEsfera2.castShadow = true;
mallaObjEsfera2.receiveShadow = false;
escena.add(mallaObjEsfera2);
objEsfera = new THREE.SphereGeometry(5, 100, 100);
mtObjEsfera = new THREE.MeshLambertMaterial({color: 0xF2E406});
mallaObjEsfera = new THREE.Mesh(objEsfera, mtObjEsfera);
mallaObjEsfera.position.set(-10, 0, 0);
mallaObjEsfera.castShadow = true;
mallaObjEsfera.receiveShadow = false;
escena.add(mallaObjEsfera);
renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setPixelRatio( window.devicePixelRatio);
renderer.setClearColor(0xEEEEEE);
renderer.shadowMap.enabled = true;
renderer.shadowMap.renderReverseSided = false;
renderer.sortObjects = false
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
renderer.setSize( window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
renderer.gammaInput = true;
renderer.gammaOutput = true;
window.onresize = function() {
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
}
}
function animate() {
requestAnimationFrame(animate);
orbitControls.update();
render();
}
function render() {
renderer.render(scene, camera);
}
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/103/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
I expect that when the spheres is behind the wall, don't show any type of reflects of light but when is on the front reflect the light .
One way to achieve your intended result is to work with shadows. So you have to set Object3D.castShadow and Object3D.receiveShadow to true for your spheres and your ground like in the following live example:
https://jsfiddle.net/85q3sfeg/
Also keep in mind that three.js does not support selective lighting so far. This issue was already discussed at github right here: https://github.com/mrdoob/three.js/issues/5180
Assuming all objects of your scene have a lit material applied, you can't define what light sources should affect what objects.
three.js R103
I am new to Threejs and facing a problem in the positioning of geometry. I want to position geometry at the bottom and it should be half cut i.e like half area should be visible but when try adding position.setY(-300), it moves down but stretches the geometry. I don't know what I am doing wrong or what will be the correct way to position the geometry without losing its aspect ratio. Can some help me to solve this?
I am also attaching the link of fiddle and code: link to fiddle
var camera, scene, renderer;
var geometry, material, muesum;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 600;
scene = new THREE.Scene();
geometry = new THREE.IcosahedronGeometry(350, 2);
material = new THREE.MeshPhongMaterial({
wireframe: true,
});
muesum = new THREE.Mesh(geometry, material);
scene.add(muesum);
muesum.position.setY(-300);
renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
}
window.addEventListener('resize', onWindowResize, false);
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function animate() {
requestAnimationFrame(animate);
muesum.rotation.x += 0.001;
muesum.rotation.y += 0.002;
renderer.clear();
renderer.render(scene, camera);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/88/three.min.js"></script>
What you call "losing its aspect ratio.", is the perspective projection, of an big object, that is very close to the camera.
If you don't want that, then you have to use the OrthographicCamera, which creates an orthographic projection matrix and projects the scene parallel on the viewport.
See the Example:
var camera, scene, renderer;
var geometry, material, muesum;
init();
animate();
function updateCameraProjection() {
var aspect = window.innerWidth / window.innerHeight;
var wndHeight = 700;
camera.right = aspect*wndHeight/2
camera.left = -camera.right;
camera.top = wndHeight/2;
camera.bottom = -camera.top;
camera.near = 1;
camera.far = 1000;
camera.updateProjectionMatrix();
}
function init() {
camera = new THREE.OrthographicCamera();
updateCameraProjection();
camera.position.z = 500;
scene = new THREE.Scene();
geometry = new THREE.IcosahedronGeometry(350, 2);
material = new THREE.MeshPhongMaterial({
wireframe: true,
});
muesum = new THREE.Mesh(geometry, material);
scene.add(muesum);
muesum.position.setY(camera.bottom);
renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
}
window.addEventListener('resize', onWindowResize, false);
function onWindowResize() {
updateCameraProjection();
muesum.position.setY(camera.bottom);
renderer.setSize(window.innerWidth, window.innerHeight);
}
function animate() {
requestAnimationFrame(animate);
muesum.rotation.x += 0.001;
muesum.rotation.y += 0.002;
renderer.clear();
renderer.render(scene, camera);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/88/three.min.js"></script>
I am trying to learn three.js, and was looking up some examples.
I was trying to run this code https://github.com/mrdoob/three.js/blob/master/examples/webgl_geometry_cube.html
however, all it displayed was a black screen.
I modified the three.js source to my directory, and I also modified the material to the following, because I don't have the crate texture.
var material = new THREE.MeshStandardMaterial({metalness: 0, roughness: 0.5});
material.color.setHex(0xc23560)
Some code with explanations:
var camera, scene, renderer;
var mesh;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.z = 400;
scene = new THREE.Scene();
light = new THREE.PointLight(0xffffff, 1, 1000); // increase the distance
light.position.set(300,300,300); // [50,50,50] - inside the cube
scene.add(light);
var geometry = new THREE.BoxBufferGeometry(200, 200, 200);
var material = new THREE.MeshStandardMaterial({
color: 0xc23560,
metalness: 0,
roughness: 0.5
});
mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
//
window.addEventListener('resize', onWindowResize, false);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function animate() {
requestAnimationFrame(animate);
mesh.rotation.x += 0.005;
mesh.rotation.y += 0.01;
renderer.render(scene, camera);
}
body {
overflow: hidden;
margin: 0;
}
<script src="https://threejs.org/build/three.min.js"></script>
I figured it out, it just turned out that the material of my box is metallic, and I added the light source wrongly.