// Copyright (c) 2017-2020 Xiamen Yaji Software Co., Ltd.

CCEffect %{
  techniques:
  - name: opaque
    passes:
    - vert: standard-vs:vert
      frag: standard-fs:frag
      properties: &props
        tilingOffset:   { value: [1.0, 1.0, 0.0, 0.0] }
        tilingOffset2:   { value: [2.0, 2.0, 0.0, 0.0] }
        mainColor:      { value: [1.0, 1.0, 1.0, 1.0], target: albedo, editor: { displayName: Albedo, type: color } }
        albedoScale:    { value: [1.0, 1.0, 1.0], target: albedoScaleAndCutoff.xyz }
        alphaThreshold: { value: 0.5, target: albedoScaleAndCutoff.w, editor: { parent: USE_ALPHA_TEST, slide: true, range: [0, 1.0], step: 0.001 } }
        occlusion:      { value: 1.0, target: pbrParams.x, editor: { slide: true, range: [0, 1.0], step: 0.001 }  }
        roughness:      { value: 0.8, target: pbrParams.y, editor: { slide: true, range: [0, 1.0], step: 0.001 }  }
     
        highlightColor: { value: [0.8, 0.8, 0.8, 1.0], editor: { displayName: Highlight Color, type: color } }
        Fresnelcol:    { value: [0.9, 0.9, 0.9, 1.0], editor: { displayName: Fresnel Color, type: color } }
        _fresnelBase:  { value: 1.0, target: rampParams.x, editor: { range: [-1.0, 1.0] } }
        _fresnelScale:  { value: 1.0, target: rampParams.y, editor: { range: [-1.0, 1.0] } }
        _fresnelIndensity: { value: 5.0, target: rampParams.z, editor: { range: [-5.0, 5.0] } }
        metallic:       { value: 0.6, target: pbrParams.z, editor: { slide: true, range: [0, 1.0], step: 0.001 } }
        SpecularIntensity:  { value: 0.5, target: pbrParams.w, editor: {  slide: true, range: [0.0, 1.0], step: 0.001 } }
        normalStrenth:  { value: 1.0, target: pbrParams.w, editor: { parent: USE_NORMAL_MAP } }
        emissive:       { value: [0.0, 0.0, 0.0, 1.0], editor: { type: color } }
        emissiveScale:  { value: [1.0, 1.0, 1.0], target: emissiveScaleParam.xyz }
        mainTexture:    { value: grey, target: albedoMap, editor: { displayName: AlbedoMap } }
        normalMap:      { value: normal       }
        pbrMap:         { value: grey         }
        metallicRoughnessMap: { value: grey   }
        occlusionMap:   { value: white        }
        emissiveMap:    { value: grey         }
      migrations:
        properties:
          pbrParams: { removeImmediately: true }
    - &deferred
      vert: standard-vs:vert
      frag: standard-fs:frag
      phase: deferred
      propertyIndex: 0
      blendState:
        targets:
        - blend: false
        - blend: false
        - blend: false
        - blend: false
      properties: *props
    - &forward-add
      vert: standard-vs:vert
      frag: standard-fs:frag
      phase: forward-add
      propertyIndex: 0
      embeddedMacros: { CC_FORWARD_ADD: true }
      depthStencilState:
        depthFunc: equal
        depthTest: true
        depthWrite: false
      blendState:
        targets:
        - blend: true
          blendSrc: one
          blendDst: one
          blendSrcAlpha: zero
          blendDstAlpha: one
      properties: *props
    - &shadow-caster
      vert: shadow-caster-vs:vert
      frag: shadow-caster-fs:frag
      phase: shadow-caster
      propertyIndex: 0
      rasterizerState:
        cullMode: front
      properties:
        tilingOffset:   { value: [1.0, 1.0, 0.0, 0.0] }
        tilingOffset2:   { value: [0.2, 0.2, 0.0, 0.0] }
        mainColor:      { value: [1.0, 1.0, 1.0, 1.0], target: albedo, editor: { displayName: Albedo, type: color } }
        albedoScale:    { value: [1.0, 1.0, 1.0], target: albedoScaleAndCutoff.xyz }
        alphaThreshold: { value: 0.5, target: albedoScaleAndCutoff.w, editor: { parent: USE_ALPHA_TEST } }
        occlusion:      { value: 1.0, target: pbrParams.x }
        roughness:      { value: 0.8, target: pbrParams.y }
        
        highlightColor: { value: [0.8, 0.8, 0.8, 1.0], editor: { displayName: Highlight Color, type: color } }
        Fresnelcol:    { value: [0.9, 0.9, 0.9, 1.0], editor: { displayName: Fresnel Color, type: color } }
        _fresnelBase:  { value: 1.0, target: rampParams.x, editor: { range: [-1.0, 1.0] } }
        _fresnelScale:  { value: 1.0, target: rampParams.y, editor: { range: [-1.0, 1.0] } }
        _fresnelIndensity: { value: 5.0, target: rampParams.z, editor: { range: [-5.0, 5.0] } }
        metallic:       { value: 0.6, target: pbrParams.z }
        normalStrenth:  { value: 1.0, target: pbrParams.w, editor: { parent: USE_NORMAL_MAP } }
        emissive:       { value: [0.0, 0.0, 0.0, 1.0], editor: { type: color } }
        emissiveScale:  { value: [1.0, 1.0, 1.0], target: emissiveScaleParam.xyz }
        mainTexture:    { value: grey, target: albedoMap, editor: { displayName: AlbedoMap } }
  - name: transparent
    passes:
    - vert: standard-vs:vert
      frag: standard-fs:frag
      depthStencilState:
        depthTest: true
        depthWrite: false
      blendState:
        targets:
        - blend: true
          blendSrc: src_alpha
          blendDst: one_minus_src_alpha
          blendDstAlpha: one_minus_src_alpha
      properties: *props
    - *forward-add
    - *shadow-caster
}%

CCProgram shared-ubos %{
  uniform Constants {
    vec4 tilingOffset;
    vec4 tilingOffset2;
    vec4 albedo;
    vec4 albedoScaleAndCutoff;
    vec4 pbrParams;
    vec4 miscParams;
    vec4 emissive;
    vec4 emissiveScaleParam;
    vec4 highlightColor;
    vec4 Fresnelcol;
    vec4 rampParams;
    

    
  };
}%

CCProgram standard-vs %{
  precision highp float;
  #include <legacy/input-standard>
  #include <builtin/uniforms/cc-global>
  #include <legacy/decode-base>
  #include <legacy/local-batch>
  #include <shared-ubos>
  #include <legacy/fog-vs>
  #include <legacy/shadow-map-vs>

  #if USE_VERTEX_COLOR
    in vec4 a_color;
    out vec4 v_color;
  #endif

  out vec3 v_position;
  out vec3 v_position_local;
  
  out mat4 matWorldIT_L;
  out vec3 v_normal;
  out vec2 v_uv;
  out vec2 v_uv1;
  // out float v_fog_factor;
  

  #if USE_NORMAL_MAP
    out vec3 v_tangent;
    out vec3 v_bitangent;
  #endif

  #if HAS_SECOND_UV || CC_USE_LIGHTMAP
    in vec2 a_texCoord1;
  #endif

  #if CC_USE_LIGHTMAP && !CC_FORWARD_ADD
    #include <legacy/lightingmap-vs>
  #endif

  vec4 vert () {
    StandardVertInput In;
    CCVertInput(In);

    mat4 matWorld, matWorldIT;
    CCGetWorldMatrixFull(matWorld, matWorldIT);
    matWorldIT_L = matWorldIT;
   
    vec4 pos = matWorld * In.position;
    v_position_local = In.position.xyz;

    
    v_position = pos.xyz;
    v_normal = normalize((matWorldIT * vec4(In.normal, 0.0)).xyz);
    #if USE_NORMAL_MAP
      v_tangent = normalize((matWorld * vec4(In.tangent.xyz, 0.0)).xyz);
      v_bitangent = cross(v_normal, v_tangent) * In.tangent.w; // note the cross order
    #endif

    v_uv = a_texCoord * tilingOffset.xy + tilingOffset.zw;
    #if SAMPLE_FROM_RT
      CC_HANDLE_RT_SAMPLE_FLIP(v_uv);
    #endif
    #if HAS_SECOND_UV
      v_uv1 = a_texCoord * tilingOffset2.xy + tilingOffset2.zw;
      #if SAMPLE_FROM_RT
        CC_HANDLE_RT_SAMPLE_FLIP(v_uv1);
      #endif
    #endif

    

    #if USE_VERTEX_COLOR
      v_color = a_color;
    #endif
    CC_TRANSFER_FOG(pos);
    CC_TRANSFER_SHADOW(pos);

    #if CC_USE_LIGHTMAP && !CC_FORWARD_ADD
      CCLightingMapCaclUV();
    #endif

    return cc_matProj * (cc_matView * matWorld) * In.position;  
    }
}%

CCProgram standard-fs %{
  precision highp float;
  #include <builtin/uniforms/cc-global>
  #include <legacy/shading-standard>
  #include <legacy/output-standard>
  #include <legacy/shading-standard-base>
  #include <legacy/shadow-map-fs>
  #include <common/color/gamma>
  #include <shared-ubos>
  #include <legacy/fog-fs>

  #if CC_USE_LIGHTMAP && !CC_FORWARD_ADD
    #include <legacy/lightingmap-fs>
  #endif

  in vec3 v_position;
  in vec3 v_position_local;
  in mat4 matWorldIT_L;
  
  in vec2 v_uv;
  in vec2 v_uv1;
  in vec3 v_normal;
  // in float v_fog_factor;
  

  #if USE_VERTEX_COLOR
    in vec4 v_color;
  #endif

  #if USE_ALBEDO_MAP
    uniform sampler2D albedoMap;
    #pragma define-meta ALBEDO_UV options([v_uv, v_uv1])
  #endif
  #if USE_NORMAL_MAP
    in vec3 v_tangent;
    in vec3 v_bitangent;
    uniform sampler2D normalMap;
    #pragma define-meta NORMAL_UV options([v_uv, v_uv1])
  #endif
  #pragma define-meta PBR_UV options([v_uv, v_uv1])
  #if USE_PBR_MAP
    uniform sampler2D pbrMap;
  #endif
  #if USE_METALLIC_ROUGHNESS_MAP
    uniform sampler2D metallicRoughnessMap;
  #endif
  #if USE_OCCLUSION_MAP
    uniform sampler2D occlusionMap;
  #endif
  #if USE_EMISSIVE_MAP
    uniform sampler2D emissiveMap;
    #pragma define-meta EMISSIVE_UV options([v_uv, v_uv1])
  #endif

  #pragma define OCCLUSION_CHANNEL r
  #pragma define ROUGHNESS_CHANNEL g
  #pragma define METALLIC_CHANNEL  b
  #pragma define SPECULARINTENSITY_CHANNEL w

  #if USE_ALPHA_TEST
    #pragma define-meta ALPHA_TEST_CHANNEL options([a, r])
  #endif

  void surf (out StandardSurface s) {
    vec4 baseColor = albedo;
    #if USE_VERTEX_COLOR
      baseColor.rgb *= SRGBToLinear(v_color.rgb);//use linear
      baseColor.a *= v_color.a;
    #endif
    #if USE_ALBEDO_MAP
      vec4 texColor = texture(albedoMap, ALBEDO_UV);
      texColor.rgb = SRGBToLinear(texColor.rgb);
      baseColor *= texColor;
    #endif
    s.albedo = baseColor;
    s.albedo.rgb *= albedoScaleAndCutoff.xyz;

    #if USE_ALPHA_TEST
      if (s.albedo.ALPHA_TEST_CHANNEL < albedoScaleAndCutoff.w) discard;
    #endif

    #if CC_USE_LIGHTMAP && !CC_FORWARD_ADD
      vec4 lightColor = texture(cc_lightingMap, v_luv.xy);
      s.lightmap = lightColor.rgb;
      s.lightmap_test = v_luv.z; /*u scale*/
    #endif

    s.normal = v_normal;
    #if USE_NORMAL_MAP
      vec3 nmmp = texture(normalMap, NORMAL_UV).xyz - vec3(0.5);
      s.normal =
        (nmmp.x * miscParams.x) * normalize(v_tangent) +
        (nmmp.y * miscParams.x) * normalize(v_bitangent) +
        nmmp.z * normalize(s.normal);
    #endif

    s.position = v_position;

    vec4 pbr = pbrParams;
    #if USE_PBR_MAP
      vec4 res = texture(pbrMap, PBR_UV);
      pbr.x *= res.OCCLUSION_CHANNEL;
      pbr.y *= res.ROUGHNESS_CHANNEL;
      pbr.z *= res.METALLIC_CHANNEL;
      pbr.w *= res.SPECULARINTENSITY_CHANNEL;
    #endif
    #if USE_METALLIC_ROUGHNESS_MAP
      vec4 metallicRoughness = texture(metallicRoughnessMap, PBR_UV);
      pbr.z *= metallicRoughness.METALLIC_CHANNEL;
      pbr.y *= metallicRoughness.ROUGHNESS_CHANNEL;
    #endif
    #if USE_OCCLUSION_MAP
      pbr.x *= texture(occlusionMap, PBR_UV).OCCLUSION_CHANNEL;
    #endif
    s.occlusion = clamp(pbr.x, 0.0, 0.96);
    s.roughness = clamp(pbr.y, 0.04, 1.0);
    s.specularIntensity = 0.5;
    s.metallic = pbr.z;

    s.emissive = emissive.rgb * emissiveScaleParam.xyz;
    #if USE_EMISSIVE_MAP
      s.emissive *= SRGBToLinear(texture(emissiveMap, EMISSIVE_UV).rgb);
    #endif
  }

  vec4 frag () {

    float fresnelBase = rampParams.x;
    float fresnelScale = rampParams.y;
    float fresnelIndensity = rampParams.z;
    vec4 cc_cameraPoslocal = matWorldIT_L * cc_cameraPos;
    vec3 N = normalize(v_normal);
    vec3 lightDir = normalize(-cc_mainLitDir.xyz);
    vec3 viewDir = normalize(cc_cameraPos.xyz - v_position);
    StandardSurface s; surf(s);
    vec4 color =  CCStandardShadingBase(s, CC_SHADOW_POSITION); 
    CC_APPLY_FOG(color);
 
    float fresnel = fresnelBase + fresnelScale*pow(1.0-dot(N, viewDir), fresnelIndensity);
    color.rgb += mix((color.rgb)+(highlightColor.rgb), Fresnelcol.rgb, fresnel) * Fresnelcol.a;
    
   

    return CCFragOutput(color);
  }
}%

CCProgram shadow-caster-vs %{
  precision highp float;
  #include <legacy/input-standard>
  #include <legacy/decode-base>
  #include <legacy/local-batch>
  #include <shared-ubos>
  #include <builtin/uniforms/cc-shadow>
#if CC_SUPPORT_CASCADED_SHADOW_MAP
  #include <builtin/uniforms/cc-csm>
#endif

  #if HAS_SECOND_UV || CC_USE_LIGHTMAP
    in vec2 a_texCoord1;
  #endif

  out vec2 v_uv;
  out vec2 v_uv1;
  out vec4 v_worldPos;

  out float v_clip_depth;

  vec4 vert () {
    StandardVertInput In;
    CCVertInput(In);

    mat4 matWorld, matWorldIT;
    CCGetWorldMatrixFull(matWorld, matWorldIT);

    v_worldPos = matWorld * In.position;
    vec4 clipPos = cc_matLightViewProj * v_worldPos;

    v_uv = a_texCoord * tilingOffset.xy + tilingOffset.zw;
    #if HAS_SECOND_UV
      v_uv1 = a_texCoord * tilingOffset2.xy + tilingOffset2.zw;
    #endif

    v_clip_depth = clipPos.z / clipPos.w * 0.5 + 0.5;

    return clipPos;
  }
}%

CCProgram shadow-caster-fs %{
  precision highp float;
  #include <shared-ubos>
  #include <common/data/packing>
   #include <builtin/uniforms/cc-shadow>
#if CC_SUPPORT_CASCADED_SHADOW_MAP
  #include <builtin/uniforms/cc-csm>
#endif

  in vec2 v_uv;
  in vec2 v_uv1;
  in float v_clip_depth;
  in vec4 v_worldPos;

  #if USE_ALBEDO_MAP
    uniform sampler2D albedoMap;
    #pragma define-meta ALBEDO_UV options([v_uv, v_uv1])
  #endif

  #if USE_ALPHA_TEST
    #pragma define-meta ALPHA_TEST_CHANNEL options([a, r])
  #endif

  vec4 frag () {
    vec4 baseColor = albedo;

    #if USE_ALBEDO_MAP
      baseColor *= texture(albedoMap, ALBEDO_UV);
    #endif

    #if USE_ALPHA_TEST
      if (baseColor.ALPHA_TEST_CHANNEL < albedoScaleAndCutoff.w) discard;
    #endif

    // spot use linear
    if(cc_shadowLPNNInfo.x > 0.000001 && cc_shadowLPNNInfo.x < 1.999999) {
      // enabled linear depth
      if (cc_shadowNFLSInfo.z > 0.000001) {
        vec4 viewStartPos = cc_matLightView * v_worldPos;
        float dist = length(viewStartPos.xyz);
        float linearDepth = cc_shadowNFLSInfo.x + (-dist / (cc_shadowNFLSInfo.y - cc_shadowNFLSInfo.x));

        return vec4(linearDepth, 1.0, 1.0, 1.0);
      }
    }

    if (cc_shadowLPNNInfo.y > 0.000001) {
      return packDepthToRGBA(v_clip_depth);
    }
  
    return vec4(v_clip_depth, 1.0, 1.0, 1.0);
  }
}%
