Chrome 16 and flickering faces with ThreeJS / WebGL

1,308 views
Skip to first unread message

Shell Bryson

unread,
Dec 16, 2011, 11:48:19 AM12/16/11
to WebGL Dev List
I've noticed that Chrome 16 has some display issue with 'nested'
objects in scenes when creating scenes via ThreeJS. Simply, when an
object contains another, if any of those objects have surfaces with
transparency at least one of those faces will flicker horribly when
the scene is animated. FireFox 8 doesn't exhibit this issue. Has
anyone else come across it, or suggest an work-around?

var container, stats;
var camera, scene, renderer;
var cube, sphere;

var targetRotationX = 10;
var targetRotationY = 10;
var targetRotationZ = 10;
var targetRotationOnMouseDown = 0;

var mouseX = 0;
var mouseXOnMouseDown = 10;

var mouseY = 0;
var mouseYOnMouseDown = 10;

var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;

var cube = [];
var cubeCount = 3;
var cubeSize = 350;


$(function() {
init();
animate();
})

function init() {

container = document.createElement( 'div' );
document.body.appendChild( container );

scene = new THREE.Scene();

camera = new THREE.PerspectiveCamera( 70, window.innerWidth /
window.innerHeight, 1, 1000 );
camera.position.y = 150;
camera.position.z = 500;
scene.add( camera );

// LIGHT IN FRONT
var light = new THREE.PointLight( 0xffffff, 2.0 );
light.position.set( 0, 500, 1000 );
light.castShadow = false;
scene.add( light );

var materials = []
for ( var i = 0; i < 6; i ++ ) {
materials.push( new THREE.MeshPhongMaterial( {
color: 0x9CDB79,
opacity: 0.5
} ) );
}

for ( var i = 0; i < cubeCount; i ++ ) {
cube[i] = new THREE.Mesh( new THREE.CubeGeometry( cubeSize,
cubeSize, cubeSize, 1, 1, 1, materials ), new
THREE.MeshFaceMaterial() );
cube[i].position.x = 0;
cube[i].position.y = 150;
cube[i].position.z = 0;
cube[i].rotation.x = 5;
cube[i].rotation.y = 5;
cube[i].rotation.z = 5;
cube[i].doubleSided = true;
cube[i].flipSided = true;
cube[i].overdraw = true;
cube[i].dynamic = true;
cube[i].scale.x = 0.01;
cube[i].scale.y = 0.01;
cube[i].scale.z = 0.01;
cubeSize -= (cubeSize * 0.40);
scene.add( cube[i] );
}

var sphereMaterial = new THREE.MeshLambertMaterial( {
color: 0xDE0005
});

var radius = 30, segments = 16, rings = 16;
sphere = new THREE.Mesh( new THREE.SphereGeometry(radius,
segments, rings), sphereMaterial);

sphere.position.x = 0;
sphere.position.y = 150;
sphere.position.z = 0;
sphere.scale.x = 0.2;
sphere.scale.y = 0.2;

scene.add( sphere );

renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize( window.innerWidth, window.innerHeight );

container.appendChild( renderer.domElement );

stats = new Stats();
$("#stats").append( stats.domElement )

document.addEventListener( 'mousedown', onDocumentMouseDown,
false );
}

function onDocumentMouseDown( event ) {
event.preventDefault();
document.addEventListener( 'mousemove', onDocumentMouseMove,
false );
document.addEventListener( 'mouseup', onDocumentMouseUp, false );
document.addEventListener( 'mouseout', onDocumentMouseOut,
false );
mouseXOnMouseDown = event.clientX - windowHalfX;
mouseYOnMouseDown = event.clientY - windowHalfY;
targetRotationOnMouseDown = 5;
}
function onDocumentMouseMove( event ) {
mouseX = event.clientX - windowHalfX;
targetRotationY = targetRotationOnMouseDown + ( mouseX -
mouseXOnMouseDown ) * 0.02;
mouseY = event.clientY - windowHalfY;
targetRotationX = targetRotationOnMouseDown + ( mouseY -
mouseYOnMouseDown ) * 0.02;
}
function onDocumentMouseUp( event ) {
document.removeEventListener( 'mousemove', onDocumentMouseMove,
false );
document.removeEventListener( 'mouseup', onDocumentMouseUp,
false );
document.removeEventListener( 'mouseout', onDocumentMouseOut,
false );
}
function onDocumentMouseOut( event ) {
document.removeEventListener( 'mousemove', onDocumentMouseMove,
false );
document.removeEventListener( 'mouseup', onDocumentMouseUp,
false );
document.removeEventListener( 'mouseout', onDocumentMouseOut,
false );
}
function animate() {
requestAnimationFrame( animate );
render();
stats.update();
}
function render() {
if (sphere.scale.x < 1) {
sphere.scale.x += 0.03;
sphere.scale.y += 0.03;
}
if (sphere.scale.x > 0.5) {
for ( var i = 0; i < cubeCount; i ++ ) {
if (cube[i].scale.x < 1) {
cube[i].scale.x += 0.01;
cube[i].scale.y += 0.01;
cube[i].scale.z += 0.01;
}
cube[i].rotation.x += ( targetRotationX -
cube[i].rotation.x ) * (0.05 - (0.01 * i));
cube[i].rotation.y += ( targetRotationY -
cube[i].rotation.y ) * (0.05 - (0.01 * i));
}
}
renderer.render( scene, camera );
}


Gregg Tavares (wrk)

unread,
Dec 16, 2011, 3:03:04 PM12/16/11
to webgl-d...@googlegroups.com
Can you post a URL to a webpage with this code working? 

Shell Bryson

unread,
Dec 19, 2011, 7:01:58 AM12/19/11
to WebGL Dev List
Hi,

Sorry it took the weekend before I could post a reply. Had to double
check that I was allowed to post day-job 'working' examples first.

Here's a demo that exhibits the issue. Rendering is fine in the latest
non-beta FireFox (sans anti-aliasing, sadly), but Chrome 16 has a
fit... (be warned, flashing images...)

http://www.shellbryson.com/demos/ux/demo_three_cube_nested.php

JS code source is here:

http://www.shellbryson.com/demos/ux/libs/demos/demo_three_cube_nested.js

S.

Benoit Jacob

unread,
Dec 19, 2011, 7:50:46 AM12/19/11
to webgl-d...@googlegroups.com
2011/12/19 Shell Bryson <sh...@shellbryson.com>:

> Rendering is fine in the latest
> non-beta FireFox (sans anti-aliasing, sadly),

FYI, Antialiasing is coming in Firefox 10.

Benoit

Shell Bryson

unread,
Dec 19, 2011, 10:02:48 AM12/19/11
to WebGL Dev List
Managed to fix the issue. It appears to be something to do with the
way I was applying materials to my cube.

Previously I was using:

var materials = []
for ( var i = 0; i < 6; i ++ ) {
materials.push( new THREE.MeshPhongMaterial( {
color: 0x9CDB79,
opacity: 0.5
} ) );
}

cube[i] = new THREE.Mesh( new THREE.CubeGeometry( cubeSize,
cubeSize, cubeSize, 1, 1, 1, materials ), new
THREE.MeshFaceMaterial() );

...to define an array containing materials for each face of my cube.
Changing this to:


cubeGeo = new THREE.CubeGeometry( cubeSize, cubeSize, cubeSize );
cube[i] = new THREE.Mesh( cubeGeo, new
THREE.MeshLambertMaterial({ color: 0x9CDB79, opacity: 0.5 }) );

has fixed the flickering in Chrome. Also it enabled me to test out
'picking' (clicking the scene causes the outer cube to become white).

Working version: http://www.shellbryson.com/demos/ux/demo_three_cube_nested_fixed.php

Shell

On Dec 16, 8:03 pm, "Gregg Tavares (wrk)" <g...@google.com> wrote:

Reply all
Reply to author
Forward
0 new messages