According to the previous example http://blog.csdn.net/wolf96/article/details/44172243 (do not get hyperlinks to the audit too slow) to get a real physical-based rendering
Escaped the lesson = =, got a bit.
The formula and the previous article, this time add CubeMap map, because of convenience, directly with surface shader, because do not ask reflect direction,
This article also shows how cubemap is used in surface shader and how it is reflected in real time http://blog.csdn.net/wolf96/article/details/41939325
OK go to the point, the previous mentioned Ops2 Brdf method, now look at OPS2 improved BRDF method
This is the code they give, the value of the F (l,h) function, where g is gloss gloss, the meaning of Ndotv,n, V, and so on in the previous article, rf0 let him be a controllable external variable.
Review the method of cook-torrance illumination model to find specular
Can be simply summed up as this formula
This calculation inherits the last method,
Instead, use the specular power variable _sp for gloss glossiness to define the external variable _GL control for this article, the specific method _sp = Pow (8192, _GL) is specular power value of 8192 gloss times, By borrowing 8192 of the already tuned parameters, I was standing on the shoulders of giants.
OPS2 developers say their BRDF is environment map pre-filtering
Simulates ambient light exposure.
Original Description The environment map blurs much more linearly across the gloss range
The range of gloss makes the blur of the environment map more linear, and the next example we can see the results
First, we define the illumination function, the exact algorithm is the same as the previous one does not repeat here. Just change the f (l,h) function BRDF to the improved method above, the code is as follows:
inline fixed4 lightingops (surfaceops s, fixed3 Lightdir, Fixed3 viewdir, fixed atten) { Viewdir = normalize (viewdir); lightdir = normalize (Lightdir); Float3 H = normalize (Lightdir + viewdir); s.normal = normalize (s.normal); FLOAT3 N = s.normal;float _sp = Pow (8192, _GL); float D = (_sp + 2)/(8 * PIE) * POW (dot (N, H), _sp);//float F = _sc + (1-_SC) *pow ((1-dot (H, Lightdir)), 5), float f = environmentbrdf (_GL, Dot (N, viewdir), _r0f), float k = 2/sqrt ( PIE * (_sp + 2)); float v = 1/((dot (n, lightdir) * (1-k) + k) * (dot (n, viewdir) * (1-k) + K); float spec = D*F*V;FLOAT4 C = FLOAT4 (S.albedo, 1); C.rgb + = (_SC + (1.0-_SC) * s.deferredfresnel) * spec;//* light.rgb;c + = SPEC*_SC;C.A = S.alpha;re Turn C;}
In the surf function we want to decode cubemap value to the light function, again this note, we use not texcube but texcubelod, see the function name know not only to solve the color, but also control lod,lod for level of detail, detail degree, We control the details by controlling the W value of his second parameter, through which we can change his roughness, which is also based on the physical rendering of the soul, and we want to make the gloss gloss the lower the coarser the more coarse. We define an external variable _nmips to control, thus debugging into the effect we want.
In the surf function also need to calculate the BRDF, in order to control the light specular gravity, make it more real
void Surf (Input in, InOut surfaceops o) {half4 c = tex2d (_maintex, In.uv_maintex) * _maintint;o. Emission = Texcubelod (_cubemap, Float4 (IN.WORLDREFL, _nmips-_gl*_nmips)). RGB * _reflamount;float cost = dot (In.viewdir, In.worldnormal);//c = (1-spec) * C;float F = ENVIRONMENTBRDF (_GL, Dot (in.worldnormal, in.viewdir), _r0f); O. Deferredfresnel = F;o. Albedo = C.rgb;o. Alpha = C.A;}
The
Effect is as follows:
I've done a variety of experiments, changed the NDF function
This is the Phong distribution function
Beckmann distribution function, they are different, Careful comparison will find Beckmann high light is stronger, more abrupt
Torrance-reitz (GXX) distribution function
Results found OPS2 is the best effect, Next is the Torrance-reitz
another family photo
Give all the code of OPS2, and the others will be changed according to the previous code
Shader "Custom/surface_cube_new ops" {Properties{_maintex ("Base (RGB)", 2D) = "White" {}_maintint ("Diffuse color", color = (1, 1, 1, 1) _cubemap ("Cubemap", CUBE) = "" "{}_reflamount (" Reflection Amount ", Range (0.01, 1)) = 0.5_SC (" Specular Color " , Color) = (1, 1, 1, 1) _gl ("Gloss", range (0, 1)) = 0.5_r0f ("r0f", range (0, 1)) = 0.5_nmips ("NMIPSF", Range (0, 5)) = 0.5}su bshader{tags{"Rendertype" = "Opaque"}lod 400cgprogram#pragma surface surf Ops noambient#pragma glsl#pragma Target 3.0SA mpler2d _maintex;samplercube _cubemap;float4 _maintint;float _reflamount;float4 _SC;float _nMips;float _GL;float _R0F; struct SURFACEOPS{FIXED3 albedo;fixed3 normal;fixed3 emission;fixed3 specular;fixed gloss;fixed Alpha;half Deferredfresnel;}; struct INPUT{FLOAT2 uv_maintex;float3 worldpos;float3 viewdir;float3 worldnormal;float3 WORLDREFL;////WORLDREFL: That is the reflection vector of world space///built-in WORLDREFL to do cubic reflection (CubeMap reflection)}; #define PIE 3.1415926535#define E 2.71828FLOAT3 ENVIRONMENTBRDF (float g, float NoV, float3 rf0) {FLOAT4t = float4 (1/0.96, 0.475, (0.0275-0.25 * 0.04)/0.96, 0.25); t *= float4 (g, G, G, g); t + = float4 (0, 0, (0.015-0.75 * 0.04)/0.96, 0.75); Float a0 = t.x * min (T.y, EXP2 ( -9.28 * NoV)) + t.z;float A1 = T.w;return Saturate (a0 + rf0 * (a1-a0 ));} Inline Fixed4 lightingops (surfaceops s, fixed3 Lightdir, Fixed3 viewdir, fixed atten) {Viewdir = normalize (viewdir); LIGHTD IR = normalize (lightdir), float3 H = normalize (Lightdir + viewdir); s.normal = normalize (s.normal); FLOAT3 N = S.normal;float _sp = Pow (8192, _GL), float d = (_sp + 2)/(8 * PIE) * POW (dot (N, H), _sp),//float f = _sc + (1-_SC) *pow ((1-dot (H, Li Ghtdir)), 5); float f = environmentbrdf (_GL, Dot (N, viewdir), _r0f), float k = 2/sqrt (PIE * (_sp + 2)), float v = 1/(dot (n, Lightdir) * (1-k) + k) * (dot (n, viewdir) * (1-k) + K); float spec = d*f*v;float4 c = float4 (S.albedo, 1); C.rgb + = (_sc + (1.0-_SC) * s.deferredfresnel) * spec;//* light.rgb;c + = SPEC*_SC;C.A = S.alpha;return C;} void Surf (Input in, InOut surfaceops o) {half4 c= tex2d (_maintex, In.uv_maintex) * _maintint;o. Emission = Texcubelod (_cubemap, Float4 (IN.WORLDREFL, _nmips-_gl*_nmips)). RGB * _reflamount;float cost = dot (In.viewdir, In.worldnormal);//c = (1-spec) * C;float F = ENVIRONMENTBRDF (_GL, Dot (in.worldnormal, in.viewdir), _r0f); O. Deferredfresnel = F;o. Albedo = C.rgb;o. Alpha = C.A;} Endcg}fallback "Diffuse"}
----by wolf96
Unity3d implementation of physically-based rendering based on physical rendering