Guest User

Untitled

a guest
Jun 27th, 2014
789
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 16.75 KB | None | 0 0
  1. Shader "BRDF/Shader"
  2. {
  3.     Properties
  4.     {
  5.         _MainTex ("Base (RGB)", 2D) = "white" {}
  6.         _BumpMap ("Normalmap", 2D) = "bump" {}
  7.         _Roughness ("Roughness", Range (0.0, 1.0)) = 1
  8.         _SubColor ("Subsurface Color", Color) = (1.0, 1.0, 1.0, 1.0)
  9.         //_NoV ("NoV", Range (0.0, 1.0)) = 1
  10.     }
  11.     SubShader
  12.     {
  13.         Tags { "RenderType"="Opaque" }
  14.         LOD 200
  15.        
  16.         CGPROGRAM
  17.         #pragma surface surf PhysicallyBased
  18.         #pragma target 3.0
  19.        
  20.         sampler2D _MainTex;
  21.         sampler2D _BumpMap;
  22.         float _Roughness;
  23.         fixed4 _SubColor;
  24.         //half _NoV;
  25.    
  26.         struct Input
  27.         {
  28.             float2 uv_MainTex;
  29.             float2 uv_BumpMap;
  30.             float2 uv_GlossMap;
  31.             //float3 worldNormal;
  32.         };
  33.  
  34. //----------------------------------------------------------------------------             
  35. // Common.usf
  36. //----------------------------------------------------------------------------
  37.    
  38.         //#define MaterialFloat half
  39.         //#define MaterialFloat3 half3
  40.         #define MaterialFloat float
  41.         #define MaterialFloat3 float3
  42.        
  43.         // Clamp the base, so it's never <= 0.0f (INF/NaN).
  44.         MaterialFloat ClampedPow(MaterialFloat X,MaterialFloat Y)
  45.         {
  46.             return pow(max(abs(X),0.000001f),Y);
  47.         }
  48.        
  49.         // Use this function to compute the pow() in the specular computation.
  50.         // This allows to change the implementation depending on platform or it easily can be replaced by some approxmation.
  51.         MaterialFloat PhongShadingPow(MaterialFloat X, MaterialFloat Y)
  52.         {
  53.             // The following clamping is done to prevent NaN being the result of the specular power computation.
  54.             // Clamping has a minor performance cost.
  55.  
  56.             // In HLSL pow(a, b) is implemented as exp2(log2(a) * b).
  57.  
  58.             // For a=0 this becomes exp2(-inf * 0) = exp2(NaN) = NaN.
  59.  
  60.             // As seen in #TTP 160394 "QA Regression: PS3: Some maps have black pixelated artifacting."
  61.             // this can cause severe image artifacts (problem was caused by specular power of 0, lightshafts propagated this to other pixels).
  62.             // The problem appeared on PlayStation 3 but can also happen on similar PC NVidia hardware.
  63.  
  64.             // In order to avoid platform differences and rarely occuring image atrifacts we clamp the base.
  65.  
  66.             // Note: Clamping the exponent seemed to fix the issue mentioned TTP but we decided to fix the root and accept the
  67.             // minor performance cost.
  68.  
  69.             return ClampedPow(X, Y);
  70.         }
  71.        
  72.         float Square( float x )
  73.         {
  74.             return x*x;
  75.         }
  76.        
  77.         MaterialFloat LuminanceUE( MaterialFloat3 LinearColor )
  78.         {
  79.             return dot( LinearColor, MaterialFloat3( 0.3, 0.59, 0.11 ) );
  80.         }
  81.    
  82. //----------------------------------------------------------------------------             
  83. // BRDF.utf
  84. //----------------------------------------------------------------------------     
  85.         // Physically based shading model
  86.         // parameterized with the below options
  87.  
  88.         // Microfacet specular = D*G*F / (4*NoL*NoV) = D*Vis*F
  89.         // Vis = G / (4*NoL*NoV)
  90.  
  91.         // Diffuse model
  92.         // 0: Lambert
  93.         // 1: Burley
  94.         // 2: Oren-Nayar
  95.         #define PHYSICAL_DIFFUSE    0
  96.        
  97.         // Microfacet distribution function
  98.         // 0: Blinn
  99.         // 1: Beckmann
  100.         // 2: GGX
  101.         #define PHYSICAL_SPEC_D     2
  102.  
  103.         // Geometric attenuation or shadowing
  104.         // 0: Implicit
  105.         // 1: Neumann
  106.         // 2: Kelemen
  107.         // 3: Schlick
  108.         // 4: Smith (matched to GGX)
  109.         // TODO: со Smith проблема. Нужна функция rcp из HLSL, я не знаю ее аналога (кроме того она доступна только на SM5)
  110.         // поэтому функция выключена
  111.         #define PHYSICAL_SPEC_G     3
  112.  
  113.         // Fresnel
  114.         // 0: None
  115.         // 1: Schlick
  116.         // 2: Fresnel
  117.         #define PHYSICAL_SPEC_F     1
  118.        
  119.         #define PI 3.14159265358979323846      
  120.        
  121.         float3 Diffuse_Lambert( float3 DiffuseColor )
  122.         {
  123.             return DiffuseColor / PI;
  124.         }
  125.            
  126.         // [Burley 2012, "Physically-Based Shading at Disney"]
  127.         float3 Diffuse_Burley( float3 DiffuseColor, float Roughness, float NoV, float NoL, float VoH )
  128.         {
  129.             float FD90 = 0.5 + 2 * VoH * VoH * Roughness;
  130.             float FdV = 1 + (FD90 - 1) * exp2( (-5.55473 * NoV - 6.98316) * NoV );
  131.             float FdL = 1 + (FD90 - 1) * exp2( (-5.55473 * NoL - 6.98316) * NoL );
  132.             return DiffuseColor / PI * FdV * FdL;
  133.         }
  134.  
  135.         // [Gotanda 2012, "Beyond a Simple Physically Based Blinn-Phong Model in Real-Time"]
  136.         float3 Diffuse_OrenNayar( float3 DiffuseColor, float Roughness, float NoV, float NoL, float VoH )
  137.         {
  138.             float VoL = 2 * VoH - 1;
  139.             float m = Roughness * Roughness;
  140.             float m2 = m * m;
  141.             float C1 = 1 - 0.5 * m2 / (m2 + 0.33);
  142.             float Cosri = VoL - NoV * NoL;
  143.             float C2 = 0.45 * m2 / (m2 + 0.09) * Cosri * ( Cosri >= 0 ? min( 1, NoL / NoV ) : NoL );
  144.             return DiffuseColor / PI * ( NoL * C1 + C2 );
  145.         }
  146.  
  147.         // [Blinn 1977, "Models of light reflection for computer synthesized pictures"]
  148.         float D_Blinn( float Roughness, float NoH )
  149.         {
  150.             float m = Roughness * Roughness;
  151.             float m2 = m * m;
  152.             float n = 2 / m2 - 2;
  153.             return (n+2) / (2*PI) * PhongShadingPow( NoH, n );      // 1 mad, 1 exp, 1 mul, 1 log
  154.         }
  155.  
  156.         // [Beckmann 1963, "The scattering of electromagnetic waves from rough surfaces"]
  157.         float D_Beckmann( float Roughness, float NoH )
  158.         {
  159.             float m = Roughness * Roughness;
  160.             float m2 = m * m;
  161.             float NoH2 = NoH * NoH;
  162.             return exp( (NoH2 - 1) / (m2 * NoH2) ) / ( PI * m2 * NoH2 * NoH2 );
  163.         }
  164.        
  165.         // GGX / Trowbridge-Reitz
  166.         // [Walter et al. 2007, "Microfacet models for refraction through rough surfaces"]
  167.         float D_GGX( float Roughness, float NoH )
  168.         {
  169.             float m = Roughness * Roughness;
  170.             float m2 = m * m;
  171.             float d = ( NoH * m2 - NoH ) * NoH + 1; // 2 mad
  172.             return m2 / ( PI*d*d );                 // 3 mul, 1 rcp
  173.         }
  174.  
  175.         // Anisotropic GGX
  176.         // [Burley 2012, "Physically-Based Shading at Disney"]
  177.         float D_GGXaniso( float RoughnessX, float RoughnessY, float NoH, float3 H, float3 X, float3 Y )
  178.         {
  179.             float mx = RoughnessX * RoughnessX;
  180.             float my = RoughnessY * RoughnessY;
  181.             float XoH = dot( X, H );
  182.             float YoH = dot( Y, H );
  183.             float d = XoH*XoH / (mx*mx) + YoH*YoH / (my*my) + NoH*NoH;
  184.             return 1 / ( PI * mx*my * d*d );
  185.         }
  186.  
  187.         float Vis_Implicit()
  188.         {
  189.             return 0.25;
  190.         }
  191.  
  192.         // [Neumann et al. 1999, "Compact metallic reflectance models"]
  193.         float Vis_Neumann( float NoV, float NoL )
  194.         {
  195.             return 1 / ( 4 * max( NoL, NoV ) );
  196.         }
  197.  
  198.         // [Kelemen 2001, "A microfacet based coupled specular-matte brdf model with importance sampling"]
  199.         float Vis_Kelemen( float3 L, float3 V )
  200.         {
  201.             return 1 / ( 2 + 2 * dot(L, V) );
  202.         }
  203.  
  204.         // Tuned to match behavior of Vis_Smith
  205.         // [Schlick 1994, "An Inexpensive BRDF Model for Physically-Based Rendering"]
  206.         float Vis_Schlick( float Roughness, float NoV, float NoL )
  207.         {
  208.             float k = Square( Roughness ) * 0.5;
  209.             float Vis_SchlickV = NoV * (1 - k) + k;
  210.             float Vis_SchlickL = NoL * (1 - k) + k;
  211.             return 0.25 / ( Vis_SchlickV * Vis_SchlickL );
  212.         }
  213.  
  214.         // Smith term for GGX
  215.         // [Smith 1967, "Geometrical shadowing of a random rough surface"]
  216.         //float Vis_Smith( float Roughness, float NoV, float NoL )
  217.         //{
  218.         //  float a = Square( Roughness );
  219.         //  float a2 = a*a;
  220.  
  221.         //  float Vis_SmithV = NoV + sqrt( NoV * (NoV - NoV * a2) + a2 );
  222.         //  float Vis_SmithL = NoL + sqrt( NoL * (NoL - NoL * a2) + a2 );
  223.         //  return rcp( Vis_SmithV * Vis_SmithL );
  224.         //}
  225.  
  226.         float3 F_None( float3 SpecularColor )
  227.         {
  228.             return SpecularColor;
  229.         }
  230.  
  231.         // [Schlick 1994, "An Inexpensive BRDF Model for Physically-Based Rendering"]
  232.         // [Lagarde 2012, "Spherical Gaussian approximation for Blinn-Phong, Phong and Fresnel"]
  233.         float3 F_Schlick( float3 SpecularColor, float VoH )
  234.         {
  235.             // Anything less than 2% is physically impossible and is instead considered to be shadowing
  236.             return SpecularColor + ( saturate( 50.0 * SpecularColor.g ) - SpecularColor ) * exp2( (-5.55473 * VoH - 6.98316) * VoH );
  237.  
  238.             //float Fc = exp2( (-5.55473 * VoH - 6.98316) * VoH );  // 1 mad, 1 mul, 1 exp
  239.             //return Fc + (1 - Fc) * SpecularColor;                 // 1 add, 3 mad
  240.         }
  241.  
  242.         float3 F_Fresnel( float3 SpecularColor, float VoH )
  243.         {
  244.             float3 SpecularColorSqrt = sqrt( clamp( float3(0, 0, 0), float3(0.99, 0.99, 0.99), SpecularColor ) );
  245.             float3 n = ( 1 + SpecularColorSqrt ) / ( 1 - SpecularColorSqrt );
  246.             float3 g = sqrt( n*n + VoH*VoH - 1 );
  247.             return 0.5 * Square( (g - VoH) / (g + VoH) ) * ( 1 + Square( ((g+VoH)*VoH - 1) / ((g-VoH)*VoH + 1) ) );
  248.         }
  249.        
  250.         float3 Diffuse( float3 DiffuseColor, float Roughness, float NoV, float NoL, float VoH )
  251.         {
  252.         #if   PHYSICAL_DIFFUSE == 0
  253.             return Diffuse_Lambert( DiffuseColor );
  254.         #elif PHYSICAL_DIFFUSE == 1
  255.             return Diffuse_Burley( DiffuseColor, Roughness, NoV, NoL, VoH );
  256.         #elif PHYSICAL_DIFFUSE == 2
  257.             return Diffuse_OrenNayar( DiffuseColor, Roughness, NoV, NoL, VoH );
  258.         #endif
  259.         }
  260.  
  261.         float Distribution( float Roughness, float NoH )
  262.         {
  263.         #if   PHYSICAL_SPEC_D == 0
  264.             return D_Blinn( Roughness, NoH );
  265.         #elif PHYSICAL_SPEC_D == 1
  266.             return D_Beckmann( Roughness, NoH );
  267.         #elif PHYSICAL_SPEC_D == 2
  268.             return D_GGX( Roughness, NoH );
  269.         #endif
  270.         }
  271.  
  272.         // Vis = G / (4*NoL*NoV)
  273.         float GeometricVisibility( float Roughness, float NoV, float NoL, float VoH, float3 L, float3 V )
  274.         {
  275.         #if   PHYSICAL_SPEC_G == 0
  276.             return Vis_Implicit();
  277.         #elif PHYSICAL_SPEC_G == 1
  278.             return Vis_Neumann( NoV, NoL );
  279.         #elif PHYSICAL_SPEC_G == 2
  280.             return Vis_Kelemen( L, V );
  281.         #elif PHYSICAL_SPEC_G == 3
  282.             return Vis_Schlick( Roughness, NoV, NoL );
  283.         #elif PHYSICAL_SPEC_G == 4
  284.             return Vis_Smith( Roughness, NoV, NoL );
  285.         #endif
  286.         }
  287.  
  288.         float3 Fresnel( float3 SpecularColor, float VoH )
  289.         {
  290.         #if   PHYSICAL_SPEC_F == 0
  291.             return F_None( SpecularColor );
  292.         #elif PHYSICAL_SPEC_F == 1
  293.             return F_Schlick( SpecularColor, VoH );
  294.         #elif PHYSICAL_SPEC_F == 2
  295.             return F_Fresnel( SpecularColor, VoH );
  296.         #endif
  297.         }
  298.    
  299.     //----------------------------------------------------------------------------             
  300.     // DeferredLightingCommon.usf
  301.     //----------------------------------------------------------------------------     
  302.    
  303.         // greatly reduces shadow mapping artifacts
  304.         float BiasedNDotL(float NDotLWithoutSaturate )
  305.         {
  306.             return saturate(NDotLWithoutSaturate * 1.08f - 0.08f);
  307.         }  
  308.    
  309.    
  310.         float3 PointLightDiffuse(SurfaceOutput s, float3 VectorToLight, float3 V, half3 N )
  311.         {
  312.             float3 L = VectorToLight;
  313.  
  314.             float3 H = normalize(V + L);
  315.             float NoL = saturate( dot(N, L) );
  316.             float NoV = saturate( dot(N, V) );
  317.             float VoH = saturate( dot(V, H) );
  318.  
  319.             return Diffuse( s.Albedo, _Roughness, NoV, NoL, VoH );
  320.         }
  321.        
  322.         float3 PointLightSpecular(SurfaceOutput s, float3 VectorToLight, float3 V, half3 N)
  323.         {
  324.             float Roughness = _Roughness;
  325.             float Energy = 1;
  326.            
  327.             //Roughness = max( Roughness, LightData.MinRoughness ); // может кому пригодится
  328.                        
  329.             // TODO: код Spot
  330.            
  331.             float a = Roughness * Roughness;
  332.            
  333.             //const float SourceRadius = LightData.SpotAnglesAndSourceRadius.z;
  334.             //const float SourceLength = LightData.SpotAnglesAndSourceRadius.w;
  335.             const float SourceRadius = 1.0;
  336.             const float SourceLength = 1.0;
  337.                        
  338.             float3 R = reflect( -V, N );
  339.             float RLengthL = rsqrt( dot( VectorToLight, VectorToLight ) );
  340.            
  341.             if( SourceLength > 0 )
  342.             {
  343.                 // Energy conservation
  344.                 // asin(x) is angle to sphere, atan(x) is angle to disk, saturate(x) is free and in the middle
  345.                 float LineAngle = saturate( SourceLength * RLengthL );
  346.                 Energy *= a / saturate( a + 0.5 * LineAngle );
  347.  
  348.                 // Closest point on line segment to ray
  349.                 //float3 Ld = LightData.LightDirection * SourceLength;
  350.                 float3 Ld = VectorToLight * SourceLength;
  351.                 float3 L0 = VectorToLight - 0.5 * Ld;
  352.                 float3 L1 = VectorToLight + 0.5 * Ld;
  353.  
  354.                 // Shortest distance
  355.                 float a = Square( SourceLength );
  356.                 float b = dot( R, Ld );
  357.                 float t = saturate( dot( L0, b*R - Ld ) / (a - b*b) );
  358.  
  359.                 VectorToLight = L0 + t * Ld;
  360.             }
  361.            
  362.             if( SourceRadius > 0 )
  363.             {
  364.                 // Energy conservation
  365.                 // asin(x) is angle to sphere, atan(x) is angle to disk, saturate(x) is free and in the middle
  366.                 float SphereAngle = saturate( SourceRadius * RLengthL );
  367.                 Energy *= Square( a / saturate( a + 0.5 * SphereAngle ) );
  368.                
  369.                 // Closest point on sphere to ray
  370.                 float3 ClosestPointOnRay = dot( VectorToLight, R ) * R;
  371.                 float3 CenterToRay = ClosestPointOnRay - VectorToLight;
  372.                 float3 ClosestPointOnSphere = VectorToLight + CenterToRay * saturate( SourceRadius * rsqrt( dot( CenterToRay, CenterToRay ) ) );
  373.                 VectorToLight = ClosestPointOnSphere;
  374.             }
  375.                        
  376.             // TODO: код Spot
  377.            
  378.             //float3 L =  VectorToLight;
  379.             float3 L = normalize( VectorToLight );
  380.  
  381.             float3 H = normalize(V + L);
  382.             float NoL = saturate( dot(N, L) );
  383.             float NoV = saturate( dot(N, V) );
  384.             float NoH = saturate( dot(N, H) );
  385.             float VoH = saturate( dot(V, H) );         
  386.            
  387.             // Generalized microfacet specular
  388.             float D = Distribution( Roughness, NoH );
  389.             float Vis = GeometricVisibility( Roughness, NoV, NoL, VoH, L, V );
  390.             float3 F = Fresnel( s.Specular, VoH );
  391.             return (Energy * D * Vis) * F;
  392.         }
  393.        
  394.         float3 PointLightSubsurface(SurfaceOutput s, float3 L, float3 V, half3 N, float SubsurfaceExtinction )
  395.         {
  396.             float3 H = normalize(V + L);
  397.             // to get an effect when you see through the material
  398.             // hard coded pow constant
  399.             float InScatter = pow(saturate(dot(L, -V)), 12) * lerp(3, .1f, s.Alpha);
  400.            
  401.             // wrap around lighting, /(PI*2) to be energy consistent (hack do get some view dependnt and light dependent effect)
  402.             float OpacityFactor = s.Alpha   ;
  403.             // Opacity of 0 gives no normal dependent lighting, Opacity of 1 gives strong normal contribution
  404.             float NormalContribution = saturate(dot(N, H) * OpacityFactor + 1 - OpacityFactor);
  405.             //float BackScatter = InGBufferData.GBufferAO * NormalContribution / (PI * 2);
  406.             float BackScatter = NormalContribution / (PI * 2);
  407.            
  408.             // lerp to never exceed 1 (energy conserving)
  409.             //return InGBufferData.SubsurfaceColor * (lerp(BackScatter, 1, InScatter) * SubsurfaceExtinction);
  410.             return  _SubColor * (lerp(BackScatter, 1, InScatter) * SubsurfaceExtinction);
  411.         }
  412.        
  413.         // Calculates lighting for a given position, normal, etc with a fully featured lighting model designed for quality. */
  414.         float4 GetDynamicLighting(SurfaceOutput s, half3 lightDir, half3 viewDir, half atten)
  415.         {
  416.             // TODO: N - это мировая нормаль, над убедиться что s.Normal это оно же
  417.             // TODO: почистить функции от всяких там нормализаций, то есть надо в них сразу кидать подсчитанное
  418.            
  419.             float3 N = s.Normal;           
  420.             float3 L = normalize(lightDir); // TODO: возможно без нормализации
  421.             float NoL = BiasedNDotL( dot(N, L) );
  422.             float DistanceAttenuation = atten;
  423.             float LightRadiusMask = 1;
  424.             float SpotFalloff = 1;
  425.            
  426.             half4 OutLighting = 0;
  427.                        
  428.             if (LightRadiusMask > 0 && SpotFalloff > 0)
  429.             {
  430.                 float OpaqueShadowTerm = 1;
  431.                 float SSSShadowTerm = 1;
  432.                
  433.                 float NonShadowedAttenuation = DistanceAttenuation * LightRadiusMask * SpotFalloff;
  434.                 float ShadowedAttenuation = NonShadowedAttenuation * OpaqueShadowTerm;
  435.                                                
  436.                 // cull behind light (saving shading computations, might not be faster on some hardware)
  437.                 ShadowedAttenuation *= saturate(dot(L, N) * 100000);
  438.                                
  439.                 // optimization that should help if there are a lot of shadowed pixels
  440.                 if (ShadowedAttenuation > 0)
  441.                 {
  442.                     //const float3 LightColor = LightData.LightColorAndFalloffExponent.rgb;
  443.                     const float3 LightColor = s.Albedo;
  444.  
  445.                     float3 DiffuseLighting = PointLightDiffuse( s, L, viewDir, N );
  446.                     float3 SpecularLighting = PointLightSpecular( s, L, viewDir, N );
  447.                     float3 SubsurfaceLighting = PointLightSubsurface( s, L, viewDir, N, SSSShadowTerm );   
  448.                    
  449.                     float4 LightColor4 = float4(LightColor, LuminanceUE(LightColor));
  450.                     float4 DiffuseLighting4 = float4(DiffuseLighting, 0);
  451.                     float4 SpecularLighting4 = float4(SpecularLighting, LuminanceUE(SpecularLighting));
  452.                     float4 SubsurfaceLighting4 = float4(SubsurfaceLighting, 0);
  453.                    
  454.                     OutLighting += LightColor4 * (  (NoL * ShadowedAttenuation) *
  455.                                                                 (DiffuseLighting4 + SpecularLighting4) +
  456.                                                                 SubsurfaceLighting4 * NonShadowedAttenuation );
  457.                 }
  458.             }
  459.            
  460.             return OutLighting;
  461.         }
  462.  
  463.         //----------------------------------------------------------------------------             
  464.         // Shader
  465.         //----------------------------------------------------------------------------             
  466.    
  467.         void surf (Input IN, inout SurfaceOutput o)
  468.         {
  469.             half4 c = tex2D (_MainTex, IN.uv_MainTex);
  470.             o.Albedo = c.rgb;
  471.             o.Alpha = c.a;
  472.             o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
  473.             o.Specular = c.a;// * _Roughness;
  474.             o.Gloss = c.a;
  475.         }
  476.                
  477.         fixed4 LightingPhysicallyBased(SurfaceOutput s, half3 lightDir, half3 viewDir, half atten)
  478.         {
  479.             return GetDynamicLighting(s, lightDir, viewDir, atten);
  480.         }
  481.         ENDCG
  482.     }
  483.     FallBack "Diffuse"
  484. }
Advertisement
Add Comment
Please, Sign In to add comment