Advertisement
Guest User

DogPBR

a guest
Jun 5th, 2016
533
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.17 KB | None | 0 0
  1. Shader "PhysicallyBased/PBRV4" {
  2. Properties {
  3. _Color ("Albedo Color", Color) = (0.5, 0.5, 0.5, 1)
  4. _AlbedoMap ("Albedo Map", 2D) = "white" {}
  5. _MultiMap ("Multipurpose (R = Rough, G = AO, B = Metalness)", 2D) = "white" {}
  6. _Normal ("Normal", 2D) = "bump" {}
  7. _Roughness ("Roughness Multiplier (Default to 1 when using roughness maps)", Float) = 0.5
  8. _Metalness ("Metalness Multiplier (Default to 1 when using metalness maps)", Float) = 0
  9. }
  10.  
  11. SubShader {
  12. Tags { "RenderType"="Opaque" }
  13. LOD 200
  14.  
  15. Pass {
  16. Name "ForwardBase"
  17. Tags {"LightMode"="ForwardBase"}
  18. CGPROGRAM
  19.  
  20. // Needed for OpenGL to compile when using texCUBElod
  21. #pragma glsl
  22. // Allows Unity to switch between Linear and Gamma space. The tonemapper must update afterwards
  23. #pragma multi_compile Linear Gamma
  24. // Allows disabling tonemapping which may not be needed in simple light setups.
  25. #pragma multi_compile tonemappingEnabled tonemappingDisabled
  26.  
  27. #pragma target 3.0
  28. #pragma exclude_renderers flash
  29. #pragma multi_compile_fwdbase
  30. #pragma vertex vert
  31. #pragma fragment frag
  32. #include "UnityCG.cginc"
  33. #include "AutoLight.cginc"
  34.  
  35. ////////////// Vertex Shader
  36. struct VertexInput {
  37. float4 vertex : POSITION;
  38. float4 texcoord : TEXCOORD0;
  39. float3 normal : NORMAL;
  40. float4 tangent : TANGENT;
  41. };
  42.  
  43. struct VertexOutput {
  44. float4 pos : SV_POSITION;
  45. float4 uv0 : TEXCOORD0;
  46. float4 posWorld : TEXCOORD1;
  47. float3 normalWorld : TEXCOORD2;
  48. float3 tangentWorld : TEXCOORD3;
  49. float3 binormalWorld : TEXCOORD4;
  50. LIGHTING_COORDS(5,6)
  51. };
  52.  
  53. VertexOutput vert (VertexInput v) {
  54. VertexOutput o;
  55. o.uv0 = v.texcoord;
  56. o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
  57. o.posWorld = mul(_Object2World, v.vertex);
  58.  
  59. // Construct the vectors for transforming normal maps to world space
  60. o.normalWorld = normalize(mul(float4(v.normal, 0.0), _World2Object).xyz);
  61. o.tangentWorld = normalize(mul(_Object2World, float4(v.tangent.xyz, 0.0)).xyz);
  62. o.binormalWorld = normalize(cross(o.normalWorld, o.tangentWorld) * v.tangent.w);
  63.  
  64. TRANSFER_VERTEX_TO_FRAGMENT(o);
  65.  
  66. return o;
  67. }
  68.  
  69. ////////////// Properties
  70. half4 _Color;
  71. sampler2D _AlbedoMap; half4 _AlbedoMap_ST;
  72. sampler2D _MultiMap; half4 _MultiMap_ST;
  73. sampler2D _Normal; half4 _Normal_ST;
  74. half _Metalness;
  75. half _Roughness;
  76.  
  77. // Light Color
  78. uniform float4 _LightColor0;
  79. // Sky
  80. uniform samplerCUBE _SpecCubeIBL;
  81. // Spherical Harmonics
  82. uniform float3 _SH0;
  83. uniform float3 _SH1;
  84. uniform float3 _SH2;
  85. uniform float3 _SH3;
  86. uniform float3 _SH4;
  87. uniform float3 _SH5;
  88. uniform float3 _SH6;
  89. uniform float3 _SH7;
  90. uniform float3 _SH8;
  91. uniform float W;
  92. uniform float _ExposureBias;
  93. uniform float IBLMask;
  94. uniform float IndirectStrength;
  95. #define DielectricSpecular (0.04, 0.04, 0.04)
  96. #define Pi 3.14159
  97. #define InvPi 0.318309
  98.  
  99. ////////////// Functions
  100. // Tonemapping - Uncharted 2
  101. inline float3 Uncharted2Tonemap(float3 x) {
  102. return ((x*(0.22*x+0.03)+0.002)/(x*(0.22*x+0.30)+0.06))-(0.0333);
  103. }
  104. inline float3 Tonemap(float3 X) {
  105. float3 curr = Uncharted2Tonemap(_ExposureBias * X); // Hardcoded Exposure Adjustment
  106. float3 whiteScale = 1.0/Uncharted2Tonemap(W);
  107. float3 color = curr*whiteScale;
  108. #ifdef Gamma
  109. color = pow(color, 0.4545);
  110. #endif
  111. return color;
  112. }
  113.  
  114. ////////////// Specular BRDF
  115.  
  116. // Same cost but likely better than pow(x, 5)
  117. inline float pow5(float i) {
  118. float i5 = i * i;
  119. return i5 * i5 * i;
  120. }
  121.  
  122. // Fresnel - Schlick
  123. inline float3 F_Schlick(float3 f0, float u) {
  124. float InvU = 1.0 - u;
  125. return f0 + (1.0 - f0) * pow5(InvU);
  126. }
  127.  
  128. // Distribution - [Lagarde 2014, "Moving Frostbite to Physically Based Rendering"
  129. inline float D_GGX_Frost(float NdotH, float m2) {
  130. float f = (NdotH * m2 - NdotH) * NdotH + 1;
  131. return m2 / (f * f);
  132. }
  133.  
  134. // Geometric - [Lagarde 2014, "Moving Frostbite to Physically Based Rendering"]
  135. inline float V_SmithGGXCorrelated (float NdotV, float NdotL, float alphaG2 ) {
  136. float Lambda_GGXV = NdotL * sqrt (( -NdotV * alphaG2 + NdotV ) * NdotV + alphaG2 );
  137. float Lambda_GGXL = NdotV * sqrt (( -NdotL * alphaG2 + NdotL ) * NdotL + alphaG2 );
  138. return 0.5 / ( Lambda_GGXV + Lambda_GGXL );
  139. }
  140.  
  141. // Spherical Harmonics - Marmoset
  142. inline float3 SHLookup(float3 dir) {
  143. //l = 0 band (constant)
  144. float3 result = _SH0.xyz;
  145.  
  146. //l = 1 band
  147. result += _SH1.xyz * dir.y;
  148. result += _SH2.xyz * dir.z;
  149. result += _SH3.xyz * dir.x;
  150.  
  151. //l = 2 band
  152. float3 swz = dir.yyz * dir.xzx;
  153. result += _SH4.xyz * swz.x;
  154. result += _SH5.xyz * swz.y;
  155. result += _SH7.xyz * swz.z;
  156. float3 sqr = dir * dir;
  157. result += _SH6.xyz * ( 3.0*sqr.z - 1.0 );
  158. result += _SH8.xyz * ( sqr.x - sqr.y );
  159.  
  160. return abs(result);
  161. }
  162.  
  163. // RGBM to linear color - Marmoset
  164. inline float3 fromRGBM(float4 c) {
  165. //c.a *= 6.0;
  166. //return c.rgb * lerp(c.a, toLinearFast1(c.a), IS_LINEAR);
  167. //7 instructions
  168. ///
  169.  
  170. //combined 6.0 * toLinear
  171. float4 IGL; //.xyz: modified versions of IS_GAMMA_LINEAR, .w: c.a*c.a
  172. IGL =
  173. float4(
  174. 19.35486, // 3.22581 * 6.0,
  175. -87.468483312, //-3.22581 * 0.7532 * 36.0,
  176. -171.964060128, //-3.22581 * 0.2468 * 216.0,
  177. c.a
  178. ) *
  179. float4(
  180. unity_ColorSpaceGrey.r,
  181. unity_ColorSpaceGrey.r,
  182. unity_ColorSpaceGrey.r,
  183. c.a
  184. ) +
  185. float4(
  186. -3.6774, //-0.6129 * 6.0,
  187. 43.73410608, // 1.6129 * 0.7532 * 36.0,
  188. 85.98176352, // 1.6129 * 0.2468 * 216.0,
  189. 0.0
  190. );
  191. return c.rgb * dot(IGL.xyz, float3(c.a, IGL.w, c.a*IGL.w));
  192. //4 instructions
  193. ///
  194. }
  195.  
  196. // BRDF for cubemaps
  197. inline float3 EnvBRDFApprox( float3 SpecularColor, float Roughness, float NoV ) {
  198. // [ Lazarov 2013, "Getting More Physical in Call of Duty: Black Ops II" ]
  199. // Adaptation to fit Unreal G term.
  200. const float4 c0 = { -1, -0.0275, -0.572, 0.022 };
  201. const float4 c1 = { 1, 0.0425, 1.04, -0.04 };
  202. float4 r = Roughness * c0 + c1;
  203. float a004 = min( r.x * r.x, exp2( -9.28 * NoV ) ) * r.x + r.y;
  204. float2 AB = float2( -1.04, 1.04 ) * a004 + r.zw;
  205. AB.y *= saturate( 50.0 * SpecularColor.g );
  206. return SpecularColor * AB.x + AB.y;
  207. }
  208.  
  209. ////////////// Fragment Shader
  210. float4 frag(VertexOutput i) : COLOR {
  211. // Construct the world space normal direction
  212. float3 normalLocal = UnpackNormal(tex2D(_Normal, TRANSFORM_TEX(i.uv0.rg, _Normal)));
  213. float3x3 local2WorldTranspose = float3x3(
  214. i.tangentWorld,
  215. i.binormalWorld,
  216. i.normalWorld);
  217. float3 normalDir = normalize(mul(normalLocal, local2WorldTranspose));
  218.  
  219. // Construct the world space view direction
  220. float3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.posWorld.xyz);
  221.  
  222. // Construct the world space reflection direction
  223. float3 reflectionDir = normalize(reflect(-viewDir, normalDir));
  224.  
  225. // Construct the world space light direction
  226. float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
  227. float ambientOcclusion = 1.0;
  228.  
  229.  
  230. // Dot Products
  231. float3 halfDir = normalize (viewDir + lightDir);
  232. float LdotH = saturate(dot(lightDir, halfDir));
  233. float NdotH = saturate(dot(normalDir, halfDir));
  234. float NdotL = saturate(dot(normalDir, lightDir));
  235. float NdotV = abs(dot(normalDir, viewDir)) + 1e-5f; // avoid artifact
  236.  
  237. float3 MultiMap = tex2D(_MultiMap, TRANSFORM_TEX(i.uv0.rg, _MultiMap)).rgb;
  238.  
  239. #ifdef Gamma
  240. MultiMap = pow(MultiMap, 2.2);
  241. #endif
  242.  
  243. // Roughness Parameters
  244. float RoughLin = saturate(clamp(_Roughness, 0.0374, .999) * MultiMap.r);
  245. float Roughness = RoughLin * RoughLin;
  246. float RoughSqr = Roughness * Roughness;
  247.  
  248. // Metal Parameter
  249. float Metalness = saturate(_Metalness) * MultiMap.b;
  250.  
  251. // Albedo Paremeter
  252. float3 AlbedoColor = _Color.rgb * tex2D(_AlbedoMap, TRANSFORM_TEX(i.uv0.rg, _AlbedoMap)).rgb;
  253. #ifdef Gamma
  254. AlbedoColor = pow(AlbedoColor, 2.2);
  255. #endif
  256.  
  257. // Construct Specular
  258. float3 SpecularColor = (DielectricSpecular - DielectricSpecular * Metalness) + AlbedoColor * Metalness; // 2 mad
  259.  
  260. // Remove metal colors from Albedo
  261. AlbedoColor = AlbedoColor - AlbedoColor * Metalness; // 1 mad
  262.  
  263. // f0 is the refractive % of specular
  264. float3 f0 = SpecularColor;
  265.  
  266. // BRDF
  267. float3 F = F_Schlick(f0, LdotH);
  268. float D = D_GGX_Frost(NdotH, RoughSqr);
  269. float Vis = V_SmithGGXCorrelated(NdotV, NdotL, RoughSqr);
  270. float3 DirectSpec = F * (D * Vis * InvPi);
  271.  
  272. // Attenuation for diffuse and specular reflection
  273. float DirectAttenuation = LIGHT_ATTENUATION(i) * NdotL;
  274. float3 DirectAttenColor = _LightColor0.rgb * DirectAttenuation * Pi;
  275.  
  276. // Direct Diffuse
  277. float3 SimpleEnergyConservation = 1.0 - F_Schlick(f0, NdotL);
  278. float3 DirectDiff = AlbedoColor * InvPi * SimpleEnergyConservation;
  279.  
  280. // Combined Direct Light
  281. float3 Direct = (DirectDiff + DirectSpec) * DirectAttenColor;
  282.  
  283. // Indirect Diffuse contribution
  284. float3 IndirectDiff = SHLookup(normalDir) * AlbedoColor;
  285.  
  286. // Indirect Specular contribution
  287. float4 lookup = float4(reflectionDir, RoughLin * 8.0);
  288. float4 specCubeHDR = texCUBElod(_SpecCubeIBL, lookup);
  289. float3 specCube = fromRGBM(specCubeHDR);
  290. #ifdef Gamma
  291. specCube = pow(specCube, 2.2);
  292. #endif
  293. float3 EnvBRDF = EnvBRDFApprox(f0, RoughLin, NdotV);
  294.  
  295. // Combine diffuse and specular Indirect
  296. float3 Indirect = IndirectDiff + specCube * EnvBRDF;
  297.  
  298. IBLMask = 1.0 - saturate(-normalDir.g) * IBLMask;
  299. Indirect *= IBLMask * IndirectStrength;
  300.  
  301. // Ambient Occlusion
  302. ambientOcclusion = MultiMap.g;
  303.  
  304. // Final
  305. float3 finalColor = Direct + Indirect * ambientOcclusion;
  306. #ifdef tonemappingEnabled
  307. finalColor = Tonemap(finalColor);
  308. #endif
  309. #ifdef tonemappingDisabled
  310. #ifdef Gamma
  311. finalColor = pow(finalColor, 0.4545);
  312. #endif
  313. #endif
  314. return float4(finalColor, 1.0);
  315. }
  316. ENDCG
  317. }
  318.  
  319. Pass {
  320. Name "ForwardAdd"
  321. Tags {"LightMode"="ForwardAdd"}
  322. Blend One One
  323. CGPROGRAM
  324.  
  325. // Allows Unity to switch between Linear and Gamma space. The tonemapper must update afterwards
  326. #pragma multi_compile Linear Gamma
  327.  
  328. #pragma target 3.0
  329. #pragma exclude_renderers flash
  330. #pragma multi_compile_fwdadd
  331. #pragma vertex vert
  332. #pragma fragment frag
  333. #include "UnityCG.cginc"
  334. #include "AutoLight.cginc"
  335.  
  336. ////////////// Vertex Shader
  337. struct VertexInput {
  338. float4 vertex : POSITION;
  339. float4 texcoord : TEXCOORD0;
  340. float3 normal : NORMAL;
  341. float4 tangent : TANGENT;
  342. };
  343.  
  344. struct VertexOutput {
  345. float4 pos : SV_POSITION;
  346. float4 uv0 : TEXCOORD0;
  347. float4 posWorld : TEXCOORD1;
  348. float3 normalWorld : TEXCOORD2;
  349. float3 tangentWorld : TEXCOORD3;
  350. float3 binormalWorld : TEXCOORD4;
  351. LIGHTING_COORDS(5,6)
  352. };
  353.  
  354. VertexOutput vert (VertexInput v) {
  355. VertexOutput o;
  356. o.uv0 = v.texcoord;
  357. o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
  358. o.posWorld = mul(_Object2World, v.vertex);
  359.  
  360. // Construct the vectors for transforming normal maps to world space
  361. o.normalWorld = normalize(mul(float4(v.normal, 0.0), _World2Object).xyz);
  362. o.tangentWorld = normalize(mul(_Object2World, float4(v.tangent.xyz, 0.0)).xyz);
  363. o.binormalWorld = normalize(cross(o.normalWorld, o.tangentWorld) * v.tangent.w);
  364.  
  365. TRANSFER_VERTEX_TO_FRAGMENT(o);
  366.  
  367. return o;
  368. }
  369.  
  370. ////////////// Properties
  371. half4 _Color;
  372. sampler2D _AlbedoMap; half4 _AlbedoMap_ST;
  373. sampler2D _MultiMap; half4 _MultiMap_ST;
  374. sampler2D _Normal; half4 _Normal_ST;
  375. half _Metalness;
  376. half _Roughness;
  377.  
  378. // Light Color
  379. uniform float4 _LightColor0;
  380.  
  381. #define DielectricSpecular (0.04, 0.04, 0.04)
  382. #define Pi 3.14159
  383. #define InvPi 0.318309
  384.  
  385. ////////////// Functions
  386. ////////////// Specular BRDF
  387.  
  388. // Same cost but likely better than pow(x, 5)
  389. inline float pow5(float i) {
  390. float i5 = i * i;
  391. return i5 * i5 * i;
  392. }
  393.  
  394. // Fresnel - Schlick
  395. inline float3 F_Schlick(float3 f0, float u) {
  396. float InvU = 1.0 - u;
  397. return f0 + (1.0 - f0) * pow5(InvU);
  398. }
  399.  
  400. // Distribution - [Lagarde 2014, "Moving Frostbite to Physically Based Rendering"
  401. inline float D_GGX_Frost(float NdotH, float m2) {
  402. float f = (NdotH * m2 - NdotH) * NdotH + 1;
  403. return m2 / (f * f);
  404. }
  405.  
  406. // Geometric - [Lagarde 2014, "Moving Frostbite to Physically Based Rendering"]
  407. inline float V_SmithGGXCorrelated (float NdotV, float NdotL, float alphaG2 ) {
  408. float Lambda_GGXV = NdotL * sqrt (( -NdotV * alphaG2 + NdotV ) * NdotV + alphaG2 );
  409. float Lambda_GGXL = NdotV * sqrt (( -NdotL * alphaG2 + NdotL ) * NdotL + alphaG2 );
  410. return 0.5 / ( Lambda_GGXV + Lambda_GGXL );
  411. }
  412.  
  413. ////////////// Fragment Shader
  414. float4 frag(VertexOutput i) : COLOR {
  415. // Construct the world space normal direction
  416. float3 normalLocal = UnpackNormal(tex2D(_Normal, TRANSFORM_TEX(i.uv0.rg, _Normal)));
  417. float3x3 local2WorldTranspose = float3x3(
  418. i.tangentWorld,
  419. i.binormalWorld,
  420. i.normalWorld);
  421. float3 normalDir = normalize(mul(normalLocal, local2WorldTranspose));
  422.  
  423. // Construct the world space view direction
  424. float3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.posWorld.xyz);
  425.  
  426. // Construct the world space light direction
  427. float3 lightDir;
  428.  
  429. // Directional light?
  430. if (0.0 == _WorldSpaceLightPos0.w) {
  431. lightDir = normalize(_WorldSpaceLightPos0.xyz); }
  432. // Point or Spot light
  433. else {
  434. float3 vertexToLightSource = _WorldSpaceLightPos0.xyz - i.posWorld.xyz;
  435. float distance = length(vertexToLightSource);
  436. lightDir = normalize(vertexToLightSource); }
  437.  
  438. // Dot Products
  439. float3 halfDir = normalize (viewDir + lightDir);
  440. float LdotH = saturate(dot(lightDir, halfDir));
  441. float NdotH = saturate(dot(normalDir, halfDir));
  442. float NdotL = saturate(dot(normalDir, lightDir));
  443. float NdotV = abs(dot(normalDir, viewDir)) + 1e-5f; // avoid artifact
  444.  
  445. float3 MultiMap = tex2D(_MultiMap, TRANSFORM_TEX(i.uv0.rg, _MultiMap)).rgb;
  446.  
  447. #ifdef Gamma
  448. MultiMap = pow(MultiMap, 2.2);
  449. #endif
  450.  
  451. // Roughness Parameters
  452. float RoughLin = saturate(clamp(_Roughness, 0.0374, .999) * MultiMap.r);
  453. float Roughness = RoughLin * RoughLin;
  454. float RoughSqr = Roughness * Roughness;
  455.  
  456. // Metal Parameter
  457. float Metalness = saturate(_Metalness) * MultiMap.b;
  458.  
  459. // Albedo Paremeter
  460. float3 AlbedoColor = _Color.rgb * tex2D(_AlbedoMap, TRANSFORM_TEX(i.uv0.rg, _AlbedoMap)).rgb;
  461. #ifdef Gamma
  462. AlbedoColor = pow(AlbedoColor, 2.2);
  463. #endif
  464.  
  465. // Construct Specular
  466. float3 SpecularColor = (DielectricSpecular - DielectricSpecular * Metalness) + AlbedoColor * Metalness; // 2 mad
  467.  
  468. // Remove metal colors from Albedo
  469. AlbedoColor = AlbedoColor - AlbedoColor * Metalness; // 1 mad
  470.  
  471. // f0 is the refractive % of specular
  472. float3 f0 = SpecularColor;
  473.  
  474. // BRDF
  475. float3 F = F_Schlick(f0, LdotH);
  476. float D = D_GGX_Frost(NdotH, RoughSqr);
  477. float Vis = V_SmithGGXCorrelated(NdotV, NdotL, RoughSqr);
  478. float3 DirectSpec = F * (D * Vis * InvPi);
  479.  
  480. // Attenuation for diffuse and specular reflection
  481. float DirectAttenuation = LIGHT_ATTENUATION(i) * NdotL;
  482. float3 DirectAttenColor = _LightColor0.rgb * DirectAttenuation * Pi;
  483.  
  484. // Direct Diffuse
  485. float3 SimpleEnergyConservation = 1.0 - F_Schlick(f0, NdotL);
  486. float3 DirectDiff = AlbedoColor * InvPi * SimpleEnergyConservation;
  487.  
  488. // Final
  489. float3 finalColor = (DirectDiff + DirectSpec) * DirectAttenColor;
  490. #ifdef Gamma
  491. finalColor = pow(finalColor, 0.4545);
  492. #endif
  493. return float4(finalColor, 1.0);
  494. }
  495. ENDCG
  496. }
  497. }
  498. FallBack "Diffuse"
  499. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement