1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
| //loy toon bxdf float3 ToonStep(float feather, float halfLambert, float threshold = 0.5f) { return smoothstep(threshold - feather, threshold + feather, halfLambert); }
FDirectLighting ToonBxDF(FGBufferData GBuffer, half3 N, half3 V, half3 L, float Falloff, float NoL, FAreaLight AreaLight, FShadowTerms Shadow) { #if GBUFFER_HAS_TANGENT half3 X = GBuffer.WorldTangent; half3 Y = normalize(cross(N, X)); #else half3 X = 0; half3 Y = 0; #endif BxDFContext Context; Init(Context, N, X, Y, V, L); SphereMaxNoH(Context, AreaLight.SphereSinAlpha, true); Context.NoV = saturate(abs(Context.NoV) + 1e-5); float SpecularOffset = 0.5; float SpecularRange = GBuffer.CustomData.x; float3 ShadowColor = 0; ShadowColor = GBuffer.DiffuseColor * ShadowColor; float offset = GBuffer.CustomData.y; float SoftScatterStrength = 0; offset = offset * 2 - 1; half3 H = normalize(V + L); float NoH = saturate(dot(N, H)); NoL = (dot(N, L) + 1) / 2; // overwrite NoL to get more range out of it half NoLOffset = saturate(NoL + offset); FDirectLighting Lighting; Lighting.Diffuse = AreaLight.FalloffColor * (smoothstep(0, 1, NoLOffset) * Falloff) * Diffuse_Lambert(GBuffer.DiffuseColor) * 2.2; float InScatter = pow(saturate(dot(L, -V)), 12) * lerp(3, .1f, 1); float NormalContribution = saturate(dot(N, H)); float BackScatter = GBuffer.GBufferAO * NormalContribution / (PI * 2); Lighting.Specular = ToonStep(SpecularRange, (saturate(D_GGX(SpecularOffset, NoH)))) * (AreaLight.FalloffColor * GBuffer.SpecularColor * Falloff * 8); float3 TransmissionSoft = AreaLight.FalloffColor * (Falloff * lerp(BackScatter, 1, InScatter)) * ShadowColor * SoftScatterStrength; float3 ShadowLightener = (saturate(smoothstep(0, 1, saturate(1 - NoLOffset))) * ShadowColor * 0.1); Lighting.Transmission = (ShadowLightener + TransmissionSoft) * Falloff; return Lighting; }
FDirectLighting IntegrateBxDF( FGBufferData GBuffer, half3 N, half3 V, half3 L, float Falloff, half NoL, FAreaLight AreaLight, FShadowTerms Shadow ) { switch( GBuffer.ShadingModelID ) { case SHADINGMODELID_DEFAULT_LIT: case SHADINGMODELID_SINGLELAYERWATER: case SHADINGMODELID_THIN_TRANSLUCENT: return DefaultLitBxDF( GBuffer, N, V, L, Falloff, NoL, AreaLight, Shadow ); case SHADINGMODELID_SUBSURFACE: return SubsurfaceBxDF( GBuffer, N, V, L, Falloff, NoL, AreaLight, Shadow ); case SHADINGMODELID_PREINTEGRATED_SKIN: return PreintegratedSkinBxDF( GBuffer, N, V, L, Falloff, NoL, AreaLight, Shadow ); case SHADINGMODELID_CLEAR_COAT: return ClearCoatBxDF( GBuffer, N, V, L, Falloff, NoL, AreaLight, Shadow ); case SHADINGMODELID_SUBSURFACE_PROFILE: return SubsurfaceProfileBxDF( GBuffer, N, V, L, Falloff, NoL, AreaLight, Shadow ); case SHADINGMODELID_TWOSIDED_FOLIAGE: return TwoSidedBxDF( GBuffer, N, V, L, Falloff, NoL, AreaLight, Shadow ); case SHADINGMODELID_HAIR: return HairBxDF( GBuffer, N, V, L, Falloff, NoL, AreaLight, Shadow ); case SHADINGMODELID_CLOTH: return ClothBxDF( GBuffer, N, V, L, Falloff, NoL, AreaLight, Shadow ); case SHADINGMODELID_EYE: return EyeBxDF( GBuffer, N, V, L, Falloff, NoL, AreaLight, Shadow ); case SHADINGMODELID_TOON: return ToonBxDF( GBuffer, N, V, L, Falloff, NoL, AreaLight, Shadow ); default: return (FDirectLighting)0; } }
|