简述
以MeshPhongMaterial为例,以此基础创建一个自定义类
注意
material的type不要轻易改动.
升级方向
- 将代码以
#include<xxx>方式插入
class
js
class GradientMaterial extends THREE.MeshPhongMaterial {
constructor(options = {}) {
super(options);
this.initShader(options);
}
initShader(options) {
this.onBeforeCompile = (shader) => {
const defaultUniforms = {
uMax: {
value: new THREE.Vector3()
},
uMin: {
value: new THREE.Vector3()
},
uGradient: {
value: 0.3
},
}
// 合并shader.uniforms 和 options.uniforms
Object.assign(shader.uniforms, defaultUniforms);
Object.assign(shader.uniforms, options.uniforms);
shader.vertexShader = shader.vertexShader.replace('#include <common>',
`
varying vec3 vPosition;
#include <common>
`)
shader.vertexShader = shader.vertexShader.replace('void main() {', `void main() {
vPosition = position;
`);
shader.fragmentShader = shader.fragmentShader.replace('#include <common>',
`
varying vec3 vPosition;
uniform vec3 uMax;
uniform vec3 uMin;
uniform float uGradient;
#include <common>
`)
shader.fragmentShader = shader.fragmentShader.replace('#include <dithering_fragment>', `#include <dithering_fragment>
vec3 color = mix(gl_FragColor.rgb * uGradient, gl_FragColor.rgb, (vPosition.z - uMin.z) / (uMax.z - uMin.z));
gl_FragColor = vec4(color, 1.0);
`);
}
}
}demo
js
// 传入一个object(模型或直接创建的mesh)
if (!object.geometry.boundingBox)
object.geometry.computeBoundingBox();
if (!object.geometry.boundingSphere)
object.geometry.computeBoundingSphere();
const {
max,
min
} = object.geometry.boundingBox;
object.material = new GradientMaterial({
color: '#00FF00',
uniforms: {
uMax: {
value: max
},
uMin: {
value: min,
},
},
});