shader学习之路(2)- 贴图uv移动模拟水流效果

    xiaoxiao2025-04-25  12

    前言

    在游戏中,水流效果是十分常见的,实现的原理除开真实流体计算以外,还有一种简易的方式实现简单的水流效果,即通过移动贴图的UV坐标,在静态的物体贴图上模拟出水流效果。 上图为《神秘海域3》的水流效果,其开发花絮讲述了该作的水流基于离线渲染、动态渲染,是复杂的物理效果,移动uv贴图的效果自然无法媲美,不过在一般情况下很多游戏的中那些非细节性的水流、岩浆等,使用移动uv贴图也是足够了。再此使用shader来进行uv坐标的偏移。

    准备知识

    再此小讲一下UV坐标,UV坐标是指二维图像作为一个平面,水平方向是U,而垂直方向是V,根据UV坐标即可确定图中任意一个像素点,U、V坐标的范围均为(0,1)。在directx中,UV坐标方向如下图: 而OpenGL中方向一般如下图: 在不同的API下,需要考虑不同的uv方向。

    准备工作

    下载Unity shaders and effects cookbook的素材资源:点击下载

    解压Unity assets中的5084_02_UnityAssets.rar,将其中的 River_GRP.fbx 与 Chapter02_WaterfallGraph_Diffuse.png 拷贝到你的工程中

    Shader编写

    接下来,来尝试下这个uv坐标偏移shader 首先,建立一个新的surface shader 打开后在Properties变量栏中删除原有属性,添加如下几个属性

    这两个属性分别为uv坐标的X Y左边的偏移速度,放在该效果中能控制水流速度。接着在SubShader段中声明与Properties同名的变量Properties:

    同时修改一下光照模型,再此我使用的是默认Lambert模型

    接下就是surf函数了 因为已经不是默认的surf函数,所以记得将inout类型写为SurfaceOutput,scrolledUV是获取贴图的UV偏移量,这个源自于所设置的采样器结构体 _Time变量是基于Unity游戏时钟的递增性浮点数,将其与偏移速度相乘,即可获得随着时间改变的uv偏移量。通过时间计算出偏移量后,将偏移量添加到原有的uv值上,传入tex2D中作为新的纹理数据。

    接下来创建一个新材质,将该shader赋予该材质

    此时还缺少个贴图,将准备好的水流贴图放入其中,即完成了整个材质的创建。

    将准备好的模型拖入场景中,在将本材质拖入到模型中的River_GEO中

    启动编辑器后即可看到水流的效果

    有些时候,可能出现水流只播放一次然后彻底变为底色的情况,如果shader没有错误,只需将贴图的wrap mode该为Repeat即可。

    完整代码:

    Shader "Custom/RiverShader" { Properties { _MainTex ("Base (RGB)", 2D) = "white" {} _ScrollXSpeed ("X Scrll Speed", Range(0, 10)) = 2 _ScrollYSpeed ("Y Scrll Speed", Range(0, 10)) = 2 } SubShader { Tags { "RenderType"="Opaque" } LOD 200 CGPROGRAM // Physically based Standard lighting model, and enable shadows on all light types #pragma surface surf Lambert // Use shader model 3.0 target, to get nicer looking lighting #pragma target 3.0 fixed _ScrollXSpeed; fixed _ScrollYSpeed; sampler2D _MainTex; struct Input { float2 uv_MainTex; }; void surf (Input IN, inout SurfaceOutput o) { fixed2 scrolledUV = IN.uv_MainTex; fixed xScrollValue = _ScrollXSpeed * _Time; fixed yScrollValue = _ScrollYSpeed * _Time; scrolledUV += fixed2(xScrollValue, yScrollValue); half4 c = tex2D(_MainTex, scrolledUV); o.Albedo = c.rgb; o.Alpha = c.a; } ENDCG } FallBack "Diffuse" }

    由于一款游戏中可能有很多需要移动uv贴图的情况,所以有时候使用脚本代码来控制,但使用shader控制也是可行的。有关代码来移动贴图,可以参考程序媛冯乐乐的博客文章: 【Unity Shaders】Using Textures for Effects——通过修改UV坐标来滚动textures

    uv移动其实还有许多用处,不仅仅是做水流,例如岩浆、火焰等都可以使用类似的原理进行模拟,这个是最初级的一种效果,shader学习之路还很漫长,愿诸君共同加油!

    参考书目

    1.Unity shaders and effects cookbook

    转载请注明原文地址: https://ju.6miu.com/read-1298428.html
    最新回复(0)