标准材质
-
可以看到图中的 蓝色框中 水壶 使用的是标准的 材质 进行渲染的效果
-
中间的 水壶 底部有火焰叠加起来的 红色的燃烧效果 (也就是本文的重点讲解内容)对标准的材质进行shader的改进( onBeforeCompile 函数的使用)
// 创建不锈钢材质
const material = new THREE.MeshStandardMaterial({
color: 0xaaaaaa, // 灰色基调
metalness: 0.8, // 高金属性
roughness: 0.2, // 低粗糙度
envMapIntensity: 1 // 环境贴图强度
});
onBeforeCompile
- onBeforeCompile 函数存在 material 中 每一个材质都有属于自己的 onBeforeCompile 函数 , 该函数 会传入 一个 shader 对象,以比喻成 material
- shader 包含 uniforms 参数信息 以及 fragmentShader || vertexShader 我们 可以同对其内容的修改 来达到我们 想要的 效果
- 修改 uniforms fragmentShader vertexShader 都是写在 一个 onBeforeCompile 中
uniforms
- 传递 自定义的 参数
material.onBeforeCompile = (shader) => {
// 自定义的 uColor 颜色值
shader.uniforms.uColor = {
value: new THREE.Color("#492781"),
};
sader.uniforms.combustionNumber = {
value:13.0
}
}
vertexShader
- 传递 自定义的 参数
material.onBeforeCompile = (shader) => {
// 替换 vertexShader 中的获取自定义参数的值
shader.vertexShader = shader.vertexShader.replace(
"#include <common>",
`
#include <common>
uniform vec3 uColor;
varying vec3 vPosition;
`
);
// 设置 vPosition 传递给 片元着色器的 值 vPosition;
shader.vertexShader = shader.vertexShader.replace(
"#include <begin_vertex>",
`
#include <begin_vertex>
vPosition = position;
`
);
}
fragmentShader
material.onBeforeCompile = (shader) => {
// 获取传递给 fragmentShader 和自定义参数的值
shader.fragmentShader = shader.fragmentShader.replace(
"#include <common>",
`
#include <common>
uniform vec3 uColor;
uniform float combustionNumber;
varying vec3 vPosition;
`
);
// 在最终 渲染片元着色器 后加上自己的 shader
shader.fragmentShader = shader.fragmentShader.replace(
"#include <dithering_fragment>",
`
#include <dithering_fragment>
if(vPosition.y<combustionNumber){
gl_FragColor = mix(
gl_FragColor,vec4(1.0,0.0,0.0,1.0),
smoothstep( combustionNumber , combustionNumber - 20.0 ,vPosition.y)
);
}
`
);
}
注 (这是我在开发中遇到的问题)
- 如果使用 以下方式设置的着色器 效果会有变化 可能会导致达不到我们理性的效果
shader.fragmentShader = shader.fragmentShader.replace(
"#include <dithering_fragment>",
`
#include <dithering_fragment>
gl_FragColor = mix(vec4(1.0,0.0,0.0,1.0),gl_FragColor,vPosition.y/4.0);
`
);
- 所以为了解决这个问题 采用了 if 判断的模式 去 阻止 vPosition.y 的颜色变化 达到最终的理想效果
shader.fragmentShader = shader.fragmentShader.replace(
"#include <dithering_fragment>",
`
#include <dithering_fragment>
if(vPosition.y<combustionNumber){
gl_FragColor = mix(
gl_FragColor,vec4(1.0,0.0,0.0,1.0),
smoothstep( combustionNumber , combustionNumber - 20.0 ,vPosition.y)
);
}
`
);
shader 处理后的标准材质效果
整合的代码
material.onBeforeCompile = (shader) => {
// 自定义的 uColor 颜色值
shader.uniforms.uColor = {
value: new THREE.Color("#492781"),
};
sader.uniforms.combustionNumber = {
value:13.0
}
// 替换 vertexShader 中的获取自定义参数的值
shader.vertexShader = shader.vertexShader.replace(
"#include <common>",
`
#include <common>
uniform vec3 uColor;
varying vec3 vPosition;
`
);
// 设置 vPosition 传递给 片元着色器的 值 vPosition;
shader.vertexShader = shader.vertexShader.replace(
"#include <begin_vertex>",
`
#include <begin_vertex>
vPosition = position;
`
);
// 获取传递给 fragmentShader 和自定义参数的值
shader.fragmentShader = shader.fragmentShader.replace(
"#include <common>",
`
#include <common>
uniform vec3 uColor;
uniform float combustionNumber;
varying vec3 vPosition;
`
);
// 在最终 渲染片元着色器 后加上自己的 shader
shader.fragmentShader = shader.fragmentShader.replace(
"#include <dithering_fragment>",
`
#include <dithering_fragment>
if(vPosition.y<combustionNumber){
gl_FragColor = mix(
gl_FragColor,vec4(1.0,0.0,0.0,1.0),
smoothstep( combustionNumber , combustionNumber - 20.0 ,vPosition.y)
);
}
`
);
}