Speed up THREE.CanvasRendering - three.js

I have created a sphere geometry and wrapped a texture on it as follows.
scene = new THREE.Scene();
texture = THREE.ImageUtils.loadTexture("RESOURCES/360.jpg");
texture.wrapS = texture.wrapT = THREE.ClampToEdgeWrapping;
mesh = new THREE.Mesh(new THREE.SphereGeometry(500,60,40),new THREE.MeshBasicMaterial({map:texture,overdraw:true}));
mesh.scale.x = -1;
scene.add( mesh );
I move my camera around the sphere. When i use WEBGL renderer everything works fine but when i switch to canvas rendering mode the movement is not smooth. It gets stuck in between. Is there any way i could speed up the canvas rendering. What effect does the value radius , segment width and height have on performance of renderer.
Thanks in advance!!

Related

Sphere object deformation after changing position of sphere

I have two sphere objects on the scene. Both of them been made with default position (scene center). There is no problem when objects are in the middle, however when I want to move one to the right and second to the left, strange deformation has a place. When spheres moving away from the center on X axis they seems to be more squeezed on Y axis. It is kind of "FishEye" lens effect. Is it possible that some default cameras value is interfering to make such a result? FOV value does not bring solution for that, and I did not find information about camera lens properties. What is wrong with that?
I have tried to play with Vector3 as a position provider and spheres has the same result.
I have tried object.position.set(vector3) with no result.
Also object.position.copy(vector3) gave the same result.
Trying translate position without animation gave the same result.
Playing with FOV parameter in camera object also did not solve the problem.
// init
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(100, window.innerWidth/window.innerHeight, 0.1,10000);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
//creating sphere
var geometry = new THREE.SphereGeometry(6, 16, 16);
var material = new THREE.MeshBasicMaterial({color: 0xffffff, wireframe: true});
var sphere = new THREE.Mesh(geometry, material);
//earth
var geometry = new THREE.SphereGeometry(3, 16, 16);
var material = new THREE.MeshBasicMaterial({color: 0x0000ff, wireframe: true});
var earth = new THREE.Mesh(geometry, material);
scene.add(sphere, earth);
camera.position.z = 10;
var animation = function(){
requestAnimationFrame(animation);
update();
renderer.render(scene,camera);
}
var update = function(){
earth.rotation.y +=0.001;
sphere.rotation.y -=0.001;
sphere.rotation.x -=0.001;
sphere.position.x +=0.001;
}
I expect to move sphere.postion.x -=1; and earth.position.x+=1; without squeezing and deformation of spheres on Y axis.
Welcome to Stack Overflow. Thank you for taking the time to take the tour, and for including your code.
The fish-eye effect is likely being caused by your camera defintion:
var camera = new THREE.PerspectiveCamera(100, window.innerWidth/window.innerHeight, 0.1,10000);
The 100 is the FOV (Field of View) for your camera, and is quite wide. In a PerspectiveCamera, the wider your FOV, the more distortion you'll see for objects closer to the edges. Try setting it lower to get a more natural effect.
Do some searches for "Perspective Distortion" and you should find a host of articles on why it happens and how to mitigate it. For starters, here's the Wikipedia page: https://en.wikipedia.org/wiki/Perspective_distortion_(photography) which has a nice animation of changing the FOV for an image of a house.

ThreeJS: White PNG image loaded as texture, used as material and rendered as plane has grey edges

I'm having an issue when rendering a white material in ThreeJS version 87.
Here are the steps to replicate:
A white PNG image that is loaded as texture
This texture is used to create a MeshBasicMaterial (passed as parameter map)
The MeshBasicMaterial is used along a plane Geometry to create a Mesh
The Mesh is added to an empty Scene and rendered on a WebGLRenderer with alpha: true and clearColor as white
The problem is that the rendered texture now has grey edges on parts that should be fully white.
This happens with any image with white edges. I've also tried many different configurations for the renderer and the material but to no avail.
I've made a very simple CodePen that replicates the behavior as simple as possible. Does anyone know how can this problem be solved?
CodePen:
https://codepen.io/ivan-i1/pen/pZxwZX
var renderer, width, height, scene, camera, dataUrl, threeTexture, geometry, material, mesh;
width = window.innerWidth;
height = window.innerHeight;
dataUrl = '//data url from image';
threeTexture = new THREE.ImageUtils.loadTexture(dataUrl);
material = new THREE.MeshBasicMaterial({
map: threeTexture,
transparent: true,
alphaTest: 0.1
});
material.needsUpdate = true;
geometry = new THREE.PlaneGeometry(5, 5);
mesh = new THREE.Mesh(geometry, material);
mesh.position.z = -5;
scene = new THREE.Scene();
scene.add(mesh);
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 );
renderer = new THREE.WebGLRenderer({
alpha: true
});
document.body.appendChild( renderer.domElement );
renderer.setSize(width, height);
renderer.setClearColor( 0xffffff, 1 );
//renderer.render(scene, camera);
function render() {
//Finally, draw to the screen
requestAnimationFrame(render);
renderer.render(scene, camera);
}
render();
Any help is truly appreciated.
ThreeJS/87
Edit:
I think I'm lacking more precision on my post.
This is the original full alpha image:
It might not show because its all white
And this is the same image with different transparencies on 4 quadrants:
This one too might not show because its all white
I got a helpful answer where I was told to make the alphaTest higher, but the problem is that doing that wipes out the transparent parts out of the images, and I need to conserve those parts.
Here is a copy of the codepen with the updated images and showing the same (but slight) grey edges:
codepen
Sorry for not being as precise the first time, any further help is even more appreciated.
Set alphaTest to 0.9.. or higher.. observe the improvement.
Your star texture has gray or black in the area outside the star, which is why you're seeing a gray halo. You can fix it by filling the image with white, (but not changing the alpha channel) in your image editing tool.
Also, you should upgrade to latest three.js (r95)
edit:
I'm not sure what your exact expectation is.. but there are many different settings that control alpha blending in THREE. There is renderer.premultipliedAlpha = true/false (defaults to true) and material.transparent = true/false; material.alphaTest is a threshold value to control at what level alpha is ignored completely. There are also the material.blending, .blendEquation .blendEquation, .blendEquationAlpha, blendDst and blendSrc. etc. etc. You probably need to read up on those.
https://threejs.org/docs/#api/materials/Material
For instance.. here is your texture with:
renderer.premultipliedAlpha = false;
notice the black border on one quadrant of your texture.
https://codepen.io/manthrax/pen/KBraNB

Why does this ThreeJs plane appear to get a kink in it as the camera moves down the y-axis?

I have an instance of THREE.PlaneBufferGeometry that I apply an image texture to like this:
var camera, scene, renderer;
var geometry, material, mesh, light, floor;
scene = new THREE.Scene();
THREE.ImageUtils.loadTexture( "someImage.png", undefined, handleLoaded, handleError );
function handleLoaded(texture) {
var geometry = new THREE.PlaneBufferGeometry(
texture.image.naturalWidth,
texture.image.naturalHeight,
1,
1
);
var material = new THREE.MeshBasicMaterial({
map: texture,
overdraw: true
});
floor = new THREE.Mesh( geometry, material );
floor.material.side = THREE.DoubleSide;
scene.add( floor );
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, texture.image.naturalHeight * A_BUNCH );
camera.position.z = texture.image.naturalWidth * 0.5;
camera.position.y = SOME_INT;
camera.lookAt(floor.position);
renderer = new THREE.CanvasRenderer();
renderer.setSize(window.innerWidth,window.innerHeight);
appendToDom();
animate();
}
function handleError() {
console.log(arguments);
}
function appendToDom() {
document.body.appendChild(renderer.domElement);
}
function animate() {
requestAnimationFrame(animate);
renderer.render(scene,camera);
}
Here's the code pen: http://codepen.io/anon/pen/qELxvj?editors=001
( Note: ThreeJs "pollutes" the global scope, to use a harsh term, and then decorates THREE using a decorator pattern--relying on scripts loading in the correct order without using a module loader system. So, for brevity's sake, I simply copy-pasted the source code of a few required decorators into the code pen to ensure they load in the right order. You'll have to scroll down several thousand lines to the bottom of the code pen to play with the code that instantiates the plane, paints it and moves the camera. )
In the code pen, I simply lay the plane flat against the x-y axis, looking straight up the z-axis, as it were. Then, I slowly pan the camera down along the y-axis, continuously pointing it at the plane.
As you can see in the code pen, as the camera moves along the y-axis in the negative direction, the texture on the plane appears to develop a kink in it around West Texas.
Why? How can I prevent this from happening?
I've seen similar behaviour, not in three.js, not in a browser with webGL but with directX and vvvv; still, i think you'll just have to set widthSegments/heightSegments of your PlaneBufferGeometry to a higher level (>4) and you're set!

Texturing down plane (WebGL, Three.JS)

I am using three.js. with webGL. I have a single texture file called support.jpg 100x100.
I am creating planes on the fly, with different heights and widths. I need the support.jpg texture to scale to the width and then repeat down the plane. (as soon in image below)
For Example. If the plane was (height:10, width: 10) it would the texture once fiting. If the plane was (height:100, width: 10) it would have 10 of the textures repeating 10by10. If the plane was (height:100, width: 50) it would have 2 of the textures repeating 50by50.
Question: How Do I Create a plane that will have the correct texture mapping.
Here is what I have so far, but it is only rendering a single texture. (this is a width 200, height 800)
function CreateSupportBeam() {
var mesh, texture, material;
texture = THREE.ImageUtils.loadTexture("images/support.png");
material = new THREE.MeshBasicMaterial({ map: texture, transparent: true });
var uvs = [];
uvs.push(new THREE.Vector2(0,0));
uvs.push(new THREE.Vector2(1,0));
uvs.push(new THREE.Vector2(1,4));
uvs.push(new THREE.Vector2(0,4));
var geo = new THREE.PlaneGeometry(200, 800);
geo.faceVertexUvs[0].push([uvs[0], uvs[1], uvs[2], uvs[3]]);
mesh = new THREE.Mesh(geo, material);
scene.add(mesh);
}
rollercoaster.dickinsonbros.com/ <- This is the project I am working on.
You do not need to change the UVs.
Use a pattern like the following to avoid distortion and ensure that the pattern repeats and starts at the "top".
var geometry = new THREE.PlaneGeometry( length, height );
var scale = height / length;
var offset = Math.floor( scale ) - scale;;
var texture = THREE.ImageUtils.loadTexture( ... );
texture.wrapT = THREE.RepeatWrapping;
texture.wrapS = THREE.ClampToEdgeWrapping;
texture.repeat.set( 1, scale );
texture.offset.set( 0, offset );
If that is not exactly what you are looking for, experiment until you get it the way you want it.
three.js r.66

Mesh with texture background color

I create a Mesh having a PlaneGeometry and the material defined by a texture loaded from a JPEG image. Everything is fine, excepting that there is a small amount of time before the texture image is loaded when the plane is displayed using a dark color. Is there a way to change this color to something else?
I tried the color option for material, but it is not applied.
var texture = new THREE.ImageUtils.loadTexture('/path/to/image');
texture.minFilter = THREE.LinearMipMapLinearFilter;
texture.magFilter = THREE.NearestFilter;
var material = new THREE.MeshBasicMaterial({
side : THREE.DoubleSide,
map : texture,
color : 0xf0f0f0
// this doesn't seem to work
});
var geometry = new THREE.PlaneGeometry(Math.abs(line.x1 - line.x0), depth);
var mesh = new THREE.Mesh(geometry, material);
That black color is the texture rendering without any texture data. The easiest fix is to load the texture and the mesh, but do not render the mesh until both have fully loaded.
Another option is to create a very small 1x1 texture that is the color you want, use that as your texture initially, and then change the mesh material to your final texture once the desired texture has fully loaded.

Resources