forked from BabylonJS/Babylon.js
-
Notifications
You must be signed in to change notification settings - Fork 0
/
pbrHelperFunctions.fx
118 lines (102 loc) · 5.44 KB
/
pbrHelperFunctions.fx
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
// AlphaG epsilon to avoid numerical issues
#define MINIMUMVARIANCE 0.0005
float convertRoughnessToAverageSlope(float roughness)
{
// Calculate AlphaG as square of roughness (add epsilon to avoid numerical issues)
return square(roughness) + MINIMUMVARIANCE;
}
float fresnelGrazingReflectance(float reflectance0) {
// For typical incident reflectance range (between 4% to 100%) set the grazing reflectance to 100% for typical fresnel effect.
// For very low reflectance range on highly diffuse objects (below 4%), incrementally reduce grazing reflecance to 0%.
float reflectance90 = saturate(reflectance0 * 25.0);
return reflectance90;
}
vec2 getAARoughnessFactors(vec3 normalVector) {
#ifdef SPECULARAA
vec3 nDfdx = dFdx(normalVector.xyz);
vec3 nDfdy = dFdy(normalVector.xyz);
float slopeSquare = max(dot(nDfdx, nDfdx), dot(nDfdy, nDfdy));
// Vive analytical lights roughness factor.
float geometricRoughnessFactor = pow(saturate(slopeSquare), 0.333);
// Adapt linear roughness (alphaG) to geometric curvature of the current pixel.
float geometricAlphaGFactor = sqrt(slopeSquare);
// BJS factor.
geometricAlphaGFactor *= 0.75;
return vec2(geometricRoughnessFactor, geometricAlphaGFactor);
#else
return vec2(0.);
#endif
}
#ifdef ANISOTROPIC
#ifdef ANISOTROPIC_LEGACY
// Aniso parameter remapping
// https://blog.selfshadow.com/publications/s2017-shading-course/imageworks/s2017_pbs_imageworks_slides_v2.pdf page 24
vec2 getAnisotropicRoughness(float alphaG, float anisotropy) {
float alphaT = max(alphaG * (1.0 + anisotropy), MINIMUMVARIANCE);
float alphaB = max(alphaG * (1.0 - anisotropy), MINIMUMVARIANCE);
return vec2(alphaT, alphaB);
}
// Aniso Bent Normals
// Mc Alley https://www.gdcvault.com/play/1022235/Rendering-the-World-of-Far
vec3 getAnisotropicBentNormals(const vec3 T, const vec3 B, const vec3 N, const vec3 V, float anisotropy, float roughness) {
vec3 anisotropicFrameDirection = anisotropy >= 0.0 ? B : T;
vec3 anisotropicFrameTangent = cross(normalize(anisotropicFrameDirection), V);
vec3 anisotropicFrameNormal = cross(anisotropicFrameTangent, anisotropicFrameDirection);
vec3 anisotropicNormal = normalize(mix(N, anisotropicFrameNormal, abs(anisotropy)));
return anisotropicNormal;
// should we also do http://advances.realtimerendering.com/s2018/Siggraph%202018%20HDRP%20talk_with%20notes.pdf page 80 ?
}
#else
// Aniso parameter remapping GLTF
// https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_materials_anisotropy
vec2 getAnisotropicRoughness(float alphaG, float anisotropy) {
float alphaT = max(mix(alphaG, 1.0, anisotropy * anisotropy), MINIMUMVARIANCE);
float alphaB = max(alphaG, MINIMUMVARIANCE);
return vec2(alphaT, alphaB);
}
vec3 getAnisotropicBentNormals(const vec3 T, const vec3 B, const vec3 N, const vec3 V, float anisotropy, float roughness) {
vec3 bentNormal = cross(B, V);
bentNormal = normalize(cross(bentNormal, B));
// This heuristic can probably be improved upon
float a = square(square(1.0 - anisotropy * (1.0 - roughness)));
bentNormal = normalize(mix(bentNormal, N, a));
return bentNormal;
}
#endif
#endif
#if defined(CLEARCOAT) || defined(SS_REFRACTION)
// From beer lambert law I1/I0 = e −α′lc
// c is considered included in alpha
// https://blog.selfshadow.com/publications/s2017-shading-course/drobot/s2017_pbs_multilayered.pdf page 47
vec3 cocaLambert(vec3 alpha, float distance) {
return exp(-alpha * distance);
}
// where L on a thin constant size layer can be (d * ((NdotLRefract + NdotVRefract) / (NdotLRefract * NdotVRefract))
vec3 cocaLambert(float NdotVRefract, float NdotLRefract, vec3 alpha, float thickness) {
return cocaLambert(alpha, (thickness * ((NdotLRefract + NdotVRefract) / (NdotLRefract * NdotVRefract))));
}
// From beerLambert Solves what alpha should be for a given result at a known distance.
vec3 computeColorAtDistanceInMedia(vec3 color, float distance) {
return -log(color) / distance;
}
vec3 computeClearCoatAbsorption(float NdotVRefract, float NdotLRefract, vec3 clearCoatColor, float clearCoatThickness, float clearCoatIntensity) {
vec3 clearCoatAbsorption = mix(vec3(1.0),
cocaLambert(NdotVRefract, NdotLRefract, clearCoatColor, clearCoatThickness),
clearCoatIntensity);
return clearCoatAbsorption;
}
#endif
// ___________________________________________________________________________________
//
// LEGACY
// ___________________________________________________________________________________
#ifdef MICROSURFACEAUTOMATIC
float computeDefaultMicroSurface(float microSurface, vec3 reflectivityColor)
{
const float kReflectivityNoAlphaWorkflow_SmoothnessMax = 0.95;
float reflectivityLuminance = getLuminance(reflectivityColor);
float reflectivityLuma = sqrt(reflectivityLuminance);
microSurface = reflectivityLuma * kReflectivityNoAlphaWorkflow_SmoothnessMax;
return microSurface;
}
#endif