Three.js - Can I force a shape to be visible, even if it's occluded? - three.js

I have a set of objects that I'd like to always be visible, even if they're occluded by another object. They objects are meshes, not particles or sprites. Here's a screenshot of the effect I'm trying to mimic. This was done in C++ and OpenGL:
Notice the red and green triangles as well as the black lines (and the text, for that matter). They all lie on the ground plane, but they're visible even though the green machine is closer.
Can I force visbility with Three.js?

you can accomplish this by disabling the depth test of the material. this means its always rendered in front of everything.
var material = new THREE.MeshBasicMaterial({color: 0xFF0000});
material.depthTest = false;
var mesh = new THREE.Mesh(new THREE.BoxGeometry(5, 5), material);

Related

Black sphere within skybox sphere forms when I try using a giant sphere to create a skybox in threejs

I'm trying to make a spherical skybox since I think that would best fit the space scene I'm making. I'm running across two issues:
I can get the skybox to work, but for some reason a sphere within my giant sphere I've made appears. I don't think its a real Object3D sphere, I have the feeling its a graphical glitch of some sort.
If I make the sphere too big (Like 1800 for the radius) it just disappears and stops working. If I set it's side to THREE.DoubleSide, I can zoom out of the scene and still see its outer side of the sphere, but inside, regardless of DoubleSide or BackSide, its invisible when 1800 or bigger
let skyboxGeom = new SphereGeometry(900, 128, 128)
let skyboxMat = new THREE.MeshPhongMaterial({map: spaceTexture});
skyboxMat.side = THREE.BackSide
let skybox = new THREE.Mesh(skyboxGeom, skyboxMat);
skybox.position.set(0,0,0)
mainScene.add(skybox)
Here is a picture of what it looks like:
The colorful ball is correct, the inner black sphere is what appears incorrectly. If I zoom in enough to the scene, the black ball shrinks and gets smaller and smaller until it disappears entirely, but I would have to zoom way too far into my scene that none of my things would show if I tried to do this to make the black ball go away
If it helps, I am using a PerspectiveCamera, and am exploring the scene using OrbitControls

How can I prevent certain instances of a instance geometry from disappearing when center position no longer in view?

I'm learning webgl, threejs and glsl shaders. The scene you see below is my attempt at working with instanced geometry. I have 3 patches of "grass". The grass is actually made of instanced cones around the central position of the mesh I'm building.
As you can see, if the central position (marked with a white wireframe cone) of the mesh is no longer in the camera view, all instances disappear.
How can I prevent this?
And to be even more specific: Are all the grass patches, or all fire instances, or all particles of the same time supposed to be instanced at once and place around the scene how we see fit? My assumption is that they should. Right?
If you are using InstancedBufferGeometry, there are two ways you can deal with frustum culling.
One way is to turn frustum culling off for the mesh:
mesh.frustumCulled = false;
The other option is to set the bounding sphere of the mesh's geometry manually, if it is known in your case:
geometry.boundingSphere = new THREE.Sphere( new THREE.Vector3(), radius );
three.js r.88

Three.js / BufferGeometry how to use mesh & line material

I'm using BufferGeometry to draw triangles.
I can use a mesh geometry, specifiyng 3 index-attribute for every triangle. I'm using a basic material without wireframe. I suposse I'll can use raycast.
Also I have seen the linesegments approach for wireframe. Interesting.
Ok, my problem... I'd like to see my triangles as a wireframe and also I need raycast. So .... the solution is to create my own shader, isn't it ?
Thanks
you dont have to create a custom shader you can have a mesh with wireframe material, and the ray should still "hit" the object
var mesh = new THREE.Mesh(geometry,new THREE.MeshBasicMaterial({wireframe : true}));
if it for some reason does not hit or you want to LineSegments object you can keep track of all transformations that affected the object, and apply them onto a mesh you wont add to scene
var segmentObject = new THREE.LineSegments(geometry,lineMaterial);
scene.add(segmentObject);
var meshNotInScene = new THREE.Mesh(geometry,dummyMaterial);
and you will use the mesh object to determine if raycast hit the object
this way you can have a different hitbox for an object for example if you have a flying donut by pairing it with a circle mesh you can select it even if you click in its hole etc...
keep in mind that materials have sides and if you dont care about which side is which set "side" to THREE.DoubleSide

THREE.ShaderMaterial is seen inverted by the shadow Camera

I have a mesh that i am loading from 3d studio max into three.js. I modified three.js to hold another typed array for the binormal data. It all seems to be working fine and dandy until shadows are involved. For some reason, the shadow map is wrong, and it seems as if its rendering the mesh with faces flipped.
In this example, the shadows are showing up correctly on the floor, because the renderer has
.shadowMapCullFace = THREE.CullFaceBack
http://dusanbosnjak.com/test/webGL/new/StojadinCeo/stojadinCeo.html
I can get other shadows to show up on my shader, but self shadowing leads to horrible artifacts, and the shadow that my mesh casts on other meshes is always inverted.
I've tried reversing the order in which the face indecis come in, (acb instead of abc), which flips the faces. This creates proper shadow cast, but the mesh shows flipped.
What im thinking of doing at the moment is exporting a flipped mesh, and reversing the cull order in the shaderMaterial, but it would be wonderful to find out why this is happening.
I basically connected the phong and shadow mapping shader chunks with what i've had.
edit
Here is an updated scene with some shadow casters and receive shadows on imported meshes
http://dusanbosnjak.com/test/webGL/new/StojadinCeo/stojadinCeo2.html
light = new THREE.SpotLight(0xaaaaaa);
light.position.set(10,10,10);
light.shadowCameraVisible = true;
light.shadowDarkness = .5;
light.castShadow = true;
light.shadowCameraNear = 1;
light.shadowCameraFar = 250;
light.shadowCameraFov = 57;
light.shadowMapWidth = 2048;
light.shadowMapHeight = 2048;
scene.add(light);
the rest of the meshes just have receiveShadow and castShadow set to true
The shadow shows on the shaderMaterial (i copied the shadowfrag chunk)
THREE.Mesh() with THREE.CubeGeometry() both casts shadows and receives shadows properly, but the shadow cast by the shaderMaterial mesh is inverted.
I can't really isolate this to 50 lines of code as it's a whole import/export process from max.
I don't understand why would the shadow camera render this one particular mesh inverted, while the normal camera renders it correctly, if that is what is happening?
You can zoom out and move the car using wasd
Unless you changed the default settings in three.js, only back-faces cast shadows. A work-around is to set:
renderer.shadowMapCullFace = THREE.CullFaceBack;
or
renderer.shadowMapCullFace = THREE.CullFaceNone;
But these options can lead to other issues.
The best approach is to make sure every mesh has depth. Avoid planes, like the car roof.
For example, you can add an interior liner to the car roof to give it depth.
Shadow mapping in WebGL can be tricky, so read all you can about it so you will be familiar with the issues involved.
three.js r.66

background occlusion

I'm trying to render 2 scenes. The first scene is just a 2D background plane. In the second scene i have set to objects. The first objects (a head) material-opacity is set to 1. I thought this was an easy and fast way to calculate the occlusion for the second object (sunglasses) in the scene. In fact that work exactly like I wanted, but now the head is also occluding the background even though he should be transparent. ( I cleared the depth buffer before rendering the second scene and set renderer.autoClear = false )
renderer.autoClear = false;
var headMaterial = new THREE.MeshBasicMaterial({ color: 0x000000, opacity: 1 });
...
//Renderloop
renderer.clear();
renderer.render( background, camera );
renderer.clear(false,true,false);
renderer.render( scene, camera);
Is there a compelling reason for rendering two scenes, rather than just one scene that contains all objects? They share the same camera, no?
Try rendering the head and sunglasses first. Mask the sunglasses with a stencil. Then render the background with a stencil test (but not depth test). You'll render fewer background pixels, resulting in a bit faster overall render.
If by saying "background" you mean a scene with only plane that has some texture on in - why don't you set your background as html background? That was you won't have to calculate your plane's right position to fill all thre screen area.
Now, for transparency issue - here is some example for you: http://jsfiddle.net/ajJmx/1/
See how you've got your front cube side set to semi-transparent and you can see othe sides of cube. And if you turn cube 45deg - you'll see that even though there is some other object on the background - your solid cube sides stay solid.
What you basically want to do is to set transparent:true, opacity:0.6 to your sunglasses material. That's it! You could also play around with material blendings and try to set blending:THREE.AdditiveBlending depending on you sunglasses type.

Resources