Three.VideoTexture stretches portrait video - three.js

I am using Three.VideoTexture(video) to load video on canvas. It's work perfectly fine with landscape videos. But when i tried to load a portrait video, on canvas video gets stretched.
var wrap3D = $("#" + threeJsPreviewHTMLElement);//.find(".wrap3d");
videoTexture = new THREE.VideoTexture(video);
videoTexture.minFilter = THREE.LinearFilter;
videoTexture.magFilter = THREE.LinearFilter;
videoTexture.format = THREE.RGBFormat;
scene = new THREE.Scene();
var WIDTH = 520, HEIGHT = 520;
var domID = "videoContext";
if (!isDesktop) {
HEIGHT = $("#modalTumbler3d").height();
WIDTH = $("#modalTumbler3d").width();
domID = "videoContextDevice";
}
renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
renderer.setSize(WIDTH, HEIGHT);
if (!wrap3D.find('#' + domID).length) {
wrap3D.append(renderer.domElement);
}
else {
wrap3D.find('#' + domID).replaceWith(renderer.domElement);
}
renderer.domElement.id = domID;
//Two CAMERA options - perspective is preferred
camera = new THREE.PerspectiveCamera(50, WIDTH / HEIGHT, .1, 20000);
camera.position.set(0, 0, 150);
scene.add(camera);
//Lights
var hemLight = new THREE.HemisphereLight(0x999999, 0xffffff, 1);
scene.add(hemLight);
var spotLight = new THREE.PointLight(0x555555);
spotLight.position.set(0, 15, -20);
scene.add(spotLight);
var spotLight = new THREE.PointLight(0x555555);
spotLight.position.set(0, -15, 20);
scene.add(spotLight);
//size and position of tumbler from camera
var Y = 0;
var A = 0;
var B = 0;
var scale = 1;
//cylinder for the movie preview
//var movieFrame = new THREE.CylinderGeometry(2, 1.8, 2.5, 50, 1, true, -1.59, Math.PI)
var movieFrame = new THREE.CylinderGeometry(1, 1, 2.5, 100, 3, true, -1.59, Math.PI)
//var movieFrame = new THREE.CylinderGeometry(2, 1.9, 2.5, 50, 1, true, -1.59, Math.PI)
var movieMaterial = new THREE.MeshBasicMaterial({ map: videoTexture, overdraw: true, side: THREE.DoubleSide });
var moviePlayer = new THREE.Mesh(movieFrame, movieMaterial);
moviePlayer.position.y = Y;
moviePlayer.rotation.y = A;
moviePlayer.renderOrder = 14;
moviePlayer.scale.set(scale, scale, scale);
scene.add(moviePlayer);
//control with the mouse or two finger pinch
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.minPolarAngle = 0; // radians
controls.maxPolarAngle = 2.5; // radians
controls.minDistance = 5;
controls.maxDistance = 10;
controls.enabled = false;
This is what i have tried to play video. I have used CylinderGeometry to load video in Cylinder form.

In this case, the texture will simply cover the whole CylinderGeometry. So any distortion you see is result of the aspect-ratio of the video not matching the aspect-ratio of the cylinder-fragment..
Based on your code you have there a height of 2.5 and a width of Math.PI, so your aspect-ratio is ~1.25. Now for a portrait-video (aspect-ratio <1) you need to adjust the geometry. (so for a 3:4 potrait-video you'd need a thetaLength of 1.875/radius instead of Math.PI).

Related

Maintain aspect on Three.js texture

I'm trying to keep a texture centered when it's shown in a different sized box.
I've seen this answer
Three.js: Make image texture fit object without distorting or repeating
But it's not quite doing it for me.
this.texture = new THREE.Texture(this.image)
const vec = new THREE.Vector3()
new THREE.Box3().setFromObject( this.rounded ).getSize(vec)
const imageAspect = this.image.width/this.image.height
const boxAspect = vec.x/vec.y
this.texture.wrapT = THREE.RepeatWrapping;
this.texture.offset.y = 0.5 * ( 1 - boxAspect/imageAspect )
//texture.wrapT = THREE.RepeatWrapping; texture.repeat.x = geometryAspectRatio / imageAspectRatio; texture.offset.x = 0.5 * ( 1 - texture.repeat.x )
this.texture.needsUpdate = true
this.rounded.material = new THREE.MeshPhongMaterial( { map: this.texture, side: THREE.DoubleSide } )
In this aspect the values are
Image: {width:399 height:275}
Texture: {width:1, height: 0.75}
In this aspect the values are
Image: {width:399 height:275}
Texture: {width:2, height: 1}
How do I fix it so the graphic is always central, maintains the aspect and is not distorted?
I hope I got you correctly, here is an option of how you can center it:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 1000);
camera.position.set(0, 0, 10);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);
var planeGeom = new THREE.PlaneBufferGeometry(16, 9);
var planeMat = new THREE.MeshBasicMaterial({
map: new THREE.TextureLoader().load("https://threejs.org/examples/textures/758px-Canestra_di_frutta_(Caravaggio).jpg", tex => {
//console.log(tex);
//console.log(tex.image.width, tex.image.height);
let imgRatio = tex.image.width / tex.image.height;
let planeRatio = planeGeom.parameters.width / planeGeom.parameters.height;
//console.log(imgRatio, planeRatio);
tex.wrapS = THREE.RepeatWrapping; // THREE.ClampToEdgeWrapping;
tex.repeat.x = planeRatio / imgRatio;
tex.offset.x = -0.5 * ((planeRatio / imgRatio) - 1);
})
});
var plane = new THREE.Mesh(planeGeom, planeMat);
scene.add(plane);
renderer.setAnimationLoop(() => {
renderer.render(scene, camera);
})
body {
overflow: hidden;
margin: 0;
}
<script src="https://threejs.org/build/three.min.js"></script>
Addition: how to re-compute UVs for ShapeBufferGeometry
var box = new THREE.Box3().setFromObject(mesh); // mesh with ShapeBufferGeometry
var size = new THREE.Vector3();
box.getSize(size);
var vec3 = new THREE.Vector3(); // temp vector
var attPos = mesh.geometry.attributes.position;
var attUv = mesh.geometry.attributes.uv;
for (let i = 0; i < attPos.count; i++){
vec3.fromBufferAttribute(attPos, i);
attUv.setXY(i,
(vec3.x - box.min.x) / size.x,
(vec3.y - box.min.y) / size.y
);
}
attUv.needsUpdate = true; // just in case

Unable to cast a shadow with THREE.js and Mapbox GL

I'm trying to add a THREE.js scene into a Mapbox GL visualization following this example. I've added a sphere and a ground plane and a DirectionalLight. Now I'm trying to get the light to cast a shadow on the ground plane. Adding a DirectionalLightHelper and a CameraHelper for the light's shadow camera, everything looks pretty reasonable to me:
I'd expect to see a shadow for the sphere on the plane.
Full code here, but here are the highlights:
class SpriteCustomLayer {
type = 'custom';
renderingMode = '3d';
constructor(id) {
this.id = id;
this.gui = new dat.GUI();
THREE.Object3D.DefaultUp.set(0, 0, 1);
}
async onAdd(map, gl) {
this.camera = new THREE.Camera();
const centerLngLat = map.getCenter();
this.center = MercatorCoordinate.fromLngLat(centerLngLat, 0);
const {x, y, z} = this.center;
this.cameraTransform = new THREE.Matrix4()
.makeTranslation(x, y, z)
.scale(new THREE.Vector3(1, -1, 1));
this.map = map;
this.scene = this.makeScene();
this.renderer = new THREE.WebGLRenderer({
canvas: map.getCanvas(),
context: gl,
antialias: true,
});
this.renderer.shadowMap.enabled = true;
this.renderer.autoClear = false;
}
makeScene() {
const scene = new THREE.Scene();
scene.add(new THREE.AmbientLight(0xffffff, 0.25));
const s = this.center.meterInMercatorCoordinateUnits();
const light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(0.000002360847837325531, 0.000004566603480958114, 0.00000725142167844218);
light.target.position.set(0, 0, 0);
light.castShadow = true;
light.shadow.mapSize.width = 1024;
light.shadow.mapSize.height = 1024;
light.shadow.camera.left = -0.000002383416166278454 * 2;
light.shadow.camera.right = 0.000002383416166278454 * 2;
light.shadow.camera.bottom = -0.000002383416166278454 * 2;
light.shadow.camera.top = 0.000002383416166278454 * 2;
light.shadow.camera.near = 0.0000012388642793465356;
light.shadow.camera.far *= s;
scene.add(light);
this.light = light;
{
const planeSize = 500;
const loader = new THREE.TextureLoader();
const texture = loader.load('/checker.png');
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
texture.magFilter = THREE.NearestFilter;
const repeats = 10;
texture.repeat.set(repeats, repeats);
const planeGeo = new THREE.PlaneBufferGeometry(planeSize, planeSize);
const planeMat = new THREE.MeshPhongMaterial({
map: texture,
side: THREE.DoubleSide,
});
const plane = new THREE.Mesh(planeGeo, planeMat);
plane.scale.setScalar(s);
plane.receiveShadow = true;
scene.add(plane);
}
{
const sphereRadius = 5e-7;
const sphereGeo = new THREE.SphereBufferGeometry(sphereRadius, 32, 32);
const sphereMat = new THREE.MeshPhongMaterial({color: '#CA8'});
const mesh = new THREE.Mesh(sphereGeo, sphereMat);
mesh.position.set(0, 0, 5e-6);
mesh.castShadow = true;
mesh.receiveShadow = false;
sphereMat.side = THREE.DoubleSide;
scene.add(mesh);
}
return scene;
}
render(gl, matrix) {
this.camera.projectionMatrix = new THREE.Matrix4()
.fromArray(matrix)
.multiply(this.cameraTransform);
this.renderer.state.reset();
this.renderer.render(this.scene, this.camera);
this.map.triggerRepaint();
}
}
Mapbox GL JS uses a coordinate system where the entire world is in [0, 1] so the coordinates are pretty tiny. It also uses x/y for lat/lng and z for up, which is different than usual Three.js coordinates.
How can I get the shadow to appear? I'm using Three.js r109 and Mapbox GL JS 1.4.0. I've tried replacing the PlaneBufferGeometry with a thin BoxGeometry to no avail.
EDIT
Forget everything I said in my old answer.
The example below scales things WAY down and the shadow remains.
The kicker was here:
shadowLight.shadow.camera.near *= (scaleDown) ? 0.1 : 10;
shadowLight.shadow.camera.far *= (scaleDown) ? 0.1 : 10;
shadowLight.shadow.camera.updateProjectionMatrix(); // <========= !!!!!
I was updating the scale, but wasn't updating the near/far of the shadow camera. Then, once I was, I was forgetting to update that camera's projection matrix. With all the pieces back together, it seems to be working well.
Try adding a call to update the shadow-casting light's camera's projection matrix after you configure the values.
If it still doesn't work, maybe you can use my example to figure out what's going on in your code.
If MY example doesn't work for you, then it might be your hardware doesn't support the level of precision you need.
// just some random colors to show it's actually rendering
const colors = [
0xff0000, // 1e+1
0x00ff00, // 1e+0
0x0000ff, // 1e-1
0xffff00, // 1e-2
0xff00ff, // 1e-3
0x00ffff, // 1e-4
0xabcdef, // 1e-5
0xfedcba, // 1e-6
0x883300, // 1e-7
0x008833, // 1e-8
0x330088, // 1e-9
0x338800 // 1e-10
];
const renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.shadowMap.enabled = true; // turn on shadow mapping
renderer.setClearColor(0xcccccc);
document.body.appendChild(renderer.domElement);
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(28, 1, 1, 1000)
camera.position.set(25, 10, 15);
camera.lookAt(0, 0, 0);
const camLight = new THREE.PointLight(0xffffff, 1);
camera.add(camLight);
const floor = new THREE.Mesh(
new THREE.PlaneBufferGeometry(50, 50),
new THREE.MeshPhongMaterial({
color: "gray"
})
);
floor.receiveShadow = true;
floor.rotation.set(Math.PI / -2, 0, 0);
floor.position.set(0, -1, 0);
const sphere = new THREE.Mesh(
new THREE.SphereBufferGeometry(2, 16, 32),
new THREE.MeshPhongMaterial({
color: colors[0]
})
);
sphere.castShadow = true;
sphere.position.set(0, 1, 0);
const shadowLight = new THREE.PointLight(0xffffff, 1);
shadowLight.castShadow = true;
shadowLight.position.set(-10, 10, 5);
const group = new THREE.Group();
group.add(floor);
group.add(sphere);
group.add(shadowLight);
group.add(camera);
scene.add(group);
function render() {
renderer.render(scene, camera);
}
function resize() {
const W = window.innerWidth;
const H = window.innerHeight;
renderer.setSize(W, H);
camera.aspect = W / H;
camera.updateProjectionMatrix();
}
window.onresize = resize;
resize();
render();
let scaler = 10;
let scaleLevel = 10;
let scaleLevelOutput = document.getElementById("scaleLevel");
let scaleDown = true;
let colorIndex = 0;
setInterval(() => {
colorIndex += (scaleDown) ? 1 : -1;
scaleLevel *= (scaleDown) ? 0.1 : 10;
shadowLight.shadow.camera.near *= (scaleDown) ? 0.1 : 10;
shadowLight.shadow.camera.far *= (scaleDown) ? 0.1 : 10;
shadowLight.shadow.camera.updateProjectionMatrix();
if (scaleLevel < 1e-9 && scaleDown) {
scaleDown = false;
}
if (scaleLevel >= 10 && !scaleDown) {
scaleDown = true;
}
scaleLevelOutput.innerText = `SCALE LEVEL: ${scaleLevel.toExponential()}`;
group.scale.set(scaleLevel, scaleLevel, scaleLevel);
sphere.material.color.setHex(colors[colorIndex]);
sphere.material.needsUpdate = true;
render();
}, 1000);
body {
margin: 0;
overflow: hidden;
}
#scaleLevel {
font-family: monospace;
font-size: 2em;
position: absolute;
top: 0;
left: 0;
font-weight: bold;
margin: 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/109/three.min.js"></script>
<div id="scaleLevel">SCALE LEVEL: 1e+1</div>

How can I rotate texture inside a plane?

have pb with rotate texture, i read this question
Three.js Rotate Texture and there guys propose rotate in canvas, and it work good if you have rectangle, but i have pb with polygon, so after rotating i will have black area in some corner, so that solution is not for me, so maybe who know how i can rotate texture by threejs???
//Here's some code showing texture rotation/repeat/offset/center/etc.
var renderer = new THREE.WebGLRenderer();
var w = 600;
var h = 200;
renderer.setSize(w, h);
document.body.appendChild(renderer.domElement);
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(
45, // Field of view
w / h, // Aspect ratio
0.1, // Near
10000 // Far
);
camera.position.set(15, 10, 15);
camera.lookAt(scene.position);
controls = new THREE.OrbitControls(camera, renderer.domElement);
var light = new THREE.PointLight(0xFFFF00);
light.position.set(20, 20, 20);
scene.add(light);
var light1 = new THREE.AmbientLight(0x808080);
light1.position.set(20, 20, 20);
scene.add(light1);
var light2 = new THREE.PointLight(0x00FFFF);
light2.position.set(-20, 20, -20);
scene.add(light2);
var light3 = new THREE.PointLight(0xFF00FF);
light3.position.set(-20, -20, -20);
scene.add(light3);
var planeGeom = new THREE.PlaneGeometry(40, 40);
var canvas = document.createElement('canvas');
canvas.width = canvas.height = 64;
var ctx = canvas.getContext('2d');
ctx.fillStyle = 'rgba(256,0,0,0.95)'
ctx.fillRect(0, 0, 32, 32);
ctx.fillRect(32, 32, 32, 32);
var srnd = (rng) => (Math.random() - 0.5) * 2 * rng
for (var i = 0; i < 300; i++) {
ctx.fillStyle = `rgba(${srnd(256)|0}, ${srnd(256)|0}, ${srnd(256)|0}, ${srnd(1)})`
ctx.fillRect(srnd(60) | 0, srnd(60) | 0, 5, 5);
}
ctx.fillStyle = 'rgba(256,256,0,0.95)'
ctx.fillText("TEST", 2, 10);
ctx.fillText("WOOO", 32, 45);
var tex = new THREE.Texture(canvas)
tex.magFilter = THREE.NearestFilter;
tex.wrapS = tex.wrapT = THREE.RepeatWrapping;
tex.magFilter = tex.minFilter = THREE.NearestFilter;
tex.needsUpdate = true;
var material = new THREE.MeshLambertMaterial({
color: 0x808080,
map: tex,
transparent: true,
side: THREE.DoubleSide
});
var mesh = new THREE.Mesh(planeGeom, material);
scene.add(mesh);
renderer.setClearColor(0xdddddd, 1);
tex.repeat.x = tex.repeat.y = 2;
//fun effect
for (var i = 1; i < 10; i++) {
var m;
scene.add(m = mesh.clone());
m.position.z += i * 1.1;
}
(function animate() {
var tm = performance.now() * 0.0001
tex.rotation = Math.sin(tm) * Math.PI
//tex.offset.x = tex.offset.y = -2;
//tex.offset.x = Math.sin(tex.rotation) * -0.5;
//tex.offset.y = Math.cos(tex.rotation) * -0.5;
tex.repeat.x = tex.repeat.y = Math.sin(tex.rotation * 1.5) * 3;
tex.center.x = 0.5;
tex.center.y = 0.5;
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
})();
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://cdn.rawgit.com/mrdoob/three.js/master/examples/js/controls/OrbitControls.js"></script>

Three Js - How to fix the blurry images on the vertices of an icosahedron

I was trying to make a rotating icosahedorn with images on each vertex using three js, but the images look blurred. Can anyone please help me? js fiddle link here: https://jsfiddle.net/prisoner849/b2tncLh8/
<div id="container"></div>
var $container = $('#container');
var renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true
});
var camera = new THREE.PerspectiveCamera(80, 1, 0.1, 10000);
var scene = new THREE.Scene();
var Ico;
scene.add(camera);
renderer.setSize(576, 576);
// Making the canvas responsive
function onWindowResize() {
var screenWidth = $(window).width();
if (screenWidth <= 479) {
renderer.setSize(300, 300);
} else if (screenWidth <= 767) {
renderer.setSize(400, 400);
} else if (screenWidth <= 991) {
renderer.setSize(500, 500);
} else if (screenWidth <= 1200) {
renderer.setSize(450, 450);
} else if (screenWidth <= 1366) {
renderer.setSize(550, 550);
}
camera.updateProjectionMatrix();
}
onWindowResize();
window.addEventListener('resize', onWindowResize, false);
$container.append(renderer.domElement);
// Camera
camera.position.z = 200;
// Material
var greyMat = new THREE.MeshPhongMaterial({
color: new THREE.Color("rgb(125,127,129)"),
emissive: new THREE.Color("rgb(125,127,129)"),
specular: new THREE.Color("rgb(125,127,129)"),
shininess: "100000000",
shading: THREE.FlatShading,
transparent: 1,
opacity: 1
});
var L2 = new THREE.PointLight();
L2.position.z = 1900;
L2.position.y = 1850;
L2.position.x = 1000;
scene.add(L2);
camera.add(L2);
var Ico = new THREE.Mesh(new THREE.IcosahedronGeometry(125, 1), greyMat);
Ico.rotation.z = 0.5;
scene.add(Ico);
var trackballControl = new THREE.TrackballControls(camera, renderer.domElement);
trackballControl.rotateSpeed = 1.0;
trackballControl.noZoom = true;
// sprites
var txtLoader = new THREE.TextureLoader();
txtLoader.setCrossOrigin("");
var textures = [
"https://threejs.org/examples/textures/UV_Grid_Sm.jpg",
"https://threejs.org/examples/textures/colors.png",
"https://threejs.org/examples/textures/metal.jpg"
];
var direction = new THREE.Vector3();
console.log(Ico.geometry.vertices.length);
Ico.geometry.vertices.forEach(function(vertex, index){
var texture = txtLoader.load(textures[index % 3]);
var spriteMaterial = new THREE.SpriteMaterial({map: texture});
var sprite = new THREE.Sprite(spriteMaterial);
sprite.scale.setScalar(10);
direction.copy(vertex).normalize();
sprite.position.copy(vertex).addScaledVector(direction, 10);
Ico.add(sprite);
});
function update() {
Ico.rotation.x += 2 / 500;
Ico.rotation.y += 2 / 500;
}
// Render
function render() {
trackballControl.update();
requestAnimationFrame(render);
renderer.render(scene, camera);
update();
}
render();
so i'm guessing because you scale the textures a lot, you're wondering how to get it more blocky and less blurry? If that's the case, with each loaded texture you should set texture.magFilter = THREE.NearestFilter.
magFilter specifies the behavior when a portion of a texture occupies more pixels than the texture's native resolution.
NearestFilter basically returns colors for the UV coordinates for pixel at Math.floor(UV.x*width). So if you have a resolution of 64 pixels, it'll color in 64 blocks across and 64 down. Nice and pixelated.
With the default, linearfilter - it will lerp in between pixel perfect values, giving you the blurring effect. The documentation for THREE.Texture can give you more info on things to try if you get stuck.
See in action.

Three.js controlling shadows

I'm having trouble controlling shadows in THREE.js. First off, the shadow in my scene is way too dark. From what I've read, there was a shadowDarkness property, that is know longer available in the current version of three.js. Does anyone know a work around?
Also, in the attached image: the "backface" geometry is not occluding light on the shadow of the seat - however, you can see the backface of the stool in the reflection of the sphere(cubeCamera). Does anyone know how to fix that?
On a side note: chrome gives me an error "Uncaught TypeError: Cannot set property 'visible' of undefined," regarding the
frameMesh.visible = false;
cubeCameraFrame.position.copy(frameMesh.position);
cubeCameraFrame.updateCubeMap(renderer, scene);
frameMesh.visible = true;
part of my code. Could that be effecting the shadows in some way? I can comment that part of the code and it will have little effect on the stoolframes "reflective" appearance. However it then no longer is reflects in the sphere. Any help is much appreciated.
///webGL - Locking down the Basics
/////////////////////////////////////////////////////////////Environment Settings///////////////////////////////////////////////////////////////////////
///Renderer
var scene = new THREE.Scene();
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMapType = THREE.PCFSoftShadowMap;
renderer.shadowMapEnabled = true;
document.body.appendChild(renderer.domElement);
///Camera's
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
scene.add(camera);
camera.position.set(0, 16, 25);
camera.rotation.x += -0.32;
var cubeCameraSphere = new THREE.CubeCamera(1, 1000, 256); // parameters: near, far, resolution
cubeCameraSphere.renderTarget.texture.minFilter = THREE.LinearMipMapLinearFilter; // mipmap filter
scene.add(cubeCameraSphere);
var cubeCameraFrame = new THREE.CubeCamera(1, 1000, 256); // parameters: near, far, resolution
cubeCameraFrame.renderTarget.texture.minFilter = THREE.LinearMipMapLinearFilter; // mipmap filter
scene.add(cubeCameraFrame);
///Controls
///Lights
var lightSpot_Right = new THREE.SpotLight(0xffffff);
lightSpot_Right.position.set(50, 50, 0);
lightSpot_Right.intensity = 1.25;
lightSpot_Right.castShadow = true;
lightSpot_Right.shadowDarkness = 0.1;
lightSpot_Right.shadowMapWidth = 2048;
lightSpot_Right.shadowMapHeight = 2048;
lightSpot_Right.shadowCameraNear = 1;
lightSpot_Right.shadowCameraFar = 100;
lightSpot_Right.shadowCameraFov = 65;
scene.add(lightSpot_Right);
var lightDirect_Left = new THREE.DirectionalLight(0xffffff, 0.25);
lightDirect_Left.position.set(-1, 0, 0);
scene.add(lightDirect_Left);
///Loaders
var loadTexture = new THREE.TextureLoader();
var loader = new THREE.JSONLoader();
///skyBox
var imagePrefix = "textures/";
var directions = ["skyboxRight", "skyboxLeft", "skyboxTop", "skyboxBottom", "skyboxFront", "skyboxBack"];
var imageSuffix = ".jpg";
var skyMaterialArray = [];
for (var i = 0; i < 6; i++)
skyMaterialArray.push(new THREE.MeshBasicMaterial({
map: new THREE.TextureLoader().load(imagePrefix + directions[i] + imageSuffix),
side: THREE.BackSide
}));
var skyMaterial = new THREE.MeshFaceMaterial(skyMaterialArray);
var skyGeometry = new THREE.CubeGeometry(1000, 1000, 1000);
var skyBox = new THREE.Mesh(skyGeometry, skyMaterial);
scene.add(skyBox);
////////////////////////////////////////////////////////Object Settings//////////////////////////////////////////////////////////////////
//Textures
var seatTexture = loadTexture.load("textures/Maharam_Mister_Notice_Diffuse.jpg");
seatTexture.wrapS = THREE.RepeatWrapping;
seatTexture.wrapT = THREE.RepeatWrapping;
seatTexture.repeat.set(3, 3);
var conceteDiffuse = loadTexture.load("textures/Contrete_Diffuse.jpg");
conceteDiffuse.wrapS = THREE.RepeatWrapping;
conceteDiffuse.wrapT = THREE.RepeatWrapping;
conceteDiffuse.repeat.set(3, 3);
var conceteNormal = loadTexture.load("textures/Contrete_Normal.jpg");
conceteNormal.wrapS = THREE.RepeatWrapping;
conceteNormal.wrapT = THREE.RepeatWrapping;
conceteNormal.repeat.set(3, 3);
var conceteSpecular = loadTexture.load("textures/Contrete_Specular.jpg");
conceteSpecular.wrapS = THREE.RepeatWrapping;
conceteSpecular.wrapT = THREE.RepeatWrapping;
conceteSpecular.repeat.set(3, 3);
///Materials
var seatMaterial = new THREE.MeshLambertMaterial({
map: seatTexture,
side: THREE.DoubleSide
});
var frameMaterial = new THREE.MeshPhongMaterial({
envMap: cubeCameraFrame.renderTarget,
color: 0xcccccc,
emissive: 0x404040,
shininess: 10,
reflectivity: .8
});
var frameHardwareMat = new THREE.MeshPhongMaterial({
color: 0x000000
});
var feetMat = new THREE.MeshPhongMaterial({
color: 0x050505,
shininess: 99
});
var sphereMat = new THREE.MeshPhongMaterial({
envMap: cubeCameraSphere.renderTarget
});
var groundMat = new THREE.MeshPhongMaterial({
map: conceteDiffuse,
specularMap: conceteSpecular,
normalMap: conceteNormal,
normalScale: new THREE.Vector2( 0.0, 0.6 ),
shininess: 50
});
///Geometry and Meshes
var barStool = new THREE.Object3D();
scene.add(barStool);
var seatMesh;
loader.load("models/stoolSeat.js", function (geometry, material) {
seatMesh = new THREE.Mesh(geometry, seatMaterial);
seatMesh.scale.set(.5, .5, .5);
seatMesh.castShadow = true;
seatMesh.receiveShadow = true;
barStool.add(seatMesh);
});
var frameMesh;
loader.load("models/stoolFrame.js", function (geometry, material) {
frameMesh = new THREE.Mesh(geometry, frameMaterial);
frameMesh.scale.set(.5, .5, .5);
frameMesh.castShadow = true;
barStool.add(frameMesh);
});
var frameFeetMesh;
loader.load("models/stoolFeet.js", function (geometry, material) {
frameFeetMesh = new THREE.Mesh(geometry, feetMat);
frameFeetMesh.scale.set(.5, .5, .5);
frameFeetMesh.castShadow = true;
barStool.add(frameFeetMesh);
});
var frameHardwareMesh;
loader.load("models/stoolHardware.js", function (geomtry, material) {
frameHardwareMesh = new THREE.Mesh(geomtry, frameHardwareMat);
frameHardwareMesh.scale.set(.5, .5, .5);
barStool.add(frameHardwareMesh);
});
var sphereGeo = new THREE.SphereGeometry(2.5, 50, 50);
var sphereMesh = new THREE.Mesh(sphereGeo, sphereMat);
scene.add(sphereMesh);
sphereMesh.position.set(-10, 5, 0);
var groundGeo = new THREE.PlaneGeometry(100, 50, 1);
var groundMesh = new THREE.Mesh(groundGeo, groundMat);
scene.add(groundMesh);
groundMesh.rotation.x = -90 * Math.PI / 180;
groundMesh.receiveShadow = true;
///Render Scene
var render = function () {
requestAnimationFrame(render);
barStool.rotation.y += 0.01;
skyBox.rotation.y -= 0.0002;
sphereMesh.visible = false;
cubeCameraSphere.position.copy(sphereMesh.position);
cubeCameraSphere.updateCubeMap(renderer, scene);
sphereMesh.visible = true;
//frameMesh.visible = false;
//cubeCameraFrame.position.copy(frameMesh.position);
//cubeCameraFrame.updateCubeMap(renderer, scene);
//frameMesh.visible = true;
renderer.render(scene, camera);
};
render();
Shadow darkness has been removed. The best work-around is to add ambient light to your scene.
scene.add( new THREE.AmbientLight( 0xffffff, 0.3 );
You may want to concurrently reduce the intensity of your SpotLight.
The shadow is actually correct given only back faces are casting shadows. It appears that the stool is hollow under the seat -- in other words, the seat is not a closed volume. Add a bottom to the underside of your seat.
Alternatively, you can leave your model as-is and experiment with
renderer.shadowMap.cullFace = THREE.CullFaceNone;
Finally, you are getting the error because you are accessing frameMesh in the animation loop before it is defined in the loader callback. The callback is asynchronous.
if ( frameMesh !== undefined ) {
// your code
}
three.js r.75

Resources