Three.js print preview canvas not fully visible but screenshot it is - three.js

I have a three.js project running where i try to print the scene with the normal window.print() function.
It kind of worked but not as i expected.
This is my scene:
This is the screenshot with function (renderer.render) which works perfectly:
This is the print preview if i click "print" in the browser:
As you can see the print preview is not centered at all and also it is shifted a little bit to the left.
Can someone explain me either how i can shift the cameras view a little bit to the right so he takes the image centered from the view, or how i can transform the taken screenshot to the print preview because the screenshot taken with renderer.render(scene, camera) works very well?
This is the code:
`
function init() {
renderer = new THREE.WebGLRenderer({
antialias: true
}, { preserveDrawingBuffer: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
renderer.domElement.className = 'realCanvas';
container.appendChild(renderer.domElement);
renderer.outputEncoding = THREE.sRGBEncoding;
renderer.toneMapping = THREE.ACESFilmicToneMapping;
pmremGenerator = new THREE.PMREMGenerator(renderer);
pmremGenerator.compileEquirectangularShader();
controls = new OrbitControls(camera, renderer.domElement);
controls.target.set(0, 50, 0);
controls.maxPolarAngle = Math.PI / 2;
controls.minDistance = 350;
controls.maxDistance = 2550;
controls.minZoom = 350;
controls.maxZoom = 2550;
controls.zoomSpeed = 0.75;
controls.panSpeed = 0.75;
controls.rotateSpeed = 0.55;
var minPan = new THREE.Vector3( - 1500, - 1500, - 1500);
var maxPan = new THREE.Vector3(1500, 1500, 1500);
var _v = new THREE.Vector3();
controls.addEventListener("change", function () {
_v.copy(controls.target);
controls.target.clamp(minPan, maxPan);
_v.sub(controls.target);
camera.position.sub(_v);
})
controls.update();
window.addEventListener('resize', onWindowResize, false);
// stats
stats = new Stats();
stats.dom.classList.add("myStats");
$('.myStats').css("display", "none");
container.appendChild(stats.dom);
}
`
This is the background init:
`
function initBackground() {
container = document.createElement('div');
container.classList.add("myCanvas");
document.body.appendChild(container);
container.style.cssText = 'position:fixed; top:0;';
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 2.0, 100000);
camera.position.set(-220, 100, -650); //(-220, 100, -650);
scene = new THREE.Scene();
scene.background = new THREE.Color(0xcce0ff);
scene.fog = new THREE.Fog(0xcce0ff, 5000, 10000);
scene.add(new THREE.AmbientLight(0x222222, 0.75));
var light = new THREE.DirectionalLight(0xffffff, 0.01);
light.position.set(200, 450, 500);
light.castShadow = true;
scene.add(light);
var gt = new THREE.TextureLoader().load("examples/textures/terrain/street4.jpg");
var gg = new THREE.PlaneBufferGeometry(32000, 32000);
var gm = new THREE.MeshPhongMaterial({
color: 0xffffff,
map: gt
});
ground = new THREE.Mesh(gg, gm);
ground.rotation.x = - Math.PI / 2;
ground.material.map.repeat.set(640, 640);
ground.material.map.wrapS = THREE.RepeatWrapping;
ground.material.map.wrapT = THREE.RepeatWrapping;
ground.material.map.encoding = THREE.sRGBEncoding;
// note that because the ground does not cast a shadow, .castShadow is left false
ground.receiveShadow = false;
ground.position.set(-20, -20, -20);
scene.add(ground);
$('div myCanvas').hide(); // before canvas but color picker colored square is also canvas
}
`
This is the code for the taken screenshot which works good:
`
jQuery('#screenshot').click(function () {
renderer.render(scene, camera);
renderer.domElement.toBlob(function(blob) {
saveAs(blob, "Configurator");
});
});
`
This is the code i used for print preview, but it does not work as expected:
`
const mediaQuery = window.matchMedia('print');
mediaQuery.addEventListener("change", () => {
renderer.render(scene, camera);
/*const c = document.getElementsByClassName("realCanvas");
if(c.width === -1){
renderer.setSize(window.innerWidth, window.innerHeight);
c.width=window.innerWidth;
} else {
renderer.setSize(1050, 800);
//renderer.setSize(window.innerWidth * 0.8, window.innerHeight * 0.8);
c.width=-1;
}*/
});
I tried to shift the cameras position but also the viewpoint but it does not work as expected.
I want to have the same view in the print preview as if i take a screenshot out of the scene.

Related

anyone knows how to work orbit control on three js if my p5 canvas have some actual control

on my p5 canvas i do set some original control as such:
this.mousePressed = function(){
//check if the playback button has been clicked
var isButtonClicked = this.playbackButton.hitCheck();
var isMouseInBlockGUI = blockMidHighLow.isMouseInGUI();
//if not make the visualisation fullscreen
if(isButtonClicked == false && isMouseInBlockGUI == false){
let fs = fullscreen();
fullscreen(!fs);
}
};
on three js wise, i have some control on the 3d animation, however its not working :
const controls = new THREE.OrbitControls(camera, render.domElement);
controls.enabled = true;
controls.target.set(1000, 0, 1000);
controls.update();
You can try this.
set up a camera
set up a renderer
use OrbitControl
set up a camera
//Object to store the size of the viewport
const size = {
width: window.innerWidth,
height: window.innerHeight,
};
//Creates the camera (point of view of the user)
const aspect = size.width / size.height;
const camera = new THREE.PerspectiveCamera(75, aspect);
camera.position.z = 15;
camera.position.y = 13;
camera.position.x = 8;
set up a renderer
//Sets up the renderer, fetching the canvas of the HTML
const threeCanvas = document.getElementById("three-canvas");
const renderer = new THREE.WebGLRenderer({
canvas: threeCanvas,
alpha: true
});
renderer.setSize(size.width, size.height);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
Setup an OrbitControl
//Creates the orbit controls (to navigate the scene)
const controls = new OrbitControls(camera, threeCanvas);
controls.enableDamping = true;
controls.target.set(-2, 0, 0);
//Animation loop
const animate = () => {
controls.update();
renderer.render(scene, camera);
requestAnimationFrame(animate);
};
Hope this helps. Thanks
Learning material
I personally recommend this blog. It's very useful to learn.
https://sbcode.net/threejs/orbit-controls/
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import Stats from 'three/examples/jsm/libs/stats.module'
const scene = new THREE.Scene()
scene.add(new THREE.AxesHelper(5))
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
)
camera.position.z = 2
const renderer = new THREE.WebGLRenderer()
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)
const controls = new OrbitControls(camera, renderer.domElement)

Intersecting Objects - Shadow Problem - Three.js

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);
}

Rendered object looks flat even with shadows

I'm a three.js newb. I've been playing around with it for a couple of days and haven't been able to figure out how to make my objects look more realistic. I suspect there's no simple answer for this question, but is there anything I can do to improve my rendering quality without going into the depth of "rendering science"? Maybe I'm missing some configs. Thank you for any advice!
Here's the relevant code used in rendering a kitchen cabinet frame.
this.renderer = new THREE.WebGLRenderer({ antialias: true })
this.renderer.setSize(this.container.offsetWidth, this.container.offsetHeight)
this.renderer.sortObjects = false
this.renderer.setClearColor(0xf0f0f0)
this.renderer.gammaFactor = 2.2
this.renderer.gammaOutput = true
this.renderer.setPixelRatio(window.devicePixelRatio)
this.renderer.shadowMap.enabled = true
this.renderer.shadowMap.type = THREE.PCFSoftShadowMap
const light = new THREE.AmbientLight(0xffffff, 0.8)
const light2 = new THREE.PointLight(0xffffff, 0.3)
light2.position.set(400, 400, 400)
light2.shadow.camera.near = 10
light2.shadow.camera.far = 10000
light2.shadow.mapSize.width = 2048
light2.shadow.mapSize.height = 2048
light2.castShadow = true
this.scene.add(light2)
this.scene.add(light)
const material = new THREE.MeshStandardMaterial({ color: 0xffffff, metalness: 0, roughness: 0 })
let scene, camera, controls, ambient, point, loader, renderer, container, stats;
const targetRotation = 0;
const targetRotationOnMouseDown = 0;
const mouseX = 0;
const mouseXOnMouseDown = 0;
const windowHalfX = window.innerWidth / 2;
const windowHalfY = window.innerHeight / 2;
init();
animate();
var box, b1, b2, b3;
function init() {
// Create a scene which will hold all our meshes to be rendered
scene = new THREE.Scene();
// Create and position a camera
camera = new THREE.PerspectiveCamera(
60, // Field of view
window.innerWidth / window.innerHeight, // Aspect ratio
/*window.innerWidth / -8,
window.innerWidth / 8,
window.innerHeight / 8,
window.innerHeight / -8,
*/
0.1, // Near clipping pane
1000 // Far clipping pane
);
scene.add(camera)
// Reposition the camera
camera.position.set(0, 5, 10);
// Point the camera at a given coordinate
camera.lookAt(new THREE.Vector3(0, 0, 0));
// Add orbit control
controls = new THREE.OrbitControls(camera);
controls.target.set(0, -0.5, 0);
controls.update();
// Add an ambient lights
ambient = new THREE.AmbientLight(0xffffff, 0.2);
scene.add(ambient);
// Add a point light that will cast shadows
point = new THREE.PointLight(0xffffff, 1);
point.position.set(25, 50, 25);
point.castShadow = true;
point.shadow.mapSize.width = 1024;
point.shadow.mapSize.height = 1024;
scene.add(point);
group = new THREE.Group();
group.position.y = 0;
scene.add(group);
rotationAnchor = new THREE.Object3D()
group.add(rotationAnchor);
box = new THREE.Mesh(new THREE.BoxGeometry(), new THREE.MeshStandardMaterial({
color: 'grey'
}))
b1 = box.clone();
b2 = box.clone();
b3 = box.clone();
b3.material = b3.material.clone()
b3.material.color.set('red')
group.add(box);
group.add(b1);
b1.position.y += 1
group.add(b2);
b2.position.z += 1
rotationAnchor.add(b3);
rotationAnchor.position.set(0.5, 0.5, 1.5)
b3.position.set(-.5, -.5, -.5)
// Create a renderer
renderer = new THREE.WebGLRenderer({
antialias: true
});
// Set size
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
// Set color
renderer.setClearColor(0xf8a5c2);
renderer.gammaOutput = true;
// Enable shadow mapping
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
// Append to the document
container = document.createElement("div");
document.body.appendChild(container);
document.body.appendChild(renderer.domElement);
// Add resize listener
window.addEventListener("resize", onWindowResize, false);
// Enable FPS stats
stats = new Stats();
container.appendChild(stats.dom);
var gui = new dat.GUI({
height: 5 * 32 - 1
});
let params = {
'test': 4,
'bevelThickness': 1,
'bevelSize': 1.5,
'bevelSegments': 3
}
gui.add(params, 'test', 0, 10).onChange(val => {
test = val
})
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function animate() {
rotationAnchor.rotation.z = (Math.cos(performance.now() * 0.001) * Math.PI * 0.25) + (Math.PI * 1.25)
requestAnimationFrame(animate);
// Re-render scene
renderer.render(scene, camera);
// Update stats
stats.update();
}
body {
overflow: hidden;
margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/96/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script src="https://threejs.org/examples/js/libs/stats.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.2/dat.gui.min.js"></script>

overlapping semitransparent objects are not rendered as expected

I have two overlapping semitransparent boxes and I'd expect to see both of them independent of the viewing angle. The first image shows a rendering from aside and the small box is visible within the bigger box. The second image shows the same scene but form another viewing angle. As you can see, the smaller box is visible but the part which is with the bigger box is invisible. What am I missing?
var camera, scene, renderer;
init();
animate();
function init() {
// Renderer.
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
// Add renderer to page
document.body.appendChild(renderer.domElement);
// Create camera.
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.1, 50);
camera.position.set(2, 2, 2);
camera.lookAt(new THREE.Vector3(0.0, 0.0, 0.0));
// Create scene.
scene = new THREE.Scene();
// Create material
var material = new THREE.MeshStandardMaterial();
material.transparent = true;
material.opacity = 0.5;
// Create cube and add to scene.
var geometry1 = new THREE.BoxGeometry(1, 1, 1);
var mesh1 = new THREE.Mesh(geometry1, material);
mesh1.position.set(0, 0, 0);
//mesh1.castShadow = true;
scene.add(mesh1);
// Create cube and add to scene.
var geometry2 = new THREE.BoxGeometry(0.5, 0.5, 0.5);
var mesh2 = new THREE.Mesh(geometry2, material);
mesh2.position.set(0.0, 0, 0.5);
//mesh2.castShadow = true;
scene.add(mesh2);
var spotLight = new THREE.SpotLight(0xffffff, 0.32);
spotLight.position.set(0, 5, 0);
spotLight.castShadow = true;
spotLight.shadow.mapSize.width = 2048;
spotLight.shadow.mapSize.height = 2048;
spotLight.shadow.camera.near = 0.1;
spotLight.shadow.camera.far = 20;
scene.add(spotLight);
let hemiLight = new THREE.HemisphereLight(0xffffbb, 0x080820, 0.8);
scene.add(hemiLight);
// Ground plane
var groundGeo = new THREE.PlaneBufferGeometry(50, 50);
var groundMat = new THREE.MeshStandardMaterial({color: 0xffffff});
var ground = new THREE.Mesh(groundGeo, groundMat);
ground.rotation.x = -Math.PI / 2;
ground.position.y = -0.5;
ground.receiveShadow = true;
scene.add(ground);
// Add listener for window resize.
window.addEventListener('resize', onWindowResize, false);
let controls = new THREE.OrbitControls(camera);
controls.enableZoom = true;
controls.enablePan = false;
controls.maxDistance = 20.0;
controls.minPolarAngle = 0;
controls.maxPolarAngle = Math.PI / 2;
controls.target.set(0, 0, 0);
controls.update();
}
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
body {
padding: 0;
margin: 0;
}
canvas {
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/98/three.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
Transparent objects in WebGL are sometimes rather problematic. It's all about the rendering order: If the small cube is rendered after the large cube, how should the rendering behave? This question has some information you might find useful.
In your particular case (though not necessarily always), one solution could be to disable renderer object sorting:
renderer.sortObjects = false;
and(!) make sure you add your objects in the correct order, i.e. the small cube first and the large one second. Here is an updated version of your snippet:
var camera, scene, renderer;
init();
animate();
function init() {
// Renderer.
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
renderer.sortObjects = false;
// Add renderer to page
document.body.appendChild(renderer.domElement);
// Create camera.
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.1, 50);
camera.position.set(2, 2, 2);
camera.lookAt(new THREE.Vector3(0.0, 0.0, 0.0));
// Create scene.
scene = new THREE.Scene();
// Create material
var material = new THREE.MeshStandardMaterial();
material.transparent = true;
material.opacity = 0.5;
// Create cube and add to scene.
var geometry2 = new THREE.BoxGeometry(0.5, 0.5, 0.5);
var mesh2 = new THREE.Mesh(geometry2, material);
mesh2.position.set(0.0, 0, 0.5);
//mesh2.castShadow = true;
scene.add(mesh2);
// Create cube and add to scene.
var geometry1 = new THREE.BoxGeometry(1, 1, 1);
var mesh1 = new THREE.Mesh(geometry1, material);
mesh1.position.set(0, 0, 0);
//mesh1.castShadow = true;
scene.add(mesh1);
var spotLight = new THREE.SpotLight(0xffffff, 0.32);
spotLight.position.set(0, 5, 0);
spotLight.castShadow = true;
spotLight.shadow.mapSize.width = 2048;
spotLight.shadow.mapSize.height = 2048;
spotLight.shadow.camera.near = 0.1;
spotLight.shadow.camera.far = 20;
scene.add(spotLight);
let hemiLight = new THREE.HemisphereLight(0xffffbb, 0x080820, 0.8);
scene.add(hemiLight);
// Ground plane
var groundGeo = new THREE.PlaneBufferGeometry(50, 50);
var groundMat = new THREE.MeshStandardMaterial({color: 0xffffff});
var ground = new THREE.Mesh(groundGeo, groundMat);
ground.rotation.x = -Math.PI / 2;
ground.position.y = -0.5;
ground.receiveShadow = true;
scene.add(ground);
// Add listener for window resize.
window.addEventListener('resize', onWindowResize, false);
let controls = new THREE.OrbitControls(camera);
controls.enableZoom = true;
controls.enablePan = false;
controls.maxDistance = 20.0;
controls.minPolarAngle = 0;
controls.maxPolarAngle = Math.PI / 2;
controls.target.set(0, 0, 0);
controls.update();
}
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
body {
padding: 0;
margin: 0;
}
canvas {
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/98/three.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

Animating canvas billboard in Three.js

I'm trying to animate a Canvas-based texture that is mapped onto a plane, like a billboard. I've made a point of including material.needsUpdate & texture.needsUpdate, but I'm still unable to get the texture to come to life. I've also included a rotating cube just so I know the animation routine is functioning on some level.
Here is the code:
<body>
<script src="http://mrdoob.github.com/three.js/build/three.min.js"></script>
<script>
if (window.innerWidth === 0) {
window.innerWidth = parent.innerWidth;
window.innerHeight = parent.innerHeight;
}
var camera, scene, renderer;
var mesh, geometry, material;
var light, sign, animTex;
var canvas, context;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 1200);
camera.position.z = 700;
scene = new THREE.Scene();
material = new THREE.MeshLambertMaterial(
{
color: 0x885522,
wireframe: false,
overdraw: false
});
geometry = new THREE.CubeGeometry(80, 120, 100, 1, 1, 1);
mesh = new THREE.Mesh(geometry, material);
sign = createSign();
light = new THREE.DirectionalLight(0xFFFFFF, 3.0);
light.position = new THREE.Vector3(5, 10, 7);
light.target = new THREE.Vector3(0, 0, 0);
scene.add(mesh);
scene.add(sign);
scene.add(light);
renderer = new THREE.CanvasRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
}
function createSign() {
canvas = document.createElement("canvas");
context = canvas.getContext("2d");
canvas.width = 200;
canvas.height = 200;
context = canvas.getContext("2d");
var texture = new THREE.Texture(canvas);
texture.needsUpdate = true;
var material = new THREE.MeshBasicMaterial({ map : texture, overdraw: true });
material.needsUpdate = true;
var mesh = new THREE.Mesh(new THREE.PlaneGeometry(200, 200), material);
mesh.doubleSided = true;
return mesh;
}
function animate() {
var time = Date.now()*0.01;
var sinTime = Math.sin(time * 0.05) * 100;
var cosTime = Math.cos(time * 0.05) * 100;
mesh.rotation.y = sinTime*0.01;
requestAnimationFrame(animate);
context.fillStyle = "black";
context.fillRect(0, 0, canvas.width, canvas.height);
context.fillStyle = "white";
context.fillRect((canvas.width/2) + sinTime, (canvas.height/2) + cosTime, 20, 20)
renderer.render(scene, camera);
}
This runs, but I can't seem to get the Canvas texture material to update. What have I overlooked?
Place this right before your render() call:
sign.material.map.needsUpdate = true;
The needsUpdate flag is reset (to false) every time the texture is used (every render loop), so it needs to be set to true in the render loop (before the render call, or it'll be a frame off). So in your example, put sign.material.map.needsUpdate = true before renderer.render( scene, camera ). texture.needsUpdate = true and material.needsUpdate = true are not needed.
Also, you only need to set the needsUpdate flag on the texture, as the material properties are not changing.

Resources