【Unity Shaders】Reflecting Your World —— Unity3D中的法线贴图和反射
本系列主要参考《Unity Shaders and Effects
Cookbook》一书(感谢原书作者),同时会加上一点个人理解或拓展。
这里是本书所有的插图。这里是本书所需的代码和资源(当然你也可以从官网下载)。
========================================== 分割线 ==========================================
写在前面
准备
- 首先,我们需要一个Cubemap来产生反射效果。所以你可以使用前一节中的Cubemap,或者生成一个新的。这一节中,我们使用的如下所示(你可以在本书资源中找到它):
- 我们还需要一张法线贴图来产生基于法线的反射效果。
- 最后,创建一个新的场景、一个球体、一个平面以及一个平行光。同时,还需要创建一个新的Shader和Material,命名为NormalMappedReflection。
实现
- 首先让我们添加新的properties,使得我们能够添加自己的Cubemap和法线贴图。这个步骤你应该非常熟悉了。向Properties块添加下列代码:
Properties {
_MainTint ("Diffuse Tint", Color) = (1,1,1,1)
_MainTex ("Base (RGB)", 2D) = "white" {}
_NormalMap ("Normal Map", 2D) = "bump" {}
_Cubemap ("Cubemap", CUBE) = ""{}
_ReflAmount ("Reflection Amount", Range(0,1)) = 0.5
} - 然后,我们需要在SubShader块声明这些properties,使得我们能够访问Properties块中的这些数据:
CGPROGRAM
#pragma surface surf Lambert samplerCUBE _Cubemap;
sampler2D _MainTex;
sampler2D _NormalMap;
float4 _MainTint;
float _ReflAmount; - 然后,修改Input结构体。这是基于法线贴图的反射的精华所在。通过使用INTERNAL_DATA声明,我们可以访问经过法线贴图修改后的平面的法线信息:
struct Input {
float2 uv_MainTex;
float2 uv_NormalMap;
float3 worldRefl;
INTERNAL_DATA
}; - 最后,我们需要修改surf函数,来得到最后的基于法线贴图的反射效果:
void surf (Input IN, inout SurfaceOutput o) {
half4 c = tex2D (_MainTex, IN.uv_MainTex); float3 normals = UnpackNormal(tex2D(_NormalMap, IN.uv_NormalMap)).rgb;
o.Normal = normals; o.Emission = texCUBE (_Cubemap, WorldReflectionVector (IN, o.Normal)).rgb * _ReflAmount;
o.Albedo = c.rgb * _MainTint;
o.Alpha = c.a;
}
Shader "Custom/NormalMappedReflection" {
Properties {
_MainTint ("Diffuse Tint", Color) = (1,1,1,1)
_MainTex ("Base (RGB)", 2D) = "white" {}
_NormalMap ("Normal Map", 2D) = "bump" {}
_Cubemap ("Cubemap", CUBE) = ""{}
_ReflAmount ("Reflection Amount", Range(0,1)) = 0.5
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200 CGPROGRAM
#pragma surface surf Lambert samplerCUBE _Cubemap;
sampler2D _MainTex;
sampler2D _NormalMap;
float4 _MainTint;
float _ReflAmount; struct Input {
float2 uv_MainTex;
float2 uv_NormalMap;
float3 worldRefl;
INTERNAL_DATA
}; void surf (Input IN, inout SurfaceOutput o) {
half4 c = tex2D (_MainTex, IN.uv_MainTex); float3 normals = UnpackNormal(tex2D(_NormalMap, IN.uv_NormalMap)).rgb;
o.Normal = normals; o.Emission = texCUBE (_Cubemap, WorldReflectionVector (IN, o.Normal)).rgb * _ReflAmount;
o.Albedo = c.rgb * _MainTint;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
效果如下(一个表明凹凸不平的反射球):
解释
float3 normals = UnpackNormal(tex2D(_NormalMap, IN.uv_NormalMap)).rgb;
o.Normal = normals;
一旦上述代码在Shader中执行后,物体的平面法线将被修改;因此,我们需要使用它来影响我们的反射。我们可以通过声明INTERNAL_DATA来访问修改后的法线信息,然后使用WorldReflectionVector (IN, o.Normal)去查找Cubemap中对应的反射信息。这是Unity提供给我们的另一个内置函数,因此我们不需要再自己写那些冗长的代码,而仅仅需要关注编写Shader中产生关键效果的部分。
更多…
float3 viewDir | 包含了视角的观察方向,主要用于计算视差效应(Parallax effects ),边缘光照,等等。 |
float4 COLOR | 包含了经过内插值(interpolated )的每个顶点的颜色值。 |
float4 screenPos | 包含了用于反射效果的屏幕坐标系的位置信息。例如,在Unity专业版的WetStreet shader中使用了它。 |
float3 worldPos | 包含了世界坐标系中的位置。 |
float3 worldRefl | 包含了世界坐标系中的反射向量,如果Surface Shader没有重写o.Normal。参考Reflect-Diffuse shader。 |
float3 worldNormal | 包含了世界坐标系中的法线向量,如果Surface Shader没有重写o.Normal。 |
float3 worldRefl; INTERNAL_DATA |
包含了世界坐标系的反射向量,如果Surface Shader重写了o.Normal。为了得到基于逐像素的法线贴图的反射向量,请使用WorldReflectionVector (IN,o.Normal) 。参考Reflect-Bumped shader。 |
float3 worldNormal; INTERNAL_DATA |
包含了世界坐标系的发现向量,如果Surface Shader重写了o.Normal。为了得到基于逐像素的法线贴图的法线向量,请使用WorldNormalVector (IN,o.Normal) 。参考Reflect-Bumped shader。 |
【Unity Shaders】Reflecting Your World —— Unity3D中的法线贴图和反射的更多相关文章
- 【Unity Shaders】Reflecting Your World —— Unity3D中简单的Cubemap反射
本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...
- 【Unity Shaders】Reflecting Your World —— Unity3D中的遮罩反射(Masking Reflections)
本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...
- Unity 着色器训练营(2) - MVP转换和法线贴图
https://mp.weixin.qq.com/s/Qf4qT15s9bWjbVGh7H32lw 我们刚刚公布了Unity 2018.1中,Unity将会内置可视化编程工具Shader Graph, ...
- Unity Shaders and Effects Cookbook (4-1)(4-2)静态立方体贴图的创建与使用
開始学习第4章 - 着色器的反射 看完了1.2节,来记录一下.反射主要是利用了 Cubemap 立方体贴图. 认识Cubemap 立方体贴图.就如同名字所说.在一个立方体上有6张图.就这样觉得吧. 假 ...
- 【Unity Shaders】Reflecting Your World(反射吧!)介绍
本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...
- 【Unity Shaders】学习笔记——SurfaceShader(二)两个结构体和CG类型
[Unity Shaders]学习笔记——SurfaceShader(二)两个结构体和CG类型 转载请注明出处:http://www.cnblogs.com/-867259206/p/5596698. ...
- Unity3D ShaderLab法线贴图
Unity3D ShaderLab法线贴图 说到法线贴图,应该算是我们最常使用的一种增强视觉效果的贴图.将法线贴图的各个像素点座位模型的法线,这样我们的光照可以模拟出高分辨率的效果, 同时也保持较低的 ...
- (转)Unity3D 游戏贴图(法线贴图,漫反射贴图,高光贴图)
原帖网址http://www.u3dpro.com/read.php?tid=207 感谢jdk900网友的辛苦编写 我们都知道,一个三维场景的画面的好坏,百分之四十取决于模型,百分之六十取决于贴图 ...
- 【Unity Shaders】Reflecting Your World —— 在Unity3D中创建一个简单的动态Cubemap系统
本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...
随机推荐
- Echarts 地图添加自定义区域
使用 Echarts 生成地图时,如果需要添加一些自定义区域,该怎么做呢?请看下面示例. 生成原始地图 index.hmtl 引入 Jquery 和 Echart <!DOCTYPE html& ...
- (转载)JVM知识小集
1. 内存模型以及分区,需要详细到每个区放什么. 2. 堆里面的分区:Eden,survival from to,老年代,各自的特点. 3. 对象创建方法,对象的内存分配,对象的访问定位. 4. GC ...
- AnyConnect使用说明(手机版)
一.下载安装客户端 iPhone手机在App Store 里搜索 “Anyconnect”下载安装. Android手机需另外下载Anyconnect. 二. 1.打开AnyConnect,点击&qu ...
- Spring统一返回Json工具类,带分页信息
前言: 项目做前后端分离时,我们会经常提供Json数据给前端,如果有一个统一的Json格式返回工具类,那么将大大提高开发效率和减低沟通成本. 此Json响应工具类,支持带分页信息,支持泛型,支持Htt ...
- Redis源码学习:字符串
Redis源码学习:字符串 1.初识SDS 1.1 SDS定义 Redis定义了一个叫做sdshdr(SDS or simple dynamic string)的数据结构.SDS不仅用于 保存字符串, ...
- Linux文件编辑命令详细整理
刚接触Linux,前几天申请了个免费体验的阿里云服务器,选择的是Ubuntu系统,配置jdk环境变量的时候需要编辑文件. vi命令编辑文件,百度了一下,很多回答不是很全面,因此编辑文件话了一些时间. ...
- Redis之(一)初识Redis
1.Redis概述 我们知道,内存是电脑主板上的存储部件,用于存储当前正在使用的数据和程序,CPU可以与内存直接沟通,所以访问速速非常高:而外存数据必须加载到内存以后程序才能使用.如果把CPU当做一个 ...
- Swift基础之侧滑Cell显示操作按钮
好久没写过博客了,今天展示一个UITableView基础的内容侧滑Cell的方法使用,之前写过OC语言的http://blog.csdn.net/hbblzjy/article/details/517 ...
- Compass实战 站内搜索
今天早上打算对这两天学习的Lucene以及Compass总结一下,想来想去,还是写个小项目来验证最好了.于是就有了今天的这篇文章.难易程度适合对于Compass或者Lucene刚入门的童鞋,大牛看到后 ...
- 在 Mac OS X 10.10 安装 pyenv 的一个小坑
小记一下. 因为全面转向 Python 3.4 作为主力开发版本,但是手上的 Mac OS X 和服务器上用的都是 Python 2.7,所以需要安装 pyenv. 按其 github 页面的说明,使 ...