Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/three.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 对网格上的材质应用颜色渐变-three.js_Javascript_Three.js_Vertex Shader_Geometry Shader - Fatal编程技术网

Javascript 对网格上的材质应用颜色渐变-three.js

Javascript 对网格上的材质应用颜色渐变-three.js,javascript,three.js,vertex-shader,geometry-shader,Javascript,Three.js,Vertex Shader,Geometry Shader,我有一个STL文件加载到我的场景中,其中一种颜色应用于phong材质 我想用一种方法将两种颜色应用于该网格的材质,并在Z轴a上应用渐变效果,如下面的示例所示。] 我有一种感觉,我可能必须引入着色器,但我还没有用three.js走到这一步 如果希望渐变是静态的,可以使用该属性向材质添加纹理。或者,如果希望属性“发光”而不需要灯光,则可以将其指定给属性 但是,如果要更改渐变,并且始终在z轴上淡入淡出,即使在旋转模型或摄影机之后,也必须编写自定义着色器,这需要您学习一些教程。您可以查看如何在Three

我有一个STL文件加载到我的场景中,其中一种颜色应用于phong材质

我想用一种方法将两种颜色应用于该网格的材质,并在Z轴a上应用渐变效果,如下面的示例所示。]


我有一种感觉,我可能必须引入着色器,但我还没有用three.js走到这一步

如果希望渐变是静态的,可以使用该属性向材质添加纹理。或者,如果希望属性“发光”而不需要灯光,则可以将其指定给属性


但是,如果要更改渐变,并且始终在z轴上淡入淡出,即使在旋转模型或摄影机之后,也必须编写自定义着色器,这需要您学习一些教程。您可以查看如何在Three.js中实现自定义着色器,并访问以更好地了解如何编写简单渐变着色器。

基于UV的简单渐变着色器:

var scene=new THREE.scene();
var摄像机=新的三个透视摄像机(60,1,1,1000);
摄像机。位置。设置(13、25、38);
摄像机。注视(场景。位置);
var renderer=new THREE.WebGLRenderer({
反别名:对
});
var canvas=renderer.domeElement
document.body.appendChild(画布);
var controls=新的三个.OrbitControls(摄影机、渲染器.doElement);
var几何=新的三个。CylinderBufferGeometry(2,5,20,32,1,true);
var material=新的3.ShaderMaterial({
制服:{
颜色1:{
值:新三种颜色(“红色”)
},
颜色2:{
价值:新三种颜色(“紫色”)
}
},
顶点着色器:`
可变vec2 vUv;
void main(){
vUv=紫外线;
gl_位置=projectionMatrix*modelViewMatrix*vec4(位置,1.0);
}
`,
碎片着色器:`
均匀vec3颜色1;
均匀vec3色2;
可变vec2 vUv;
void main(){
gl_FragColor=vec4(混合(颜色1,颜色2,vUv.y),1.0);
}
`,
线框:正确
});
var mesh=新的三个网格(几何体、材质);
场景。添加(网格);
render();
函数调整大小(渲染器){
const canvas=renderer.domeElement;
const width=canvas.clientWidth;
常数高度=canvas.clientHeight;
const needResize=canvas.width!==width | | canvas.height!==height;
如果(需要调整大小){
设置大小(宽度、高度、假);
}
返回需要调整大小;
}
函数render(){
如果(调整大小(渲染器)){
camera.aspect=canvas.clientWidth/canvas.clientHeight;
camera.updateProjectMatrix();
}
渲染器。渲染(场景、摄影机);
请求动画帧(渲染);
}
html,
身体{
身高:100%;
保证金:0;
溢出:隐藏;
}
帆布{
宽度:100%;
身高:100%;
展示;
块
}

如果要保留
MeshPhongMaterial的功能,可以尝试扩展该材质

这是一个比较宽泛的话题,有几种方法,您可以深入阅读

phong材质着色器中有一行如下所示

vec4 diffuseColor = vec4( diffuse, opacity );
vec4 diffuseColor = vec4( mix(diffuse, myColor, vec3(myFactor)), opacity);
因此,在学习了着色器手册或其他一些教程之后,您将了解到可以通过使用规格化因子(0,1之间的数字)混合两种颜色

这意味着你可以把这行改成这样

vec4 diffuseColor = vec4( diffuse, opacity );
vec4 diffuseColor = vec4( mix(diffuse, myColor, vec3(myFactor)), opacity);
可以这样扩展着色器

const myFactor = { value: 0 }
const myColor = {value: new THREE.Color}


myMaterial.onBeforeCompile = shader=>{
  shader.uniforms.myFactor = myFactor
  shader.uniforms.myColor = myColor
  shader.fragmentShader = `
  uniform vec3 myColor;
  uniform float myFactor;
  ${shader.fragmentShader.replace(
    vec4 diffuseColor = vec4( diffuse, opacity );
    vec4 diffuseColor = vec4( mix(diffuse, myColor, vec3(myFactor)), opacity);
  )}
`
现在,当您更改
myFactor.value
时,对象的颜色应该从
myMaterial.color
更改为
myColor.value

现在要把它变成一个渐变,你可以用一些动态的东西来代替
myFactor
。我喜欢使用紫外线。这完全是在javascript中完成的,在这个着色器中连接起来非常简单。其他方法可能需要更多的着色器工作

vec4 diffuseColor = vec4( mix(diffuse, myColor, vec3(vUv.y)), opacity);
现在,您可能会遇到问题-如果调用
new PhongMaterial({color})
即,如果没有提供任何纹理,着色器将在没有
vUv
的情况下编译。 有许多条件会导致它编译并对您有用,但我不确定它们是否会破坏其他内容:

#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )
所以,添加一些类似于

myMaterial.defines = {USE_MAP:''} 

可能使
vUv
变量可用于着色器。通过这种方式,您可以使phong材质的所有灯光影响材质,您只需更改基础颜色

哦,这是完美的,我认为基于UV的渐变着色器已经足够了,但我现在有一些东西可以玩,如果我需要的话,可以尝试使用顶点颜色-谢谢!!我对加载模型(STL文件)尝试了第一种方法,它只在整个网格上应用第一种颜色。这适用于加载程序对象吗?@Huskie69如果对象具有UV是。您可以将边界框传递给着色器,并将其与对象顶点的坐标一起使用。@Huskie69我已使用制服中的
.min
.max
.boundingBox
值更新了答案。让我们一起来吧。由于您的答案,我已将该问题标记为最喜欢的问题。非常有用。另一个非常有用的答案,谢谢
myMaterial.defines={USE\u MAP:'}
在最新版本(当前版本为
r111
)中,他们添加了
USE\u UV:'
以启用UV。