Unity 粒子轮廓着色器

问题描述 投票:0回答:3

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

这是大纲的通行证(在 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);
object中心向外拉伸顶点,而不是网格中心。

有人有替代着色器或了解如何解决此问题吗?

谢谢, rbjacob

unity-game-engine shader cg shaderlab
3个回答
1
投票

事实证明我误解了这个问题。当访问顶点的

POSITION
语义时,您将获得 世界空间 中发射粒子的顶点;因此,通过乘法拉伸顶点实际上只是将它们缩放到远离世界中心的位置。

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

现在我们可以从着色器访问

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

以下是大纲通道的最终 vert 和 frag 片段:

        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: 启用顶点流,为粒子中心添加流,并在着色器中访问该值以向外缩放各个顶点。


0
投票

我怀疑线

v.vertex *= ( 1 + _Outline);
从对象中心向外拉伸顶点,而不是网格中心。

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

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

但是我不确定该着色器在应用于粒子时是否会起作用。我怀疑不加修改就可以,但你可以尝试一下。


0
投票

你是如何创造两种颜色的? 我正在尝试在 Shader Graph 中复制您的代码 - 我正在向片段部分添加颜色,并且它为整个网格着色(在代码期间更改大小的网格)。

© www.soinside.com 2019 - 2024. All rights reserved.