改变Three.js中不同网格的着色值

嘿,我正在为Three.js写Shader。

我的目标是让多个对象具有相同的着色器,并且每个对象都应该在该对象上设置一个颜色,然后将颜色设置给着色器。 目标是拥有多个“单元”(想一下RTS游戏),每个单元都有团队的颜色。

两个单位的屏幕截图 我通过几个文档页红色,我不知道如何处理。 我查看了https://threejs.org/docs/#api/materials/ShaderMaterial 。

我努力了:

  • 改变uniform但从我有限的知识和反复试验中得出的结论是,我不能在抽奖期间改变统一的价值。
  • 改变onBeforeRender中的制服,这给了我一个没有定义v的错误

我不知道现在该怎么办。 在ShaderMaterial文档中写道:

建议您根据Object3D.onBeforeRender中的对象和相机更新自定义统一值,因为材质可以在网格中共享,Scene和Camera的matrixWorld在WebGLRenderer.render中更新,而某些效果(例如:VREffect)渲染场景私人自己的相机。

所以我只是改变了错误的价值观,它实际上是一个统一的改变? 在这个Github的问题有人想用不同的颜色绘制网格,并建议为每个网格创建不同的材料( https://github.com/mrdoob/three.js/issues/1532 )。 但是,这会杀死每个单元有一个着色器的想法,不管团队。

感谢gman的帮助:

每个对象都有一个材质。 在你链接的页面中,顶部的屏幕截图显示了5个不同颜色的人,所以你将有5个材料,每个人有一个人的颜色设置。 如果你想改变一个人的颜色,你只需要设置该人物的颜色。 每个人都会有一个网格。 每个网格将使用相同的几何体,但是该人的材质。 1几何,5材料,5网格

这里是解决scheme:

在这里输入图像说明 用相同的统一名称准备不同的材料。

 let team1knightUniforms = { textureKnight: { type: "t", value: THREE .ImageUtils .loadTexture("objects/customObjs/knight/Myknight.png") }, teamcolor: { value: new THREE.Color(options.teamcolor1) } }; let team1KnightMaterial = new THREE.ShaderMaterial( { vertexShader: document .getElementById("teamcolorVertexShader") .textContent, fragmentShader: document .getElementById("teamcolorFragmentShader") .textContent, uniforms: team1knightUniforms } ); let team2knightUniforms = { textureKnight: { type: "t", value: THREE .ImageUtils .loadTexture("objects/customObjs/knight/Myknight.png") }, teamcolor: { value: new THREE.Color(options.teamcolor2) } }; let team2KnightMaterial = new THREE.ShaderMaterial( { vertexShader: document .getElementById("teamcolorVertexShader") .textContent, fragmentShader: document .getElementById("teamcolorFragmentShader") .textContent, uniforms: team2knightUniforms } ); 

然后添加对象两次并为不同的材质分配。 这些材料具有相同的纹理和统一名称:

 let objFile = "objects/customObjs/knight/Myknight.obj"; let loader = new THREE.OBJLoader(); loader.load( objFile, function( object ) { object.children.forEach( function (obj, index) { obj.material = team1KnightMaterial; obj.position.x = 5; obj.position.z = 5; obj.teamNumber = 1; objects.push( obj ); }); shaderExampleScene.add(object); }); loader.load( objFile, function( object ) { object.children.forEach( function (obj, index) { obj.material = team2KnightMaterial; obj.position.x = 5; obj.position.z = 10; obj.teamNumber = 2; objects.push( obj ); }); shaderExampleScene.add(object); }); 

最后,Fragmentshader拿起制服,在Alpha变得透明的地方混合颜色:

 precision mediump float; uniform sampler2D textureKnight; uniform vec3 teamcolor; varying vec2 vUv; void main() { vec4 fragColor = texture2D(textureKnight, vUv); fragColor.r = fragColor.r * fragColor.a + teamcolor.r * ( 1.0 - fragColor.a); fragColor.g = fragColor.g * fragColor.a + teamcolor.g * ( 1.0 - fragColor.a); fragColor.b = fragColor.b * fragColor.a + teamcolor.b * ( 1.0 - fragColor.a); gl_FragColor = fragColor; }