transparent material rendering artifacts - three.js

I have a 3d surface which I would like to make it transparent so the map under it is visible.
The problem is that some face hidden are rendered not making the transparency constant (highlighted). Is possible to render the yellow/green of the right image transparent without these artefacts?

Folling #WestLangley comment I was able to fix the issue rendering twice:
once colorWrite = false and then colorWrite = true . The simplest way I found is with a MultiMaterialObject.
let material = new THREE.MeshPhongMaterial(
{ color: 0xffffff88,
side: THREE.DoubleSide,
opacity: 0.4,
transparent: true,
colorWrite : false,
vertexColors: THREE.VertexColors,
shininess: 60
} )
let material_cw = material.clone()
material_cw.colorWrite = true
let mesh = THREE.SceneUtils.createMultiMaterialObject(
geometry,[material,material_cw] )

Related

Converting from CanvasRenderer to WebGLRenderer

I was using CanvasRenderer in my scenes to render a brain with neurons.
The problem is that when I draw the neurons (every neuron consists of many many lines) the scene is really slow because I render a lot of neurons. So I switched into WebGLRenderer and it is much faster and smoother, but the scene looked completely different! No opacity is applied any more which made the neurons hidden inside the brain
Here is a comparison between the two scenes:
CanvasRenderer:
The brain has some transparency, and there is a green sphere represents a region of interest (ROI) also has transparency.
WebGLRenderer:
The transparency has completely gone!
I am using the following materials for the brain model and the ROI model:
var brain_material = new THREE.MeshPhongMaterial({
wireframe: false,
color: 0xaaaaaa,
specular: 0xcccccc,
opacity: 0.4
});
var roi_material = new THREE.MeshBasicMaterial({
color: selected_roi_color,
opacity: 0.2,
visible: true
})
and here is my renderer:
renderer = new THREE.WebGLRenderer({alpha:true});
renderer.setClearColor(renderer_clear_color);
renderer.setPixelRatio(viewport_width / viewport_height);
renderer.setSize(viewport_width, viewport_height);
renderer.sortObjects = false;
container.appendChild(renderer.domElement);
How can I get a similar result to the CanvasRenderer using the WebGLRenderer?
Thank you very much
If you use opacity, then you have to use it with transparent:
var brain_material = new THREE.MeshPhongMaterial({
wireframe: false,
color: 0xaaaaaa,
specular: 0xcccccc,
transparent: true, // here
opacity: 0.4
});
var roi_material = new THREE.MeshBasicMaterial({
color: selected_roi_color,
transparent: true, // here
opacity: 0.2,
visible: true
})

Three.js - transparent planes hiding sprites

When we add text-spites on scene, we saw that our transparent planes hide sprites, but didn't hide any 3d Objects.
Why is this and how to make sprites visible under transparent planes?
To look PNG example click here
My plane is:
// transparent plane
geometry = new THREE.PlaneGeometry(200, 200, 200);
material = new THREE.MeshBasicMaterial({
color: 0xa6cfe2,
side: THREE.DoubleSide,
transparent: true,
opacity: 0.5,
depthFunc: THREE.LessDepth,
});
But it seems no work good.
So, for that examle i wrote some code on fiddle, to figure out the problem:
look fidddle example
three.js renders opaque objects first, then transparent objects.
You can use this pattern to prevent your transparent objects from writing to the depth buffer:
// transparent plane
geometry = new THREE.PlaneBufferGeometry( 200, 200, 1, 1 );
material = new THREE.MeshBasicMaterial( {
color: 0xa6cfe2,
side: THREE.DoubleSide,
transparent: true,
opacity: 0.5,
depthWrite: false
} );
three.js r.112

ThreeJS remove texture

I have a ThreeJS scene and I'd like to provide the option of seeing all models in different modes (with or without textures and/or wireframe).
I'm trying to accomplish this using only one Geometry and one Material for each object.
When I try to remove the texture of an object by setting the map property of its material to null something bizarre happens. The object takes the latest loaded texture, even if it was loaded and applied to another object. Is this somehow an expected behavior? If not, how should I remove the map?
a good approach would be to initialize the materials you will need from the beginning :
var materials = {};
materials['lambert'] = new THREE.MeshLambertMaterial( { color: 0xdddddd, shading: THREE.SmoothShading } );
materials['phong'] = new THREE.MeshPhongMaterial( { color: 0xFF0000, specular: 0x009900, shininess: 30, shading: THREE.FlatShading } );
materials['basic'] = new THREE.MeshBasicMaterial( { color: 0xffaa00, transparent: true, blending: THREE.AdditiveBlending } );
materials['wireframe'] = new THREE.MeshBasicMaterial( { color: 0xffffff, wireframe : true } );
and replace the material of your object when you need to :
function changeMaterial(id){
mesh.material = materials[id];
}
changeMaterial('wireframe');
I did a fiddle that demonstrates that : http://jsfiddle.net/95t964o0/75/
I did not use a material with a texture because it's a bit tricky for jsfiddle.com to load an image.
Note : be carefull when many objects share the same material! If you make changes to the material of an object it affects all the others (obviously because it is shared).

Mesh materials are not visible through a transparent background of the sprite

I have a scene with a mesh (MeshPhongMaterial), box helper around this mesh, green spherical point markers (MeshLambertMaterial) and sprites (png images of "pins" with transparent backgrounds). And I am running into this issue:
http://imgur.com/nDQ3VRk
http://imgur.com/53NJhpK
Both my green markers and box helper lines are visible through the transparent background of my "pin" sprite, but my main mesh material isn't. In fact in the second image above the green marker that is visible through the png background is inside of the bronze mesh object and would not be visible otherwise.
Here are my materials:
1) Main mesh material JSON:
'Bronze': {
emissive: '#000000',
color: "#cd7f32",
specular: 0x83776B,
shininess: 100,
reflectivity: 1,
shading: THREE.SmoothShading,
metal: true,
envMap: textureEquirec, // our own hdri reflection image
transparent:true,
depthTest: true
}
2) Material for the green marker:
THREE.MeshLambertMaterial({ color: 0x00ff00 })
3) Material for the box helper:
THREE.LineBasicMaterial({ color: 0xdddddd })
4) Material/texture for the Sprite:
var textures = {
...
selectedPin: 'images/sprites/selected.png'
};
this.selectedPinTexture = THREE.ImageUtils.loadTexture( textures.selectedPin);
this.selectedPinMaterial = new THREE.SpriteMaterial( { map: this.selectedPinTexture } );
Please advise,
Thank you,
Anton.
If your pin sprite is drawing before the mesh, and writing depth (depthWrite:true) then the mesh will not appear.
Set .renderOrder of the sprite to always draw after the mesh if you want it to be transparent the mesh to be visible through it.
Add an alphaTest to you material like 0.5. For an explanation look at http://threejs.org/docs/#Reference/Materials/Material

Transparent texture in pointCloudMaterial and depth-buffer

I use threejs to add a pointCloud to the screen , and set texture map, But I find that the top point can cover the one behind it.
after I add AdditiveBlending , It's much better, but still have some problem.
Because I have another objects so I can't add depthTest:false , how can I solve this problem?
below is the code and the texture
var geometryBig = new THREE.Geometry();
var meshBig = new THREE.PointCloud(geometryBig, new THREE.PointCloudMaterial({
size: 4,
color: 0xFFFFFF,
transparent: true,
blending: THREE.AdditiveBlending,
// depthTest: false,
transparent: true,
sizeAttenuation: true,
map: THREE.ImageUtils.loadTexture(
"img/particle.png"
),
}));
Add to your PointCloudMaterial:
depthWrite: false

Resources