Javascript 通过使用OnBeforeComile扩展three.js material类将颜色渐变应用于材质

Javascript 通过使用OnBeforeComile扩展three.js material类将颜色渐变应用于材质,javascript,three.js,geometry,vertex-shader,Javascript,Three.js,Geometry,Vertex Shader,在我的THREE.js场景中,有一个.obj文件加载了THREE.OBJLoader 我想在z轴上将线性颜色渐变应用到该对象上,同时保留MeshStandardMaterial着色器。下面是应用于对象的双色线性渐变的示例 我需要这样做,同时保留MeshStandardMaterial类附带的着色器。我认为要做到这一点,我需要为MeshStandardMaterial的vertexShader和MaterialShader注入一些代码 对此的回答部分实现了这一点。这些答案创建了一个新的着色器材质,

在我的THREE.js场景中,有一个.obj文件加载了THREE.OBJLoader

我想在z轴上将线性颜色渐变应用到该对象上,同时保留MeshStandardMaterial着色器。下面是应用于对象的双色线性渐变的示例

我需要这样做,同时保留MeshStandardMaterial类附带的着色器。我认为要做到这一点,我需要为MeshStandardMaterial的vertexShader和MaterialShader注入一些代码

对此的回答部分实现了这一点。这些答案创建了一个新的着色器材质,没有我需要的MeshStandardMaterial属性

我尝试使用,但我不知道在上面提到的问题的答案中列出的代码注入到哪里。我对着色器只有基本的了解


我的对象的材质由THREE.MeshStandardMaterial类定义。我设置了类的以下属性:金属度、粗糙度、透明度和不透明度。我使用纹理设置贴图和环境贴图属性。

MeshStandardMaterial着色器编译成数百行代码,因此在保持环境反射、照明、金属度、粗糙度和所有这些行为的同时,很难精确地确定更改颜色的位置。你可能想得太多了。如果您只需要在
MeshStandardMaterial
上创建渐变,为什么不使用渐变创建纹理,然后将其指定给属性?如果您添加一个白色的
环境光
,您应该能够毫无问题地看到渐变

或者,如果希望渐变不受灯光影响,可以将纹理指定给材质的属性


最后,如果要避免纹理,可以为每个顶点指定一种颜色,然后将其设置为true。

MeshStandardMaterial着色器编译成数百行代码,因此在保持环境反射、照明、金属性、粗糙度的同时,很难精确地确定更改颜色的位置,所有这些行为。你可能想得太多了。如果您只需要在
MeshStandardMaterial
上创建渐变,为什么不使用渐变创建纹理,然后将其指定给属性?如果您添加一个白色的
环境光
,您应该能够毫无问题地看到渐变

或者,如果希望渐变不受灯光影响,可以将纹理指定给材质的属性


最后,如果要避免纹理,可以为每个顶点指定一种颜色,然后设置为true。

很难了解着色器块中的内容,但并非不可能

正文{
溢出:隐藏;
保证金:0;
}

从“导入*为三”https://cdn.jsdelivr.net/npm/three@0.121.1/build/three.module.js”;
从导入{OrbitControls}”https://cdn.jsdelivr.net/npm/three@0.121.1/examples/jsm/controls/OrbitControls.js”;
让场景=新的三个。场景();
让摄像头=新的三个透视摄像头(60,内宽/内高,11000);
摄像机位置设置(0,10,20);
让renderer=new THREE.WebGLRenderer();
设置大小(innerWidth,innerHeight);
document.body.appendChild(renderer.doElement);
let controls=新的轨道控件(摄影机、渲染器.doElement);
让光=新的三个方向光(0xffffff,1);
灯。位置。设置刻度(10);
场景。添加(灯光);
添加(新的三个环境光(0xffffff,1));
设g=新的三个圆环几何体(5,1,128,16);
g、 rotateX(-Math.PI*0.5);
g、 computeBoundingBox();
让制服={
bbMin:{value:g.boundingBox.min},
bbMax:{value:g.boundingBox.max},
color1:{value:new THREE.Color(0xff0000)},
color2:{value:new THREE.Color(0xffff00)}
}
控制台日志(g);
设m=新的三点网格标准材料({
粗糙度:0.25,
金属度:0.75,
映射:新的3.TextureLoader().load(“https://threejs.org/examples/textures/floors/FloorsCheckerboard_S_Diffuse.jpg“,tex=>{
tex.wrapps=3.wrapping;
tex.wrapT=3.0;
tex.repeat.set(16,1);
}),
onbeforecomile:shader=>{
shader.uniforms.bbMin=uniforms.bbMin;
shader.uniforms.bbMax=uniforms.bbMax;
shader.uniforms.color1=uniforms.color1;
shader.uniforms.color2=uniforms.color2;
shader.vertexShader=`
可变vec3 VPO;
${shader.vertexShader}
`.替换(
`#包括`,
`#包括
vPos=转化;
`
);
shader.fragmentShader=`
均匀vec3bbmin;
均匀vec3bbmax;
均匀vec3颜色1;
均匀vec3色2;
可变vec3 VPO;
${shader.fragmentShader}
`.替换(
`vec4 diffuseColor=vec4(漫反射,不透明度);`,
`
浮动f=夹具((vPos.z-bbMin.z)/(bbMax.z-bbMin.z),0,1.);
vec3 col=混合(颜色1、颜色2、f);
vec4漫反射颜色=vec4(颜色,不透明度)`
);
console.log(shader.vertexShader);
console.log(shader.fragmentShader);
}
});
设o=新的三个网格(g,m);
场景。添加(o);
renderer.setAnimationLoop(()=>{
渲染器。渲染(场景、摄影机);
});

很难理解着色器块中的内容,但并非不可能

正文{
溢出:隐藏;
保证金:0;
}

从“导入*为三”https://cdn.jsdelivr.net/npm/three@0.121.1/build/three.module.js”;
从导入{OrbitControls}”https://cdn.jsdelivr.net/npm/three@0.121.1/examples/jsm/controls/OrbitControls.js”;
让场景=新的三个。场景();
让摄像头=新的三个透视摄像头(60,内宽/内高,11000);
摄像机位置设置(0,10,20);
让renderer=new THREE.WebGLRenderer();
设置大小(innerWidth,innerHeight);
document.body.appendChild(renderer.doElement);
let controls=新的轨道控件(摄影机、渲染器.doElement);
让光=新的三个方向光(0xffffff,1);