菲涅尔效果,指当光到达两种材质的接触面时,一些光在接触面的表面被反射出去,而另一部分光将发生折射穿过接触面。
现在要用shader来实现这种效果,如果要精确地描述这种底层的物理,其计算公式是非常复杂的,性能消耗也比较大。我们的目的是使创建的图像看上去真实,因此我们不使用菲涅尔公式本身,而是使用以下经验公式,它能够用非常少的计算获得很好的效果。
reflectionCoefficient = max(0, min(1, bias + scale * pow(1 + dot(I,N), power)))
finalColor = reflectionCoefficient * reflectedColor + (1 - reflectionCoefficient ) * refractedColor
在unity3d中的渲染效果如下:
如用shaderLab写的一个例子shader如下:
1 Shader "Custom/Test" 2 { 3 Properties 4 { 5 _Cube("Cube", Cube) = "white" {} 6 _EtaRatio("Eta ratio", float) = 0.8 7 _FresnelPower("Fresnel power", float) = 2 8 _FresnelScale("Fresnel scale", float) = 1 9 _FresnelBias("Fresnel bias", float) = 0 10 } 11 12 SubShader 13 { 14 Tags 15 { 16 "RenderType" = "Opaque" 17 } 18 19 Pass 20 { 21 CGPROGRAM 22 #pragma vertex Vert 23 #pragma fragment Frag 24 25 uniform samplerCUBE _Cube; 26 uniform float _EtaRatio; 27 uniform float _FresnelPower; 28 uniform float _FresnelScale; 29 uniform float _FresnelBias; 30 31 struct AppData 32 { 33 float4 pos : POSITION; 34 float3 nor : NORMAL; 35 }; 36 37 struct V2F 38 { 39 float4 pos : SV_POSITION; 40 float reflectionFactor : Color; 41 float3 r : TEXCOORD0; 42 float3 t : TEXCOORD1; 43 }; 44 45 V2F Vert(AppData vi) 46 { 47 V2F fi; 48 fi.pos = mul(UNITY_MATRIX_MVP, vi.pos); 49 50 float3 worldPos = mul(_Object2World, vi.pos.xyz); 51 float3 n = mul(_Object2World, vi.nor); 52 float3 i = worldPos - _WorldSpaceCameraPos.xyz; 53 fi.r = reflect(i, n); 54 55 i = normalize(i); 56 n = normalize(n); 57 fi.t = refract(i, n, _EtaRatio); 58 59 fi.reflectionFactor = _FresnelBias + _FresnelScale * pow(1 + dot(i, n), _FresnelPower); 60 61 return fi; 62 } 63 64 float4 Frag(V2F fi) : Color 65 { 66 float4 reflectC = texCUBE(_Cube, fi.r); 67 float4 refractC = texCUBE(_Cube, fi.t); 68 return lerp(refractC, reflectC, fi.reflectionFactor); 69 } 70 71 ENDCG 72 } 73 } 74 }
转载请注明出处: http://www.cnblogs.com/jietian331/p/5564901.html
时间: 2024-09-28 02:49:11