three.js transparent sphere glitch - three.js

I have a transparent sphere and a spot light and that's about it. My sphere displays visual glitches, like striations.
see: http://jsfiddle.net/blwoodley/tvcogqkg/3/
(Note the grid is not necessary to manifest the bug. I just put it in there to show that transparency is working otherwise fine).
Any thoughts on how to get rid of these glitches? They seem to depend on the relative position of the camera and spot light.
Using three.js, r71.
Here is the code from the fiddle since SO seems to want it:
var SCREEN_WIDTH = window.innerWidth - 100;
var SCREEN_HEIGHT = window.innerHeight - 100;
var camera, scene, _planeMesh;
var canvasRenderer, webglRenderer;
var container, mesh, geometry, plane;
container = document.createElement('div');
document.body.appendChild(container);
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(30, window.innerWidth / window.innerHeight, 1, 100000);
camera.position.set( 380, 80, 100 );
var spotLight = new THREE.SpotLight( 0xffffff );
spotLight.position.set( 180, 160, 0 );
var grid = new THREE.GridHelper(400, 40);
grid.position.y = -20;
scene.add(grid);
scene.add(spotLight);
camera.lookAt( scene.position );
var material = new THREE.MeshPhongMaterial( {
color: 0xaaaa00,
emissive: 0xaa0000,
specular: 0xaa00aa,
shininess: 10,
side: THREE.DoubleSide,
shading: THREE.SmoothShading,
opacity: .8, transparent: true } );
var size = 16.0;
var sphereGeo = new THREE.SphereGeometry( size, 32, 16 );
var mesh = new THREE.Mesh( sphereGeo, material);
scene.add(mesh);
var mesh = new THREE.Mesh( sphereGeo, material);
mesh.position.y = 40;
scene.add(mesh);
var mesh = new THREE.Mesh( sphereGeo, material);
mesh.position.x = 60;
scene.add(mesh);
// RENDERER
webglRenderer = new THREE.WebGLRenderer();
webglRenderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
webglRenderer.domElement.style.position = "relative";
container.appendChild(webglRenderer.domElement);
animate();
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
webglRenderer.render(scene, camera);
}

Remove the attribute side: THREE.DoubleSide. Since you are drawing spheres, you don't need it.

Related

Black screen appears while loading an image texture with Three.js

The black screen happens within this script:
var renderer;
var scene;
var camera;
var mesh;
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.getElementById('container').appendChild(renderer.domElement);
//Scene init
scene = new THREE.Scene();
//Camera init
camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.set(0, 0, 1000);
scene.add(camera);
var geometry = new THREE.PlaneGeometry( 500, 500, 10, 10 );
var texture = new THREE.TextureLoader().load( './annie-spratt-kG-ZwDuQ8ME-unsplash.jpg' );
var material = new THREE.MeshBasicMaterial( { map: texture } );
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
renderer.render(scene, camera,mesh);
I'm doing this explicitly but the black screen comes up and the image does not load. How do I solve this problem?
You render your scene before the texture has been loaded. Try it with this approach:
const renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize(window.innerWidth, window.innerHeight);
document.getElementById('container').appendChild(renderer.domElement);
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.set(0, 0, 1000);
scene.add(camera);
const geometry = new THREE.PlaneGeometry(500, 500);
const texture = new THREE.TextureLoader().load('https://threejs.org/examples/textures/uv_grid_opengl.jpg', render);
const material = new THREE.MeshBasicMaterial({
map: texture
});
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
function render() {
renderer.render(scene, camera);
}
body {
margin: 0;
}
<script src="https://cdn.jsdelivr.net/npm/three#0.131.3/build/three.min.js"></script>
<div id="container">
</div>

Three.js PlaneBufferGeometry not rendering

I'm not able to render a planeBufferGeometry. Not sure what Im doing wrong. This is my first attempt with BufferGeometry. This works fine if I replace the code with a Geometry.Sphere or any other Geometry object.
var geometry = new THREE.PlaneBufferGeometry( 5, 20, 32 );
var material = new THREE.MeshBasicMaterial( {color: 0xCC0000, side: THREE.DoubleSide} );
var plane = new THREE.Mesh( geometry, material );
scene.add(plane);
function update () {
// Draw!
renderer.render(scene, camera);
// Schedule the next frame.
requestAnimationFrame(update);
}
// Schedule the first frame.
requestAnimationFrame(update);
CAmera Position
const WIDTH = window.innerWidth;
const HEIGHT = window.innerHeight;
// Set some camera attributes.
const VIEW_ANGLE = 45;
const ASPECT = WIDTH / HEIGHT;
const NEAR = 0.1;
const FAR = 10000;
// Get the DOM element to attach to
const container =
document.querySelector('#container');
// Create a WebGL renderer, camera
// and a scene
const renderer = new THREE.WebGLRenderer();
const camera =
new THREE.PerspectiveCamera(
VIEW_ANGLE,
ASPECT,
NEAR,
FAR
);
const scene = new THREE.Scene();
Thanks
Just an example with your code of instancing the buffer plane:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(0, 0, 10); // set the position of the camera
var renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var controls = new THREE.OrbitControls(camera, renderer.domElement);
var geometry = new THREE.PlaneBufferGeometry(5, 20, 32, 32);
var material = new THREE.MeshBasicMaterial({
color: 0xCC0000,
side: THREE.DoubleSide
});
var plane = new THREE.Mesh(geometry, material);
scene.add(plane);
render();
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
}
body {
overflow: hidden;
margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/91/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

Three js - moving rotation axis

Using threejs I created a simple cylinder object and rotating it in z-axis. The object rotates around the center axis, both the ends of the cylinder rotate around the axis which is at the center of the cylinder.
How can I make it rotate in a different axis? I would like the cylinder to rotate by having one end in a fixed point while the other end goes around in circles. My code is below.
init();
function init() {
renderer = new THREE.WebGLRenderer({ canvas: document.getElementById('myCanvas'), antialias: true });
renderer.setClearColor(0xeaebed);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
camera = new THREE.PerspectiveCamera(5, window.innerWidth / window.innerHeight, 0.1, 4000);
scene = new THREE.Scene();
//LIGHTS
var light = new THREE.AmbientLight(0xffffff, 1);
scene.add(light);
var light1 = new THREE.PointLight(0xffffff, 0.3);
scene.add(light1);
//Gun holder
var gunHolder = new THREE.Object3D();
var gunHolderColour = 0x0f4207;
var gunHolderBaseCylinderGeometry = new THREE.CylinderGeometry(10, 10, 50, 32);
var gunHolderBaseCylinderMaterial = new THREE.MeshStandardMaterial({
color: gunHolderColour,
metalness: 0.5,
roughness: 0.5
});
var gunHolderBaseCylinderMesh = new THREE.Mesh(gunHolderBaseCylinderGeometry, gunHolderBaseCylinderMaterial);
gunHolderBaseCylinderMesh.position.set(0, -8, -3000);
scene.add(gunHolderBaseCylinderMesh);
requestAnimationFrame(render);
function render() {
gunHolderBaseCylinderMesh.rotation.z += 0.01;
renderer.render(scene, camera);
requestAnimationFrame(render);
}
}
You can use .translate() method of your geometry:
var gunHolderBaseCylinderGeometry = new THREE.CylinderGeometry(10, 10, 50, 32); // height is 50
gunHolderBaseCylinderGeometry.translate(0, 25, 0); // move upwards at half of height, 25
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setClearColor(0xeaebed);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(5, window.innerWidth / window.innerHeight, 0.1, 4000);
scene = new THREE.Scene();
//LIGHTS
var light = new THREE.AmbientLight(0xffffff, 1);
scene.add(light);
var light1 = new THREE.PointLight(0xffffff, 0.3);
scene.add(light1);
//Gun holder
var gunHolder = new THREE.Object3D();
var gunHolderColour = 0x0f4207;
var gunHolderBaseCylinderGeometry = new THREE.CylinderGeometry(10, 10, 50, 32);
gunHolderBaseCylinderGeometry.translate(0, 25, 0);
var gunHolderBaseCylinderMaterial = new THREE.MeshStandardMaterial({
color: gunHolderColour,
metalness: 0.5,
roughness: 0.5
});
var gunHolderBaseCylinderMesh = new THREE.Mesh(gunHolderBaseCylinderGeometry, gunHolderBaseCylinderMaterial);
gunHolderBaseCylinderMesh.position.set(0, -8, -3000);
scene.add(gunHolderBaseCylinderMesh);
requestAnimationFrame(render);
function render() {
requestAnimationFrame(render);
gunHolderBaseCylinderMesh.rotation.z += 0.01;
renderer.render(scene, camera);
}
body {
overflow: hidden;
margin: 0;
}
<script src="https://threejs.org/build/three.js"></script>

Three.js self transparency, object should not be see through

Codepen demonstrating the problem
https://codepen.io/anon/pen/GjJpYw?editors=0010
I have 2 meshes, one which contains 2 cubes, and the other which is 1 cube. The mesh with 2 cubes sandwiches the mesh with one cube (so the single cube is in the center). When I set all cubes to transparent but set the opacity of the center cube to 1, I would not expect to be able to see the back cube when looking through the front cube but I can.
I was wondering is there any easy way to fix this? This is a very simplified version of the problem I'm facing so I can't easily split the geometries. I also cannot just set transparent to false since ideally I would like to be able to have the middle cube partially transparent as well. Any suggestions?
var width = window.innerWidth;
var height = window.innerHeight;
var renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(width, height);
document.body.appendChild(renderer.domElement);
var scene = new THREE.Scene();
var cubeGeometry = new THREE.CubeGeometry(100, 100, 100);
var cube = new THREE.Mesh(cubeGeometry);
cube.position.set(0, 25, -200);
var cube2 = new THREE.Mesh(cubeGeometry);
cube2.position.set(0, -25, 200);
cube.updateMatrix();
cube2.updateMatrix();
var singleGeometry = new THREE.Geometry();
singleGeometry.merge(cube.geometry, cube.matrix);
singleGeometry.merge(cube2.geometry, cube2.matrix);
var combinedMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000, opacity: 0.5, transparent: true});
var mesh = new THREE.Mesh(singleGeometry, combinedMaterial);
var cubeGeometry = new THREE.CubeGeometry(200, 200, 200);
var cubeMaterial = new THREE.MeshBasicMaterial({ color: 0x0000ff, opacity: 0.8, transparent: true});
var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
scene.add(cube);
scene.add(mesh);
var camera = new THREE.PerspectiveCamera(60, width / height, 1, 1000);
camera.position.z = 500;
var controls = new THREE.OrbitControls(camera);
controls.addEventListener('change', render);
var pointLight = new THREE.PointLight(0xffffff);
pointLight.position.set(0, 300, 200);
scene.add(pointLight);
render();
animate();
function animate() {
requestAnimationFrame( animate );
controls.update();
}
function render() {
renderer.render( scene, camera );
}

THREE.js Texture is not visible with SVGRenderer

We've tried the next code:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 0.0001, 999);
camera.position.set( 0, 0, 3 );
scene.add( camera );
var material = new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: true } );
var image = $('#tmp')[0]
var texture = new THREE.Texture(image);
texture.needsUpdate = true;
var img_material = new THREE.MeshBasicMaterial({color: 0x000000, map: texture });
var plane_geometry = new THREE.PlaneGeometry(2, 2);
var imageMesh = new THREE.Mesh(plane_geometry, img_material);
imageMesh.doubleSided = true;
scene.add(imageMesh);
renderer = new THREE.CanvasRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
$('#container').append( renderer.domElement );
renderer.render(scene, camera);
but when we switched to:
renderer = new THREE.SVGRenderer();
it stop rendering texture over image geometry. Can anybody say why so?
THREE.SVGRenderer doesn't support textures.

Resources