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)