Same SharderMaterial gets different effects in different three version

Hello!
I got the effect I wanted in version 132, but the result was completely different in version 162.

  function setMaterial(mesh, isUpper) {
    if (!mesh.geometry.attributes.color) {
      mesh.geometry.setAttribute("color", new THREE.BufferAttribute(new Float32Array(mesh.geometry.attributes.position.array.length), 3));
    }

    const colorArr = mesh.geometry.attributes.color.array;
    for (let i = 0, len = colorArr.length; i < len; i += 3) {
      colorArr[i] = 1
      colorArr[i + 1] = 1
      colorArr[i + 2] = 1
    }

    const geometry = mesh.geometry;
    geometry.computeBoundingBox();
    geometry.attributes.normal || geometry.computeVertexNormals();

    const positionAttribute = geometry.attributes.position,
      colorAttribute = geometry.attributes.color,
      meshHeight = Math.abs(geometry.boundingBox.max.y - geometry.boundingBox.min.y);
    // 设置color属性
    for (let i = 0, len = positionAttribute.count; i < len; i++) {
      const pointHeight = Math.abs(positionAttribute.array[3 * i + 1] - geometry.boundingBox.min.y) / meshHeight;
      let lutDataIndex = 4 * Math.floor((isUpper ? 1 - pointHeight : pointHeight) * textures.lutMap.image.height * textures.lutMap.image.width);
      if (lutDataIndex < 0) lutDataIndex = 0;
      if (lutDataIndex > textures.lutData.length - 3) lutDataIndex = textures.lutData.length - 3;

      const color = new THREE.Color(textures.lutData[lutDataIndex] / 255, textures.lutData[lutDataIndex + 1] / 255, textures.lutData[lutDataIndex + 2] / 255);
      colorAttribute.setXYZ(i, color.r, color.g, color.b);
    }
    colorAttribute.needsUpdate = true;

    const material = new THREE.ShaderMaterial({
      uniforms: {
        diffuse: {
          value: new THREE.Vector3(0.92, 0.88, 0.89)
        },
        lightColor: {
          value: new THREE.Color(10457232)
        },
        pointLights: {
          value: [
            {
              position: new THREE.Vector3(0, 0, 4),
              // color: new THREE.Color(0.41, 0.47, 0.45)
              color: new THREE.Color(0.41, 0.47, 0.45)
            },
            {
              position: new THREE.Vector3(-2, 0, -4),
              color: new THREE.Vector3(0, 0, 0)
            },
            {
              position: new THREE.Vector3(-2, 0, -4),
              color: new THREE.Vector3(0, 0, 0)
            }
          ]
        },
        opacity: {
          value: 1
        },
        reflection: {
          value: 0.64
        },
        illumination: {
          value: 0
        },
        glossiness: {
          value: 0.69
        },
        reflectivity: {
          value: 0.44
        },
        shineFactor: {
          value: 1.81
        },
        reflectMap: {
          value: textures.reflectMap
        }
      },
      vertexShader: `
            varying vec3 vColor;
            varying vec3 vNormal;
            varying vec4 mPos;
            
            void main() {
                vColor = color;
                
                vec3 objectNormal = vec3( normal );
                vec3 transformedNormal = objectNormal;
                transformedNormal = normalMatrix * transformedNormal;
                vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
                
                vNormal = transformedNormal;
                
                vec4 projectedVertex = projectionMatrix * mvPosition;
                gl_Position = projectedVertex;
                mPos = mvPosition;
            }
                `
      ,
      fragmentShader: `
            precision highp float;
            precision highp int;
            
            uniform vec3 diffuse;
            uniform vec3 lightColor;
            uniform float opacity;
            uniform float reflection;
            uniform float illumination;
            uniform float glossiness;
            uniform float reflectivity;
            uniform float shineFactor;
            uniform sampler2D reflectMap;
            
            varying vec3 vColor;
            varying vec3 vNormal;
            varying vec4 mPos;
            
            struct PointLight {
                vec3 position;
                vec3 color;
            };
            uniform PointLight pointLights[ 3 ];
            
            void main() {
                vec4 diffuseColor = vec4( diffuse, opacity );
                diffuseColor *= vec4(vColor, 1.0);
                
                float roughness = 2.0 * pow(100.0, glossiness);
                float roughnessResult = 13.0 - 10.0 * glossiness;
                float reflectionF = pow(reflectivity, 2.0) * pow(glossiness, 0.5);
                float reflection = reflectionF * reflection;
                float iReflection = sqrt(1.0 - reflectionF * reflection);
                float highLightFactor = reflectivity * pow(glossiness, 0.5) * shineFactor;
                vec3 lighting = lightColor;
                vec3 highLight = vec3(0.0);
                vec3 normal = normalize( vNormal );

                #ifdef FLAT_SHADED
                    vec3 fdx = vec3( dFdx( vViewPosition.x ), dFdx( vViewPosition.y ), dFdx( vViewPosition.z ) );
                    vec3 fdy = vec3( dFdy( vViewPosition.x ), dFdy( vViewPosition.y ), dFdy( vViewPosition.z ) );
                    normal = normalize( cross( fdx, fdy ) );
                #else
                    float faceDirection = gl_FrontFacing ? 1.0 : - 1.0;
                    normal = normalize( vNormal );
                    normal *= faceDirection;
                #endif
            
                PointLight pointLight;
                for (int i = 0; i < 3; i++) {
                    pointLight = pointLights[ i ];
                    lighting += max(dot(normal, normalize(pointLight.position)), 0.0) * pointLight.color;
                    float highLightValue = max(dot(normalize(reflect(pointLight.position - mPos.xyz, normal)), normalize(mPos.xyz)), 0.001);
                    float tempLight = 1.0 / max(pow(highLightValue, roughness), 0.001);
                    highLight += pointLight.color[i] * pow(roughnessResult, 1.0 - tempLight) * tempLight;
                }
                
                vec3 specularValue = vec3(1.0);
                vec3 reflectionColor = vec3(0.0);
                vec3 reflectNormal = normalize(reflect(mPos.xyz, normal));
                if (reflectNormal.z < 0.0)
                    reflectNormal.xy *= 2.0 / length(reflectNormal.xy) - 1.0;
                reflectionColor = texture2D(reflectMap, vec2(0.5, 0.5) - reflectNormal.xy * 0.25).rgb;
            
                vec3 fColor = mix(diffuseColor.rgb * lighting, diffuseColor.rgb, illumination);
                fColor *= mix(vec3(1.0), vec3(iReflection) + reflectionColor * reflection, specularValue);
                vec3 resultingColor = fColor + (highLight * highLightFactor * specularValue);
                gl_FragColor = vec4( resultingColor, opacity );
            }
		`,
      transparent: false,
      vertexColors: true,
      side: THREE.DoubleSide
    });
    material.color = new ShaderColor(material.uniforms, 0.9216, 0.8863, 0.8941);
    mesh.material = material;
  };

function ShaderColor(a, d, e, g) {
  this.r = d;
  this.g = e;
  this.b = g;
  this.clone = function () {
    return new ShaderColor(a, this.r, this.g, this.b);
  };
  this.copy = function (f) {
    this.r = f.r;
    this.g = f.g;
    this.b = f.b;
    a.diffuse.value = new THREE.Vector3(f.r, f.g, f.b);
    return this;
  };
  this.setRGB = function (f, l, k) {
    this.r = f;
    this.g = l;
    this.b = k;
    a.diffuse.value = new THREE.Vector3(f, l, k);
    return this;
  };
  this.setRGB(d, e, g);


 function loadTextures() {
    const promises = ["static/textures/uvDiffuse.png", "static/textures/NormalMap.png", "static/textures/reflectMap.png", "static/textures/lutMap.png"].map((path) => {
      return new Promise((resolve, reject) => {
        new THREE.TextureLoader().load(
          path,
          (res) => {
            resolve(res);
          },
          null,
          (err) => {
            reject(err);
          }
        );
      });
    });

    const scope = this;
    return new Promise((resolve, reject) => {
      Promise.all(promises).then((data) => {
        textures.uvMap = data[0];
        textures.normalMap = data[1];
        textures.reflectMap = data[2];
        textures.lutMap = data[3];

        const canvas = document.createElement("canvas");
        canvas.width = textures.lutMap.image.width;
        canvas.height = textures.lutMap.image.height;
        const ctx = canvas.getContext("2d");
        ctx.drawImage(textures.lutMap.image, 0, 0, canvas.width, canvas.height);
        textures.lutData = ctx.getImageData(0, 0, canvas.width, canvas.height).data;
        window.textures = textures;
        console.log(canvas.width, canvas.height);
        
        resolve();
      });
    });
  }
}

Whether the sharderMaterial is written differently in different versions?
What should I do if I want to implement the image in a higher version of threejs?
Thank you very much if you have any suggestions!

Crown_11.stl (429.9 KB)
static.zip (669.5 KB)

Later three.js revisions require the Point Light intensity be increased, maybe by a factor of between 100 - 1000, and since you seem to have several point lights then maybe try increasing their intensity.

EDIT: By looking at your code again, it looks like these Point Lights might not actually be related to the actual three.js THREE.PointLight control

Lights intensity decreased to 3. Decay changed.
Read migration guide: Migration Guide · mrdoob/three.js Wiki · GitHub
Last pointLight.intensity=1;
New must be pointLight.intensity=1*3;
Colors of lights now converted to srgb.
A week ago i successfully migrate from 140 to 169 with same color and postprocessing, but for postprocess i used outputPass for srgb correction.

This looks strongly like a color space issue, but I think the use of a custom “ShaderColor” class instead of THREE.Color is likely to make a solution rather more complex. For details (and how to opt-out of color management, if you prefer) at:

Just out of curiosity, I did bother using your code with r169 and the attached picture shows what I got.

Some functions were shuffled and there are some minor changes or adaptations that I applied so this could run with python http.server and from the same folder.

All files are in the attached zip file and I don’t recall making any changes to the actual vertex / fragment shaders code.

Maybe try using this html file just for testing.

EDIT: After creating this post and looking at reply from @donmccurdy, I did additionally add the opt-out line of THREE.ColorManagement.enabled = false; and the attached picture reflects new change (it seems to be rather close to the original picture posted by the OP but with whitesmoke background).

Crown.zip (857.0 KB)

@rookie does your shader code have any limitations for other users to use it in their projects?

It is kind of assumed that when users post the code in this forum then other users could also use it if necessary.

The reason I ask is because your shader code could possibly be useful to visually enhance not only teeth but other models as well. The attached picture shows the original STL tooth crown and a PLY model available in the three.js repository (which is using the same shader material but with slightly different diffuse and light color). This new code is available in the attached ZIP file.

Crown.zip (1.8 MB)