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
|
#ifndef __BRDF_INC
#define __BRDF_INC
#include "pbr.cginc"
#include "lighting.cginc"
#include "lysenko.cginc"
#include "math.cginc"
// Schlick "An Inexpensive BRDF Model for Physically-based Rendering".
// Equation 24.
// f0: Reflectance at normal incidence. Typically around 0.04.
// f90: Reflectance at grazing incidence. Typically around 1.0.
float F_Schlick(float LoH, float f0, float f90) {
float term = 1.0f - LoH;
float term2 = term * term;
float term5 = term2 * term2 * term;
return f0 + (f90 - f0) * term5;
}
float4 brdf(Pbr pbr, LightData data) {
float3 specular = 0;
float3 diffuse = 0;
// Direct
if (true) {
float F = F_Schlick(data.direct.LoH, 0.04f, 1.0f);
float D = D_GGX(pbr.roughness, data.direct.NoH, data.direct.H);
float V = V_SmithGGXCorrelated_Fast(pbr.roughness, data.common.NoV, data.direct.NoL);
float denom = 4.0f * data.common.NoV * data.direct.NoL;
float FDV = denom > _BRDF_Specular_Min_Denom ? F * D * V / denom : 0.0f;
specular += FDV * data.direct.color * data.direct.NoL;
float Fd = Fd_OrenNayar(pbr.roughness, data.common.NoV, data.direct.NoL, data.direct.LoV);
float3 remainder = (1.0f - F);
diffuse += (Fd / PI) * remainder * pbr.albedo.xyz * data.direct.color;
remainder *= (1.0f - (Fd / PI) * pbr.albedo);
}
// Indirect
if (true) {
float F = F_Schlick(data.indirect.LoH, 0.04f, 1.0f);
specular += F * data.indirect.specular;
float Fd = 1.0f; // Lambertian divide is baked into SH
float3 remainder = (1.0f - F);
diffuse += Fd * remainder * pbr.albedo.xyz * data.indirect.diffuse;
remainder *= (1.0f - Fd * pbr.albedo);
}
return float4(diffuse + specular, 1);
}
#endif // __BRDF_INC
|