2

我希望为发射立方体网格的粒子系统创建一个无光照着色器,这样每个发射的网格周围都有一个坚硬的黑色轮廓。

这是大纲的通行证(在 Cg 中):

struct appdata {
    float4 vertex : POSITION;
    float3 normal : NORMAL;
};

struct v2f {
    float4 pos : POSITION;
    float4 color : COLOR;
};

uniform float _Outline;
uniform float4 _OutlineColor;

v2f vert(appdata v) {
    v2f o;

    v.vertex *= ( 1 + _Outline);

    o.pos = UnityObjectToClipPos(v.vertex);

    o.color = _OutlineColor;
    return o;
}

half4 frag(v2f i) :COLOR { return i.color; }

(在此之后是一个简单的传递来渲染网格本身的无光照几何......)

如您所见,我们只是将顶点向外拉伸……但是从什么开始呢?

对于单个立方体网格,着色器完美运行:

应用于单个立方体网格的着色器

但是,当应用于发射立方体网格的粒子系统时,着色器会发生故障:

应用于粒子系统发射立方体的着色器

我的怀疑是这条线从对象v.vertex *= ( 1 + _Outline);中心向外延伸顶点,而不是网格中心。

是否有人对如何解决此问题有替代着色器或见解?

谢谢, 雅各布

4

2 回答 2

1

事实证明我误解了这个问题。当访问POSITION顶点的语义时,您将获得世界空间中发射粒子的顶点;因此,通过相乘来拉伸顶点实际上只是将它们从世界中心缩放。

要访问相对于每个粒子的顶点,我们必须能够从着色器中访问每个粒子的网格中心。为此,我们在粒子系统的渲染器模块中启用“自定义顶点流”,然后按 + 按钮添加中心流。

渲染器模块中的自定义顶点流

现在我们可以TEXCOORD0从着色器访问(或在粒子渲染器 GUI 中中心流右侧指定的任何内容)以获取世界空间中的网格中心。然后我们从每个顶点位置减去网格中心,向外缩放,然后将网格中心添加回来。瞧,每个粒子都有一个轮廓。

以下是大纲通道的最终顶点和片段片段:

        struct appdata {
            float3 vertex : POSITION;
            float4 color : COLOR;
            float3 center : TEXCOORD0;
        };

        struct v2f {
            float4 pos : POSITION;
            float4 color : COLOR;
            float3 center : TEXCOORD0;

        };

        uniform float _Outline;
        uniform float4 _OutlineColor;

        v2f vert(appdata v) {
            v2f o;
            o.center = v.center;
            float3 vert = v.vertex - v.center;
            vert *= ( 1 + _Outline);
            v.vertex = vert + v.center;
            o.pos = UnityObjectToClipPos(v.vertex);

            o.color = _OutlineColor;
            return o;
        }

        half4 frag(v2f i) :COLOR { return i.color; }

TLDR:启用顶点流,为粒子中心添加一个流,并在着色器中访问此值以向外缩放各个顶点。

于 2019-08-24T02:48:47.407 回答
0

我的怀疑是这条线v.vertex *= ( 1 + _Outline); 从对象中心向外延伸顶点,而不是网格中心。

那是正确的。或者大部分是正确的(粒子系统将所有粒子组合到一个运行时网格中,这就是您的着色器所应用的,而不是底层的单个粒子网格,这并不明显)。在非凸面网格(也不是粒子)上尝试使用轮廓着色器:您会发现凹面部分没有所需的轮廓,这证实了您的怀疑。

几年前我写了这个着色器,因为我能发现生成的轮廓的唯一免费着色器要么是(a)不是免费的,要么是(b)“只是将它放大”种类。它仍然存在问题(例如在大厚度值下出现锯齿状和怪异),但我从未能够令人满意地解决它们。它使用几何通道将源网格的边缘转换为面向相机的四边形,然后使用模板魔法仅渲染轮廓部分。

但是我不确定该着色器在应用于粒子时是否会起作用。我怀疑它不会未经修改,但你可以自由地试一试。

于 2019-08-23T14:21:51.307 回答