vec4 xll_tex2Dlod(sampler2D s, vec4 coord) {
   return texture2DLod( s, coord.xy, 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]);
}
mat3 xll_constructMat3_mf4x4( mat4 m) {
  return mat3( vec3( m[0]), vec3( m[1]), vec3( m[2]));
}
struct Lamp {
    vec4 posRange;
    vec4 colorImp;
    vec4 spotParam;
};
struct v2f {
    vec4 pos;
    vec3 hybridDir;
    vec3 hybridCol;
    vec3 ambient;
    vec2 uv;
};
struct HybridAppData {
    vec4 vertex;
    vec4 tangent;
    vec3 normal;
    vec4 texcoord;
    vec4 bakedCol;
    vec2 bakedDir;
};
uniform vec3 _WorldSpaceCameraPos;
uniform mat4 _Object2World;
uniform mat4 _World2Object;

uniform vec3 _Tonemap_blackLevel;
uniform vec3 _Tonemap_toeLength;
uniform vec3 _Tonemap_heel;
uniform vec3 _Tonemap_shoulder;
uniform vec3 _Tonemap_colorScale1;
uniform vec3 _Tonemap_colorScale2;
uniform vec3 _HybridSunDir;
uniform vec4 _HybridSunCol;
uniform vec3 GridLightTextureStartCell;
uniform vec3 GridLightTextureCellSize;
uniform sampler2D GridLightTexture;
uniform vec4 IngameGridLimit;
uniform vec4 LightPos[30];
uniform vec4 LightCol[30];
uniform vec4 _MainTex_ST;
float Luma( in vec3 c ) {
    return dot( c, vec3( 0.22, 0.707, 0.071));
}
void CalcDynamicLight( in vec3 worldVert, in vec3 worldNorm, in Lamp lamp[4], inout vec3 hybridDir, inout vec3 hybridCol )
{
    vec3 lAgg = vec3( 0.0);
    float wAgg = 0.001;
    vec4 atten;
    int i = 0;
    for ( ; (i < 4); (i++)) {
        vec3 lightToVert = (lamp[i].posRange.xyz - worldVert);
        float lengthSq = dot( lightToVert, lightToVert);
        vec3 lightToVertNorm = (lightToVert * inversesqrt(lengthSq));
        atten[i] = max( (1.0 - ((lengthSq * lamp[i].posRange.w) * 0.8)), 0.0);
        atten[i] *= atten[i];
        float nDotL = max( dot( lightToVertNorm, worldNorm), 0.05);
        float weight = ((atten[i] * lamp[i].colorImp.w) * nDotL);
        lAgg += (weight * lightToVertNorm);
        wAgg += weight;
    }
    float w = (Luma( hybridCol) * 2.0);
    lAgg += (hybridDir * w);
    wAgg += w;
    hybridDir = (lAgg / wAgg);
    int j = 0;
    for ( ; (j < 4); (j++)) {
        vec3 lightToVertNorm_1 = normalize((lamp[j].posRange.xyz - worldVert));
        hybridCol += (lamp[j].colorImp.xyz * atten[j]);
    }
}
ivec4 GetLightIdxFromGrid( in vec3 worldVert )
{
    vec2 pos = ((worldVert - GridLightTextureStartCell) * GridLightTextureCellSize).xz;
    pos = clamp( pos, IngameGridLimit.xy, IngameGridLimit.zw);
    return ivec4((xll_tex2Dlod( GridLightTexture, vec4( pos.x, pos.y, 0.0, 0.0)) * 255.0));
}
vec3 DecodeBakedCol( in vec3 bakedCol )
{
    vec3 c = (bakedCol * 3.0);
    return (c * c);
}
vec3 DecodeNormal( in vec2 enc )
{
    vec4 nn = ((enc.xyxy * vec4( 2.0, 2.0, 0.0, 0.0)) + vec4( -1.0, -1.0, 1.01, -1.0));
    float l = dot( nn.xyz, (-nn.xyw));
    nn.z = l;
    nn.xy *= sqrt(l);
    return ((nn.xyz * 2.0) + vec3( 0.0, 0.0, -1.0));
}
void DecodeBaking( in vec4 bakedColor, in vec2 bakedDir, out vec3 hybridCol, out vec3 hybridDir )
{
    hybridDir = (DecodeNormal( bakedDir) * (bakedColor.w * 2.0));
    hybridCol = DecodeBakedCol( bakedColor.xyz);
}
void LoadBakedLight( in vec3 worldVert, in vec3 worldNorm, in vec4 bakedColor, in vec2 bakedDir, out vec3 hybridCol, out vec3 hybridDir )
{
    DecodeBaking( bakedColor, bakedDir, hybridCol, hybridDir);
}
void ReadLightArray3( in ivec4 lightIdx, out Lamp l0, out Lamp l1, out Lamp l2, out Lamp l3 )
{
    l0.posRange = LightPos[lightIdx.x];
    l0.colorImp = LightCol[lightIdx.x];
    l0.spotParam = vec4( 0.0, 0.0, 0.0, 1.0);
    l1.posRange = LightPos[lightIdx.y];
    l1.colorImp = LightCol[lightIdx.y];
    l1.spotParam = vec4( 0.0, 0.0, 0.0, 1.0);
    l2.posRange = LightPos[lightIdx.z];
    l2.colorImp = LightCol[lightIdx.z];
    l2.spotParam = vec4( 0.0, 0.0, 0.0, 1.0);
    l3.posRange = LightPos[lightIdx.w];
    l3.colorImp = LightCol[lightIdx.w];
    l3.spotParam = vec4( 0.0, 0.0, 0.0, 1.0);
}
vec3 JimTonemapping( in vec3 x )
{
    x = max( (x - (_Tonemap_blackLevel * 0.25)), vec3( 0.0, 0.0, 0.0));
    x = ((x * ((_Tonemap_colorScale1 * x) + _Tonemap_heel)) / ((x * ((_Tonemap_colorScale2 * x) + _Tonemap_shoulder)) + _Tonemap_toeLength));
    return x;
}
vec3 NichTonemap( in vec3 x )
{
    return (JimTonemapping( (x * 0.25)) * 4.0);
    float total = (length(x) + 0.0001);
    vec3 norm = (x / total);
    float tonemapped = (JimTonemapping( vec3( 0.0, (total * 0.25), 0.0)).y * 4.0);
    return (norm * tonemapped);
}
vec3 VertexTonemap( in vec3 x )
{
    return NichTonemap( x);
}
void DoCalcHybridLight2( in vec3 worldVert, in vec3 worldNorm, out vec3 hybridDir, out vec3 hybridCol, out vec3 ambient, in vec4 bakedColor, in vec2 bakedDir )
{
    LoadBakedLight( worldVert, worldNorm, bakedColor, bakedDir, hybridCol, hybridDir);
    ivec4 lightIdx = GetLightIdxFromGrid( worldVert);
    Lamp l[4];
    ReadLightArray3( lightIdx, l[0], l[1], l[2], l[3]);
    CalcDynamicLight( worldVert, worldNorm, l, hybridDir, hybridCol);
    hybridCol = VertexTonemap( hybridCol);
    ambient = VertexTonemap( (_HybridSunCol.xyz * dot( worldNorm, _HybridSunDir)));
}
v2f vert (in HybridAppData v)
{
    v2f o;
    o.pos = (gl_ModelViewProjectionMatrix * v.vertex);
    o.uv = ((v.texcoord.xy * _MainTex_ST.xy) + _MainTex_ST.zw);
    vec3 worldVert = (_Object2World * v.vertex).xyz;
    vec3 worldNorm = normalize((xll_constructMat3_mf4x4( _Object2World) * v.normal.xyz));
    DoCalcHybridLight2( worldVert, worldNorm, o.hybridDir, o.hybridCol, o.ambient, v.bakedCol, v.bakedDir);
    vec3 eyeToVert = normalize((_WorldSpaceCameraPos.xyz - worldVert));
    vec3 binormal = (cross( v.normal, v.tangent.xyz) * v.tangent.w);
    mat3 rotation = xll_transpose_mf3x3(mat3( v.tangent.xyz, binormal, v.normal));
    o.hybridDir = (rotation * (xll_constructMat3_mf4x4( _World2Object) * o.hybridDir));
    return o;
}
attribute vec4 TANGENT;
varying vec3 xlv_TEXCOORD0;
varying vec3 xlv_TEXCOORD1;
varying vec3 xlv_COLOR;
varying vec2 xlv_TEXCOORD2;
void main()
{
    v2f xl_retval;
    HybridAppData xlt_v;
    xlt_v.vertex = vec4(gl_Vertex);
    xlt_v.tangent = vec4(TANGENT);
    xlt_v.normal = vec3(gl_Normal);
    xlt_v.texcoord = vec4(gl_MultiTexCoord0);
    xlt_v.bakedCol = vec4(gl_Color);
    xlt_v.bakedDir = vec2(gl_MultiTexCoord1);
    xl_retval = vert( xlt_v);
    gl_Position = vec4(xl_retval.pos);
    xlv_TEXCOORD0 = vec3(xl_retval.hybridDir);
    xlv_TEXCOORD1 = vec3(xl_retval.hybridCol);
    xlv_COLOR = vec3(xl_retval.ambient);
    xlv_TEXCOORD2 = vec2(xl_retval.uv);
}
