接上文:https://blog.csdn.net/Jaihk662/article/details/113248074

四、菲涅尔反射

菲涅尔反射(Fresnel Reflection)就是同时考虑反射和漫反射,或是说同时考虑反射和折射:当光照到物体上时,一部分发生反射,一部分进入物体内部发生折射和散射。当你站在湖边低头看脚边的水面时,会发现水几乎是透明的,可以很清晰的看到湖底,但是当你抬头看远处的水面时,就几乎看不到任何水下的场景。几乎任何物体都多多少少包含了菲涅尔反射的现象

现实中的菲涅尔反射计算非常的复杂,因此往往采用如下的近似方式:

其中  为反射系数, 代表视角方向, 代表表面法线

下面为叠加反射和漫反射的 Shader:

Shader "Jaihk662/Fresnel1"
{Properties{_DiffuseColor ("DiffuseColor", Color) = (1, 1, 1, 1)_FresnelScale ("FresnelScale", Range(0, 1)) = 0.5_Cubemap ("ReflectionCubemap", Cube) = "_Skybox" {}}SubShader{LOD 200PASS {Tags { "LightMode" = "ForwardBase" }CGPROGRAM#pragma vertex vert             //声明顶点着色器的函数#pragma fragment frag           //声明片段着色器的函数#include "UnityCG.cginc"#include "Lighting.cginc"fixed4 _DiffuseColor;fixed _FresnelScale;samplerCUBE _Cubemap;struct _2vert {float4 vertex: POSITION;float3 normal: NORMAL;float4 texcoord: TEXCOORD0;};struct vert2frag {float4 pos: SV_POSITION;float3 wPos: TEXCOORD0;float3 wNormal: TEXCOORD1;float3 wViewDir: TEXCOORD2;float3 wReflect: TEXCOORD3;};vert2frag vert(_2vert v) {vert2frag o;o.pos = UnityObjectToClipPos(v.vertex);o.wNormal = normalize(UnityObjectToWorldNormal(v.normal));o.wPos = mul(unity_ObjectToWorld, v.vertex).xyz;o.wViewDir = normalize(UnityWorldSpaceViewDir(o.wPos));o.wReflect = reflect(-o.wViewDir, o.wNormal);return o;}fixed4 frag(vert2frag i): SV_Target {fixed3 wLightDir = normalize(UnityWorldSpaceLightDir(i.wPos));fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;fixed3 diffuse = _LightColor0.rgb * _DiffuseColor.rgb * (0.5 * dot(i.wNormal, wLightDir) + 0.5);            fixed3 reflection = texCUBE(_Cubemap, i.wReflect).rgb;fixed fresnel = saturate(_FresnelScale + (1 - _FresnelScale) * pow(1 - dot(i.wViewDir, i.wNormal), 5));return fixed4(ambient + lerp(diffuse, reflection, fresnel), 1.0); } ENDCG}}FallBack "Specular"
}

可以看出,垂直视角下漫反射的效果明显,而在倾斜视角下,反射效果明显

类似的可以实现叠加反射和折射的 Shader:

Shader "Jaihk662/Fresnel1"
{Properties{_DiffuseColor ("DiffuseColor", Color) = (1, 1, 1, 1)_FresnelScale ("FresnelScale", Range(0, 1)) = 0.5_RefractRatio ("RefractiRatio", Range(0.1, 1)) = 0.5_CubeMap ("ReflectionCubeMap", Cube) = "_Skybox" {}}SubShader{LOD 200PASS {Tags { "LightMode" = "ForwardBase" }CGPROGRAM#pragma vertex vert             //声明顶点着色器的函数#pragma fragment frag           //声明片段着色器的函数#include "UnityCG.cginc"#include "Lighting.cginc"fixed4 _DiffuseColor;fixed _FresnelScale;fixed _RefractRatio;samplerCUBE _CubeMap;struct _2vert {float4 vertex: POSITION;float3 normal: NORMAL;float4 texcoord: TEXCOORD0;};struct vert2frag {float4 pos: SV_POSITION;float3 wPos: TEXCOORD0;float3 wNormal: TEXCOORD1;float3 wViewDir: TEXCOORD2;float3 wReflect: TEXCOORD3;float3 wRefract: TEXCOORD4;};vert2frag vert(_2vert v) {vert2frag o;o.pos = UnityObjectToClipPos(v.vertex);o.wNormal = normalize(UnityObjectToWorldNormal(v.normal));o.wPos = mul(unity_ObjectToWorld, v.vertex).xyz;o.wViewDir = normalize(UnityWorldSpaceViewDir(o.wPos));o.wReflect = reflect(-o.wViewDir, o.wNormal);o.wRefract = refract(-o.wViewDir, o.wNormal, _RefractRatio);return o;}fixed4 frag(vert2frag i): SV_Target {fixed3 wLightDir = normalize(UnityWorldSpaceLightDir(i.wPos));fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;      fixed4 reflection = texCUBE(_CubeMap, i.wReflect);fixed4 refraction = texCUBE(_CubeMap, i.wRefract);fixed fresnel = saturate(_FresnelScale + (1 - _FresnelScale) * pow(1 - dot(i.wViewDir, i.wNormal), 5));return fixed4(ambient, 1) + fresnel * reflection + (1 - fresnel) * refraction;              //此处应考虑能量守恒,而非使用插值} ENDCG}}FallBack "Specular"
}

五、动态环境映射

在上一节中实现了假反射,也就是物体仅能反射天空盒,而无法反射周边的其它的物体

可以尝试在不考虑性能的情况下实现以下动态环境映射,也就是实现“真”反射

1):动态生成立方体贴图:

可以依靠 Unity 自带的函数 Camera.RenderToCubemap(cubemap) 来生成以当前物体为中心,周围场景的天空盒:

Unity 官网上给出了一个很经典的例子如下:

using UnityEngine;
using UnityEditor;
using System.Collections;public class RenderCubemapWizard : ScriptableWizard
{public Transform renderFromPosition;public Cubemap cubemap;void OnWizardUpdate(){string helpString = "Select transform to render from and cubemap to render into";bool isValid = (renderFromPosition != null) && (cubemap != null);}void OnWizardCreate(){// create temporary camera for renderingGameObject go = new GameObject("CubemapCamera");go.AddComponent<Camera>();// place it on the objectgo.transform.position = renderFromPosition.position;go.transform.rotation = Quaternion.identity;// render into cubemapgo.GetComponent<Camera>().RenderToCubemap(cubemap);// destroy temporary cameraDestroyImmediate(go);}[MenuItem("GameObject/Render into Cubemap")]static void RenderCubemap(){ScriptableWizard.DisplayWizard<RenderCubemapWizard>("Render cubemap", "Render!");}
}

这是一份工具代码,应用后,就可以在这里找到自己的“编辑器”:

点击 Render 就可以将图象渲染到上面设置的立方体纹理中,其中立方体纹理的创建如下:

不过需要注意的是,这个立方体需要设置可读,不然会出现报错“Unable to render into cubemap, make sure it's marked as 'Readable'”

2):渲染到 RT

根据 1),我们可以得到一个很暴力的实现方法,对于每一帧每一个物体都动态生成对应的立方体贴图,并将其作为前面的 Shader 中的 CubeMap

当然在实现过程中需要用到渲染纹理(RenderTexture),这部分就在后面介绍了

还是能得到一个很不错的效果的

UnityShader18.1:立方体贴图(下)相关推荐

  1. UnityShader18:立方体贴图(上)

    一.天空盒 使用立方体贴图最直接的目的就是展现天空盒,或者更进一步用于实现环境映射(反射与折射) 关于立方体贴图的采样原理:https://blog.csdn.net/Jaihk662/article ...

  2. WebGL 利用FBO完成立方体贴图。

    这篇主要记录WebGL的一些基本要点,顺便也学习下如何使用FBO与环境贴图.先看下效果图(需要支持WebGL,Chrome,火狐,IE11). 主要实现过程如下,先用FBO输出当前环境在立方体纹理中, ...

  3. LearnOpenGL->立方体贴图

    立方体贴图 立方体贴图 在本节中,我们将讨论的是将多个纹理组合起来映射到一张纹理上的一种纹理类型:立方体贴图(Cube Map). 简单来说,立方体贴图就是一个包含了6个2D纹理的纹理,每个2D纹理都 ...

  4. OpenGL 核心技术之立方体贴图

    笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,国家专利发明人;已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社和<Unity3D ...

  5. OpenGL ES 3. 天空盒 立方体贴图

    大家好,接下来将为大家介绍OpenGL ES 3. 天空盒 立方体贴图. OpenGL ES 立方体贴图本质上还是纹理映射,是一种 3D 纹理映射.立方体贴图所使的纹理称为立方图纹理,它是由 6 个单 ...

  6. OpenGL 入门 17:立方体贴图

    立方体贴图(Cube Map) 立方体贴图是由"上下左右前后"6个2D纹理合并成的一张纹理.与2D纹理使用(u,v)坐标采样不同的是,立方体纹理使用一个方向向量进行采样. 1. 方 ...

  7. 第三十七章 立方体贴图总结

    立方体贴图:将多个纹理组合起来映射到一张纹理上的一种纹理类型. 一个立方体贴图时包含了6个2D纹理的纹理,每个2D纹理都组成了立方体的一个面,相当于是一个有纹理的立方体. 创建立方体贴图: 首先需要生 ...

  8. 天空图立方体贴图转化为辐照度立方体贴图

    创建立方体贴图 注意:立方体贴图的大小决定被转化的辐照度贴图的精度. irradianceCubeMap = new CubeMap(32); 调用 CubeMap::CubeMap(int Cube ...

  9. 第十八课,立方体贴图(加载天空盒)

    原理我在这里不再过多叙述,主要从代码的运行方向来解读立方体贴图 添加天空盒顶点 float skyboxVertices[] = {// positions -1.0f, 1.0f, -1.0f,-1 ...

最新文章

  1. Windows程序设计零基础自学_7_进程操作
  2. java工单自动化流程控件,一种工单审批的自动化处理方法及系统与流程
  3. 11个强大的Visual Studio调试小技巧
  4. easyui-window窗口不遮挡_眼睛是心灵的窗口、佩戴舒适又时尚的米家防蓝光护目镜 Pro...
  5. 解决浏览器下载excel文件时显示“文件已损坏”
  6. linux7系统如何配置网卡,Linux 7 配置网卡(nmcli)
  7. Python--进程、线程、协程对比
  8. 如何修改7 服务器配置,centos7修改服务器配置
  9. 面向小姐姐的编程——JAVA面向对象之继承(二)
  10. Mr.J--验证码登陆模块
  11. 数据属性和访问器属性
  12. python爬虫教程-Python爬虫入门教程——爬取自己的博客园博客
  13. 如何快速调整图片亮度和对比度?
  14. Matlab学习笔记之Matlab中括号用法
  15. 2020 年的风口是什么?
  16. Hazelcast IMDG参考中文版手册-第三章-概述
  17. BERT模型的结构,特点和实践
  18. js统计字符串中字母个数以及统计最多字母数
  19. 基本统计值的计算(平均值,中位数,方差)
  20. 最近感冒恢复中,读了《平凡的世界》,写点感受。

热门文章

  1. python和java先学哪个-java和python先学哪个
  2. python能做什么软件-python可以编写什么软件
  3. 0基础学python要多久-零基础学Python的过程有多难?需要多久?
  4. 阿里开源自研语音识别模型DFSMN 准确率高达96.04%
  5. 语音识别相关书籍抖音十大先看哪一本最好
  6. php中splite,PHP语言 的 chunk_split() 函数
  7. jQueryQQ音乐动态轮播图
  8. 移动web-双飞翼(圣杯)布局
  9. 计算机知识wendang,计算机基础知识Microsoft Word 文档
  10. IIS 301重定向跳转