在Project中可以创建我们自己的Cubemaps,现在,我们可以来看一下如何使用这种新的贴图类型来在Shaders中模拟反射效果。使用Cubemaps进行反射的原理实际上非常简单,但是这将给你的Shader效果带来翻天覆地的变化。它的原理主要是通过模型表面的每个顶点的法向量,去查找Cubemap贴图上的某一个位置。这种查找将会返回一个颜色值,来模拟这个Cubemap反射到你的对象上的这种效果。
这篇教程将会教给你用Cubemaps来进行反射的第一步!Unity实际上给我们提供了自动得到反射向量的方法,所以我们不需要自己去计算它了。这是在Input结构体中的内置的worldRefl向量中实现的。这会帮助我们去查找对应的Cubemap贴图中的位置。因此,第一步的内容将非常简单!

准备工作

在我们开始写Shader代码之前,我们需要搭建一个简单的场景。
  1. 创建一个新的scene,Material,和Shader,可以取名为SimpleReflection。
  2. 附着新的Shader到新的Material上,然后创建一个物体,并把Material赋值给它。
  3. 最后,创建或者找到一个Cubemap,之后将用于我们的Shader。
下面的截图显示了我们这节中将要使用的Cubemap

实现

下面,让我们来实现真正的Shader代码吧!
  1. 首先在Properties块中创建新的properties。我们需要一个位置来得到我们的Cubemap贴图对象以及来控制反射的程度:

    Properties {  
    1. _MainTex ("Base (RGB)", 2D) = "white" {}
    2. _MainTint ("Diffuse Tint", Color) = (1,1,1,1)
    3. _Cubemap ("CubeMap", CUBE) = ""{}
    4. _ReflAmount ("Reflection Amount", Range(0.01, 1)) = 0.5
    5. }
       Properties {
    _MainTex ("Base (RGB)", 2D) = "white" {}
    _MainTint ("Diffuse Tint", Color) = (1,1,1,1)
    _Cubemap ("CubeMap", CUBE) = ""{}
    _ReflAmount ("Reflection Amount", Range(0.01, 1)) = 0.5
    }
  2. 同样,我们还需要在SubShader块中创建和properties中各变量的联系。这将允许我们从Properties块中访问这些数据。
    CGPROGRAM  
    1. #pragma surface surf Lambert
    2. sampler2D _MainTex;
    3. samplerCUBE _Cubemap;
    4. float4 _MainTint;
    5. float _ReflAmount
         CGPROGRAM
    #pragma surface surf Lambert
    sampler2D _MainTex;
    samplerCUBE _Cubemap;
    float4 _MainTint;
    float _ReflAmount
  3. 为了让我们能够模拟正确的反射角度,我们需要得到一个向量来提供给我们合适的世界反射方向。因此,我们可以使用上面提到的Unity的Surface Shaders内置的变量。在Input结构体中,下面的代码将提供给我们一个世界反射向量,来用于接下来的Shader中:
    1. struct Input {
    2. float2 uv_MainTex;
    3. float3 worldRefl
    4. };
            struct Input {
    float2 uv_MainTex;
    float3 worldRefl
    };
  4. 最后,我们仅仅需要从Cubemap中得到贴图信息,即使用texCUBE函数和Input提供给我们的新的世界反射向量。添加下面的代码到你的surf函数中:
    void surf (Input IN, inout SurfaceOutput o) {  
    1. half4 c = tex2D (_MainTex, IN.uv_MainTex) * _MainTint;
    2. o.Emission = texCUBE(_Cubemap, IN.worldRefl).rgb * _ReflAmount;;
    3. o.Albedo = c.rgb;
    4. o.Alpha = c.a;
           void surf (Input IN, inout SurfaceOutput o) {
    half4 c = tex2D (_MainTex, IN.uv_MainTex) * _MainTint;
    o.Emission = texCUBE(_Cubemap, IN.worldRefl).rgb * _ReflAmount;;
    o.Albedo = c.rgb;
    o.Alpha = c.a;
    
整体代码如下:
Shader "Custom/SimpleReflection" {  
  1. Properties {
  2. _MainTint ("Diffuse Tint", Color) = (1,1,1,1)
  3. _MainTex ("Base (RGB)", 2D) = "white" {}
  4. _Cubemap ("CubeMap", CUBE) = ""{}
  5. _ReflAmount ("Reflection Amount", Range(0.01, 1)) = 0.5
  6. }
  7. SubShader {
  8. Tags { "RenderType"="Opaque" }
  9. LOD 200
  10. CGPROGRAM
  11. #pragma surface surf Lambert
  12. sampler2D _MainTex;
  13. samplerCUBE _Cubemap;
  14. float4 _MainTint;
  15. float _ReflAmount;
  16. struct Input {
  17. float2 uv_MainTex;
  18. float3 worldRefl;
  19. };
  20. void surf (Input IN, inout SurfaceOutput o) {
  21. half4 c = tex2D (_MainTex, IN.uv_MainTex) * _MainTint;
  22. o.Emission = texCUBE(_Cubemap, IN.worldRefl).rgb * _ReflAmount;;
  23. o.Albedo = c.rgb;
  24. o.Alpha = c.a;
  25. }
  26. ENDCG
  27. }
  28. FallBack "Diffuse"
  29. }
最后,当我们和上一篇中创建的Cubemap结合起来后,就可以得到下面的效果。可以看到其中的球有反射的效果。

解释

上面代码能够成功的主要原因就是Unity3D提供的Surface Shader的Input结构的内置属性。worldRefl变量给我们需要的反射向量来正确的采样我们的Cubemap。我们仅需要在函数中使用worldRefl属性,就可以很方便地得到正确的反射视角。
下面的截图展示了一个什么是传递给Shader的反射数据的例子。

【Unity Shaders】Reflecting Your World —— Unity3D中简单的Cubemap反射相关推荐

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

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

  2. Unity网络(二)-Unity3D中的网络

    正所谓:没有网络是没有灵魂的 欢迎关注公众号:雷潮课堂 Unity3D中的网络 一.WWW 1-1 Get 1-2 Post 1-3 案例(网络下载,本地存储与读取) 二.UnityWebReques ...

  3. Unity3D中简单地应用玻璃材质

    最近在学习Unity3D.发现Unity3D中的玻璃效果要用到Shader才能实现.虽然简单学习了一下能看懂Shader的结构了,但要自己写一个实现自己想要的效果的Shader暂时还无能为力.这个要么 ...

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

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

  5. 【Unity Shaders】Lighting Models —— 灯型号Lit Sphere

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

  6. unity游戏中提示信息如何实现_RPG游戏中的剧情在Unity3D中如何实现呢?

    原标题:RPG游戏中的剧情在Unity3D中如何实现呢? RPG游戏想必不用多介绍了,剧情系统是RPG游戏中必不可少的功能. 曾经听过一些朋友谈论:目前正在做一款RPG游戏,但是不知道如何实现RPG游 ...

  7. (八)unity自带的着色器源码剖析之——————Unity3D的全局光照和阴影:下篇(unity3D中的球谐光照和SH球谐函数、unity实时阴影抗锯齿解决方案)

    一.探针基于球谐函数的全局光照 球谐光照是基于预计算辐射度传输理论实现的一种实时渲染技术.预计算辐射度传输技术能够重现在区域面光源照射下的全局照明效果.这种技术通过在运行前对场景中光线的相互作用进行预 ...

  8. 【Unity Shaders】最简单的顶点/片元着色器3

    微信号:ITComputerGraph 更多精彩内容,关注公众号<IT木子李> Shader "Unity Shaders/Simple Shader3" {SubSh ...

  9. Unity3D中项目在Unity编辑器下正常运行打包成功exe后无法正常运行

    Unity3D中项目在Unity编辑器下正常运行打包成功exe后无法正常运行 一.遇到的情况描述: 项目中涉及到了文件读取的相关操作 项目在Unity下能够正常获取到文件信息并且不报错 项目能够成功打 ...

最新文章

  1. 如何利用 JConsole观察分析Java程序的运行,进行排错调优
  2. 最长公共子序列Java代码实现
  3. 命名空间“Microsoft.AspNet”中不存在类型或命名空间名“Mvc”
  4. poj 1201 差分约束
  5. export LD_LIBRARY_PATH 的使用
  6. 【转】正确认识动脉压力波形
  7. python最大分词_中文分词算法之最大正向匹配算法(Python版)
  8. html数据摘要算法,Hash函数和消息摘要算法(示例代码)
  9. ZendGuard-5_0_1 使用备忘
  10. js 内置对象之数组Array
  11. 书单丨724运维日,为运维人干杯
  12. 抛出异常,打印错误信息,追踪错误
  13. 计算机房用还原保护软件,“小哨兵”还原卡v9.1在机房的巧妙应用
  14. 怎么将多个Excel工作簿合并成一个新的工作簿
  15. Mac OS X 平台有哪些优秀应用可以将视频转成 GIF?Mac视频转gif软件推荐
  16. html拼凑成一张图片,(代码片段)利用canvas,把多张图合并成一张图片
  17. XMPP——Smack[2]会话、消息监听、字体表情和聊天窗口控制
  18. bzoj4416 阶乘字符串 子集dp
  19. 注入漏洞-sql注入
  20. RK3568关于RK808的定时开关机

热门文章

  1. 关于2010年7月日本语能力测试报名的通知
  2. Java各阶段学习书籍推荐
  3. 矩阵运算实现求样本与样本之间欧式距离
  4. 「接口汇总」APISpace 常用的免费API 整理
  5. (自用,无内容,勿点)MySQL必知必会笔记
  6. C++实现员工管理系统
  7. linux共享文件夹密码,[Linux]ubuntu下共享文件夹密码设置和重置-smbpasswd -a user
  8. 仙侣奇缘3新版登录器界面设定
  9. matlab时间复杂度,MATLAB中的矩阵乘法时间复杂度
  10. 量子叠加态和量子纠缠_从无到有的量子隐形传态。 第2部分-在真实设备上进行操作...