SHOW:
|
|
- or go back to the newest paste.
1 | analytic | |
2 | ||
3 | ::begin parameters | |
4 | color Diffuse 1 0 0 | |
5 | color Specular 1 1 1 | |
6 | float DiffuseScale 0 1 0.5 | |
7 | float SpecularScale 0 1 .028 | |
8 | float Roughness 0.00005 2 0.2 | |
9 | float Roughness2 0.00005 2 0.2 | |
10 | float Retroreflective 0 1 0 | |
11 | bool FullFresnel 0 1 0 | |
12 | bool isotropic 1 | |
13 | ::end parameters | |
14 | ||
15 | ::begin shader | |
16 | ||
17 | //Thanks to Chris_F for starting ideas. | |
18 | // Cook-Torrance, GGX distribution (bastardised with ashikhman shirley), Smith geometry, qualitative Oren-Nayar diffuse. | |
19 | ||
20 | float saturate(float x) { return clamp(x,0,1); } | |
21 | ||
22 | vec3 Fresnel(float CosTheta, vec3 Ks) | |
23 | { | |
24 | CosTheta = min(CosTheta, 0.99999999999999999); | |
25 | vec3 n2 = (1.0 + sqrt(Ks)) / (1.0 - sqrt(Ks)); | |
26 | vec3 SinTheta = vec3(sqrt(1 - CosTheta * CosTheta)); | |
27 | ||
28 | vec3 SinThetaT = SinTheta / n2; | |
29 | vec3 CosThetaT = sqrt(1 - SinThetaT * SinThetaT); | |
30 | ||
31 | vec3 n2CosThetaT = n2 * CosThetaT; | |
32 | vec3 n2CosTheta = n2 * CosTheta; | |
33 | ||
34 | vec3 RsSqrt = (CosTheta - n2CosThetaT) / (CosTheta + n2CosThetaT); | |
35 | vec3 Rs = RsSqrt * RsSqrt; | |
36 | ||
37 | vec3 RpSqrt = (n2CosTheta - CosThetaT) / (n2CosTheta + CosThetaT); | |
38 | vec3 Rp = RpSqrt * RpSqrt; | |
39 | ||
40 | return (Rs + Rp) / 2; | |
41 | } | |
42 | ||
43 | vec3 BRDF( vec3 L, vec3 V, vec3 N, vec3 X, vec3 Y ) | |
44 | { | |
45 | //vec3 temp = L; L = V; V = temp; | |
46 | float PI = 3.14159265358979323846; | |
47 | vec3 Kd = Diffuse * DiffuseScale; | |
48 | vec3 Ks = Specular * SpecularScale; | |
49 | ||
50 | vec3 H = normalize(L + V); | |
51 | float NdotL = clamp(dot(N, L), 0, 1); | |
52 | float NdotV = dot(N, V); | |
53 | float NdotH = dot(N, H); | |
54 | float LdotV = dot(L, V); | |
55 | float VdotH = dot(V, H); | |
56 | float LdotH = dot(L, H); | |
57 | float HdotX = dot(H,X); | |
58 | float HdotY = dot(H,Y); | |
59 | ||
60 | float m1 = 1/Roughness; | |
61 | float m2 = 1/Roughness2; | |
62 | float M = isotropic ? Roughness : (1-(NdotH*NdotH)) / ( m1*HdotX*HdotX + m2*HdotY*HdotY ); | |
63 | float M_2 = isotropic ? M * M : M* min(Roughness, Roughness2); | |
64 | ||
65 | NdotH = mix( mix( NdotH, max(NdotH,LdotV), saturate(Retroreflective*2) ), LdotV, saturate(Retroreflective*2-1) ); | |
66 | ||
67 | float NdotL_2 = NdotL * NdotL; | |
68 | float NdotV_2 = NdotV * NdotV; | |
69 | float NdotH_2 = NdotH * NdotH; | |
70 | float OneMinusNdotL_2 = 1.0 - NdotL_2; | |
71 | float OneMinusNdotV_2 = 1.0 - NdotV_2; | |
72 | ||
73 | vec3 Fd = 1.0 - Ks; | |
74 | ||
75 | float gamma = clamp(dot(V - N * NdotV, L - N * NdotL), 0, 1); | |
76 | float A = 1.0 - 0.5 * (M_2 / (M_2 + 0.33)); | |
77 | float B = 0.45 * (M_2 / (M_2 + 0.09)); | |
78 | float C = sqrt(OneMinusNdotL_2 * OneMinusNdotV_2) / max(NdotL, NdotV); | |
79 | ||
80 | vec3 Rd = Kd * Fd * (A + B * gamma * C) * 1/PI; | |
81 | ||
82 | float ggxDenom = NdotH_2 * (M_2 + (1-NdotH_2)/NdotH_2); | |
83 | float D = M/ggxDenom; | |
84 | D = D*D/PI; | |
85 | D *= isotropic ? 1 : min(m1,m2)/max(m1,m2); | |
86 | ||
87 | vec3 Fs; | |
88 | if( FullFresnel ) | |
89 | Fs = Fresnel(NdotV, Ks); | |
90 | else | |
91 | Fs = Ks + Fd * pow(1-LdotH, 5); | |
92 | ||
93 | float G1_1 = 1.0 + sqrt(1.0 + M_2 * (OneMinusNdotL_2 / NdotL_2)); | |
94 | float G1_2 = 1.0 + sqrt(1.0 + M_2 * (OneMinusNdotV_2 / NdotV_2)); | |
95 | float G = ((2/G1_1) * (2/G1_2))/(4 * NdotV * NdotL); | |
96 | ||
97 | vec3 Rs = Fs * D * G; | |
98 | ||
99 | return vec3(Rd + Rs); | |
100 | } | |
101 | ||
102 | ::end shader |