// =========================================================
// Highpoly Nagisa Ver.4.0 - Custom SSS Skin Shader
// Branchless SSS Injection for DOAXVV
// =========================================================

cbuffer vector_register_block : register(b0)
{
  float4 gSkinSweatParameter : packoffset(c0);
  float4 gSkinSweatDropSpecularColor : packoffset(c1);
  float4 gSkinSweatDropIblSpecularColor : packoffset(c2);
  float4 gSkinSweatMaterialParameter : packoffset(c3);
  float4 gSkinSuntanColor : packoffset(c4);
  float4 gTranslucencyLightParam : packoffset(c5);
  float4 gWetLightColor : packoffset(c6);
  float4 gWetLightDir : packoffset(c7);
  float4 gSkinFlushParam : packoffset(c8);
}

cbuffer ps_default_cb : register(b2)
{
  float4 gHDRRate : packoffset(c0);
  float4 gAlphaParam : packoffset(c1);
  float4 gTexBlendAlpha[2] : packoffset(c2);
  float4 gTexBlendScaleBias[2] : packoffset(c4);
  float4 gNormalTexBlendAlpha : packoffset(c6);
  float4 gNormalTexBlendScaleBias : packoffset(c7);
  float4 gShadowCsBias : packoffset(c8);
  float4 gIDandFresnel : packoffset(c9);
  float4 gReflectionColor : packoffset(c10);
  float4 gReflectionVisibilityParam : packoffset(c11);
  float4 gEyePosition : packoffset(c12);
  float4 gEyePlane : packoffset(c13);
  float4 gIblDiffuseColor : packoffset(c14);
  float4 gIblSpecularColor : packoffset(c15);
  float4 gVelvetyRimParam : packoffset(c16);
  float4 gSpecularColor : packoffset(c17);
  float4 gSpecularVisibilityParam : packoffset(c18);
  float4 gVelvetyColor : packoffset(c19);
  float4 gRimColor : packoffset(c20);
  float4 gLScatterHighFreq : packoffset(c21);
  float4 gMaterialMulColor : packoffset(c22);
  float4 gMaterialAddColor : packoffset(c23);
  float4 gMaterialParam : packoffset(c24);
  float4 gMaterialParam2 : packoffset(c25);
}

SamplerState gTextureSampler0_SamplerState_s : register(s0);
SamplerState gTextureSampler1_SamplerState_s : register(s1);
SamplerState gTextureSampler2_SamplerState_s : register(s2);
SamplerState gTextureSampler3_SamplerState_s : register(s3);
SamplerState gSuntanTextureSampler_SamplerState_s : register(s10);
Texture2D<float4> gTextureSampler0_Texture : register(t0);
Texture2D<float4> gTextureSampler1_Texture : register(t1);
Texture3D<float4> gTextureSampler2_Texture : register(t2);
Texture2D<float4> gTextureSampler3_Texture : register(t3);
Texture2D<float4> gSuntanTextureSampler_Texture : register(t10);

// --- Custom SSS Texture Binding ---
Texture2D<float4> gSssTexture : register(t100);

// 3Dmigoto declarations
#define cmp -
Texture1D<float4> IniParams : register(t120);

void main(
  float4 v0 : SV_Position0,
  linear centroid float4 v1 : COLOR1,
  linear centroid float3 v2 : COLOR0,
  linear centroid float4 v3 : TEXCOORD0,
  linear centroid float4 v4 : TEXCOORD1,
  float4 v5 : TEXCOORD2,
  linear centroid float4 v6 : TEXCOORD3,
  linear centroid float4 v7 : TEXCOORD4,
  linear centroid float4 v8 : TEXCOORD5,
  uint v9 : SV_IsFrontFace0,
  out float4 o0 : SV_Target0,
  out float4 o1 : SV_Target1,
  out float4 o2 : SV_Target2,
  out float4 o3 : SV_Target3,
  out float4 o4 : SV_Target4)
{
  float4 r0,r1,r2,r3;
  uint4 bitmask, uiDest;
  float4 fDest;

  // Default Engine Setup
  r0.x = gSuntanTextureSampler_Texture.Sample(gSuntanTextureSampler_SamplerState_s, v4.zw).x;
  r0.x = -r0.x * gSkinSweatMaterialParameter.z + 1;
  r0.yzw = r0.xxx * gSkinSuntanColor.xyz + -gSkinSuntanColor.xyz;
  r0.x = 1 + -r0.x;
  r1.xyz = gSkinSuntanColor.xyz * r0.xxx;
  r1.xyz = r1.xyz * float3(0.5,0.5,0.5) + float3(1,1,1);
  r0.xyz = float3(1,1,1) + r0.yzw;
  r0.w = gSkinSweatDropSpecularColor.z * gSkinSweatParameter.x;
  r2.xyzw = gTextureSampler1_Texture.Sample(gTextureSampler1_SamplerState_s, v3.zw).xyzw;
  r2.xyz = float3(1,1,1) + -r2.xyz;
  o4.w = gSkinSweatParameter.x * r2.w;
  r2.xyz = -r2.xyz * r0.www + float3(1,1,1);
  r3.xyzw = gTextureSampler0_Texture.Sample(gTextureSampler0_SamplerState_s, v3.xy).xyzw;
  r2.xyz = r3.xyz * r2.xyz;
  o2.w = r3.w;
  r0.xyz = r2.xyz * r0.xyz;
  r0.xyz = log2(r0.xyz);
  r0.xyz = r1.xyz * r0.xyz;
  r0.xyz = exp2(r0.xyz);
  r1.xyzw = gTextureSampler3_Texture.Sample(gTextureSampler3_SamplerState_s, v4.zw).xyzw;
  r2.xyz = gSkinFlushParam.xyz * r1.www;
  o2.xyz = r1.xyz;
  r1.xyz = r2.xyz * gSkinSweatMaterialParameter.www + float3(1,1,1);
  r0.xyz = r1.xyz * r0.xyz;
  r0.xyz = r0.xyz * gMaterialMulColor.xyz + gMaterialAddColor.xyz;

  float3 baseColor = v2.xyz * r0.xyz;
  o0.xyz = baseColor;
  r0.x = v9.x ? 1 : -1;
  o0.w = saturate(v1.w * r0.x);
  r0.xyz = v8.xyz * r0.xxx;
  r1.xy = v4.xy;
  r1.z = gSkinSweatParameter.z;
  r1.xyz = gTextureSampler2_Texture.Sample(gTextureSampler2_SamplerState_s, r1.xyz).xyz;
  r1.xyz = r1.xyz * float3(2,2,2) + float3(-1,-1,-1);
  r2.xyz = v7.xyz * r1.yyy;
  r1.xyw = r1.xxx * v6.xyz + r2.xyz;
  r1.xyz = r1.zzz * r0.xyz + r1.xyw;
  r0.w = cmp(gMaterialParam2.y != 0.000000);
  r1.xyz = r0.www ? -r1.xyz : r1.xyz;
  r0.w = dot(r1.xyz, r1.xyz);
  r0.w = rsqrt(r0.w);

  // Engine View-Space Normal Generation
  o1.xyz = r1.xyz * r0.w;
  o1.w = gShadowCsBias.z;

  // =========================================================
  // --- Highpoly Nagisa SSS Injection Core ---
  
  // 1. SSS Map & Alpha Mask Extraction
  float4 sssData = gSssTexture.Sample(gTextureSampler0_SamplerState_s, v3.xy);
  float3 sssColor = sssData.xyz; 
  float sssMask = sssData.w;

  // 2. Mipmapped Shadow Term Calculation
  float3 smoothAlbedo = gTextureSampler0_Texture.SampleLevel(gTextureSampler0_SamplerState_s, v3.xy, 3.0).xyz;
  float3 smoothBaseColor = v2.xyz * smoothAlbedo;
  float smoothBrightness = dot(smoothBaseColor, float3(0.299, 0.587, 0.114));
  float shadowTerm = smoothstep(0.30, 0.52, smoothBrightness) * (1.0 - smoothstep(0.58, 0.82, smoothBrightness));

  // 3. View Term (Rim Mask)
  float NdotV = saturate(abs(o1.z)); 
  float viewTerm = pow(1.0 - NdotV, 3.0); 

  // 4. Edge Mask & Raw Intensity
  float edgeMask = lerp(0.025, 1.0, viewTerm); 
  float rawIntensity = saturate((shadowTerm * edgeMask) + (viewTerm * 0.28));

  // 5. Scattering Profile (Cold-Milk Pink)
  float3 scatterProfile = float3(1.00, 0.80, 0.92); 

  // 6. Wavelength Dispersion (Decay curve)
  float3 dispersionalIntensity = float3(
      pow(rawIntensity, 1.0),
      pow(rawIntensity, 1.1), 
      pow(rawIntensity, 1.15)  
  );

  // 7. Final Scatter & Base Bleed Synthesis
  float3 finalScatter = sssColor * dispersionalIntensity * scatterProfile * 1.2;
  float3 pinkBase = baseColor * (float3(1.0, 1.0, 1.0) + sssColor * shadowTerm * 0.20);

  // 8. Final Compositing (Masked Alpha Blend)
  o0.xyz = saturate((pinkBase + finalScatter) * sssMask + baseColor * (1.0 - sssMask));

  // =========================================================

  // Fresnel & Output Configuration
  o3.xyz = gIDandFresnel.xyw;
  o3.w = gMaterialMulColor.w;
  r1.xy = v4.xy;
  r1.z = gSkinSweatParameter.w;
  r1.xyz = gTextureSampler2_Texture.Sample(gTextureSampler2_SamplerState_s, r1.xyz).xyz;
  r1.xyz = r1.xyz * float3(2,2,2) + float3(-1,-1,-1);
  r2.xyz = v7.xyz * r1.yyy;
  r1.xyw = r1.xxx * v6.xyz + r2.xyz;
  r0.xyz = r1.zzz * r0.xyz + r1.xyw;
  r0.w = dot(r0.xyz, r0.xyz);
  r0.w = rsqrt(r0.w);
  o4.xyz = r0.xyz * r0.w;
  
  return;
}