如何在着色器之间实时切换?

Dan*_*Lip 1 unity-game-engine unityscript

问题是我有两个着色器。如果我在游戏运行时更改着色器,它将不会生效。仅当我使用当前着色器启动游戏时,它才会使用该着色器,但不会使用我切换到的着色器。

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

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

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

    renderer.material = materials[count];
}
Run Code Online (Sandbox Code Playgroud)

小智 6

简答

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

Unity 教程的 Thomas 说得最好:

您最有可能想到的第一件事是:

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

容易,对吧?只需抓住该颜色并进行动画处理即可。这样做的问题是,为了更改着色器中的颜色,Unity 需要告诉 GPU 该对象将以不同的方式渲染,而唯一的方法就是更改材质实例。因此,当您第一次访问 renderer.material 时,Unity 会创建材质的副本。

这意味着可能存在大量材料副本,所有这些都在消耗内存 1

包含 2500 个球体的场景,全部共享相同的材质。其他 39 个材质用于场景中的其他项目。1

在此输入图像描述 1

在摆弄了GameObject.renderer.material.shader2500 个物体之后。请注意材料如何从40 种跃升至 2540种材料!

在此输入图像描述 1

长答案

首先复习一下。在 Unity 中,您创建(或从资源商店购买)着色器,然后创建材质。然后,材质引用着色器,提供着色器可能需要的任何参数,例如纹理;凹凸贴图;以及标量,该标量将区分该材质与可能使用相同着色器的任何其他材质。完成后,您可以将材质应用到对象上。

我的意思是在同一个游戏对象上的着色器之间切换

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

您想要做的是切换对象上的材质

如果我在游戏运行时更改着色器,它将不会生效

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

解决方法

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

MaterialPropertyBlock 由 Graphics.DrawMesh 和 Renderer.SetPropertyBlock 使用。当您想要绘制具有相同材质但属性略有不同的多个对象时,请使用它。例如,如果您想稍微更改绘制的每个网格的颜色。不支持更改渲染状态 更多...

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

这么简单的事情却有很多复杂性。最好提前拥有预先设计的材料。这可以说是一种更好的做法。

告诉我更多

  1. 优秀文章物质属性块的魔力

  2. “仅更改一个对象的材质颜色”答案,Unity