UnityShader[4]几何着色器与可交互草地

GeometryShader执行顺序在顶点着色器之后,片元着色器以前。GeometryShader以一个/多个顶点组成的图元为输入,开发人员可以修改/添加顶点,修改为完全不同的网格,得到更多好看的效果。
缺点:并行困难,对移动端不友好,需要ShaderModel4.0以上
定义一个几何着色器,首先需要在声明模块添加几何着色器的声明;添加顶点着色器向几何着色器输出的结构体;修改ShaderModel版本为4.0以上

#pragma vertex vert
#pragma geometry geo
#pragma fragment frag

#include "UnityCG.cginc"
#pragma target 5.0

struct appdata
{
   
    float4 vertex : POSITION;
    float2 uv : TEXCOORD0;
};

struct v2g
{
   
    float4 vertex : POSITION;
    float2 uv : TEXCOORD0;
};

struct g2f
{
   
    float2 uv : TEXCOORD0;
    float4 vertex : SV_POSITION;
};

然后编写geometryShader主体:

[maxvertexcount(3)] // 最多调用3个顶点
// 输入:point / line / lineadj / triangle / triangleadj
// 输出:LineStream / PointStream / TriangleStream 
void geo(triangle v2g input[3], inout PointStream<g2f> outStream)
{
   
    g2f o;
    o.vertex = input[1].vertex;
    o.uv = input[1].uv;
    outStream.Append(o);
}
  • [maxvertexcount(value)] 代表告诉Shader该几何着色器最多单次调用多少个顶点
  • triangle v2g input[3] 参数代表以一个三角形图元为单位进行输入,包含3个顶点;
  • inout PointStream outStream 参数代表以一个点(PointStream)为单位进行输出;
  • outStream.Append(o) 代表将o点添加到outStream中;

可以看到几何着色器是以流为单位进行输入输出的,输入和输出关键字的区别会让流的解析发生改变,例如输出选择了PointStream,该类型的流会认为给定的数据中包含一个顶点,然后进行解析,将这个顶点输出;而选择了TriangStream则会认为给定的数据包含三个顶点,进行解析时会将三个顶点合成为一个三角形输出
上述代码:输入一个三角形,输出该三角形中的2号顶点(数组中顶点编号0,1,2代表三角形顶点编号1,2,3)。可以得到一个点阵Shader:
在这里插入图片描述

[maxvertexcount(3)]
void geo(triangle v2g input[3], inout LineStream<g2f> outStream)
{
   
    g2f o;
    for(int i=0; i<2; i++)
    {
   
        o.vertex = input[i].vertex;
        o.uv = input[i].uv;
        outStream.Append(o);
    }
}

上述代码:输入一个三角形,输出该三角形的0顶点、1顶点连接成的线段。(网格效果)

在这里插入图片描述

几何着色器还可以根据已有顶点生成新的顶点并构建图形,达到一些其他效果。此处尝试给每个三角形生成中心点:

[maxvertexcount(9)]
void geo(triangle v2g input[3], inout TriangleStream<g2f> outStream)
{
   
    g2f o;

    // 获取中心顶点
    float3 centerPos = (input[0].vertex + input[1].vertex + input[2].vertex) / 3;
    float2 centerUV = (input[0].uv + input[1].uv + input[2].uv) / 3;

    for(uint i=0; i<3; i++)
    {
   
        o.vertex = UnityObjectToClipPos(input[i].vertex);
        o.uv = input[i].uv;
        outStream.Append(o);

        uint j = (i + 1) % 3;
        o.vertex = UnityObjectToClipPos(input[j].vertex);
        o.uv = input[j].uv;
        outStream.Append(o);

        o.vertex = UnityObjectToClipPos(float4(centerPos, 1.0));
        o.uv = centerUV;
        outStream.Append(o);
                    
        // 重置剥
        outStream.RestartStrip();
    }
}

此时要适当提高控制的顶点数(9个,因为会输出3个三角面)。算法计算得出中心点在模型空间中的位置、uv等参数,将三个顶点(0号、1号、中心点)合成一个三角面添加进入outStream,直到将中心点分割得到的三个三角面均添加进入outStream,最后输出:
在这里插入图片描述

需要注意的是,如果先进行了顶点着色,即进入几何着色步骤时顶点已经转换到齐次裁剪空间下,会导致中心顶点计算错误,法线不匹配等问题。解决的方法就是将空间变换算法移动到中心顶点计算之后进行,如上述算法就是将UnityObjectToClipPos写到中心顶点计算完成之后(VertexShader只进行了数据转移操作)。
之后让中心点根据自身法线进行外扩,获取法线方向,然后对中心点坐标进行移动:

float3 edgeA = input[1].vertex - input[0].vertex;
float3 edgeB = input[2].vertex - input[0].vertex;
float3 normal = normalize(cross(edgeA, edgeB));
// 中心点向外挤出
centerPos += normal.xyz * _Length;

可以获得刺球效果:
在这里插入图片描述

生成大面积草地

几何着色器可用于生成网格,如果在其中增加一些随机数,就能让网格获得不同的旋转角度、弯曲程度、高度、摆动速度…足够生成一片随机的草地,而且因为没有使用预设的网格/实例,性能也变得可观。
参考:https://zhuanlan.zhihu.com/p/29632347
首先利用CPU生成大量随机位置,然后GPU在其上生成网格,渲染为草。
草的网格:
在这里插入图片描述

偶数顶点在左侧、奇数顶点在右侧,方便遍历和计算uv。
Shader需要根据给定顶点产生多个上述网格:

[maxvertexcount(30)]
void geo(point v2g input[1], inout TriangleStream<g2f> outStream)
{
   
    const uint vertexCount = 12; // 顶点数量
    g2f o[vertexCount]
  • 8
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
引用中提到了一种使用草地着色器的方法,该方法通过传递透明度贴图和顶点色来控制草的形状和颜色。这种方法可以有效减少DrawCall的数量,并且通过传递顶点的法线可以产生不同的受光效果。这样的草地着色器可以实现草地交互效果。 另外,引用中提到了一些草地着色器的拓展性功能,例如延迟恢复、画笔工具、风压控制和引燃效果等。这些功能可以进一步增强草地交互效果。 而引用中提到了草地着色器的优化方法。草地在风中会有规律性的摆动,因此需要生成具有规律的系数来控制草的宽度和高度。通过这种方法,可以实现个体上的随机性和整体上的一致性动画效果。 综上所述,Unity草地着色器可以通过传递透明度贴图和顶点色来控制草的形状和颜色,并可以通过拓展性功能实现更多的交互效果。另外,通过优化草地着色器,可以实现草地在风中的规律性摆动效果。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [UnityShader[4]几何着色器与可交互草地](https://blog.csdn.net/Thanatos_Left/article/details/126141627)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值