卡通风格水体渲染实现【v0.2】

3.23 | v0.2


grass
这种麦浪/可交互草有人感兴趣嘛? :expressionless:,有空整理出来。


3.22 | v0.1

效果图

最近在学习unity的地编,用Shader Graph实现了个简单的卡通风格水体。看见论坛有个小伙伴在问基于深度图的水体,所以试着在creator实现了一下,先来一张效果GIF图。(由于暂时无法对Terrain生成深度图,暂时就用石头代替了:rofl:)
water

实现

  • 基于PBR Shader的实现,这里直接使用了默认的builtin-standard材质。随便调下参数就可以有不错的高光和反射效果。

  • 水波的实现,这里使用双层法线混合,通过改变法线的速度和强度来实现。

    Shader代码:
    // 法线1
    // 上下文中的uv使用水面世界位置的xz值,即uv = v_position.xz
    vec2 uv0 = uv * bigNormalParam.x + cc_time.x * bigNormalParam.y;
    vec3 nmmp0 = texture(normalMap, uv0).xyz - vec3(0.5);
    vec3 normal0 = (nmmp0.x * bigStrength) * tangentNormalize + (nmmp0.y * bigStrength) * bitangentNormalize + nmmp0.z * normalNormalize;
    // 法线2
    vec2 uv1 = uv * smallNormalParam.x + cc_time.x * smallNormalParam.y;
    vec3 nmmp1 = texture(normalMap, uv1).xyz - vec3(0.5);
    vec3 normal1 = (nmmp1.x * smallStrength) * tangentNormalize + (nmmp1.y * smallStrength) * bitangentNormalize + nmmp1.z * normalNormalize;
    // 法线混合
    Unity_NormalBlend_float(normal0, normal1, s.normal);

  • 水体边缘的柔和处理,这里使用水面的深度值场景深度值smoothstep水面深度值通过一个变量来控制,场景深度值由深度图获得,由于creator暂时不支持深度图,这里直接使用了麒麟子大佬的实现

    Shader代码:
    vec3 vertVec = v_position - cameraPos.xyz;
    // 求出水面的深度值
    float vertZ = dot(vertVec, cameraDirection);
    // 重映射
    float vertZR = Remap(vertZ, 0.0, far, 0.0, 1.0);
    // 水面的深度
    float waterAlphaZR = Remap((vertZ + depthParam.x), 0.0, far, 0.0, 1.0);
    // 水面边缘过渡
    float a = smoothstep(linear01Depth, vertZR, waterAlphaZR);

  • 浅水颜色/深水颜色/雾颜色的过渡浅水和深水的颜色过渡还是和水体边缘检测一样的处理,通过另一个变量来控制深度,更远处的雾颜色用雾距离变量水和摄像机的距离比来控制。

    Shader代码:
    // 控制水面的颜色深度
    float waterColorZR = Remap((vertZ + depthParam.y), 0.0, far, 0.0, 1.0);
    float colorSmo = smoothstep(linear01Depth, vertZR, waterColorZR);
    // 浅水和深水颜色的过渡
    vec4 depthCol = Lerp(colorSmo, shallowColor, deepColor);
    // 求与摄像机的距离
    float dis = distance(v_position, cameraPos.xyz);
    // 0 - 1
    float disCla = clamp(dis / depthParam.z, 0.0, 1.0);
    // 与雾颜色过渡
    vec4 col = Lerp(disCla, depthCol, fogColor);

  • 浅水区的水面波纹,这里采用水面颜色与Voronoi图相加,通过控制采样Voronoi图的角度偏移/密度/功率来实现。关于Voronoi图大家可以自行搜索,这里贴一张普通噪声图Voronoi噪声图的对比。

    Shader代码:
    vec2 uv2 = uv * depthParam.w + cc_time.x * 0.05;
    float angleOffset = cc_time.x * 3.0;
    float voronoiOut = 0.0;
    vec4 rippleColor = vec4(2.0, 2.0, 2.0, 0.0);
    // 采样Voronoi图
    Unity_Voronoi_float(uv2, angleOffset, 0.7, voronoiOut);
    // 与水面颜色混合
    col += (pow(voronoiOut * (1.0 - colorSmo), 5.0) * rippleColor);

  • Shader中的自定义函数

    // 以下是Unity中的实现
    // 法线强度混合
    void Unity_NormalBlend_float(vec3 A, vec3 B, out vec3 Out) {
     Out = normalize(vec3(A.rg + B.rg, A.b * B.b));
    }
    // 重映射
    float Remap(float x, float t1, float t2, float s1, float s2) {
     return (x - t1) / (t2 - t1) * (s2 - s1) + s1;
    }
    // 插值
    vec4 Lerp(float x, vec4 a, vec4 b) {
     return a + x * (b - a);
    }
    // Voronoi图的采样
    vec2 Unity_Voronoi_RandomVector_float(vec2 UV, float offset)
    {
     mat2 m = mat2(15.27, 47.63, 99.41, 89.98);
     UV = fract(sin(UV * m) * 46839.32);
     return vec2(sin(UV.y * +offset) * 0.5 + 0.5, cos(UV.x * offset) * 0.5 + 0.5);
    }
    // Voronoi图的采样
    void Unity_Voronoi_float(vec2 UV, float AngleOffset, float CellDensity, out float Out) {
     vec2 g = floor(UV * CellDensity);
     vec2 f = fract(UV * CellDensity);
     float t = 8.0;
     vec3 res = vec3(8.0, 0.0, 0.0);
     for(int y = -1; y <= 1; y++) {
      for(int x = -1; x <= 1; x++) {
       vec2 lattice = vec2(x, y);
       vec2 offset = Unity_Voronoi_RandomVector_float(lattice + g, AngleOffset);
       float d = distance(lattice + offset, f);
       if(d < res.x) {
        res = vec3(d, offset.x, offset.y);
        Out = res.x;
       }
      }
     }
    }

OVER!

此贴仅抛砖引玉,后续会整理一下详细拆分和细节讲解。也会在creator中使用地编/INSTANCE 草/原神角色模型导入/RPG游戏中的人物动作和战斗动作等,期待creator新版的Terrain和Marionette系统,也希望creator可以尽快完善渲染流程。

8赞

《随便调下》

工程文件在商城搜索 卡通风格水体渲染 ,没有就是在审核 :confused:

mark,mark

:+1:

大佬

随便调下,TQL


审核大大贴贴,这么快就通过了 :kissing_closed_eyes:,欢迎下载。

1赞

想问下,2d精灵图可以用吗?

没太懂您说的,是要把材质应用于ui吗?

是的,没错。

big old six six six!

Terrain可以给一个自定义的Effect,把builtin-terrain.effect copy一份,改改就行。

:rofl:原来那个effect指shader啊,找了半天没发现自定义材质在哪,感谢。

膜拜大佬大佬

【v0.2】

:+1: :+1: :+1: :+1: :+1:

膜拜大佬神操作