如何实时切换着色器?

How can I switch between shaders in real time?

问题是我有两个着色器。如果我在游戏 运行 时在着色器之间切换,它将不会生效。只有当我使用当前着色器开始游戏时,它才会使用该着色器,而不是我切换到的着色器。

我看到了这段代码,但它正在切换材质,我想切换着色器。 我的意思是在同一个游戏对象上的着色器之间切换。我不确定这段代码中应该包含哪些材料?

var materials : Material[];
var count = 0;

function OnMouseDown() {
    if (count == materials.Length - 1)
        count = 0;
    else
        count++;

    renderer.material = materials[count];
}

您可以使用 GameObject.renderer.material.shader 设置着色器。 API 有这方面的例子。查看 documentation

简答

不要这样做。通过游戏对象的渲染器分配更改 materialshader 属性 会导致创建 material 的多个实例,这不仅在计算上很昂贵,而且在术语方面也很昂贵GPU 上的内存。

Thomas of Unity 教程说得最好:

The first thing that will most likely jump into your mind is the following:

GetComponent<Renderer>().material.color = ...

Easy, right? Just grab that color and animate away. The problem with this is that in order to change the color in the shader, Unity needs to tell the GPU that this object is going to be rendered differently, and the only way it can do so is by changing the material instance. Because of this, Unity creates a copy of a material when you access renderer.material for the first time.

This means that there are potentially a lot of material copies out there, all eating memory 1

2500 个球体共享同一个 material 的场景。其他 39 materials 用于场景中的其他项目。 1

1

在 2500 个对象上摆弄 GameObject.renderer.material.shader 之后。请注意 materials 如何从 40 跳 到 2540 materials!

1

长答案

首先复习一下。在 Unity 中,您创建(或从 Asset Store 购买)着色器,然后创建 material。 material 然后指的是提供着色器可能需要的任何参数的着色器,例如纹理;凹凸贴图;和标量,它将 material 与可能使用相同着色器的任何其他 material 区分开来。完成后,您可以将 material 应用于一个对象。

I mean to switch between shaders on the same GameObject

所以想要切换着色器真的没有意义。对象直接与着色器对话不仅不正确,而且它没有足够的细节让着色器这样做。

您想要做的是 在对象上切换 materials 而不是

If I change between the shaders while the game is running it will not take effect

没有看到你的代码,很难说。无论如何,您最好提前定义所有资产而不是动态创建。这样您就可以为已知的保真度或平台烘焙它,而无需代码决定它应该使用哪个着色器级别。

解决方法

如果您必须在运行时更改 materials,您可能需要考虑 Unity 的 MaterialPropertyBlock

MaterialPropertyBlock is used by Graphics.DrawMesh and Renderer.SetPropertyBlock. Use it in situations where you want to draw multiple objects with the same material, but slightly different properties. For example, if you want to slightly change the color of each mesh drawn. Changing the render state is not supported More...

不幸的是,您现在需要将 PerRendererData 添加到您的着色器中,正如 Thomas 在他下面的文章中所解释的那样。

如此简单的事情却要复杂很多。提前预先设计 material 会更好。这可以说是一种更好的做法。

告诉我更多

  1. 优秀文章THE MAGIC OF MATERIAL PROPERTY BLOCKS

  2. "Change the color of a material for only one object", Answers, Unity