21

我有大量(~1000)个THREE.Mesh对象,它们是由相同的THREE.GeometryTHREE.MeshPhongMaterial(有一张地图)构成的。

我想单独为这些对象着色(着色)。

天真地,我尝试更改mesh.material.color属性,但是更改任何对象的此属性会立即更改所有对象的颜色。这是有道理的,因为只有一种材质在所有对象之间共享。

我的下一个想法是为每个对象创建一个单独THREE.MeshPhongMaterial的对象。所以,现在我有大量THREE.Mesh由相同构造的对象THREE.Geometry,但有个体THREE.MeshPhongMaterials(共享相同纹理)。这允许我单独更改颜色,但性能更差。chrome 分析器显示该应用程序正在花费大量时间来处理材质方面的事情,例如切换纹理。

材质颜色只是着色器中的统一。所以,更新制服应该很快。

问题:有没有办法从网格级别覆盖材质颜色?

如果有的话,我相信我可以在所有对象之间共享材料并恢复我的表现,同时仍然单独更改颜色。

[我在v49和v54上测试过,它们的性能和降级是一样的]

更新:我已经建立了一个测试用例,因此导致的性能下降比我想象的要小,但仍然可以测量。

这里有两个链接:

在第一种情况下,只有两种材料,在第二种情况下,每个立方体都有自己的材料。我在这台机器上测得第一种情况的帧率是53fps,第二种情况的帧率是46fps。这大约下降了 15%。

在这两种情况下,每个立方体的材质颜色每帧都会改变。在有许多材料的情况下,我们实际上看到每个立方体都有自己的颜色,在只有两种材料的情况下,我们看到它们都具有相同的颜色(如预期的那样)。

4

2 回答 2

7

是的。对于每个对象,使用 克隆您的材质material.clone(),修改其emissivecolor,并将对象的材质设置为此克隆。着色器和属性是通过引用复制的,所以不用担心每次都克隆整个材质;实际上,唯一按值复制的东西是制服(例如emissivecolor)。因此,您可以更改每个单独的对象。

我个人将原始材料存储在对象的单独自定义属性中,以便以后可以轻松切换回它;取决于你的需求是什么。

于 2014-04-14T11:22:32.040 回答
0

如果您正在编写自己的着色器,则可以将uniform变量用于一般色调(不是特定于顶点)并将其传递给着色器以考虑整体颜色。 vec4f_t并且vec4f()在 C 部分中不是标准的,但您的代码可能已经有等价物。

C:

vec4f_t hue = vec4f(....);  // fill in as desired
// load the shader so that GLuint shader_id is available.
// "hue" is a uniform var in the vertexshader
GLUint hue_id = glGetUniformLocation(shader_id, "hue"); 
// later, before rendering the object:
glUniform4fv(hue_id, 1, &hue);

.vertexshader:

uniform vec4 hue;  // add this and use it in the texture's color computation
于 2013-08-04T06:20:16.680 回答