本系列主要参考《Unity Shaders and Effects Cookbook》一书(感谢原书作者),同时会加上一点个人理解或拓展。

这里是本书所有的插图。这里是本书所需的代码和资源(当然你也可以从官网下载)。

========================================== 分割线 ==========================================

题外话

新年第一篇!在此就献给了这个系列。马上就可以放假回家了,虽然还有一些事情需要处理,但是能和家人团聚实在是件很难得的事了。希望所有朋友也能记得多回家看看,借最近很热门的电影《私人定制》(我没看过甲方乙方什么的,觉得这个还不错啦)中的插曲《时间都去哪儿了》,不要等到时间都不见了才想起家人,希望朋友们和朋友的家人们在新年里都能幸福!

门前老树长新芽
院里枯木又开花
半生存了多少话
藏进了满头白发

记忆中的小脚丫
肉嘟嘟的小嘴巴
一生把爱交给他
只为那一声爸妈

时间都去哪儿了
还没好好感受年轻就老了
生儿养女一辈子
满脑子都是孩子哭了笑了

时间都去哪儿了
还没好好看看你眼睛就花了
柴米油盐半辈子
转眼就只剩下满脸的皱纹了

准备工作

  1. 打开Unity,创建一个新的Shader和一个新的Material,名字分别为ScrollingUVs;
  2. 确保你已下载相关资源,将第二章所需资源(在Unity assets下)导入Unity;
  3. 新建一个场景,名为ScrollingUV_Scene,并新建一个光源。找到第二步中导入Unity中的模型River_GRP.fbx,拖入新建的场景中,调节摄像机位置,使River_GRP出现在合适的视角范围内;
  4. 场景中的River_GRP应该包含了两个子物体,Ground_GEO和River_GEO。改变River_GEO使用的Material为第一步中创建的新的Material,Ground_GEO使用其默认材质即可。
  5. 最后你可以看到类似下面的情景(我更改了Ground_GEO使用的材质的颜色,因此会呈现出土黄色):

实现

  1. 添加两个新的Properties,使得我们可以调整texture的滚动速度:
    	Properties {
    _MainTex ("Base (RGB)", 2D) = "white" {}
    // Add two properties
    _ScrollXSpeed ("X Scroll Speed", Range(0, 10)) = 2
    _ScrollYSpeed ("Y Scroll Speed", Range(0, 10)) = 2
    }
  2. 在CGPROGRAM部分修改代码,添加两个新的变量,对应上面新增的两个Properties,以使我们可以在后面访问它们:
                    CGPROGRAM
    #pragma surface surf Lambert sampler2D _MainTex;
    fixed _ScrollXSpeed;
    fixed _ScrollYSpeed;
  3. 修改surf函数,通过tex2D函数来改变UV坐标。然后使用内置的_Time变量来根据运行时间滚动texture:
    		void surf (Input IN, inout SurfaceOutput o) {
    fixed2 scrolledUV = IN.uv_MainTex; fixed xScrollValue = _ScrollXSpeed * _Time.y;
    fixed yScrollValue = _ScrollYSpeed * _Time.y; scrolledUV += fixed2(xScrollValue, yScrollValue); half4 c = tex2D (_MainTex, scrolledUV);
    o.Albedo = c.rgb;
    o.Alpha = c.a;
    }
  4. 最后,Shader代码如下所示:
    Shader "Custom/ScrollingUVs" {
    Properties {
    _MainTex ("Base (RGB)", 2D) = "white" {}
    // Add two properties
    _ScrollXSpeed ("X Scroll Speed", Range(0, 10)) = 2
    _ScrollYSpeed ("Y Scroll Speed", Range(0, 10)) = 2
    }
    SubShader {
    Tags { "RenderType"="Opaque" }
    LOD 200 CGPROGRAM
    #pragma surface surf Lambert sampler2D _MainTex;
    fixed _ScrollXSpeed;
    fixed _ScrollYSpeed; struct Input {
    float2 uv_MainTex;
    }; void surf (Input IN, inout SurfaceOutput o) {
    fixed2 scrolledUV = IN.uv_MainTex; fixed xScrollValue = _ScrollXSpeed * _Time.y;
    fixed yScrollValue = _ScrollYSpeed * _Time.y; scrolledUV += fixed2(xScrollValue, yScrollValue); half4 c = tex2D (_MainTex, scrolledUV);
    o.Albedo = c.rgb;
    o.Alpha = c.a;
    }
    ENDCG
    }
    FallBack "Diffuse"
    }
  5. 回到Unity的Inspector面板,给材质拖拽适当的texture(例如Chapter02_WaterfallGraph_Diffuse)。最后你会看到如下的效果(点击Play后可以看到动态效果):

解释

  1. 添加的两个Properties允许我们可以在Material的Inspector面板中控制Shader中使用的那些变量。详情可见上一章;
  2. 在surf函数中,我们首先将UV坐标存储在scrolledUV变量中,并且该变量需要是float2类型或者fixed2类型。这是因为我们是通过以下定义的结构来传递UV的:
                    struct Input {
    float2 uv_MainTex;
    };
  3. 随后,我们通过内置变量_Time计算UV偏移量。_Time变量返回一个float4类型的变量。关于Unity内置变量的详细信息请参见官方文档
  4. 最后,我们将计算而得的偏移量叠加到之前得到的UV坐标scrolledUV上,得到最终的UV坐标,并通过tex2D函数访问该像素值。

结束语

上面最后的效果还是不尽如人意。实际上,很多时候我们使用C#代码等来控制材质滚动,而不是在Shader中。这是因为不同的surface可能使用同一个Shader,但是需要不同的滚动速度,如果在Shader中定义这种速度,就无法实现不同的移动效果。
上面的Shader之所以不是非常美观,还有一点是因为它的光照渲染模型是Diffuse。而很多情况下,还需要透明、反射等性质。下面我们给出一种比较实用的Shader和UV滚动代码。
效果图如下:
Shader如下:
Shader "Mobile/Transparent/Vertex Color" {
Properties {
_Color ("Main Color", Color) = (1,1,1,1)
_SpecColor ("Spec Color", Color) = (1,1,1,0)
_Emission ("Emmisive Color", Color) = (0,0,0,0)
_Shininess ("Shininess", Range (0.1, 1)) = 0.7
_MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
} Category {
Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
ZWrite Off
Alphatest Greater 0
Blend SrcAlpha OneMinusSrcAlpha
SubShader {
Material {
Diffuse [_Color]
Ambient [_Color]
Shininess [_Shininess]
Specular [_SpecColor]
Emission [_Emission]
}
Pass {
ColorMaterial AmbientAndDiffuse
Fog { Mode Off }
Lighting Off
SeparateSpecular On
SetTexture [_MainTex] {
Combine texture * primary, texture * primary
}
SetTexture [_MainTex] {
constantColor [_Color]
Combine previous * constant DOUBLE, previous * constant
}
}
}
}
}

控制UV滚动代码如下:

using UnityEngine;
using System.Collections; public class WaterFlow : MonoBehaviour { public float m_SpeedU = 0.1f;
public float m_SpeedV = -0.1f; // Update is called once per frame
void Update () {
float newOffsetU = Time.time * m_SpeedU;
float newOffsetV = Time.time * m_SpeedV; if (this.renderer)
{
renderer.material.mainTextureOffset = new Vector2(newOffsetU, newOffsetV);
}
}
}

河流所使用的Material的Shader配置如下(这里的River仅仅是一个Plane):

当然,可以选择不同的texture并调整上面的Main Color、Spec Color、Emmisive Color、Shininess等值来得到需要的效果。
需要注意的是,上面的River下面实际上还包含了一层地面,即如果没有River,画面是这样的:
除了Shader外,上面的代码很好理解。对于Shader内部的实现原理,呜,还需要深入理解一下,希望在后面的内容里会补充到。
好了,这次就到这里!

【Unity Shaders】Using Textures for Effects——通过修改UV坐标来滚动textures的更多相关文章

  1. 【Unity Shaders】Using Textures for Effects —— 实现Photoshop的色阶效果

    本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...

  2. 【Unity Shaders】Using Textures for Effects——打包和混合textures

    本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...

  3. 【Unity Shaders】Using Textures for Effects介绍

    本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...

  4. 【Unity Shaders】Using Textures for Effects——让sprite sheets动起来

    本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...

  5. 【Unity Shaders】使用Unity Render Textures实现画面特效——建立画面特效脚本系统

    本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...

  6. 【Unity Shaders】使用Unity Render Textures实现画面特效——画面特效中的亮度、饱和度和对照度

    本系列主要參考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同一时候会加上一点个人理解或拓展. 这里是本书全部的插图. 这里是本书所需的代码 ...

  7. 【Unity Shaders】《Unity Shaders and Effects Cookbook》总结篇

    我的唠叨 不知不觉,从发表第一篇关于<Unity Shaders and Effects Cookbook>已经快十个月了.一开始的初衷就是学习笔记,毕竟将来回过头去看的时候,再看英文难免 ...

  8. Unity Shaders and Effects Cookbook (3-4) 使用高光贴图

    在学习完上一节之后.已经了解了在Unity 中怎样实现一个高光 Shader ,可是会有一个问题.就是效果看起来不切实际,如以下的问题 我用一张图片贴到了Cube上面.然后用了一个高光材质,得到了下图 ...

  9. 【Unity Shaders】Reflecting Your World —— Unity3D中的遮罩反射(Masking Reflections)

    本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...

随机推荐

  1. ORA-01207: file is more recent than control file - old control file的处理方法

    1. 连接数据库 sqlplus / as sysdba2. 启动数据库,此时会报标题中的错误startup 3.备份创建控制文件的脚本语句,并从中拷贝出相关的NORESETLOGS模式的创建控制文件 ...

  2. Linux下使用MD5加密BASE64加密

    这里以字符串123456为例子,它的md5密文值为:e10adc3949ba59abbe56e057f20f883e 这里以1.txt为需要被加密的文件. 一. 用oppnssl md5 加密字符串和 ...

  3. Docker常见仓库Nginx

    Nginx 基本信息 Nginx 是开源的高效的 Web 服务器实现,支持 HTTP.HTTPS.SMTP.POP3.IMAP 等协议. 该仓库提供了 Nginx 1.0 ~ 1.7 各个版本的镜像. ...

  4. Android Multimedia框架总结(二十四)MediaMuxer实现手机屏幕录制成gif图

    转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/53866405 前言:上篇中,介绍 ...

  5. 到底什么是集群&分布式

    对于楼主这样工作一年的菜鸟,偶尔会看到一些文章标题带有"分布式""集群"关键字,然后就懵逼了.最近对这些概念进行了一定的了解,整理了一下思路,在这里分享给各位猿 ...

  6. React Native之ScrollView控件详解

    概述 ScrollView在Android和ios原生开发中都比较常见,是一个 滚动视图控件.在RN开发中,系统也给我们提供了这么一个控件.不过在RN开发中 ,使用ScrollView必须有一个确定的 ...

  7. SpringMVC基础配置(通过注解配置,非xml配置)

    SpringMVC是什么,有多火,我这里就不再啰嗦了,SpringMVC比Struts2好用太多,我在学校的时候私下里两种都接触过,对比之后果断选择了SpringMVC,后来在做Android应用开发 ...

  8. SpriteKit关于SKScene中的渲染Loop

    在本节中,我将来说明一下SKScene在SKView显示之后发生了神马. 在更传统的iOS app中,你可能只会渲染view的内容仅仅一次,然后它将保持静态直到view的模式发生了显示的改变,这对于商 ...

  9. Xcode8之后,苹果列出了最新App被拒十大原因

    开发者在开发应用程序之前,熟悉苹果审核应用的技术.内容以及设计准则是非常重要的,可以大大降低应用审核被拒的可能性. 最近,苹果通过一个专门的页面给出了截止2016年10月10日应用提交审核被拒的十大原 ...

  10. Effective C++ ——构造/析构/赋值运算符

    条款五:了解C++默认编写并调用那些函数 是否存在空的类? 假设定义类为class Empty{}:当C++编译器处理过后会变成如下的形式: class Empty{ Empty(){} ~Empty ...