Untitled

 avatar
unknown
glsl
a year ago
6.8 kB
6
Indexable
#define BUMP_2_CHANNEL 1

#define PI 3.141592654f

#define CASCADES 4

struct V_OUT
{
    float4 Position : SV_Position;
    float2 UV : TEXCOORD0;
    float3 Normal : NORMAL;    
    float3 Tangent : TANGENT;
    float3 Binormal : BINORMAL;

    float3 ViewDirection : TEXCOORD1;
    float ViewDepth : TEXCOORD2;

    float4 ShadowMapCoords[CASCADES] : TEXCOORD3;
};

struct DirectionalLight
{
    float3 AmbientColor;
    float p1;

    float3 LightDirection;
    float p2;

    float3 LightColor;
    float SpecularPower;
};
ConstantBuffer<DirectionalLight> DirLightCB : register(b3);

struct ShadowMapPixel
{
    float4 CascadeDistances; // Max 4 cascades
    
    float Bias;
    float ShadowWidthPercent;
    float2 TexelSize;

    float PCFSampleCount;
    float PCFSampleRange;
    float CascadeCount;
    float p;

    float4 PoissonDisc[16];
};
ConstantBuffer<ShadowMapPixel> ShadowPixelCB : register(b5);

struct MaterialProperties
{
    float3 BaseColorFactor;
    float Roughness;    

    float AlphaCutoff;
    float IOR;
    float Dispersion;
    float Metallic; // Unused until fixed
};
ConstantBuffer<MaterialProperties> MatPropCB : register(b1);

Texture2D g_texture : register(t0);
Texture2D g_normalMap : register(t1);
Texture2D g_specularMap : register(t2);
TextureCube g_irradiance : register(t3);
TextureCube g_envMap : register(t4);
Texture2D g_blueNoise : register(t5);

Texture2D g_shadowMap : register(t6);

SamplerState g_sampler : register(s0);

float D_GGX(float NdH, float roughness);
float3 F_Schlick(float cosTheta, float3 F0);
float G_Smith(float NdL, float NdV, float roughness);
float G_Smith_IBL(float NdL, float NdV, float roughness);

float4 main(V_OUT input) : SV_Target
{    
    float blueNoise = saturate(g_blueNoise.Sample(g_sampler, input.UV).r);

    float4 cascadeComparison = (input.ViewDepth > ShadowPixelCB.CascadeDistances);

    float fCascadeIndex = dot(float4(ShadowPixelCB.CascadeCount > 0, ShadowPixelCB.CascadeCount > 1, ShadowPixelCB.CascadeCount > 2, ShadowPixelCB.CascadeCount > 3), cascadeComparison);
    fCascadeIndex = min(fCascadeIndex, CASCADES); // Why?
    int iCascadeIndex = (int)fCascadeIndex - 1;    

    float3 shadowCoords = input.ShadowMapCoords[iCascadeIndex];
    shadowCoords.y = 1 - shadowCoords.y;
    shadowCoords.x = ShadowPixelCB.ShadowWidthPercent * (shadowCoords.x + iCascadeIndex);
    float pixelDepth = shadowCoords.z + ShadowPixelCB.Bias;    

    float test = g_shadowMap.Sample(g_sampler, shadowCoords.xy).r;
    //return float4(test, test, test, 1);

    float shadowFactor = 0;
    int i = 0;
    for (float y = -ShadowPixelCB.PCFSampleRange; y <= ShadowPixelCB.PCFSampleRange; y++)
        for (float x = -ShadowPixelCB.PCFSampleRange; x <= ShadowPixelCB.PCFSampleRange; x++)
        {
            int poissonIndex = (i * blueNoise * ShadowPixelCB.PCFSampleCount) % ShadowPixelCB.PCFSampleCount;
            float2 coord = shadowCoords.xy + (float2(x, y) * ShadowPixelCB.PoissonDisc[poissonIndex].xy) * ShadowPixelCB.TexelSize;
            float shadowMapDepth = g_shadowMap.Sample(g_sampler, coord).r;

            //return float4(shadowMapDepth, shadowMapDepth, shadowMapDepth * (fCascadeIndex / CASCADES), 1);

            shadowFactor += pixelDepth < shadowMapDepth;   
            i++;
        }
    shadowFactor /= i;        

    float4 tex = g_texture.Sample(g_sampler, input.UV);          

    if (tex.a < MatPropCB.AlphaCutoff)
        discard;    

    tex.rgb = pow(tex.rgb, 2.2f);

#if BUMP_2_CHANNEL
    float2 bump = g_normalMap.Sample(g_sampler, input.UV).rg;

    float3 normalTangentSpace;
    normalTangentSpace.xy = bump * 2.0f - 1.0f;
    normalTangentSpace.z = sqrt(1.0f - dot(normalTangentSpace.xy, normalTangentSpace.xy));
#else
    float3 normalTangentSpace = g_normalMap.Sample(g_sampler, input.UV).rgb;
    normalTangentSpace.xyz = normalTangentSpace.xyz * 2.0f - 1.0f;
#endif    

    float3 occlusionRoughnessMetallic = g_specularMap.Sample(g_sampler, input.UV).rgb;    
    float roughness = occlusionRoughnessMetallic.g * MatPropCB.Roughness;
    float metalness = occlusionRoughnessMetallic.b * MatPropCB.Metallic;

    float3 N = normalize(normalTangentSpace.x * input.Tangent + normalTangentSpace.y * input.Binormal + normalTangentSpace.z * input.Normal);    
    float3 L = normalize(DirLightCB.LightDirection);
    float3 V = normalize(input.ViewDirection);
    float3 H = normalize(-L + V);
    float3 R = reflect(-V, N);

    float NdL = saturate(dot(N, -L)) * shadowFactor;     
    float NdV = saturate(dot(N, V));
    float HdV = saturate(dot(H, V));
    float NdH = saturate(dot(N, H));
    float HdL = saturate(dot(H, -L));   

    float envMapMipLevels = 12;

    float3 irradiance = g_irradiance.SampleLevel(g_sampler, N, 0).rgb;   

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

    float3 albedo = tex.rgb * MatPropCB.BaseColorFactor;
    float3 F0 = lerp(0.04f, albedo, metalness);

    float D = D_GGX(NdH, roughness);    
    float3 F = F_Schlick(HdV, F0);
    float G = G_Smith(NdL, NdV, roughness);

    float kS = max(0, F);
    float kD = (1.0f - kS);

    float3 envReflections = g_envMap.SampleLevel(g_sampler, R, roughness * envMapMipLevels).rgb;
    envReflections *= kS * (1 - roughness) * metalness;    

    float3 specularDFG = (D * F * G) / max(0.001f, 4.0f * NdV);
    float3 specular = specularDFG * DirLightCB.LightColor * kS;    
    
    float3 diffuse = irradiance * kD * albedo * DirLightCB.LightColor * NdL;  
    diffuse *= 1 - metalness;    

    float3 ambient = irradiance * kD * albedo * DirLightCB.AmbientColor; 

    float3 Lo = diffuse + specular + ambient + envReflections;

    Lo = pow(Lo, 1.0f / 2.2f);    
    return float4(Lo, tex.a);
}

float D_GGX(float NdH, float roughness)
{
    float a = roughness * roughness;
    float a2 = a * a;
    float denominator = (NdH * NdH * (a2 - 1.0f) + 1.0f);
    return a2 / max(0.001f, PI * denominator * denominator);
}

// 5 is the sharpness, can be modified
float3 F_Schlick(float cosTheta, float3 F0)
{
    return F0 + (1.0f - F0) * pow(1.0f - cosTheta, 5.0f);
}

float G_Smith(float NdL, float NdV, float roughness)
{
    float r = roughness + 1;
    float k = (r * r) / 8.0f;
    
    float ggxL = NdL / (NdL * (1.0f - k) + k);
    float ggxV = NdV / (NdV * (1.0f - k) + k);

    return ggxL * ggxV;
}

float G_Smith_IBL(float NdL, float NdV, float roughness)
{
    float r = roughness;
    float k = (r * r) / 2.0f;
    
    float ggxL = NdL / (NdL * (1.0f - k) + k);
    float ggxV = NdV / (NdV * (1.0f - k) + k);

    return ggxL * ggxV;
}
Editor is loading...
Leave a Comment