Physics CG:菲涅尔(fresnel)反射

news/2024/11/14 15:15:29/

      这一篇是物理学CG的开篇,其实我多开了一个分类也是心理无奈的,自身水平有限,而很多物理图形学知识积累太少,有些甚至根本没学过。然而高级图形学知识中,或者说高级图形着色效果中,很大一部分是基于“真实”物理公式来实现的。但是,我看了部分物理公式和推导过程(我甚至在家里翻箱倒柜找到一本物理书看了一些),这些物理公式给我的感觉就是公式优雅,推导过程完备,匹配真实世界物理规律,但是就是不知道这些公式怎么来的。

      记得以前的物理老师跟我们说的是,物理公式是前人实验总结的数学表达结果,我们也亲手做过很多简单的物理实验,理解其数学表达式的含义。直到质能方程、麦克斯韦方程、高斯定理等,我的天,我最多只能用公式去计算。其完整的推导过程以及过程后面的含义都让我迷迷糊糊,最后接受的教条就是能用就行,大致理解其中的道理。因为我也不是数学系的,线性代数/微积分及以下数学领域常用的公式推导还能勉强讲解,至于高端一点的物理公式我也只能结合其数学表达式使用和找一些文献查看其由来或者推导了,至于让我深层解释其意义,我是无能为力。

      当然学到今天这个地步,不涉及到物理图形学,基本上就没有更深的东西可以来学习了,其他常用图形学技术,已经可以默默的看一个懂一个,懂一个写一个了,所以还是要开展一些物理相关图形学的学习。

      好了,说到这里,今天主要来说一下菲涅尔公式,先回顾一下以前的菲涅尔折射计算:refract计算 菲涅尔反射

      这里主要来说一下菲涅尔反射(折射我们都知道,光线通过不同介质的时候会发生折射,折射公式n1 * sinθ1 = n2 * sinθ2,n1θ1为入射折射率和入射角,n2sinθ2为反射折射率和折射角),原文描叙如下:

      当你站在湖边,低头看脚下的水,你会发现水是透明的,反射不是特别强烈,如果你抬头看远处的湖面,会发现水不是透明的,反射非常强烈,这就是“菲涅尔效应”。从数学上来讲,就是视线垂直于水平面呈90°,则反射较弱,而视线方向逐渐改变,非垂直于水平面,而是与水平面夹角从90°慢慢减小,反射就越明显。如果你正对着看一个球体,视线聚焦于球心的时候反射较弱,视线越靠近球体边缘反射越强,这个菲涅尔反射效应在现实世界和三维图形中有很广泛的使用。

      这是我查到的菲涅尔反射应用简化计算公式:

      float fresnel =  F_base + F_scale*((1-v*n)^power);       F_base/F_scale/power都是菲涅尔控制系数,可以抛出调参的。

      顺便解释一下,v为视点到视口的单位朝向向量,n为视点的单位法向量。所以综合公式来看,当“低头看向脚下湖水”,dot(v,n)趋于1,fresnel趋于F_base,当“抬头看向远处的湖面”,dot(v,n)趋于0,fresnel趋于F_base + F_scale(power幂次方为大于1的情况)。那么总结来说,这个公式能达到越抬头望向远处,fresnel值越大(F_base/F_scale均为正数)。

      这也很符合“菲涅尔效应”,如果将fresnel作为颜色混合权重参数,混合因子为原始颜色和反射颜色,那么“低头”时fresnel越小,则越表现原始颜色,”抬头“时fresnel越大越表现反射颜色。

      如果看了光照模型那些应该就感觉的出来,和光照模型中计算diffuse和specular很像。

      既然知道这个菲涅尔反射意义和应用计算公式,那么接下来我们就来实现一下:

      

Shader "Unlit/FresnelReflectShader"
{Properties{_MainTex ("Texture", 2D) = "white" {}_FresnelBase("F Base",Range(0,1)) = 1_FresnelScale("F Scale",Range(0,1)) = 1_FresnelPower("F Power",Range(1,10)) = 5_FresnelColor("F Color",Color) = (1,1,1,1)}SubShader{//前向渲染模式Tags { "RenderType"="Opaque" "LightMode" = "ForwardBase" }LOD 100Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct appdata{float4 vertex : POSITION;float2 uv : TEXCOORD0;float3 normal : NORMAL;			/*建模空间法向量源数据*/};struct v2f{float2 uv : TEXCOORD0;float4 vertex : SV_POSITION;float3 worldV : TEXCOORD1;			/*世界空间视点到视口朝向向量*/float3 worldN : TEXCROOD2;			/*世界空间视点法向量*/};sampler2D _MainTex;float4 _MainTex_ST;/*三个菲涅尔控制系数*/float _FresnelBase;				float _FresnelScale;float _FresnelPower;/*菲涅尔反射颜色*/float4 _FresnelColor;v2f vert (appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);o.uv = TRANSFORM_TEX(v.uv, _MainTex);//处理世界空间中视点(顶点)到视口朝向向量o.worldV = normalize(WorldSpaceViewDir(v.vertex));//o.worldV = normalize(_WorldSpaceCameraPos.xyz - mul(unity_ObjectToWorld, v.vertex)).xyz;//处理建模到世界空间的法向量变换o.worldN = normalize(UnityObjectToWorldNormal(v.normal));return o;}/*颜色混合*/fixed4 blendColor(fixed4 col, fixed4 fcol, float wei){return col * (1-wei) + fcol * wei;}fixed4 frag (v2f i) : SV_Target{fixed4 col = tex2D(_MainTex, i.uv);//逐片段计算fresnel值float fresnel = saturate(_FresnelBase + _FresnelScale * pow(1 - dot(i.worldN, i.worldV), _FresnelPower));//混合源颜色和反射颜色权重fixed4 bcol = blendColor(col, _FresnelColor, fresnel);return bcol;}ENDCG}}
}

      使用到了unityCG.cginc自带的辅助函数,如下:

   

   

   表现效果如下:

   

   比较符合在湖边观察湖水的情况,同时上面的sphere也展示了fresnel效应在普通物体上的表现效果。

   当然了,我们可以修改一下shader增加环境反射,将fresnelColor修改为采样环境反射cubemap的颜色值,实现表现效果比较好的fresnel效应,如下:

   

Shader "Unlit/FresnelReflectShader"
{Properties{_MainTex ("Texture", 2D) = "white" {}_FresnelBase("F Base",Range(0,1)) = 1_FresnelScale("F Scale",Range(0,1)) = 1_FresnelPower("F Power",Range(1,10)) = 5_FresnelCube("F Cube",CUBE) = "" {}}SubShader{//前向渲染模式Tags { "RenderType"="Opaque" "LightMode" = "ForwardBase" }LOD 100Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct appdata{float4 vertex : POSITION;float2 uv : TEXCOORD0;float3 normal : NORMAL;			/*建模空间法向量源数据*/};struct v2f{float2 uv : TEXCOORD0;float4 vertex : SV_POSITION;float3 worldV : TEXCOORD1;			/*世界空间视点到视口朝向向量*/float3 worldN : TEXCROOD2;			/*世界空间视点法向量*/float3 worldR : TEXCOORD3;			/*环境反射向量*/};sampler2D _MainTex;float4 _MainTex_ST;/*三个菲涅尔控制系数*/float _FresnelBase;				float _FresnelScale;float _FresnelPower;/*环境盒子贴图*/samplerCUBE _FresnelCube;v2f vert (appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);o.uv = TRANSFORM_TEX(v.uv, _MainTex);//处理世界空间中视点(顶点)到视口朝向向量o.worldV = normalize(WorldSpaceViewDir(v.vertex));//o.worldV = normalize(_WorldSpaceCameraPos.xyz - mul(unity_ObjectToWorld, v.vertex)).xyz;//处理建模到世界空间的法向量变换o.worldN = normalize(UnityObjectToWorldNormal(v.normal));//使用cg自带reflect采样o.worldR = reflect(-o.worldV, o.worldN);return o;}/*颜色混合*/fixed4 blendColor(fixed4 col, fixed4 fcol, float wei){return col * (1-wei) + fcol * wei;}fixed4 frag (v2f i) : SV_Target{fixed4 col = tex2D(_MainTex, i.uv);fixed4 rcol = texCUBE(_FresnelCube, i.worldR);//逐片段计算fresnel值float fresnel = saturate(_FresnelBase + _FresnelScale * pow(1 - dot(i.worldN, i.worldV), _FresnelPower));//混合源颜色和反射颜色权重fixed4 bcol = blendColor(col, rcol, fresnel);return bcol;}ENDCG}}
}

    效果图如下:

  

   这也是三维图形学中对菲涅尔效应的应用。

   后面持续对基于物理学的shader进行学习总结。


http://www.ppmy.cn/news/781713.html

相关文章

菲涅尔透镜的原理及应用

1. 菲涅尔透镜的作用 菲涅尔透镜,简单的说就是在透镜的一侧有等距的齿纹。通过这些齿纹,可以达到对指定光谱范围的光带通(反射或者折射)的作用。传统的打磨光学器材的带通光学滤镜造价昂贵,菲涅尔透镜可以极大的降低成本。 菲涅尔透镜 典型…

Unreal 4 Fresnel Material 菲涅尔材质

1.Fresnel with normal map 菲涅尔效果与法线贴图 材质球: 注意点: 1)Blend Model改为Translucent,在Translucency面板下,更改Lighting Model为Surface Translucency Volume ,才能激活Normal属性。 2&a…

Matlab:实现菲涅尔圆孔衍射仿真

本文基于光学原理,用Matlab实现菲涅尔圆孔衍射现象仿真。 以下使用了两种菲涅尔衍射的数值计算方法: 菲涅尔衍射积分的离散求和菲涅尔衍射FFT法 Project Code % 作者:ZQJ % 日期:2021.7.22 星期四%**********************基于光…

【实时渲染】菲涅尔反射率

《Real Time Rendering 4th》9.5 章读书笔记 经典的折射和反射定律 光通过两个不同介质的界面的时候,会发生反射和折射现象。反射是指光从另一个路径离开界面,折射是指光通过界面进入了另一种介质中。其中满足条件: 反射角等于入射角折射角…

MATLAB:菲涅尔公式(反射/透射公式)

目录 案例1:光疏到光密介质 案例2:光密到光疏介质 案例1:光疏到光密介质 平面光波从空气(折射率为)入射到石英玻璃中(折射率为),用 MATLAB作出p、s分量的振幅反射率和振幅透射率以…

Fresnel(菲涅尔)

背景: 菲涅耳公式用来描述光在不同折射率的介质之间的行为。菲涅尔公式是光学中的重要公式,用它能解释反射光的强度、折射光的强度、相位与入射光的强度的关系。 1. 反射公式: fresnel fresnel基础值 fresnel缩放量*pow( 1 - dot( N, V ), 5 ) Code:菲涅尔反射 …

液晶屏的软硬屏之间的battle,谁更胜一筹?

平时所用到的液晶屏硬屏LCD,就是屏幕的像素是鱼鳞状,方向是朝左的,因为类似人字形,所以也俗称“人”。硬屏之所以硬,是因为在屏幕上按压触摸后不会出现水纹,要么是液晶屏加树脂保护膜,要么是硬屏…

​菲涅尔反射(Fresnel Reflection)​理论概要

离线渲染中,通常可以用kd,ks,kt(分别代表物体的漫反射系数,镜面反射系数,透射系数)来简单地描述一个物体的基本材质,例如,我们将一个物体设置为:kd0,ks0.1,kt0.9,即代表一束光击中该物体表面后,其中的90%发…