• 初次尝试GPU Driver —— 大范围植被渲染之着色


    初次尝试GPU Driver —— 大范围植被渲染之着色

    《初次尝试GPU Driven —— 大范围植被渲染》中实现了草地分布,本文实现草的着色。

    本文分四个部分:

    • 生成网格
    • 随机调整
    • 着色
    • 风场

    生成草网格

    网格形状通常有矩形和三角形,本文使用三角形的网格。

    草网格

    上图从左到右依次提高细节。

    随机调整

    用上一步生成的网格渲染,会看到这样的画面。

    整齐

    很显然,分布的太整齐了,草丛不是整齐排列的,所以每颗草不能都用一样的方向和大小渲染,在这一步将草随机一下。思路是通过草的世界坐标得出随机值,用该随机数去旋转&缩放顶点,因为每颗草的世界坐标是固定的,所以随机数也是固定的,又因为每颗草的坐标都不一样,所以随机数也可能会不一样(这不是病句)。

    随机数的计算方法有很多,只要让其尽可能乱就行了,计算出缩放和旋转后,再加上之前算出来的世界坐标,就可以构建变换矩阵了。

    float3 wcoord = _GrassCoords[instanceID];
    
    ...
    
    float random(float2 pos)
    {
        return frac(sin(dot(pos, float2(12.9898, 78.2330))) * 1.9);
    }
    
    ...
    
    //  平移/缩放/旋转
    float  rand  = random(wcoord.xz);
    //  随机缩放
    float2 scale = lerp(float2(0.2, 0.5),
                        float2(0.3, 1.0), rand);
    //  随机旋转
    float2 rotate = float2(cos(rand * UNITY_PI * 2),
                           sin(rand * UNITY_PI * 2));
    
    float4x4 transform = float4x4(float4(scale.x * rotate.x,       0, -rotate.y, wcoord.x),
                                  float4(                 0, scale.y,         0, wcoord.y),
                                  float4(         -rotate.y,       0,  rotate.x, wcoord.z),
                                  float4(0, 0, 0, 1));
    
    ...
    
    o.wcoord = mul(transform, v.vertex);
    o.vertex = UnityWorldToClipPos(o.wcoord);
    

    随机

    草已经被打乱了,但每颗草太直了,接下来压弯每颗草,思路是将草往前倾斜,同时降低Y轴值,Y轴值越大,则倾斜越大,下压力越大。

    float2 forward = float2(0, 1);
    float2 offset = forward * scale.y * _Bend
                  * v.vertex.y * v.vertex.y;
    v.vertex.xz += offset;
    v.vertex.y  -= length(offset);
    

    压弯

    把数量翻10倍后,画面如下:

    10倍

    着色

    着色这部分简单处理,给定两个基础颜色,分别表示草的顶部和底部色,随后用Lambert光照着色。

    float3 worldCoord = i.wcoord;
    float3 worldNormal = normalize(i.normal);
    float3 lightNormal = UnityWorldSpaceLightDir(worldCoord);
    float4 color = lerp(_BottomColor, _TopColor, i.vcoord.y);
    
    fixed3 ambient = color * UNITY_LIGHTMODEL_AMBIENT.rgb;
    fixed  wDotL = max(0.2, dot(worldNormal,lightNormal));
    fixed3 diffuse = color * wDotL * _LightColor0.rgb;
    color.rgb += ambient;
    color.rgb += diffuse;
    return color;
    

    着色

    风场

    这一步加入风的影响,通过风向,风速,风力三个因素定义风,随时间挪动影响范围。

    本文的风区分微风和强风,微风持续影响,强风按频率影响,可以抖动一下频率效果更佳。

    本文强风用下图频率:

    波浪

    //  基础风
    float3 wind      = _WindDirect * _WindPower * v.vertex.y * v.vertex.y;
    float  windValue = tex2Dlod(_WindMask, float4(wcoord.xz / 64, 0, 0)).r;
    //  微风
    wcoord.xyz += wind * sin(_Time.y * _WindSpeed + dot(wcoord, _WindDirect)) * 0.3;
    //  强风
    wcoord.xyz += wind * saturate(sin(_Time.y * _WindSpeed + dot(wcoord, _WindDirect))) * windValue;
    wcoord.xyz += wind * saturate(sin(0.75 * _Time.y * _WindSpeed + dot(wcoord, _WindDirect))) * windValue;
    wcoord.xyz += wind * saturate(sin(0.25 * _Time.y * _WindSpeed + dot(wcoord, _WindDirect))) * windValue;
    

    到此,渲染部分就结束了,下面展示一段加入高度图后的最终表现:

    最终渲染
    最终渲染

    签名: 你还在追逐你的人生巅峰,但你的人生巅峰很可能早已逝去。
  • 相关阅读:
    dubbo入门(一)
    java中文件操作《一》
    Unity 游戏框架搭建 2019 (七) 自定义快捷键
    凉鞋:我所理解的框架 【Unity 游戏框架搭建】
    Unity 游戏框架搭建 2019 (六) MenuItem 复用
    Unity 游戏框架搭建 2019 (五) 打开所在文件夹
    Unity 游戏框架搭建 2019 (四) 导出 UnityPackage
    Unity 游戏框架搭建 2019 (三) 生成文件名到剪切板
    Unity 游戏框架搭建 2019 (二) 文本复制到剪切板
    Unity 游戏框架搭建 2019 (一) 简介与第一个示例文件名的生成
  • 原文地址:https://www.cnblogs.com/mmc1206x/p/15570374.html
Copyright © 2020-2023  润新知