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

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

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

写在前面


通过上一节,我们已经知道如何创建我们自己的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(这是通过在上一篇的基础上,在场景中球体所在的位置创建的自己的Cubemap)。你的可能和它不一样,没有关系,我们仅仅是想展示一下使用的Cubemap的样子,以便在最后的效果中不会产生任何难理解的地方。使用自己的也是完全可以的。





实现


下面,让我们来实现真正的Shader代码吧!

  1. 首先在Properties块中创建新的properties。我们需要一个位置来得到我们的Cubemap贴图对象以及来控制反射的程度:

    	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
    #pragma surface surf Lambert sampler2D _MainTex;
    samplerCUBE _Cubemap;
    float4 _MainTint;
    float _ReflAmount
  3. 为了让我们能够模拟正确的反射角度,我们需要得到一个向量来提供给我们合适的世界反射方向。因此,我们可以使用上面提到的Unity的Surface Shaders内置的变量。在Input结构体中,下面的代码将提供给我们一个世界反射向量,来用于接下来的Shader中:
    		struct Input {
    float2 uv_MainTex;
    float3 worldRefl
    };
  4. 最后,我们仅仅需要从Cubemap中得到贴图信息,即使用texCUBE函数和Input提供给我们的新的世界反射向量。添加下面的代码到你的surf函数中:
    		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" {
Properties {
_MainTint ("Diffuse Tint", Color) = (1,1,1,1)
_MainTex ("Base (RGB)", 2D) = "white" {}
_Cubemap ("CubeMap", CUBE) = ""{}
_ReflAmount ("Reflection Amount", Range(0.01, 1)) = 0.5
} SubShader {
Tags { "RenderType"="Opaque" }
LOD 200 CGPROGRAM
#pragma surface surf Lambert sampler2D _MainTex;
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) * _MainTint;
o.Emission = texCUBE(_Cubemap, IN.worldRefl).rgb * _ReflAmount;;
o.Albedo = c.rgb;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}


最后,当我们和上一篇中创建的Cubemap结合起来后,就可以得到下面的效果。可以看到其中的球有反射的效果。



解释


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

下面的截图展示了一个什么是传递给Shader的反射数据的例子。

【Unity Shaders】Reflecting Your World —— Unity3D中简单的Cubemap反射的更多相关文章

  1. Unity3D中简单的C#异步Socket实现

    Unity3D中简单的C#异步Socket实现 简单的异步Socket实现..net框架自身提供了很完善的Socket底层.笔者在做Unity3D小东西的时候需要使用到Socket网络通信.于是决定自 ...

  2. 【Unity Shaders】学习笔记——SurfaceShader(九)Cubemap

    [Unity Shaders]学习笔记——SurfaceShader(九)Cubemap 如果你想从零开始学习Unity Shader,那么你可以看看本系列的文章入门,你只需要稍微有点编程的概念就可以 ...

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

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

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

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

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

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

  6. 【Unity Shaders】Lighting Models —— 光照模型之Lit Sphere

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

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

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

  8. Unity3D中的常用方法

    备注:文中所使用的this均指脚本所依附的对象 1.移动(用Translate方法进行移动) ; //移动速度 this.transform.Translate(Vector3.down * Time ...

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

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

随机推荐

  1. 59. Spiral Matrix II(中等,同54题)

    Given an integer \(n\), generate a square matrix filled with elements from 1 to \(n^2\) in spiral or ...

  2. dict 字典的用法

    因为这一章节用的比较多,而需要注意的得比较多, 所以总结的笔记也相对比较多一点,我就直接单独写了一页 ##    {key:value} 1. key不能为列表 2.value可以是任意类型值 3.返 ...

  3. python学习之路基础篇(第五篇)

    前四天课程回顾 1.python简介 2.python基本数据类型 类: int:整型 | str:字符串 | list:列表 |tuple:元组 |dict:字典 | set:集合 对象: li = ...

  4. 跟着小菜学习RabbitMQ启动和基础(系列一)

    前言 今天开始我们正式进入RabbitMQ系列学习,在这系列博客中也会发表.NET Core和EF Core文章,网上关于RabbitMQ例子比比皆是,我将综合网上所提供的信息并加上我个人的理解来详细 ...

  5. kexec 内核快速启动流程分析

    一.命令行 1. kexec -l $kpwd --append="$arg" 其中$kpwd =目标内核的路径 $arg =传给内核的参数,与/proc/cmdline一致时表示 ...

  6. 关于bedtools merge 功能中sort 命令的解释

    Bedtools 是一个很好的用来处理区间的工具,很多时候用这个底层语言编写的小工具比自己写的脚本运行快很多,但是这个工具中的某些功能对输入文件有一定的要求,比如说里面的一个merge函数,这是里面的 ...

  7. Node.js Net 模块

    Node.js Net 模块提供了一些用于底层的网络通信的小工具,包含了创建服务器/客户端的方法,我们可以通过以下方式引入该模块: var net = require("net") ...

  8. Linux 性能监测:Memory

    这里的讲到的 "内存" 包括物理内存和虚拟内存,虚拟内存(Virtual Memory)把计算机的内存空间扩展到硬盘,物理内存(RAM)和硬盘的一部分空间(SWAP)组合在一起作为 ...

  9. React Native(一) FlexBox布局

    欢迎转载,转载请标明出处: http://blog.csdn.net/johnny901114/article/details/53241550 本文出自:[余志强的博客] 在React Native ...

  10. 剑指Offer——网易笔试题+知识点总结

    剑指Offer--网易笔试题+知识点总结 Fibonacci package cn.edu.ujn.nk; import java.util.ArrayList; import java.util.S ...