本教程介绍了反射贴图(以及实现它的立方体贴图)。

这是Unity中使用立方体贴图的环境映射的一系列小教程中的第一篇。本章基于章节“平滑镜面高光”中介绍的逐像素光照以及章节“纹理球体”中介绍的纹理映射概念。

一个天空反射贴图

一个大型反射表面的例子


一个天空盒是一个(无限)大的盒子包围着整个场景。这里一条反射的摄像机射线跟天空盒其中的一个纹理表面相交。

上面插画描述了一个静态天空盒反射贴图的概念:一条观察射线会在一个物体表面上的一个点被反射,并且被反射的射线跟天空盒相交以决定相应像素的颜色。天空盒只是一个有纹理表面的大型立方体环绕着整个场景。应该注意到天空盒通常是静态的并且不包含场景的任何动态物体。但是,反射贴图的“天空盒”通常从某种角度说会渲染包括场景。但是,这已经超出了本教程的范围。

而且,本教程只涵盖了反射的计算,它并不包含章节“天空盒”中讨论的天空盒的渲染。对于一个物体中天空盒的反射,我们必须渲染这个物体并且把摄像机的射线反射到表面法向量所在的表面点上。这个反射的数学跟表面法向量处光线的反射是一样的,它在章节“镜面高光”中有讨论。

一旦我们得到了反射射线,它跟大型天空盒的交点就必须被计算。如果天空盒无限大的话这个计算实际就变得很简单了:在这种情况下表面点的位置就无关紧要了,因为它到坐标系原点的距离相对于天空盒的尺寸来说是无限小的;于是只有反射射线的方向是有关的而不是它的位置。因此,我们可以实际考虑一条从一个小型天空盒而不是从其它地方开始的射线。(如果你不熟悉这个想法,你最好花点时间了解一下。)取决于反射光线的方向,它会跟纹理天空盒的六个面中一个相交。我们会计算哪个面相交,在哪里相交以及对指定面的纹理贴图进行纹理查找(参考章节“纹理球体”)。于是,我们要做的就是为环境提供一个立方体纹理,把它作为一个着色器属性,以及使用有反射方向的texCUBE指令来获取立方体纹理相应位置的颜色。

立方体贴图

在Unity着色器中,一个被叫做_Cube的立方体贴图着色器属性可以这样定义:

   Properties{_Cube ("Reflection Map", Cube) = "" {}}

在Cg着色器中,相应的uniform变量可以这样定义:

 uniform samplerCUBE _Cube;

为了创建一个立方体贴图,在Project Window中选择Create > Legacy > Cubemap。然后你必须在in the Inspector Window中为立方体的表面指定六张纹理贴图。你可以在Unity的资源商店里找到这种纹理的免费示例(选择Windows > Asset Store然后搜索“skyboxes”)。此外,你应该在Inspector Window中为立方体贴图选中MipMaps;这个可以为反射映射带来更好的视觉效果。或者,你可以在Inspector Window中导入立方体贴图(它在一个图像文件中包含了六个面的纹理),设置Texture Type为Cubemap。

顶点着色器必须计算观察方向viewDir以及方向normalDir,这些在章节“镜面高光”中有所讨论。为了在片元着色器中反射观察方向,我们可以使用同样在章节“镜面高光”中讨论过的Cg函数reflect。

float3 reflectedDir = reflect(input.viewDir, normalize(input.normalDir));

在立方体贴图中执行纹理查找以及在片元颜色中存储最终颜色,我们可以简单使用:

 return texCUBE(_Cube, reflectedDir);

完整着色器代码

Shader "Cg shader with reflection map" {Properties {_Cube("Reflection Map", Cube) = "" {}}SubShader {Pass {   CGPROGRAM#pragma vertex vert  #pragma fragment frag#include "UnityCG.cginc"// User-specified uniformsuniform samplerCUBE _Cube;struct vertexInput {float4 vertex : POSITION;float3 normal : NORMAL;};struct vertexOutput {float4 pos : SV_POSITION;float3 normalDir : TEXCOORD0;float3 viewDir : TEXCOORD1;};vertexOutput vert(vertexInput input) {vertexOutput output;float4x4 modelMatrix = _Object2World;float4x4 modelMatrixInverse = _World2Object; output.viewDir = mul(modelMatrix, input.vertex).xyz - _WorldSpaceCameraPos;output.normalDir = normalize(mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);output.pos = mul(UNITY_MATRIX_MVP, input.vertex);return output;}float4 frag(vertexOutput input) : COLOR{float3 reflectedDir = reflect(input.viewDir, normalize(input.normalDir));return texCUBE(_Cube, reflectedDir);}ENDCG}}
}

总结

恭喜!你完成了环境映射的第一篇教程。我们学到了:

  • 如何计算物体内天空盒的反射。
  • 如果在Unity生成方位体贴图以及如何把他们用到反射映射上。

扩展阅读

如果你还想了解得更多:

  • 关于向量的反射,你可以阅读章节“镜面高光”。
  • 关于Unity中的立方体贴图,你可以阅读文档。
  • 关于在Unity中渲染到一个立方体贴图,你可以阅读Unity关于Camera.RenderToCubemap的文档。

Cg Programming/Unity/Reflecting Surfaces反射表面相关推荐

  1. Cg Programming/Unity/Lighting Textured Surfaces光照纹理表面

    本教程涵盖了纹理表面的逐顶点光照. 它结合了章节"纹理球体"和章节"镜面高光"的着色器代码,使用由一张贴图决定的漫反射材质颜色来计算光照.如果你没有读过那些章节 ...

  2. Cg Programming/Unity/Specular Highlights镜面高光

    本教程涵盖了使用Phone反射模型的逐顶点光照(也叫做高洛德着色).它在章节"漫反射"中通过两个额外的术语扩展了着色器代码:环境光和镜面反射.这三个术语一起构成了Phone反射模型 ...

  3. Cg Programming/Unity/Brushed Metal拉丝金属

    本教程涵盖了各向异性镜面高光. 这是几个关于光照教程中的其中一个教程,这个光照超出了Phone反射模型的范围.但是,它是基于章节"镜面高光"(逐顶点光照)以及章节"光滑镜 ...

  4. 可重构/大规模智能反射表面reconfigurable/large intelligent surface综述

    闻道洛阳花正好,家家遮户春风.道人饮处百壶空.年年花下醉,看尽几番红. 此拐又从何处去,飘蓬一任西东.语声虽异笑声同.一轮清夜月,何处不相逢. ---- 临江仙·与刘拐 更多精彩内容请关注微信公众号 ...

  5. 图像条纹检测 python_【连载4.5】特征检测技术研究面向强反射表面的多传感器三维检测技术研究...

    本章大纲 4 光条纹中心提取技术研究 4.1 结构光条纹特征 4.2 常用的像素级别特征提取方法 4.2.1 灰度重心法4.2.2 极值法4.2.3 方向模板法4.2.4 阈值法4.2.5 几何中心法 ...

  6. 图像条纹检测 python_【连载2.1】结构光三维检测引言面向强反射表面的多传感器三维检测技术研究...

    本章大纲 2.1 引言 2.2 多传感器三维检测系统介绍 2.2.1 多传感器三维检测总体模型2.2.2 多传感器三维检测系统工作原理 2.3 坐标系统一化全局标定方法 2.3.1 全局标定方法介绍2 ...

  7. unity中的反射探头和光照反射探头

    今天我们来学习一下unity里的反射探头和是光照反射探头 要设置反射探头,一开始我们就要做好准备工作,第一步也是我们unity里如果要渲染和烘焙灯光都一个要做的第一步就是趁我们的场景里东西并不多的时候 ...

  8. Advanced Programming: Unity Game Dev Course(4)-Closing the Loop

    1.Alternate Singleton 主要介绍: 修改Singleton 具体实现: 之前Intermediate Programming: Unity Game Dev Courses(1)- ...

  9. Intermediate Programming: Unity Game Dev Courses(2)- Loot System

    1.Setting up Our Scriptable Objects 主要介绍: 补充全ItemPickUp_SO脚本并判定loot对象 具体实现: 使用Beginner Programming: ...

最新文章

  1. 【每日一算法】独特的电子邮件地址
  2. win8 下免安装版mysql
  3. Boost库之asio io_service以及run、run_one、poll、poll_one区别
  4. “悟道”公开课第四讲丨悟道开发案例:​悟空策论——议论文写作平台
  5. Spring中的Spring JSR-250 注释之@Resource
  6. 使用多种MIME类型测试REST
  7. java中输出系统时间
  8. pandas 转换为文本类型_分享5个高效的pandas函数!
  9. MySQL 日志文件
  10. 在macOS Big Sur上如何重置蓝牙?
  11. log4j+flume+HDFS实现日志存储
  12. DCEP | 农行将上线数字人民币刷脸支付
  13. 数显之家快讯:【SHIO世硕心语】未来15年,重点关注8大前沿领域,9大战略产业
  14. QAndroidJniObject::callStaticObjectMethod参数含义
  15. 银联的跨行清算体系架构分析
  16. 室内定位技术及机场方案建议
  17. termux最新安装kali
  18. python绘图输出上下标中的上下标
  19. ublox的芯片设置成GPS+北斗+SBAS(星基增强系统)+QZSS(准天顶卫星系统)
  20. 个人网站支付,个人APP支付,接入支付

热门文章

  1. python 爬取图片环绕_用python几行代码爬取秀美图上图片(福利)
  2. 农夫过河【数据结构实验报告】
  3. 如何强制安卓平板谷歌浏览器桌面版网页
  4. 这一节学一学时序例外约束
  5. distinct多个字段mysql_MySQL中索引优化distinct语句及distinct的多字段操作
  6. 2021Eclipse安装教程
  7. MT6625L处理器参数规格
  8. 马云怒怼阿尔法狗,称搞阿尔法狗没意义,人工智能的意义在哪?
  9. 算法设计与分析笔记整理——蛮力法——例题:解数字谜
  10. 西部数据Ultrastar DC SN840 体验分享