2. onBeforeCompile修改材质shader
# .onBeforeCompile
修改材质shader
上节课给大家说过,你可以通过材质.onBeforeCompile
方法查看材质的着色器代码,其实也可以通过函数参数shader
获取顶点或片元着色器GLSL ES的字符串进行二次修改。
const material = new THREE.MeshLambertMaterial();
material.onBeforeCompile = function (shader) {
console.log('顶点着色器', shader.vertexShader);
console.log('片元着色器', shader.fragmentShader);
//你可以增删shader.vertexShader字符串
//你可以增删shader.fragmentShader字符串
}
本节课修改结果:
const material = new THREE.MeshLambertMaterial({
map: texture,
});
// 修改材质material默认的着色器shader代码
material.onBeforeCompile = function (shader) {
// console.log('片元着色器', shader.fragmentShader);
// 在片元着色器main函数里面最后一行插入代码
shader.fragmentShader = shader.fragmentShader.replace(
'#include <dithering_fragment>',//一行代码字符串,你可以用单双引号
//多行代码字符串,用模板字符串``更方便
`
#include <dithering_fragment>
gl_FragColor.r = 0.0;
gl_FragColor.g = 0.0;
`
)
}
# gl_FragColor
多次执行
在片元着色器主函数main中,内置变量gl_FragColor
可以多次调用设置RGBA分量的值。
// 片元着色器代码
const fragmentShader = `
void main() {
gl_FragColor = vec4(0.0,1.0,1.0,1.0);
//重新访问rgb属性赋值
gl_FragColor.g = 0.0;
}
`
// 片元着色器代码
const fragmentShader = `
void main() {
gl_FragColor = vec4(0.0,1.0,1.0,1.0);
//可以多次赋值
gl_FragColor = vec4(1.0,0.0,0.0,1.0);
}
`
# 查看材质MeshLambertMaterial
片元着色器代码
你可以直接去threejs官方文件包目录\src\renderers\shaders\ShaderLib
,查看MeshLambertMaterial
对应的shader文件meshlambert.glsl.js
。
meshlambert.glsl.js
里面有两个字符串,一个是顶点着色器代码,一个片元着色器代码。
const material = new THREE.MeshLambertMaterial();
也可以直接浏览器控制台log打印
material.onBeforeCompile = function (shader) {
console.log('片元着色器', shader.fragmentShader);
}
因为threejs经常改变,不太稳定,所以这里强烈提醒,不同版本threejs,同一个材质的shader代码可能一样,也可能不一样,代码打印结果,以你使用的threejs版本为准,并不一定要和我视频完全一致。
你可以确定下你当前threejs版本,MeshLambertMaterial
片元着色器主函数main里面最后一行代码是什么,我这里是#include <dithering_fragment>
。
void main() {
...
...
...
#include <dithering_fragment>
}
# .replace()
方法介绍
.replace()
JavaScript语言处理字符串的一个方法,算是普通前端基础。如果你了解,可以跳过去,如果不熟悉,就跟着视频熟悉下。
.replace()
功能就是修改一串字符串,具体方式就是检索字符串是否包含参数1表示的字符串,去替换新的字符串。
const str = '我爱加班';
const newStr = str.replace('爱加班','不爱加班');
console.log('改变后字符串', newStr);
# 修改MeshLambertMaterial
片元着色器代码
目标:在MeshLambertMaterial
片元着色器主函数main里面最后一行后面增加代码。
void main() {
...
...
...
#include <dithering_fragment>
// 在这里增加代码
}
材质的片元着色器代码shader.fragmentShader
本身就是一个字符串,所以我们可以用.replace()
去修改替换shader.fragmentShader
里面的部分代码。
const material = new THREE.MeshLambertMaterial({
map: texture,
});
// 修改材质material默认的着色器shader代码
material.onBeforeCompile = function (shader) {
// console.log('片元着色器', shader.fragmentShader);
// 在片元着色器main函数里面最后一行插入代码
shader.fragmentShader = shader.fragmentShader.replace(
'#include <dithering_fragment>',//一行代码字符串,你可以用单双引号
//多行代码字符串,用模板字符串``更方便
`
#include <dithering_fragment>
gl_FragColor.r = 0.0;
gl_FragColor.g = 0.0;
`
)
}