Improving the visual appearance of an obj / stl in a scene with a base, lighting and shadows

Hi all,

I’m struggling a little with this one. Basically I am trying to get this obj file Simple.obj (115 Bytes) to look like what I have in the following picture. There is no .mtl files associated with the files I am looking at

I have tried using all sort of lighting (point , directional etc…) and different materials but they all look terrible. Reading up on this I believe it’s do with a mixture of things that I am doing wrong. so here are my questions

  • Normals information in the obj. How do I check if there is this is present or not and what is the correct way to create these if there are not. I’m assuming without this no directional lighting will work and materials will not look right??
  • What material should I use to get the effect ? If I wanted it to be more metallic looking what would I do?
  • How do I get a bottom grid similar to what is in the picture. Is there something built in to threejs or do I need to load my own image?
  • Should my light source position be coming from the same position as the camera?
  • I also need to load stl files. Does it work in the same way with regards normals?

Thanks in advance

  1. Object is black even when you add a light to the scene = normals are broken or not there. Otherwise, normals are there (if lights look weird on the model, you can open the model in Blender, enter edit mode -> ctrl + a -> press space / f3 -> search for Recalculate normals -> press enter.)
  1. To get the effect from the screenshot you can use MeshStandardMaterial with roughness set to .75 and metalness to .1. To get more metallic effect just increase metalness.

  2. GridHelper should help (be sure to use antialiasing + correct pixel ratio in the renderer, otherwise it may look bad.)

  3. On the screenshot light source is above the camera. Placing it on the exactly same spot as camera can, in some cases, make shadows invisible (since shadow camera will be equivalent to the view camera.)

  4. All normals work the same - normal vector is a math representation of plane direction, not a three-specific thing.

Thanks for the prompt response - very helpful

You are correct - the object is showing as black so I presume the normals are broken. Is there a way to recalculate them programmatically inside threejs without having to use Blender?

  1. Make sure there’s a light on the scene - adding an ambient light (with default parameters) will show you if it’s really normals that causes the issue.
  2. You can try using BufferGeometry.computeVertexNormals, but it’s best to do it using Blender. Geometry with messed normals should just be treated as invalid and be fixed before using in an app - recalculating and fixing normals for complex models on the go can take a lot of time and still cause issues.

Thanks I’ll mark this as a solution and open it up again if I run into problems

Ok - So I installed blender and imported the obj file. without doing anything it looks pretty good in blender so I’m assuming it has normals . see this image

This is my code in threejs. (I pass the contents of the obj file as this.objtext)

var loader = new OBJLoader2();   
loader.setLogging(true, true);     
loader.setUseIndices(true);
loader.setDisregardNormals(false);
this.object = loader.parse(this.objtext);

this.dirLight = new THREE.DirectionalLight( 0xffffff, 1 );
this.dirLight.position.set( -1, 0.75, 1 );

this.dirLight.name = "dirlight";
this.dirLight.castShadow = true;

this.scene.add( this.dirLight );

var material = new THREE.MeshStandardMaterial( {
  color: 0Xcae1ff,
  
  metalness: 0.1,   // between 0 and 1
  roughness: 0.75, // between 0 and 1           

} );

this.object.traverse( function ( child ) {

  if ( child instanceof THREE.Mesh ) {

      child.material = material;

  }

} );

this.scene.add(this.object);

The object still looks terrible. Any ideas what I am doing wrong? Am I loading in the material incorrectly?

Can you share a screenshot of what you mean by “terrible”, it’s a bit ambiguous ?

Yes, but normals can be flipped, which causes the geometry to look quite abstract. See this video (at 0:43) - toggle Face Orientation in Blender and make sure the entire model is blue.

Great little video - it’s all coming as blue in blender which is good I believe?

Here is what I am getting with my code. Looks like it’s shading the inside but not the outside

  1. Can you please share the model? It may be easier to test what’s going on.
  2. It’s always a good idea to test models in an online model viewer - either creators3D (for all types of models) or glTFViewer (for gltf / glb.) You’ll then see if it’s the model that is causing the issue.

I had attached the obj in the first post ( simple.obj). I’ve played around with it since my last post and it looks like it’s how I am lighting it is the problem as I’m getting better results now. Just not exactly sure how to get it more like the desired image I want it to be in the first post

I am using a DirectionalLight and it looks ok on certain views but I’m not sure if this is the best choice for what I am trying to achieve. I am assuming I’ll have to add more Directional lights if I want to use something like Orbitcontrols with it, as there will be no light on the opposite side of the view if the camera moves around to that side when using Orbitcontrols. Does adding more directional lights start creating it’s own problems with regards enabling shadowing in the scene etc.?

Is there a better way to approach lighting a scene in general? It seems very much try it and refine type approach. Maybe that’s just the way it is and experience is everything or possibly there is a more mathematical type approach??