How can I rotate texture inside a plane? - three.js

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>

Related

Selfshadow plane affected by a displacement map not working

Working on some kind of fictional treasure map. I'm cutting a large displacement map intosmaller tiles as I don't yet how wide the final terrain is going to be -- right now it's 5*5, but it could be wider in the future
For some reasons, I am having issues projecting shadows on the displaced planes.
I don't know where the problem is coming from. Maybe it's the way I push meshes into an array through a function, i'm afraid i'm not doing this the right way.
I'd like to achieve the result using a directional light
Here is a c4d draft of what i'm trying to achieve
and here is what i'm able to do in the browser (didnt manage to tile them properly yet :^)
var renderer = new THREE.WebGLRenderer();
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
var material = [];
var texture = [];
var tile = [];
var planeRes = 128;
var planesize = 1;
var dim = 5;
var size = dim * dim;
var DispScale = 2;
var geometry = new THREE.PlaneBufferGeometry(planesize,planesize,planeRes, planeRes);
function tileGenerator(inc) {
if (inc < 10) {
texture[inc] = new THREE.TextureLoader().load('cut25lowres/image_part_00' + inc + '.jpg');
} else {
texture[inc] = new THREE.TextureLoader().load('cut25lowres/image_part_0' + inc + '.jpg');
}
material[inc] = new THREE.MeshPhongMaterial({
color: 0xffffff,
displacementMap: texture[inc],
side: THREE.DoubleSide,
receiveShadow : true,
castShadow : true
});
tile[inc] = new THREE.Mesh(geometry, material[inc]);
}
for (var i = 1; i < size + 1; i++) {
tileGenerator(i);
}
for (var i = 1; i < size + 1; i++) {
tile[i].position.set(-planesize * (i % dim)+1, 0, -planesize * Math.ceil(i / dim)+1 );
tile[i].rotation.x = Math.PI / 2 + Math.PI;
tile[i].rotation.z = Math.PI / 2;
scene.add(tile[i]);
}
var dirLight = new THREE.DirectionalLight( 0xffffff, 1 );
dirLight.castShadow = true;
dirLight.shadow.camera.near = 0.1;
dirLight.shadow.camera.far = 6;
dirLight.shadow.mapSize.set( 1024, 1024 );
var targetObject = new THREE.Object3D();
targetObject.position.x = -10;
targetObject.position.z = -10;
dirLight.position.y = 3;
scene.add(targetObject);
dirLight.target = targetObject;
scene.add( dirLight );
Edit : Here is a cleaner version without the array as it's not part of the problem
jsfiddle.net/clemtre/3y9tqc6j/34
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
var renderer = new THREE.WebGLRenderer();
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var controls = new THREE.OrbitControls(camera, renderer.domElement);
var scene = new THREE.Scene();
var heightmap = new THREE.TextureLoader().load('https://i.imgur.com/MVYhfd7.jpeg');
var geometry = new THREE.PlaneGeometry(20, 20, 100, 100);
var material = new THREE.MeshPhongMaterial({
color: 0xffffff,
displacementMap: heightmap,
displacementScale: 10
});
var light = new THREE.DirectionalLight(0xffffff);
light.position.set(0, 1, 1).normalize();
light.castShadow = true;
scene.add(light);
var plane = new THREE.Mesh(geometry, material);
plane.rotation.x = -Math.PI/2;
scene.add(plane);
camera.position.z = -20;
camera.position.y = 5;
controls.update();
var animate = function() {
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
};
animate();
Many thanks!

Two objects don't cast a shadow while other one does

I have exactly the same three cube objects except their x position.
I want them to cast a shadow, but somehow two of them don't cast a shadow while the other one does.
Here is the pic of what's happening.
https://ibb.co/z6Vwxmf
I'm sure that castShadow is set to true on all the objects.
And I don't think I missed any shadow setting property either (because the middle object casts a shadow properly.)
These objects are created under //left cube //right cube comments in the below code.
< script >
window.addEventListener('load', init, false);
function init(event) {
createScene();
createLights();
createTile01();
createTile02();
createTile03();
createBase();
loop();
}
var scene, camera, Width, Height, renderer, container;
function createScene() {
Width = window.innerWidth;
Height = window.innerHeight;
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.x = 0;
camera.position.y = 10;
camera.position.z = 50;
camera.lookAt(scene.position);
renderer = new THREE.WebGLRenderer();
renderer.setClearColor(new THREE.Color(0x000000));
renderer.setSize(Width, Height);
renderer.shadowMap.enabled = true;
container = document.getElementById('scene');
container.appendChild(renderer.domElement);
window.addEventListener('resize', handleWindowResize, false);
}
function handleWindowResize() {
Height = window.InnerHeight;
Width = window.InnerWidth;
renderer.setSize(Width, Height);
camera.aspect = Width / Height;
camera.updateProjectionMatrix();
}
var ambiLight, spotLight;
function createLights() {
ambiLight = new THREE.AmbientLight(0xffffff);
scene.add(ambiLight);
spotLight = new THREE.DirectionalLight(0xffffff);
spotLight.position.set(0, 30, -0);
spotLight.intensity = 1;
spotLight.castShadow = true;
scene.add(spotLight);
}
Tile01 = function() {
var geom = new THREE.BoxGeometry(10, 10, 2);
var mat = new THREE.MeshPhongMaterial({
color: 0x53b0df
});
this.mesh = new THREE.Mesh(geom, mat);
this.mesh.receiveShadow = true;
this.mesh.castShadow = true;
}
var tile01;
function createTile01() {
tile01 = new Tile01();
tile01.mesh.position.set(0, 0, 0);
scene.add(tile01.mesh);
}
//right cube
Tile02 = function() {
var geom = new THREE.BoxGeometry(10, 10, 2);
var mat = new THREE.MeshPhongMaterial({
color: 0x25b0cf
});
this.mesh = new THREE.Mesh(geom, mat);
this.mesh.receiveShadow = true;
this.mesh.castShadow = true;
}
var tile02;
function createTile02() {
tile02 = new Tile02();
tile02.mesh.position.set(20, 0, 0);
scene.add(tile02.mesh);
}
//left cube
Tile03 = function() {
var geom = new THREE.BoxGeometry(10, 10, 2);
var mat = new THREE.MeshPhongMaterial({
color: 0x00b0df
});
this.mesh = new THREE.Mesh(geom, mat);
this.mesh.receiveShadow = true;
this.mesh.castShadow = true;
}
var tile03;
function createTile03() {
tile03 = new Tile03();
tile03.mesh.position.set(-20, 0, 0);
scene.add(tile03.mesh);
}
Base = function() {
var geom = new THREE.CylinderGeometry(100, 30, 5, 60);
var mat = new THREE.MeshPhongMaterial({
color: 0xcf34ec
});
this.mesh = new THREE.Mesh(geom, mat);
this.mesh.castShadow = true;
this.mesh.receiveShadow = true;
}
var base;
function createBase() {
base = new Base();
base.mesh.position.set(0, -10, -20);
scene.add(base.mesh);
}
function loop() {
renderer.render(scene, camera);
requestAnimationFrame(loop);
}
< /script>
Could you help me figure out what's wrong with the setting?
I was able to resolve the issue myself.
Referring to some solutions I found at other Q/As about a shadow issue, I added a shadow.camera.left/right/top/bottom properties to the light and it worked.
The below is the code I corrected.
Now I can see the shadows of all the three objects.
var ambiLight, spotLight;
function createLights() {
ambiLight = new THREE.AmbientLight(0xffffff);
scene.add(ambiLight);
spotLight = new THREE.DirectionalLight(0xffffff);
spotLight.position.set(0, 30, -0);
spotLight.intensity = 1;
spotLight.castShadow = true;
spotLight.shadow.camera.left = -400;
spotLight.shadow.camera.right = 400;
spotLight.shadow.camera.top = 400;
spotLight.shadow.camera.bottom = -400;
spotLight.shadow.camera.near = 1;
spotLight.shadow.camera.far = 1000;
spotLight.shadow.mapSize.width = 2048;
spotLight.shadow.mapSize.height = 2048;
scene.add(spotLight);
}

Three.VideoTexture stretches portrait video

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).

shadowMap cant detect all instances on THREE.InstancedBufferGeometry

I'm implementing something similar to the buffer geometry instancing dynamic example.
Basically the idea is having one bufferGeometry duplicated and having an attribute array with the offsets of my objects (like they have in the above example).
If I try to add shadows, I only get shadows on 1 object, which I assume is because we only have 1 geometry.
Is there a way of adding shadows to all my objects?
var scene, camera, renderer, controls;
var offsets;
init();
animate();
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.set(0, 250, 1000);
renderer = new THREE.WebGLRenderer();
renderer.shadowMap.enabled = true
renderer.shadowMap.type = THREE.PCFSoftShadowMap
renderer.gammaInput = true
renderer.gammaOutput = true
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
controls = new THREE.OrbitControls(camera, renderer.domElement);
// Lights
var ambient = new THREE.AmbientLight(0xcccccc);
scene.add(ambient);
var spot = new THREE.SpotLight(0x999999, 1, 0, Math.PI / 2, 1);
spot.position.set(700, 700, 700)
spot.target.position.set(0, 0, 0);
spot.castShadow = true
spot.angle = Math.PI / 4
spot.penumbra = 0.05
spot.decay = 2
spot.distance = 10000
spot.shadow.mapSize.width = 1024
spot.shadow.mapSize.height = 1024
spot.shadow.camera.near = 1
spot.shadow.camera.far = 10000
scene.add(spot);
var spotHelper = new THREE.SpotLightHelper(spot)
scene.add(spotHelper);
// Floor
var geometry = new THREE.PlaneGeometry(3000, 3000, 10, 10);
var material = new THREE.MeshPhongMaterial({
color: new THREE.Color(0x777777),
shininess: 5
});
var ground = new THREE.Mesh(geometry, material);
ground.rotation.x = -1.57;
ground.receiveShadow = true;
scene.add(ground);
// instanced geometry
var instances = 10;
var geometry = new THREE.InstancedBufferGeometry();
var icosahedron = new THREE.BufferGeometry().fromGeometry(new THREE.IcosahedronGeometry(200, 3));
geometry.addAttribute('position', icosahedron.attributes.position);
geometry.addAttribute('normal', icosahedron.attributes.normal);
geometry.addAttribute('uv', icosahedron.attributes.uv);
geometry.setIndex(icosahedron.index);
offsets = new THREE.InstancedBufferAttribute(new Float32Array(instances * 3), 3, 1);
var vector = new THREE.Vector3();
for (var i = 0; i < offsets.count; i++) {
var x = Math.random() * 1000 - 500;
var y = Math.random() * 1000 - 500;
var z = Math.random() * 1000 - 500;
vector.set(x, y, z).normalize();
offsets.setXYZ(i, x + vector.x * 5, y + vector.y * 5, z + vector.z * 5);
}
geometry.addAttribute('offset', offsets);
var material = new THREE.ShaderMaterial({
uniforms: {},
vertexShader: document.getElementById('vertexShader').textContent,
fragmentShader: document.getElementById('fragmentShader').textContent,
side: THREE.DoubleSide,
});
var mesh = new THREE.Mesh(geometry, material);
mesh.castShadow = true;
mesh.receiveShadow = true;
scene.add(mesh);
}
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
Example JsFiddle

ThreeJS shadow not rendering

I've looked through a number of other S.O. questions, followed all of the advice, but I'm still clueless as to why I can't get shadows to render on this very basic scene.
http://jsfiddle.net/4Txgp/
[Updated] Code:
var SCREEN_WIDTH = window.innerWidth - 25;
var SCREEN_HEIGHT = window.innerHeight - 25;
var camera, scene;
var canvasRenderer, webglRenderer;
var container, mesh, geometry, plane;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
init();
animate();
function init() {
container = document.createElement('div');
document.body.appendChild(container);
camera = new THREE.PerspectiveCamera(30, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.x = 1200;
camera.position.y = 1000;
camera.lookAt({
x: 0,
y: 0,
z: 0
});
scene = new THREE.Scene();
var groundMaterial = new THREE.MeshLambertMaterial({
color: 0x6C6C6C
});
plane = new THREE.Mesh(new THREE.PlaneGeometry(10000, 10000, 100, 100), groundMaterial);
plane.rotation.x = -Math.PI / 2;
plane.receiveShadow = true;
scene.add(plane);
// LIGHTS
// scene.add(new THREE.AmbientLight(0x666666));
/*
var light;
light = new THREE.DirectionalLight(0xdfebff, 1.75);
light.position.set(600, 800, 100);
//light.position.multiplyScalar(1.3);
light.castShadow = true;
light.shadowCameraVisible = true;
light.shadowMapWidth = light.shadowMapHeight = 2048;
var d = 50;
light.shadowCameraLeft = -d;
light.shadowCameraRight = d;
light.shadowCameraTop = d;
light.shadowCameraBottom = -d;
light.shadowCameraFar = 500;
light.shadowDarkness = 0.5;
scene.add(light);
*/
var spotLight = new THREE.SpotLight( 0xffffff );
spotLight.position.set( 700, 1000, 100 );
spotLight.castShadow = true;
spotLight.shadowCameraVisible = true;
spotLight.shadowMapWidth = 2048;
spotLight.shadowMapHeight = 2048;
spotLight.shadowCameraNear = 100;
spotLight.shadowCameraFar = 2000;
spotLight.shadowCameraFov = 30;
scene.add( spotLight );
var boxgeometry = new THREE.CubeGeometry(100, 200, 100);
var boxmaterial = new THREE.MeshLambertMaterial({
color: 0x0aeedf
});
var cube = new THREE.Mesh(boxgeometry, boxmaterial);
cube.position.x = 0;
cube.position.y = 100;
cube.position.z = 0;
scene.add(cube);
// RENDERER
webglRenderer = new THREE.WebGLRenderer();
webglRenderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
//webglRenderer.domElement.style.position = "relative";
webglRenderer.shadowMapEnabled = true;
webglRenderer.shadowMapSoft = true;
container.appendChild(webglRenderer.domElement);
}
function animate() {
var timer = Date.now() * 0.0002;
camera.position.x = Math.cos(timer) * 1000;
camera.position.z = Math.sin(timer) * 1000;
requestAnimationFrame(animate);
render();
}
function render() {
camera.lookAt(scene.position);
webglRenderer.render(scene, camera);
}
I have a scene with a plane, an object (cube), a spotlight (copied directly from http://threejs.org/docs/58/#Reference/Lights/SpotLight for testing purposes) , and a camera. It renders fine, except that the cube is not casting a shadow on the "ground" (plane), and the shading looks like everything has been done in a basic material. I'm using a combo of Phongs and Lamberts.
My directional light is set to castShadow = true;, and my plane is set with receiveShadow = true, along with shadow map settings. The renderer itself has shadowMapEnabled = true.
I've tried various solutions, I remember with previous versions of ThreeJS there would be external library calls depending on what you wanted to do, but I've also seen other examples on JSFiddle just calling ThreeJS by itself, as well as examples from the official site, that work fine.
Any hints/info/constructive remarks about overlooking something simple and small?
You need to set
cube.castShadow = true;
and make sure the shadow camera far plane reaches the cube.
three.js r.144

Resources