Unity Community


Results 1 to 16 of 16

Thread: Cook-Torrance


  1. Location
    Russia, Moscow
    Posts
    36

    Cook-Torrance

    Hello, who can help with the conversion of this shader in Unity?
    I found many examples of shaders, but, more correctly, I do not quite understand, here are some of them
    http://www.gamedev.ru/code/articles/Cook-Torrance
    http://steps3d.narod.ru/tutorials/li...-tutorial.html
    http://content.gpwiki.org/index.php/..._Cook-Torrance

    Code:  
    1. float CookTorrance(vec3 _normal, vec3 _light, vec3 _view, float roughness_val)
    2. {
    3.  if (roughness_val <= 0.0) return 0.0;
    4. }
    5.    vec3  half_vec = normalize( _view + _light );
    6.    float NdotL    = max( dot( _normal, _light ), 0.0 );
    7.    float NdotV    = max( dot( _normal, _view ), 0.0 );
    8.    float NdotH    = max( dot( _normal, half_vec ), 1.0e-7 );
    9.    float VdotH    = max( dot( _view,   half_vec ), 0.0 );
    10.  
    11.    float geometric = 2.0 * NdotH / VdotH;
    12.    geometric = min( 1.0, geometric * min(NdotV, NdotL) );
    13.  
    14.    float r_sq          = roughness_val * roughness_val;
    15.    float NdotH_sq      = NdotH * NdotH;
    16.    float NdotH_sq_r    = 1.0 / (NdotH_sq * r_sq);
    17.    float roughness_exp = (NdotH_sq - 1.0) * ( NdotH_sq_r );
    18.    float roughness     = exp(roughness_exp) * NdotH_sq_r / (4.0 * NdotH_sq );
    19.    float fresnel       = 1.0 / (1.0 + NdotV);
    20.    Rs = min(1.0, (fresnel * geometric * roughness) / (NdotV * NdotL + 1.0e-7));
    21.  
    22.    vResult = vAmbient + LdotN  * (vDiffuse + vSpecular * Rs)
    Last edited by Nose; 11-14-2012 at 04:51 PM.


  2. Location
    Turkey
    Posts
    1,920
    cook-torrance is a lighting model, and its best you apply it as a custom lighting function in a surface shader.
    Check the unity shader include files in unity/data/cgincludes folder and there you will see some examples of how to make your own custom lighting functions.

    Thing is, cook-torrance is mathematically heavy and unnecessary for most cases.


  3. Location
    Leeds, UK
    Posts
    2,059
    I think that should do it...

    Code to generate the Beckmann lookup texture can be found at the bottom of this page;
    http://www.altdevblogaday.com/2011/1...ng-in-unity3d/

    Roughness slider:
    Code:  
    1. Shader "Custom/CookTorrance" {
    2.     Properties {
    3.         _Color ("Main Color", Color) = (1,1,1,1)
    4.         _MainTex ("Diffuse (RGB) Alpha (A)", 2D) = "white" {}
    5.         _Roughness ("Roughness", Range(0,1)) = 0.5
    6.         _BumpMap ("Normal (Normal)", 2D) = "bump" {}
    7.         _Beckmann ("Beckmann Lookup (RGB)", 2D) = "gray" {}
    8.         _Fresnel ("Fresnel Value", Float) = 0.028
    9.         _Cutoff ("Alpha Cut-Off Threshold", Range(0,1)) = 0.5
    10.     }
    11.  
    12.     SubShader{
    13.         Tags { "Queue" = "Geometry" "IgnoreProjector" = "True" "RenderType" = "TransparentCutout" }
    14.  
    15.         CGPROGRAM
    16.  
    17.             #pragma surface surf CookTorrance exclude_path:prepass nolightmap nodirlightmap fullforwardshadows
    18.             #pragma target 3.0
    19.  
    20.             struct Input
    21.             {
    22.                 float2 uv_MainTex;
    23.             };
    24.  
    25.             sampler2D _MainTex, _BumpMap, _Beckmann;
    26.             float _Fresnel, _Cutoff, _Roughness;
    27.  
    28.             void surf (Input IN, inout SurfaceOutput o)
    29.             {
    30.                 fixed4 albedo = tex2D(_MainTex, IN.uv_MainTex);
    31.                 o.Albedo = albedo.rgb;
    32.                 o.Alpha = albedo.a;
    33.  
    34.                 o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_MainTex));
    35.             }
    36.  
    37.             inline fixed4 LightingCookTorrance (SurfaceOutput s, fixed3 lightDir, fixed3 viewDir, fixed atten)
    38.             {
    39.                 clip ( s.Alpha - _Cutoff );
    40.  
    41.                 viewDir = normalize ( viewDir );
    42.                 lightDir = normalize ( lightDir );
    43.                 float3 h = normalize ( lightDir + viewDir );
    44.                 float NdotL_unsat = dot ( s.Normal, lightDir );
    45.                 float NdotH_unsat = dot ( s.Normal, h );
    46.                 float NdotL = saturate( NdotL_unsat );
    47.                 float NdotH = saturate( NdotH_unsat );
    48.                 float NdotV = saturate( dot ( s.Normal, viewDir ) );
    49.                 float VdotH = saturate( dot ( viewDir, h ) );
    50.  
    51.                 float geo_numerator = 2.0 * NdotH;
    52.                 float geo_b = ( geo_numerator * NdotV ) / VdotH;
    53.                 float geo_c = ( geo_numerator * NdotL ) / VdotH;
    54.                 float geo = min( 1.0f, min( geo_b, geo_c ) );
    55.  
    56.                 fixed roughness = tex2D( _Beckmann, float2 ( NdotH_unsat * 0.5 + 0.5, _Roughness ) ).r;
    57.  
    58.                 float fresnel = pow( 1.0 - VdotH, 5.0 );
    59.                 fresnel *= ( 1.0 - _Fresnel );
    60.                 fresnel += _Fresnel;
    61.  
    62.                 float3 spec = float3 ( fresnel * geo * roughness ) / ( NdotV * NdotL );
    63.  
    64.                 fixed4 c;
    65.                 c.rgb = NdotL * (  _LightColor0.rgb * spec + s.Albedo ) * atten;
    66.                 c.a = s.Alpha;
    67.                 return c;
    68.             }
    69.  
    70.         ENDCG
    71.     }
    72.     FallBack "Transparent/Cutout/VertexLit"
    73. }

    Rougness texture:
    Code:  
    1. Shader "Custom/CookTorrance" {
    2.     Properties {
    3.         _Color ("Main Color", Color) = (1,1,1,1)
    4.         _MainTex ("Diffuse (RGB) Alpha (A)", 2D) = "white" {}
    5.         _Roughness ("Roughness (R)", 2D) = "gray" {}
    6.         _BumpMap ("Normal (Normal)", 2D) = "bump" {}
    7.         _Beckmann ("Beckmann Lookup (RGB)", 2D) = "gray" {}
    8.         _Fresnel ("Fresnel Value", Float) = 0.028
    9.         _Cutoff ("Alpha Cut-Off Threshold", Range(0,1)) = 0.5
    10.     }
    11.  
    12.     SubShader{
    13.         Tags { "Queue" = "Geometry" "IgnoreProjector" = "True" "RenderType" = "TransparentCutout" }
    14.  
    15.         CGPROGRAM
    16.  
    17.             #pragma surface surf CookTorrance exclude_path:prepass nolightmap nodirlightmap fullforwardshadows
    18.             #pragma target 3.0
    19.  
    20.             struct Input
    21.             {
    22.                 float2 uv_MainTex;
    23.             };
    24.  
    25.             sampler2D _MainTex, _BumpMap, _Beckmann, _Roughness;
    26.             float _Fresnel, _Cutoff;
    27.  
    28.             void surf (Input IN, inout SurfaceOutput o)
    29.             {
    30.                 fixed4 albedo = tex2D(_MainTex, IN.uv_MainTex);
    31.                 o.Albedo = albedo.rgb;
    32.                 o.Alpha = albedo.a;
    33.                 o.Specular = tex2D(_Roughness, IN.uv_MainTex).r;
    34.  
    35.                 o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_MainTex));
    36.             }
    37.  
    38.             inline fixed4 LightingCookTorrance (SurfaceOutput s, fixed3 lightDir, fixed3 viewDir, fixed atten)
    39.             {
    40.                 clip ( s.Alpha - _Cutoff );
    41.  
    42.                 viewDir = normalize ( viewDir );
    43.                 lightDir = normalize ( lightDir );
    44.                 float3 h = normalize ( lightDir + viewDir );
    45.                 float NdotL_unsat = dot ( s.Normal, lightDir );
    46.                 float NdotH_unsat = dot ( s.Normal, h );
    47.                 float NdotL = saturate( NdotL_unsat );
    48.                 float NdotH = saturate( NdotH_unsat );
    49.                 float NdotV = saturate( dot ( s.Normal, viewDir ) );
    50.                 float VdotH = saturate( dot ( viewDir, h ) );
    51.  
    52.                 float geo_numerator = 2.0 * NdotH;
    53.                 float geo_b = ( geo_numerator * NdotV ) / VdotH;
    54.                 float geo_c = ( geo_numerator * NdotL ) / VdotH;
    55.                 float geo = min( 1.0f, min( geo_b, geo_c ) );
    56.  
    57.                 fixed roughness = tex2D( _Beckmann, float2 ( NdotH_unsat * 0.5 + 0.5, s.Specular ) ).r;
    58.  
    59.                 float fresnel = pow( 1.0 - VdotH, 5.0 );
    60.                 fresnel *= ( 1.0 - _Fresnel );
    61.                 fresnel += _Fresnel;
    62.  
    63.                 float3 spec = float3 ( fresnel * geo * roughness ) / ( NdotV * NdotL );
    64.  
    65.                 fixed4 c;
    66.                 c.rgb = NdotL * (  _LightColor0.rgb * spec + s.Albedo ) * atten;
    67.                 c.a = s.Alpha;
    68.                 return c;
    69.             }
    70.  
    71.         ENDCG
    72.     }
    73.     FallBack "Transparent/Cutout/VertexLit"
    74. }
    Last edited by Farfarer; 11-21-2012 at 04:14 AM.


  4. Location
    Russia, Moscow
    Posts
    36
    This solution is not entirely correct. No need to use any textures except diffuse.
    Specular And Roughness should be managed by sliders or float


  5. Location
    Leeds, UK
    Posts
    2,059
    If you want those values per-material, sure. If you want parts of your texture to be glossy and others to be matte, then... no.

    It shouldn't take you more than 1 minute to swap it out for sliders, though.

    I've edited it to make the version you want.
    Last edited by Farfarer; 11-19-2012 at 07:20 AM.


  6. Location
    GMA950
    Posts
    3,031
    Quote Originally Posted by Nose View Post
    This solution is not entirely correct. No need to use any textures except diffuse.
    Specular And Roughness should be managed by sliders or float
    What do you mean by correct?

    Uniform reflectance and roughness across the whole model would be unfortunately restrictive use of such a complex lighting model. Farfarer's use of textures for these values lets you have smoother, rougher, more and less reflective areas on the same model.

    The Beckmann lookup texture is a good trade of a tiny bit of VRAM for a constant speedup in the fragment shader. Two of your three links use this texture.


  7. Posts
    1,547
    Using textures would make far more sense, now i have to convert it back, thankyou for the example Farfarer your contributions to Unity shaders have been really useful for me in these forums


  8. Location
    Russia, Moscow
    Posts
    36
    I found the correct shader, and I was able to convert it to Unity3D,
    I was very happy with the result.


  9. Location
    Leeds, UK
    Posts
    2,059
    Isn't that what the one I wrote did?


  10. Location
    Russia, Moscow
    Posts
    36
    No) I use one texture, duffuse


  11. Location
    Leeds, UK
    Posts
    2,059


  12. Location
    GMA950
    Posts
    3,031
    Quote Originally Posted by Nose View Post
    I found the correct shader, and I was able to convert it to Unity3D
    Just in case anyone comes across this thread in the future, it's worth noting that there is nothing incorrect about Farfarer's implementation. It's just faster and more versatile than the version Nose wanted.


  13. Location
    Russia, Moscow
    Posts
    36
    I agree, the only difference is in the use of Beckman, I just bad speak English


  14. Posts
    1,547
    Quote Originally Posted by Daniel Brauer View Post
    Just in case anyone comes across this thread in the future, it's worth noting that there is nothing incorrect about Farfarer's implementation. It's just faster and more versatile than the version Nose wanted.
    Indeed i've set out to replicate Nose's discovery because sometimes the good isnt bad enough


  15. Location
    GMA950
    Posts
    3,031
    Quote Originally Posted by lazygunn View Post
    Indeed i've set out to replicate Nose's discovery because sometimes the good isnt bad enough
    Can you explain?


  16. Posts
    1,547
    Quote Originally Posted by Daniel Brauer View Post
    Can you explain?
    Haha sorry i was being a smartass and agreeing with you with a silly joke, dont mind me!

    Thankyou for supplying both Farfarer, im sure id have figured it but im at the point of learning shaders (rewriting other peoples and smooshing them together mainly) where being able to compare is very handy

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •