before asking a question let you know that I already tried some ways.
I-asked-before-this-question-but-no-help
Mixing HTML Pages Inside Your WebGL
stemkoski-css3d.html
http://run.plnkr.co/preview/ck7d1p1t4000a3b5uxqhm17vk/
and more..
I'm trying to embedding youtube on my three.js scene.
But I have issues that I cannot embed it.
Thre problem for now, Youtube is not appear.
On chrome debugger, I can see css3dobject's frame, but there is nothing on Three.js scene.
Here's my code.
...
//create css3dobject
let element = document.createElement('iframe');
element.src = [ 'https://www.youtube.com/embed/jO2viLEW-1A', '?rel=0' ].join( '' ); //test url
element.style.width = '200px';
element.style.height = '150px';
let cssObject = new THREE.CSS3DObject( element );
cssObject.position.set(325, 50, 25);// = child.position;
cssObject.rotation.set( 0, 0, 0);// = child.rotation;
cssObject.scale.x = 100;
cssObject.scale.y = 100;
cssObject.scale.z = 100;
cssScene.add(cssObject);
//setting renderer..
renderer = new THREE.WebGLRenderer( {antialias: true} );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.shadowMap.enabled = true;
renderer.setClearColor(0x000000, 0);
renderer.domElement.style.position = 'absolute';
renderer.autoClear = false;
container.appendChild( renderer.domElement );
cssRenderer = new THREE.CSS3DRenderer({alpha: true});
cssRenderer.setSize( window.innerWidth, window.innerHeight );
cssRenderer.domElement.style.position = 'absolute';
cssRenderer.domElement.style.top = 0;
document.body.appendChild(cssRenderer.domElement);
renderer.domElement.style.position = 'absolute';
renderer.domElement.style.top = 0;
renderer.domElement.style.zIndex = 1;
cssRenderer.domElement.appendChild(renderer.domElement);
...
function render(){
cssRenderer.render(cssScene, camera);
renderer.render(scene, camera);
}
renderer = new THREE.WebGLRenderer( {antialias: true, alpha:true, preserveDrawingBuffer: true} );
renderer.domElement.style.background = ''
renderer.domElement.style.zIndex = 0;
cssRenderer.domElement.style.zIndex = 1;
You're spelling .zIndex wrong. it's case sensitive. Also included some other tricks you may need, going forward, if you plan to to anything more fancy.
Related
When I have intersecting objects there is a weird line of light in the shadow where the objects intersect. I’ve tried different types of lights, materials, browsers (MacOS), and render settings. It occurs with one or more lights.
I found that adjusting the shadow bias (spotLight.shadow.bias = 0.0005) and using a relatively large shadowmap helped reduce the lines but did not get rid of them entirely. I'm guessing that this is issue relates to how the shadowmap is rendered.
Does anyone have any ideas for what is causing this, and how to solve it?
Example image showing lines of light in shadow on intersecting objects - Demo code: https://codepen.io/henryegloff/pen/eYyRJpx
import * as THREE from 'three';
import { OrbitControls } from 'https://unpkg.com/three#0.139.0/examples/jsm/controls/OrbitControls.js';
let scene, camera, renderer, controls;
let cube_mesh;
init();
function init() {
scene = new THREE.Scene();
scene.background = new THREE.Color(0xffffff);
camera = new THREE.PerspectiveCamera(25, window.innerWidth / window.innerHeight, 0.1,1000);
camera.position.set(0,1.5,-10);
renderer = new THREE.WebGLRenderer({ antialias:true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
//renderer.shadowMap.type = THREE.PCFShadowMap;
renderer.setAnimationLoop( animation );
renderer.toneMapping = THREE.LinearToneMapping;
renderer.physicallyCorrectLights = true;
document.body.appendChild(renderer.domElement);
window.addEventListener('resize', onWindowResize);
controls = new OrbitControls(camera, renderer.domElement);
controls.target = new THREE.Vector3(0, 1, 0);
// Spotlight
const spotLight = new THREE.SpotLight( 0xffffff, 11 );
spotLight.position.set( 2, 4, -2 );
spotLight.castShadow = true;
// spotLight.shadow.bias = 0.0005;
spotLight.shadow.mapSize.width = 2048;
spotLight.shadow.mapSize.height = 2048;
spotLight.angle = 0.6;
spotLight.penumbra = 1;
// spotLight.decay = 1;
// const spotLightHelper = new THREE.SpotLightHelper( spotLight );
// scene.add( spotLightHelper );
scene.add( spotLight );
// Materials
const material_1 = new THREE.MeshPhongMaterial({color: 0xffffff,});
const material_2 = new THREE.MeshPhongMaterial({color: 0xbbbbbb,});
// Ground Plane
const ground_geometry = new THREE.PlaneGeometry(20, 20);
const ground_mesh = new THREE.Mesh(ground_geometry, material_2);
ground_mesh.receiveShadow = true;
ground_mesh.rotateX(-Math.PI / 2);
scene.add(ground_mesh);
// Cube
const cube_geometry = new THREE.BoxGeometry(1, 1, 1);
cube_mesh = new THREE.Mesh(cube_geometry, material_1);
cube_mesh.castShadow = true;
cube_mesh.position.y = 2;
scene.add(cube_mesh);
// Sphere
const sphere_geometry = new THREE.SphereGeometry( .75, 128,128 );
const sphere = new THREE.Mesh( sphere_geometry, material_1 );
sphere.castShadow = true;
sphere.receiveShadow = true;
sphere.position.set(0,.75,0);
scene.add( sphere );
const sphere_2_geometry = new THREE.SphereGeometry( 1, 128, 128 );
const sphere_2 = new THREE.Mesh( sphere_2_geometry, material_1 );
sphere_2.castShadow = true;
sphere_2.receiveShadow = true;
sphere_2.position.set(-1,1.5,1);
scene.add( sphere_2 );
}
function animation(time) {
cube_mesh.rotation.x += 0.01;
cube_mesh.rotation.y += 0.01;
controls.update();
renderer.render(scene, camera);
}
// Resize Window
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
I'm loading eight 8192 x 4096 textures on init. Naturally there's a delay prior to display as the textures load. Is there a way for me to detect when first display has taken place? With the example below, I'd like onDocumentMouseDown to fire only when I can see the textures - not while the screen is still blank as loading takes place.
function init() {
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 );
scene = new THREE.Scene();
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
var sphereGeometry = new THREE.SphereBufferGeometry(500, 100, 100);
sphereGeometry.scale(-1, 1, 1);
var renderList = ["DF_DC_DS", "DF_DC_LS", "DF_LC_DS", "DF_LC_LS", "LF_DC_DS", "LF_DC_LS", "LF_LC_DS", "LF_LC_LS"];
for (var i = 0; i < renderList.length; i++) {
var texture = new THREE.TextureLoader().load( "img/high-quality/" + renderList[i] + ".jpg",
function ( texture ) {
textureLoadedCount++;
if (textureLoadedCount == 8) {
allLoaded = true;
}
}
);
texture.anisotropy = renderer.capabilities.getMaxAnisotropy();
var material = new THREE.MeshBasicMaterial( { map: texture } );
var mesh = new THREE.Mesh( sphereGeometry, material );
scene.add( mesh );
}
document.addEventListener( "mousedown", onDocumentMouseDown, false );
}
I have a basic json scene exported from the three.js/editor. I want to add a repeated texture wrap to an object in this scene but I do not know how to do so since the only examples I have found add the wrap in the creation of the object.
I have already tried accessing the texture and giving it a wrap, but I think I might need to add a texture to the object from the JavaScript then declare the texture wrap instead of trying to add it to an already loaded texture.
<script>
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();
var objectLoader = new THREE.ObjectLoader();
objectLoader.load( "models/cube.json", function ( obj ) {
scene.add( obj )
obj.traverse(function(child) {
if (child instanceof THREE.Mesh) {
child.castShadow = true;
child.receiveShadow = true;
}
});
obj.name = "cube";
obj.position.set(0,0,0);
obj.scale.set(200,200,200);
});
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
//
window.addEventListener( 'resize', onWindowResize, false );
while (scene.getObjectByName('Box 1')){
var texture = scene.getObjectByName('Box 1').material;
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
texture.repeat.set( 2, 2 );
}
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
requestAnimationFrame( animate );
if (scene.getObjectByName('Box 1') ){
scene.getObjectByName('Box 1').material.map.offset.x += 0.001;
}
renderer.render( scene, camera );
}
</script>
You need to set the wrap and repeat properties of the texture/map and not of the material. Docs also say it's important to set needsUpdate to true, if wrap settings changed. And you are trying to set the properties before the json is loaded (in a while loop?). You should do it within the load callback.
objectLoader.load( "models/cube.json", function ( obj ) {
scene.add( obj )
obj.traverse(function(child) {
if (child instanceof THREE.Mesh) {
child.castShadow = true;
child.receiveShadow = true;
}
});
obj.name = "cube";
obj.position.set(0,0,0);
obj.scale.set(200,200,200);
var box1 = scene.getObjectByName('Box 1');
if (box1) {
var texture = box1.material.map;
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
texture.repeat.set( 2, 2 );
texture.needsUpdate = true;
}
});
I am having a simple three.js scene and have added some spheres. I want to achieve a simple lighting and shadowing effect but I get strange dark shapes on my spheres.
I guess something is wrong with my settings : jsFiddle
this is the core of this simple piece of code :
// renderer
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.physicallyBasedShading = true;
renderer.shadowMapEnabled = true;
renderer.shadowMapSoft = true;
renderer.shadowMapEnabled = true;
renderer.shadowMapSoft = true;
renderer.shadowCameraNear = 0.1;
renderer.shadowCameraFar = 1000;
renderer.shadowCameraFov = 100;
renderer.shadowMapBias = 0.0039;
renderer.shadowMapDarkness = 0.5;
renderer.shadowMapWidth = 1024;
renderer.shadowMapHeight = 1024;
document.body.appendChild( renderer.domElement );
// scene
scene = new THREE.Scene();
// camera
camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.set( 150, 50, 150 );
// controls
controls = new THREE.OrbitControls( camera );
// lights
var light = new THREE.SpotLight( 0xF5F6CE, 1 );
light.position.set( 300, 300, 60 );
light.castShadow = true;
light.shadowMapWidth = 1024; // power of 2
light.shadowMapHeight = 1024;
light.shadowCameraNear = 200; // keep near and far planes as tight as possible
light.shadowCameraFar = 500; // shadows not cast past the far plane
light.shadowCameraFov = 20;
light.shadowBias = -0.00022; // a parameter you can tweak if there are artifacts
light.shadowDarkness = 0.8;
light.shadowCameraVisible = true;
scene.add( light );
// axes
scene.add( new THREE.AxisHelper( 200 ) );
for (var x = 0; x < 3; x++) {
for (var y = 0; y < 3; y++) {
for (var z = 0; z < 3; z++) {
var sphere = new THREE.Mesh(new THREE.SphereGeometry(10,32, 32), new THREE.MeshPhongMaterial({ color: "#FFFF00", side: THREE.DoubleSide, })); // with MeshLambertMaterial still not working
sphere.position.set(20*x, 20*y, 20*z);
castShadow = true;
sphere.castShadow = true;
sphere.receiveShadow = true ;
scene.add(sphere);
}
}
}
The blackish artifacts are coming from the two-sidedness of the spheres combined with shadow mapping.
Remove side: THREE.DoubleSide from their material definition and you should be good.
http://jsfiddle.net/Us54P/331/
You can also get different results with tweaking the shading parameters, for example, you can add renderer.shadowMapType = THREE.PCFSoftShadowMap;. See here: http://jsfiddle.net/Us54P/332/
Could also be a bug (or a debugging feature), because it disappears when you disable light.shadowCameraVisible = true;: http://jsfiddle.net/Us54P/334/
I am trying to load a collada file using Threejs. All works well, but if I make the object spin I can see that the rendering is not right. Check the image:
Here is the code (which was partially stolen from another example):
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
var info = document.createElement( 'div' );
info.style.position = 'absolute';
info.style.top = '10px';
info.style.width = '100%';
info.style.textAlign = 'center';
info.innerHTML = 'Drag to spin the cube';
container.appendChild( info );
camera = new THREE.PerspectiveCamera( 20, window.innerWidth / window.innerHeight, .1, 10000 );
camera.position.x=50;
camera.position.y=50;
camera.position.z=50;
camera.lookAt(new THREE.Vector3(0,0,0));
scene = new THREE.Scene();
renderer = new THREE.CanvasRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
var ambientLight = new THREE.AmbientLight(0x000000);
scene.add(ambientLight);
var directionalLight = new THREE.DirectionalLight(0xffffff);
directionalLight.position.set(100,50,80).normalize();
scene.add(directionalLight);
var loader = new THREE.ColladaLoader();
loader.options.convertUpAxis = true; // this rotates so it looks right
loader.load('models/VM.dae', function (result) {
cube = result.scene;
// cube.doubleSided = true;
// cube.flipSided = true;
console.log(cube);
cube.updateMatrix();
scene.add(result.scene);
animate();
});
}
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
cube.rotation.y += 0.01;
// plane.rotation.y = cube.rotation.y += ( targetRotation - cube.rotation.y ) * 0.05;
renderer.render( scene, camera );
}
New update:
I changed the loader to a MTL+OBJ one. The result is exactly the same:
var loader = new THREE.OBJMTLLoader();
loader.addEventListener("load", function (event) {
cube = event.content;
cube.doubleSided = true;
console.log(event);
scene.add(cube);
animate();
});
loader.load ("models/VM.obj", "models/VM.mtl");
Fiddle: http://jsfiddle.net/qMqH7/
Your model is throwing errors in the Console, I would suggest you track them down.
What you are seeing is a known limitation of CanvasRenderer related to depth-sorting. It is made worse by your geometry which has several elongated faces. The model renders correctly with WebGLRenderer.
Also, object.doubleSided has been deprecated. It has been replaced by material.side = THREE.DoubleSide. It does not appear that flag is required in this case.
three.js r.58