SpecularDiffuseToAlbedo.shader 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. Shader "Hidden/TriLib/SpecularDiffuseToAlbedo"
  2. {
  3. SubShader
  4. {
  5. // No culling or depth
  6. Cull Off ZWrite Off ZTest Always
  7. Pass
  8. {
  9. CGPROGRAM
  10. #pragma vertex vert
  11. #pragma fragment frag
  12. #include "UnityCG.cginc"
  13. struct appdata
  14. {
  15. float4 vertex : POSITION;
  16. float2 uv : TEXCOORD0;
  17. };
  18. struct v2f
  19. {
  20. float2 uv : TEXCOORD0;
  21. float4 vertex : SV_POSITION;
  22. };
  23. v2f vert(appdata v)
  24. {
  25. v2f o;
  26. o.vertex = UnityObjectToClipPos(v.vertex);
  27. o.uv = v.uv;
  28. return o;
  29. }
  30. sampler2D _DiffuseTexture;
  31. sampler2D _SpecularTexture;
  32. float getPerceivedBrightness(float3 linearColor)
  33. {
  34. float r = linearColor.x;
  35. float b = linearColor.y;
  36. float g = linearColor.z;
  37. return sqrt(0.299 * r * r + 0.587 * g * g + 0.114 * b * b);
  38. }
  39. float solveMetallic(float diffuseBrightness, float specularBrightness, float oneMinusSpecularStrength) {
  40. const float3 dielectricSpecular = float3(0.04, 0.04, 0.04);
  41. const float epsilon = 1e-6;
  42. specularBrightness = max(specularBrightness, dielectricSpecular.x);
  43. float a = dielectricSpecular.x;
  44. float b = diffuseBrightness * oneMinusSpecularStrength / (1.0 - dielectricSpecular.x) + specularBrightness - 2.0 * dielectricSpecular.x;
  45. float c = dielectricSpecular.x - specularBrightness;
  46. float D = b * b - 4.0 * a * c;
  47. return clamp((-b + sqrt(D)) / (2.0 * a), 0.0, 1.0);
  48. }
  49. float4 frag(v2f i) : SV_Target
  50. {
  51. const float3 dielectricSpecular = float3(0.04,0.04,0.04);
  52. const float epsilon = 1e-6;
  53. float4 diffuse = tex2D(_DiffuseTexture, i.uv);
  54. float3 specular = tex2D(_SpecularTexture, i.uv).xyz;
  55. float diffuseBrightness = getPerceivedBrightness(diffuse);
  56. float specularBrightness = getPerceivedBrightness(specular);
  57. float specularStrength = max(max(specular.x, specular.y), specular.z);
  58. float oneMinusSpecularStrength = 1.0 - specularStrength;
  59. float metallic = solveMetallic(diffuseBrightness, specularBrightness, oneMinusSpecularStrength);
  60. float3 baseColorFromDiffuse = diffuse * oneMinusSpecularStrength / ((1.0 - dielectricSpecular.x) * max(1.0 - metallic, epsilon));
  61. float3 baseColorFromSpecular = (specular - dielectricSpecular * (1.0 - metallic)) / max(metallic, epsilon);
  62. float3 baseColor = clamp(lerp(baseColorFromDiffuse, baseColorFromSpecular, metallic * metallic), 0.0, 1.0);
  63. return float4(baseColor, diffuse.w);
  64. }
  65. ENDCG
  66. }
  67. }
  68. }