/***************************************************************************
 *                         Zanoza Modeler v3.3.x                           *
 *     This is unpublished proprietary source code of Zanoza Software.     *
 *      The copyright notice does not evidence any actual or intended      *
 *                    publication of such source code.                     *
 *                                                                         *
 *                 Copyright (c) 2002-2024 Zanoza Software.                *
 *                                                                         *
 *                        All rights reserved.                             *
 ***************************************************************************
 *--------------------------------------------------------------------------
 * @author:   Oleg M.
 *--------------------------------------------------------------------------
 * @purpose:  ZModeler 3.3.x Pure (no parameters) solid flat-shaded shader.
 *--------------------------------------------------------------------------
 * @history: 12.05.2024. Created
 * @Description:
   Shader for default rendering (with no materials) with build-in
   FlatShade support on geometry shader. Color/light computation
   is therefor moved to pixel shader. When flat shading is not
   required, it's preferable to pick "Shade.zsh" pure shader instead
   as it does all calculations on vertex shader.
<[[
UserName = "Flatshaded Wireframe/solid for dual render targets"
Version  = 2.0.1
Options  = PURE DUAL
Engine = 11
]]>
*/

#pragma pack_matrix( row_major ) 

struct VS_INPUT
{
    float4 vPosition        : SV_POSITION;
    float4 vNormal          : NORMAL;
    float4 vTangent         : TANGENT;
    float4 vColorDif        : COLOR0;
    float4 vDeformPosition  : TEXCOORD5;
    float4 vDeformNormal    : COLOR2;
    uint4  vBones0          : BLENDINDICES0;
    uint4  vBones1          : BLENDINDICES1;
    float4 vWeights0        : BLENDWEIGHT0;
    float4 vWeights1        : BLENDWEIGHT1;
};

struct VS_OUTPUT
{
    float4  vPosition : SV_POSITION;
    float4  vPos3D    : POSITION1;
    float4  vViewer   : TANGENT;
    float4  vNormal   : NORMAL;
    float4  vDiffuse  : COLOR;
};

struct PS_OUTPUT
{
    float4  color0 : SV_TARGET0;
    float4  color1 : SV_TARGET1;
};

#include "zmCommonBuffers.inl"
#include "zmCommonRoutines.inl"

#ifdef GEOMETRY_SHADER
//
// point expand to bilboard quad geometry shader:
[maxvertexcount(4)]
void pointGS(point VS_OUTPUT ptIn[1], inout TriangleStream<VS_OUTPUT> tristream)
{
  VS_OUTPUT gout;
  [unroll]
  for (int i = 0; i < 4; i++)
  {
    gout = ptIn[0];
    float2 vOffset2D = (float2(i&1, i>>1)*2 - 1)*g_geomLevels.x;
    vOffset2D = vOffset2D*g_viewport.zw;
    gout.vPosition.xy += vOffset2D*gout.vPosition.w;
    tristream.Append(gout);
  }
}

[maxvertexcount(3)]
void flatshadeGS(triangle VS_OUTPUT ptIn[3], inout TriangleStream<VS_OUTPUT> tristream)
{
  VS_OUTPUT gout;
  float4 vNorm = normalFromPoints(ptIn[0].vPos3D, ptIn[1].vPos3D, ptIn[2].vPos3D);
  [unroll]
  for (int i = 0; i < 3; i++)
  {
    gout = ptIn[i];
    gout.vNormal = lerp(ptIn[i].vNormal, vNorm, g_geomLevels.z); //adjust normal to flat-shaded (%)
    tristream.Append(gout);
  }
}
#endif //GEOMETRY_SHADER

#ifdef VERTEX_SHADER
VS_OUTPUT mainVS(in VS_INPUT v, uint vtxID : SV_VertexID)
{
    VS_OUTPUT output;
    //transform to screen:
    float4 vNorm    = v.vNormal;
    float4 vTangent = v.vTangent;
    float4 vViewer  = (float4)0;

    output.vPosition = transformInput(v, output.vPos3D, vNorm, vTangent, vViewer);
    output.vViewer = normalize(vViewer);
    output.vNormal = vNorm;
    output.vDiffuse = v.vColorDif;

    return output;
}
#endif //VERTEX_SHADER

PS_OUTPUT mainPS(in VS_OUTPUT v) : SV_TARGET
{
  PS_OUTPUT sOut;
  //
  // basic diffuse blend (per-vertex and material)
  float4 vertColor = (any(v.vDiffuse.rgb) ? v.vDiffuse : 1);
  sOut.color0 = lerp(1, g_colors[1], g_colorBlend.y) * 
               lerp(1, vertColor, g_colorBlend.x);

  //dim on diffuse light:
  float3 normal = normalize(v.vNormal.xyz);
  sOut.color0.rgb = (g_colors[0].rgb + 0.2*v.vDiffuse.rgb + 0.2*g_ambientLight.rgb)*g_ambientLight.rgb +
              sOut.color0*saturate(saturate(dot(-g_lightDir.xyz, normal)) + g_colors[3].w + g_colorBlend.z);

  //
  // add global emissive:
  sOut.color0.rgb += g_colors[3].rgb*g_colors[3].w;

  //
  // desaturate on back-facing: color level:
  v.vViewer.w = step(0, dot(v.vViewer.xyz, v.vNormal.xyz));
  sOut.color0.rgb = lerp(dot(sOut.color0.rgb, float3(0.3, 0.59, 0.11)), sOut.color0.rgb, 
                          saturate(g_faders.x + v.vViewer.w));
  //
  // add transparency:
  sOut.color0.a = g_colors[1].a*lerp(1, vertColor.a, g_colorBlend.a)*
			saturate(g_faders.y + v.vViewer.w);//fade on back-facing
  sOut.color1 = float4(g_colors[2].rgb, g_colors[2].a);
  return sOut;
}

