1

I am trying to apply a THREE.MeshLambertMaterial to a model in the Autodesk Forge Viewer. The viewer3D.js version is 7.87.0. As soon as I call fragList.setMaterial(fragId, lambertMaterial), the model disappears and the following console warning appears:

GL_INVALID_OPERATION: Active draw buffers with missing fragment shader outputs.

Using THREE.MeshBasicMaterial works without errors, but I want to take advantage of the Lambert material's shading ability. Ideally I would use THREE.MeshPhongMaterial, but it appears that the Forge Viewer uses a modified version of THREE.MeshPhongMaterial, so the effects that normally work well with Phong no longer work anymore (e.g. material.envMap does not behave like it does with a normal THREE material, and the material.combine property that effects envMap blending cannot be changed).

I have created a Github repository and test page to demonstrate this issue.

Repository: https://github.com/throw-away-97743/ForgeViewerTests

Live Demo: https://throw-away-97743.github.io/ForgeViewerTests/basic-lambert-test.html

Relevant JavaScript code:

// please refer to the live demo and repository
// for a more interactive example
const fragList = model.getFragmentList();
const matMan = Viewer.impl.matman();
const fragIds = Object.keys(fragList.fragments.fragId2dbId);
const lambertMaterial = new THREE.MeshLambertMaterial();
lambertMaterial.color = new THREE.Color(0xff0000);
matMan.addNonHDRMaterial("lambertMaterial", lambertMaterial);
lambertMaterial.envMap = null;
lambertMaterial.needsUpdate = true;
fragIds.forEach(fragId => fragList.setMaterial(fragId, lambertMaterial));
Viewer.impl.invalidate(true);

Edit 2023-04-20: What I'm trying to achieve

In short, I need a material to behave exactly how the MeshLambertMaterial example behaves at https://threejs.org/docs/#api/en/materials/MeshLambertMaterial

But at a bare minimum, I need the following to be met:

  1. I want to be able to set an envmap on the material, and the material's envmap should wrap around the entire mesh.
  2. The material must receive lighting, but not use IBL. I don't mind if I have to create an ambient or point light somewhere.
  3. The material's .combine property should work like a typical THREE.js MeshLambertMaterial.
  4. The material should be able to receive a plain color.
  5. The material should be able to receive a texture.
  6. The material should be able to receive a bump/normal map.
  7. The material should be able to receive an alpha map.
  8. The material should support transparency.

Basically, everything a THREE.MeshLambertMaterial supports.

Here is a graphic explaining a bit more: enter image description here

Here is a THREE.MeshLambertMaterial demo on the THREE.js docs site: enter image description here

xblz
  • 21
  • 3
  • Something I don't see in your code when using MeshLamberMaterial is a light source. I know it needs it in order to shine on the sphere in this case. I checked the sample and when turning on the section analysis on the toolbar and I activate the Lambert option I see it does a cut on the plane on an invisible object, but the sphere it is there. I will continue playing with your code to find the solution to it, but I wanted to share what I have found so far. – Jaime Rosales Apr 18 '23 at 23:00
  • @JaimeRosales Τhаnk you for looking into this--I was assuming lights existed in the scene already, but if there are none, how are models illuminated to begin with? – xblz Apr 18 '23 at 23:17
  • There is always one light source with forge viewer. It’s the IBL. Ie. Half-Dome light source. Ie. Environment lighting – michael beale Apr 19 '23 at 03:18
  • That’s right. All shaders are modified to support PBR Prism material with an assumed IBL env light source and the fresnel effect. Phong is the same shader as standardMaterial. Lambert is not the same as three.js because it has fresnel and IBL lighting applied. – michael beale Apr 19 '23 at 03:27
  • @michaelbeale I would like to get the lambert material to work like the one that normally comes with THREE.js--i.e. without the fresnel and IBL. Is this possible? I've seen the custom shaders you're talking about that are included in viewer3D.js called "firefly_basic" and "firefly_phong". I didn't see a "firefly_lambert", but regardless, if there is a way to get lambert to work the way that it normally does, please let me know. Thanks for your help also. – xblz Apr 19 '23 at 14:20

1 Answers1

0

You could remove the fresnel effect with this blog post info:

https://aps.autodesk.com/blog/fix-material-reflections-forge-viewer

.. and choose a flat IBL lighting environment from the settings.

Alternatively, If you just want to apply a texture to a THREE Mesh object, perhaps a simple custom shader, without lighting.

ie. Add a maps-box texture to a THREE Quad Mesh, like this:

https://gist.github.com/wallabyway/e1e40100c8a71b092fa34d9b28533bad

I'm not clear if you want a reflection to appear, or you just want to apply a texture to a surface?

michael beale
  • 1,014
  • 1
  • 6
  • 5
  • I edited my question and added more details on what look I'm trying to achieve. It's ultimately the same as a normal THREE.MeshLambertMaterial: the envmap wraps around the entire mesh with non-IBL shading. Please check my edits and let me know if you need more info. – xblz Apr 20 '23 at 15:02
  • UPDATED my answer above: with https://gist.github.com/wallabyway/e1e40100c8a71b092fa34d9b28533bad – michael beale Apr 20 '23 at 22:34
  • I don't need "true" reflections on the material, just the ability to set an envmap. It must also receive lighting (but not IBL). Instead of listing out all the individual things I need here, I'll just say it's everything a typical `THREE.MeshLambertMaterial` supports. Is this even possible in the Forge Viewer? – xblz Apr 21 '23 at 03:10
  • LMV has modified the THREE.MeshLambertMaterial to always use the IBL (ie. EnvMap texture channel). There's no easy way to remove it. You could create your own IBL/envMap but it's hard. Here's the solution: https://github.com/wallabyway/adding-shadows#bonus-section – michael beale Apr 21 '23 at 18:58