#extension GL_ARB_shader_texture_lod : require

vec4 xll_texCUBElod(samplerCube s, vec4 coord) {
  return textureCubeLod( s, coord.xyz, coord.w);
}
mat3 xll_transpose_mf3x3(mat3 m) {
  return mat3( m[0][0], m[1][0], m[2][0],
               m[0][1], m[1][1], m[2][1],
               m[0][2], m[1][2], m[2][2]);
}
float xll_saturate_f( float x) {
  return clamp( x, 0.0, 1.0);
}
vec3 xll_saturate_vf3( vec3 x) {
  return clamp( x, 0.0, 1.0);
}
vec3 xll_matrixindex_mf3x3_i (mat3 m, int i) { vec3 v; v.x=m[0][i]; v.y=m[1][i]; v.z=m[2][i]; return v; }
struct VertexOutput {
    vec4 pos;
    vec4 tex;
    vec4 posWorld;
    vec3 normalWorld;
    vec4 tangentWorld;
    vec3 extra;
    vec4 _ShadowCoord;
    vec3 lightDir;
};
uniform vec3 _WorldSpaceCameraPos;
uniform vec4 _ProjectionParams;
uniform vec4 _ScreenParams;
uniform vec4 _ZBufferParams;
uniform vec4 _WorldSpaceLightPos0;
uniform vec4 unity_SHAr;
uniform vec4 unity_SHAg;
uniform vec4 unity_SHAb;
uniform vec4 unity_SHBr;
uniform vec4 unity_SHBg;
uniform vec4 unity_SHBb;
uniform vec4 unity_SHC;
uniform vec4 _LightShadowData;


uniform mat4 _Object2World;
uniform mat4 _World2Object;
uniform vec4 unity_Scale;
uniform mat4 glstate_matrix_transpose_modelview0;




uniform mat4 unity_MatrixV;
uniform mat4 unity_MatrixVP;
uniform samplerCube _Cube;
uniform sampler2D _MainTex;
uniform vec4 _MainTex_ST;
uniform sampler2D _DetailAlbedoMap;
uniform vec4 _DetailAlbedoMap_ST;
uniform sampler2D _AlphaMap;
uniform sampler2D _Occlusion;
uniform sampler2D _DetailNormalMap;
uniform vec4 _DetailNormalMap_ST;
uniform float _DetailNormalMapScale;
uniform sampler2D _BumpMap;
uniform float _BumpScale;
uniform float _Exposure;
uniform float _DetailBumpScale;
uniform float _AlphaTestRef;
uniform float _DetailBumpTiling;
uniform vec4 _Color;
uniform vec4 _SpecularColor;
uniform sampler2D _SpecGlossMap;
uniform float _Glossiness;

uniform vec4 unity_ColorSpaceGrey;

uniform sampler2D _ShadowMapTexture;
uniform vec4 _LightColor0;

uniform samplerCube _SpecCube;
uniform vec4 unity_LightmapST;
uniform sampler2D unity_Lightmap;
uniform sampler2D unity_LightmapInd;
uniform float _SelfIllumScale;
uniform sampler2D _SelfIllum;

vec3 Albedo( in vec4 texcoords ) {
    vec3 albedo = (_Color.xyz * texture2D( _MainTex, texcoords.xy).xyz);
    albedo *= (2.0 * texture2D( _DetailAlbedoMap, texcoords.zw).xyz);
    return albedo;
}
float Alpha( in vec2 uv ) {
    return (texture2D( _AlphaMap, uv).w * _Color.w);
}
float BlinnPhongTerm( in float roughness, in float NdotH ) {
    float m = (pow( roughness, 4.0) + 1e-05);
    float n = ((1.0 / m) - 2.0);
    float normTerm = ((n + 1.0) / 6.28318);
    float specTerm = pow( NdotH, n);
    return (specTerm * normTerm);
}
float BlinnTerm( in vec3 normal, in vec3 halfDir ) {
    return max( 0.0, dot( normal, halfDir));
}
float FresnelTerm( in float F0, in float cosA ) {
    float _Falloff = 5.0;
    float t = pow( abs((1.0 - cosA)), _Falloff);
    return (F0 + ((1.0 - F0) * t));
}
float CTGeometricTerm( in float NdotL, in float NdotH, in float NdotV, in float VdotH ) {
    VdotH += 1e-05;
    return min( 1.0, min( (((2.0 * NdotH) * NdotV) / VdotH), (((2.0 * NdotH) * NdotL) / VdotH)));
}
float GeometricTerm( in float NdotL, in float NdotH, in float NdotV, in float VdotH, in float LdotV ) {
    return CTGeometricTerm( NdotL, NdotH, NdotV, VdotH);
}
float LambertTerm( in vec3 normal, in vec3 lightDir ) {
    return max( 0.0, dot( normal, lightDir));
}
float RGBToLuminance( in vec3 color ) {
    vec3 lumSensitivity = vec3( 0.299, 0.587, 0.114);
    float luminance = dot( color, lumSensitivity);
    return luminance;
}
vec3 BRDF_Disney_PBS( in vec3 baseColor, in vec3 lightColor, in vec3 specColor, in float specular, in float roughness, in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 ambient, in vec3 env ) {
    vec3 halfDir = normalize((lightDir + viewDir));
    float nl = LambertTerm( normal, lightDir);
    float nh = BlinnTerm( normal, halfDir);
    float nv = max( 0.0, dot( normal, viewDir));
    float vh = max( 0.0, dot( viewDir, halfDir));
    float lv = max( 0.0, dot( lightDir, viewDir));
    float lh = max( 0.0, dot( lightDir, halfDir));
    float F = FresnelTerm( specular, vh);
    float G = GeometricTerm( nl, nh, nv, vh, lv);
    float R = BlinnPhongTerm( roughness, nh);
    R = max( 0.0, R);
    float Fd90 = (0.5 + ((2.0 * pow( lh, 2.0)) * roughness));
    float nlPow = pow( (1.00001 - nl), 5.0);
    float nvPow = pow( (1.00001 - nv), 5.0);
    float disneyDiffuse = ((1.0 + ((Fd90 - 1.0) * nlPow)) * (1.0 + ((Fd90 - 1.0) * nvPow)));
    float specularTerm = max( 0.0, (((F * G) * R) / ((4.0 * nv) + 1e-05)));
    float diffuseTerm = (disneyDiffuse * nl);
    vec3 diffuseColor = baseColor;
    vec3 color = (((diffuseColor * (ambient + (diffuseTerm * lightColor))) + (specColor * (env + (lightColor * specularTerm)))) + ((((1.0 - RGBToLuminance( specColor)) * (1.0 - roughness)) * FresnelTerm( 0.0, nv)) * env));
    return color;
}
vec3 DecodeLightmap( in vec4 color ) {
    return ((8.0 * color.w) * color.xyz);
}
vec3 DirLightmapDiffuse( in mat3 dirBasis, in vec4 color, in vec4 scale, in vec3 normal, in bool surfFuncWritesNormal, out vec3 scalePerBasisVector ) {
    vec3 lm = DecodeLightmap( color);
    scalePerBasisVector = DecodeLightmap( scale);
    if (surfFuncWritesNormal){
        vec3 normalInRnmBasis = xll_saturate_vf3((dirBasis * normal));
        lm *= dot( normalInRnmBasis, scalePerBasisVector);
    }
    return lm;
}
void DecodeDirLightmap( in vec3 normal, in vec4 colorLM, in vec4 scaleLM, out vec3 lightColor, out vec3 lightDir ) {
    mat3 unity_DirBasis = xll_transpose_mf3x3(mat3( vec3( 0.816497, 0.0, 0.57735), vec3( -0.408248, 0.707107, 0.57735), vec3( -0.408248, -0.707107, 0.57735)));
    vec3 scalePerBasisVector;
    lightColor = DirLightmapDiffuse( unity_DirBasis, colorLM, scaleLM, normal, true, scalePerBasisVector);
    lightDir = normalize((((scalePerBasisVector.x * xll_matrixindex_mf3x3_i (unity_DirBasis, 0)) + (scalePerBasisVector.y * xll_matrixindex_mf3x3_i (unity_DirBasis, 1))) + (scalePerBasisVector.z * xll_matrixindex_mf3x3_i (unity_DirBasis, 2))));
}
vec3 EnergyCalculator( in vec3 specColor, in float specular, in vec3 baseColor ) {
    return min( baseColor, (vec3( 1.0, 1.0, 1.0) - specular));
}
float toLinearFast1( in float c ) {
    float c2 = (c * c);
    return dot( vec2( 0.7532, 0.2468), vec2( c2, (c * c2)));
}
vec3 fromRGBM( in vec4 c ) {
    return ((c.xyz * toLinearFast1( c.w)) * _Exposure);
}
vec3 EnvMap( in vec4 worldNormal ) {
    vec4 envTexel = xll_texCUBElod( _SpecCube, vec4( worldNormal.xyz, worldNormal.w));
    return fromRGBM( envTexel);
}
float Occlusion( in vec2 uv ) {
    return texture2D( _Occlusion, uv).x;
}
vec4 SpecularGloss( in vec2 uv ) {
    vec4 specGloss = texture2D( _SpecGlossMap, uv);
    return vec4( specGloss.xyz, specGloss.w);
}
vec3 BlendNormals( in vec3 n1, in vec3 n2 ) {
    return normalize(vec3( (n1.xy + n2.xy), (n1.z * n2.z)));
}
vec3 UnpackScaleNormal( in vec4 packednormal, in float bumpScale ) {
    vec3 normal;
    normal.xy = ((packednormal.wy * 2.0) - 1.0);
    normal.xy *= bumpScale;
    normal.z = sqrt((1.0 - xll_saturate_f(dot( normal.xy, normal.xy))));
    return normal;
}
vec3 TangentNormal( in vec4 texcoords ) {
    vec3 normalTangent = UnpackScaleNormal( texture2D( _BumpMap, texcoords.xy), _BumpScale);
    vec3 detailNormalTangent = UnpackScaleNormal( texture2D( _DetailNormalMap, texcoords.zw), _DetailNormalMapScale);
    normalTangent = BlendNormals( normalTangent, detailNormalTangent);
    return normalTangent;
}
mat3 TangentToWorld( in vec3 normal, in vec3 tangent, in vec3 flip ) {
    vec3 binormal = (cross( normal, tangent) * flip);
    return xll_transpose_mf3x3(mat3( tangent, binormal, normal));
}
float unitySampleShadow( in vec4 shadowCoord ) {
    float shadow = texture2DProj( _ShadowMapTexture, shadowCoord).x;
    return shadow;
}
vec4 frag( in VertexOutput i ) {
    float atten = unitySampleShadow( i._ShadowCoord);
    mat3 tanToWorld = TangentToWorld( i.normalWorld, i.tangentWorld.xyz, vec3( i.tangentWorld.w));
    i.normalWorld = normalize(i.normalWorld);
    vec3 normalTangent = TangentNormal( i.tex);
    vec3 normalWorld = (normalTangent * tanToWorld);
    vec3 eyeVec = normalize((i.posWorld.xyz - _WorldSpaceCameraPos));
    vec4 specGloss = SpecularGloss( i.tex.xy);
    vec3 specColor = specGloss.xyz;
    float specular = RGBToLuminance( specGloss.xyz);
    float roughness = (1.0 - specGloss.w);
    vec3 env = vec3( 0.0);
    env = (EnvMap( vec4( reflect( eyeVec, normalWorld), (roughness * 5.0))) * Occlusion( i.tex.xy));
    vec3 lightColor = (_LightColor0.xyz * 2.0);
    vec3 lightDir = _WorldSpaceLightPos0.xyz;
    float subsurface = 1.0;
    vec3 ambient = vec3( 0.0);
    vec4 lmtex = texture2D( unity_Lightmap, i.extra.xy);
    vec4 lmIndTex = texture2D( unity_LightmapInd, i.extra.xy);
    vec3 lightDirTangent;
    DecodeDirLightmap( normalTangent, lmtex, lmIndTex, lightColor, lightDirTangent);
    lightDir = (lightDirTangent * tanToWorld);
    lightDir = normalize(lightDir);
    vec3 baseColor = EnergyCalculator( specColor, specular, Albedo( i.tex));
    vec3 color = BRDF_Disney_PBS( baseColor, (atten * lightColor), specColor, specular, roughness, normalWorld, lightDir, (-eyeVec), ambient, env);
    color += (texture2D( _SelfIllum, i.tex.xy).xyz * _SelfIllumScale);
    float alpha = Alpha( i.tex.xy);
    return vec4( color, alpha);
}
varying vec4 xlv_TEXCOORD0;
varying vec4 xlv_TEXCOORD1;
varying vec3 xlv_TEXCOORD2;
varying vec4 xlv_TEXCOORD3;
varying vec3 xlv_TEXCOORD4;
varying vec4 xlv_TEXCOORD5;
varying vec3 xlv_TEXCOORD7;
void main() {
    vec4 xl_retval;
    VertexOutput xlt_i;
    xlt_i.pos = vec4(0.0);
    xlt_i.tex = vec4(xlv_TEXCOORD0);
    xlt_i.posWorld = vec4(xlv_TEXCOORD1);
    xlt_i.normalWorld = vec3(xlv_TEXCOORD2);
    xlt_i.tangentWorld = vec4(xlv_TEXCOORD3);
    xlt_i.extra = vec3(xlv_TEXCOORD4);
    xlt_i._ShadowCoord = vec4(xlv_TEXCOORD5);
    xlt_i.lightDir = vec3(xlv_TEXCOORD7);
    xl_retval = frag( xlt_i);
    gl_FragData[0] = vec4(xl_retval);
}
