The Basics of Fresnel Shading



ref:http://kylehalladay.com/blog/tutorial/2014/02/18/Fresnel-Shaders-From-The-Ground-Up.html


I recently stumbled on the awesome article: Everything Has Fresnel (if you haven’t read it, go read it now). The main premise of the article is that real world materials are not actually as neat and tidy as programmers would like to believe, and more specifically, that virtually everything in real life has some degree of fresnel reflectivity.

Fresnel isn’t an effect that I’ve seen often in Unity projects and in fact wasn’t an effect that I was familiar with building, so I decided to kill two birds with one project and put together my latest shader pack: Fresnel Shaders. It’s all free to use, MIT license, all that jazz, so enjoy :D

But, as usual, I’d also like to make things a bit easier for the next googler looking for an intro to Fresnel reflection. So if writing Fresnel shaders (or adding Fresnel to existing ones) sounds as much fun to you as it was for me, read on!


An unlit Fresnel shader


What is the Fresnel Effect

In essence, the fresnel effect describes the relationship between the angle that you look at a surface and the amount of reflectivity you see. This is very easy to demonstrate if you have a window nearby. If you look at the window straight on you can see through the window as intended, however, if you move so that you try to look through the window at a glancing angle (ie: your view direction is approaching parallel to the window’s surface) the window becomes much closer to a mirror.

But this effect isn’t limited to windows, or even particularly shiny objects. As John Hable points out in Everything Has Fresnel, pretty much everything (including towels and bricks!) exhibit the fresnel effect to some degree. I’ve made a game out of trying to spot instances of it as I walk to work (without looking I’ve lost my mind).

So what does this look like when added to an object in Unity? Here’s a few more examples from my shader pack:


The Shaders in the Fresnel Shader Pack


How is it implemented?

As it turns out, Fresnel equations are complicated, way more so than can be adequately covered by a blog post, and way more than is feasible to execute in real time for most applications. In practice, it’s far more realistic to use an approximation of these equations. In searching, I’ve ended up finding two such approximations have so far seemed appropriate to use in real time shaders.

The first is the Schlick Approximation. This is easy enough to google for, but I’ll put here just for reference as well:

R(θ) = R 0  + (1 - R 0)(1 - cosθ) 5


In the above equation, R0 refers to the reflection coefficient for light moving between 2 interfaces with different refractivity (most commonly, air and whatever type of material the surface is). If you’re really interested, definitely check out more detailed sources online. In practice, I’ve found that while this method gives decent looking results, the next option gives us much greater control over the appearance of our materials at the cost of physical correctness. Given that real time graphics are anything but physically correct, I’m ok with this tradeoff.

The second approximation comes from chapter 7 of the Cg Tutorial from NVidia, which refers to it as the “Empricial Approximation.”

R = max(0, min(1, bias + scale * (1.0 + I • N) power))


  • R is a Fresnel term describing how strong the Fresnel effect is at a specific point
  • I is the vector from the eye to a point on the surface
  • N is the world space normal of the current point
  • bias, scale and power are values exposed to allow control over the appearance of the Fresnel effect

This equation is a bit of a double edged sword. It’s very easy to make hideous looking Fresnel by tweaking the values of bias, scale and power, but it also gives you the ability to fine tune your materials to exactly how you want them to look.


Fresnel gone wrong


A Fresnel Shader

So what does this look like in a shader? It’s actually very simple. First, you need to calculate the value of R. For this example, we’ll do that in the vertex shader:

vOUT vert(vIN v)
{
	vOUT o;
	o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
	o.uv = v.texcoord;

	float3 posWorld = mul(_Object2World, v.vertex).xyz;
	float3 normWorld = normalize(mul(float3x3(_Object2World), v.normal));

	float3 I = normalize(posWorld - _WorldSpaceCameraPos.xyz);
	o.R = _Bias + _Scale * pow(1.0 + dot(I, normWorld), _Power);

	return o;
}

There isn’t too much to say about this, since it’s pretty much the equation above verbatim. One handy tip though: I’ve found that I’ve been perfectly happy with the results I get if I omit the bias parameter entirely, and doing so makes it more difficult to produce wonky results.

Once you have the R value calculated, the rest of the implementation is just a lerp in the fragment shader:

float4 frag(vOUT i) :  COLOR
{  
	float4 col = tex2D(_MainTex, i.uv.xy * _MainTex_ST.xy + _MainTex_ST.zw);
	return lerp(col,_Color, i.R);
}

If you’re not a Unity programmer, ignore all the _MainTex_ST stuff, that’s just a unity specific bit of code to handle tiling textures across an object.

Otherwise, all that’s new here is the lerp function. In this example, rather than reflecting anything, our Fresnel Rim is just a single color (_Color), but the principle is the same. If you wanted to turn the rim into a reflection, you’d simply replace the _Color variable with a color sampled from a cube map, or taken from a camera, or however else you want to pass in a reflection.

Otherwise though, this is all there is to it to write a simple Fresnel shader, so go forth and make all of your objects more believable! And feel free to download the Fresnel Shader Pack that I’ve posted in the graphics section of this site to see some examples of more complicated Fresnel effects.

If you’ve spotted an error on here, or have anything to add, feel free to send me a message on twitter. Happy shading!


磁共振成像(MRI)是一种非侵入性的医学影像技术,通过使用强磁场和无害的无线电波,生成高分辨率的人体内部图像。MRI的基本原理包括磁共振现象和信号处理。 首先,MRI利用强磁场产生静态磁场。这个强磁场使得人体内的原子(通常是氢)的原子核在磁场中定向,使其自旋沿磁场方向预先排列。 其次,MRI利用无线电频率的脉冲来激发人体内的原子核,使其从平衡状态中倾斜。 然后,MRI探测激发后原子核的归位,这个过程称为回波信号。原子核的归位过程会产生微弱的无线电信号。 接下来,MRI系统采集这些回波信号并进行信号处理。信号处理包括一个复杂的计算过程,其基本目标是确定回波信号的来源和特征。通过这种方式,系统可以构建数百个不同方向上的切片图像。 最后,计算机将切片图像组合在一起,形成三维结构,可以帮助医生观察和分析人体内部组织和器官的详细结构。 MRI是一种非常有用的影像技术,因为它能够提供清晰的高对比度图像,并且不涉及使用有害的X射线。它在医学诊断中广泛应用,特别是用于观察脑部、骨骼、关节、脊椎和内脏器官等结构。同时,MRI还可以用来检测肿瘤、损伤、疾病和其他异常,并且具有较高的准确性和灵敏度。 总之,MRI是一种基于磁共振原理的医学影像技术,可生成高分辨率、非侵入性的人体内部图像,对于医学诊断和研究具有重要意义。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值