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

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

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

写在前面

有时候,我们并不想让物体的所有部分都反射,例如一个物体可能某些部分是玻璃材质的可以反射,而有些是塑料材质就不会反射。

在这篇教程里,我们将会学习一种技术来控制反射范围,这是通过一张texture作为遮罩(mask)来实现的。也就是说,我们可以使用一张texture的灰度值去决定该平面该如何反射,这意味着,一个为黑色的灰度值对应一个不会反射的子平面,而一个白色的灰度值对应一个完全反射的子平面。如今,基本所有的游戏制作都是使用这种方法来控制反射效果的。

下面,我们来看看在Unity里怎么使用Surface Shaders来实现它。

准备工作

  1. 首先,我们需要一个Cubemap,你可以生成一个新的或者使用前一篇用到的Cubemap。本教程所用的Cubemap如下(在本书的附带资源中可以找到):
  2. 我们还需要一个texture来描述我们对象的那些部分是可以反射的,而哪些不可以。记住,黑色表示没有任何反射性,而白色表示可以完全反射。下面的图片是我们将会用到的texture:
  3. 最后,我们需要创建一个新的场景以及场景中的一个对象、平面和一个平行光,来让我们观察反射效果。除此之外,新建一个Shader和对应的Material,并命名为MaskedReflection。

实现

  1. 添加新的Properties:
    	Properties {
    _MainTex ("Base (RGB)", 2D) = "white" {}
    _MainTint ("Diffuse Tint", Color) = (1,1,1,1)
    _ReflAmount ("Reflection Amount", Range(0, 1)) = 1
    _Cubemap ("Cubemap", CUBE) = ""{}
    _ReflMask ("Reflection Mask", 2D) = ""{}
    }
  2. 在SubShader块中添加它们的引用变量:
    		CGPROGRAM
    #pragma surface surf Lambert sampler2D _MainTex;
    sampler2D _ReflMask;
    samplerCUBE _Cubemap;
    float4 _MainTint;
    float _ReflAmount;
  3. 修改Input结构体:
    		struct Input {
    float2 uv_MainTex;
    float3 worldRefl;
    };
  4. 修改surf函数:
    		void surf (Input IN, inout SurfaceOutput o) {
    half4 c = tex2D (_MainTex, IN.uv_MainTex);
    float3 reflection = texCUBE(_Cubemap, IN.worldRefl).rgb;
    float4 reflMask = tex2D(_ReflMask, IN.uv_MainTex); o.Albedo = c.rgb * _MainTint;
    o.Emission = (reflection * reflMask.r) * _ReflAmount;
    o.Alpha = c.a;
    }
最后整体代码如下:
Shader "Custom/MaskedReflection" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
_MainTint ("Diffuse Tint", Color) = (1,1,1,1)
_ReflAmount ("Reflection Amount", Range(0, 1)) = 1
_Cubemap ("Cubemap", CUBE) = ""{}
_ReflMask ("Reflection Mask", 2D) = ""{}
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200 CGPROGRAM
#pragma surface surf Lambert sampler2D _MainTex;
sampler2D _ReflMask;
samplerCUBE _Cubemap;
float4 _MainTint;
float _ReflAmount; struct Input {
float2 uv_MainTex;
float3 worldRefl;
}; void surf (Input IN, inout SurfaceOutput o) {
half4 c = tex2D (_MainTex, IN.uv_MainTex);
float3 reflection = texCUBE(_Cubemap, IN.worldRefl).rgb;
float4 reflMask = tex2D(_ReflMask, IN.uv_MainTex); o.Albedo = c.rgb * _MainTint;
o.Emission = (reflection * reflMask.r) * _ReflAmount;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}

将场景中球体对应的材质设置如下图所示:

最后效果如图,其中左面的球体使用了遮罩反射,对比右面没有使用遮罩反射:

解释

这个Shader非常的简单,仅仅使用了texCUBE函数在Cubemap中采样。这个函数是内置的CGFX函数,它提供给我们一个Cubemap中的颜色值,然后我们将该值应用到平面上。Unity通过Input结构体中的worldRefl变量来帮我们在Cubemap中找到对应的采样位置。正如上一篇解释的一样,这个属性将会把摄像机视角的反射向量传递给我们。
一旦我们知道了反射元素(即反射的颜色值),我们就需要接着去采样我们的遮罩贴图。我们可以使用tex2D函数来完成它,这个函数在第二章中就接触过。
当我们知道了两个textures对应的值后,我们就可以把Cubemap的颜色值乘以反射贴图的颜色值,并传递给o.Emission。最后,为了可以全局控制反射密度,我们需要把结果再乘以_ReflAmount属性。这可以帮我们控制平面的整体反射量(越大表明反射度越高,越接近镜子的效果)。
下面展示了不同的_ReflAmount值对应的不同的反射效果:

【Unity Shaders】Reflecting Your World —— Unity3D中的遮罩反射(Masking Reflections)的更多相关文章

  1. 【Unity Shaders】Reflecting Your World —— Unity3D中简单的Cubemap反射

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

  2. 【Unity Shaders】Reflecting Your World —— Unity3D中的法线贴图和反射

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

  3. 【Unity Shaders】Reflecting Your World(反射吧!)介绍

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

  4. 【Unity Shaders】Reflecting Your World —— 在Unity3D中创建一个简单的动态Cubemap系统

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

  5. 【Unity Shaders】Reflecting Your World —— 在Unity3D中创建Cubemaps

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

  6. 【Unity Shaders】Shader中的光照

    写在前面 自己写过Vertex & Fragment Shader的童鞋,大概都会对Unity的光照痛恨不已.当然,我相信这是因为我们写得少...不过这也是由于官方文档对这方面介绍很少的缘故, ...

  7. 【unity shaders】:Unity中的Shader及其基本框架

    shader和Material的基本关系 Shader(着色器)实际上就是一小段程序,它负责将输入的Mesh(网格)以指定的方式和输入的贴图或者颜色等组合作用,然后输出.绘图单元可以依据这个输出来将图 ...

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

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

  9. 【Unity Shaders】Diffuse Shading——在Surface Shader中使用properties

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

随机推荐

  1. 【给你一个承诺 - 玩转 AngularJS 的 Promise】

    了解Promise 在谈论Promise之前我们要了解一下一些额外的知识:我们知道JavaScript语言的执行环境是"单线程",所谓单线程,就是一次只能够执行一个任务,如果有多个 ...

  2. jquery插件存档

    1.选择插件selectMenu github地址:https://github.com/josiaho/selectMenu 2.选择插件bootstrap_multiselect 官方地址:htt ...

  3. Linux下查看进程打开的文件句柄数

    ---查看系统默认的最大文件句柄数,系统默认是1024 # ulimit -n ----查看当前进程打开了多少句柄数 # lsof -n|awk '{print $2}'|sort|uniq -c|s ...

  4. Rabbitmq集群

    分享到 一键分享 QQ空间 新浪微博 百度云收藏 人人网 腾讯微博 百度相册 开心网 腾讯朋友 百度贴吧 豆瓣网 搜狐微博 百度新首页 QQ好友 和讯微博 更多... 百度分享 Rabbitmq集群高 ...

  5. 让你的代码量减少3倍!使用kotlin开发Android(四) kotlin bean背后的秘密

    上一篇我们介绍了缩短五倍的java bean,不知道你在看的时候有没有一种疑问捏? 本文同步自博主的私人博客wing的地方酒馆 再来回顾一下,两种代码的对比 public class User { p ...

  6. Java经典设计模式之七大结构型模式(附实例和详解)

    博主在大三的时候有上过设计模式这一门课,但是当时很多都基本没有听懂,重点是也没有细听,因为觉得没什么卵用,硬是要搞那么复杂干嘛.因此设计模式建议工作半年以上的猿友阅读起来才会理解的比较深刻.当然,你没 ...

  7. Linux 下的一个全新的性能测量和调式诊断工具 Systemtap, 第 3 部分: Systemtap

    Systemtap的原理,Systemtap与DTrace比较,以及安装要求和安装步骤本系列文章详细地介绍了一个Linux下的全新的调式.诊断和性能测量工具Systemtap和它所依赖的基础kprob ...

  8. Dynamics CRM 安装CRM程序系统检查界面报未将对象引用设置到对象的实例的解决方法

    今天在安装CRM的时候,在系统检查阶段遇到了如下的错误,咋看之下直接是懵逼的 但不要着急,界面上有两个按钮,一个是详细信息,一个是帮助,详细信息不用看了就那一行字也看不出什么,咱们点下帮助看看,定位到 ...

  9. Dynamics CRM 删除字段时检测到有组件类型为查看的依赖组件而无法删除问题

    今天在删除一个字段的时候报如下截图错误,点开详细信息会看到是一个快速查找视图,但却在视图列中没有找到我要删的那个字段,然后回过头来又看到组件类型是查看,这是啥类型?有点摸不着头脑了. 最后想到是不是查 ...

  10. androidApp的完全退出

    思路:搜集整个工程所有的activity,通过循环把工程中所有的activity都关闭. 搜集工程中的activity,可以由单例模式实现, [java] view plaincopy import  ...