forked from cocos/cocos-engine
-
Notifications
You must be signed in to change notification settings - Fork 1
/
shading-standard.chunk
169 lines (139 loc) · 5.25 KB
/
shading-standard.chunk
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
// Copyright (c) 2017-2020 Xiamen Yaji Software Co., Ltd.
// reference: 'moving frostbite to pbr' & UE4 BRDF.usf
#include <cc-global>
#include <cc-shadow>
#if CC_USE_IBL
#include <cc-environment>
#include <unpack>
#include <texture-lod>
#endif
#if USE_LIGHTMAP && !USE_BATCHING && !CC_FORWARD_ADD
#include <lightingmap-fs>
#endif
#include <common>
#include <gamma>
float GGXMobile (float roughness, float NoH, vec3 H, vec3 N) {
vec3 NxH = cross(N, H);
float OneMinusNoHSqr = dot(NxH, NxH);
float a = roughness * roughness;
float n = NoH * a;
float p = a / (OneMinusNoHSqr + n * n);
return p * p;
}
float CalcSpecular (float roughness, float NoH, vec3 H, vec3 N) {
return (roughness*0.25 + 0.25) * GGXMobile(roughness, NoH, H, N);
}
vec3 BRDFApprox (vec3 specular, float roughness, float NoV) {
const vec4 c0 = vec4(-1.0, -0.0275, -0.572, 0.022);
const vec4 c1 = vec4(1.0, 0.0425, 1.04, -0.04);
vec4 r = roughness * c0 + c1;
float a004 = min( r.x * r.x, exp2( -9.28 * NoV ) ) * r.x + r.y;
vec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;
AB.y *= clamp(50.0 * specular.g, 0.0, 1.0);
return specular * AB.x + AB.y;
}
struct StandardSurface {
// albedo
vec4 albedo;
// these two need to be in the same coordinate system
vec3 position;
vec3 normal;
// emissive
vec3 emissive;
// PBR params
float roughness;
float metallic;
float occlusion;
};
#if CC_FORWARD_ADD
#include <lighting>
vec4 CCStandardShading (StandardSurface s) {
// Calculate diffuse & specular
vec3 diffuse = s.albedo.rgb * (1.0 - s.metallic);
vec3 specular = mix(vec3(0.04), s.albedo.rgb, s.metallic);
vec3 diffuseContrib = diffuse / PI;
vec3 N = normalize(s.normal);
vec3 V = normalize(cc_cameraPos.xyz - s.position);
float NV = max(abs(dot(N, V)), 0.001);
specular = BRDFApprox(specular, s.roughness, NV);
vec3 finalColor = vec3(0.0);
for (int i = 0; i < LIGHTS_PER_PASS; i++) {
vec3 SLU = cc_lightPos[i].xyz - s.position;
vec3 SL = normalize(SLU);
vec3 SH = normalize(SL + V);
float SNL = max(dot(N, SL), 0.001);
float SNH = max(dot(N, SH), 0.0);
float distSqr = dot(SLU, SLU);
float litRadius = cc_lightSizeRangeAngle[i].x;
float litRadiusSqr = litRadius * litRadius;
float illum = PI * (litRadiusSqr / max(litRadiusSqr , distSqr));
float attRadiusSqrInv = 1.0 / max(cc_lightSizeRangeAngle[i].y, 0.01);
attRadiusSqrInv *= attRadiusSqrInv;
float att = GetDistAtt(distSqr, attRadiusSqrInv);
vec3 lspec = specular * CalcSpecular(s.roughness, SNH, SH, N);
if (cc_lightPos[i].w > 0.0) {
float cosInner = max(dot(-cc_lightDir[i].xyz, SL), 0.01);
float cosOuter = cc_lightSizeRangeAngle[i].z;
float litAngleScale = 1.0 / max(0.001, cosInner - cosOuter);
float litAngleOffset = -cosOuter * litAngleScale;
att *= GetAngleAtt(SL, -cc_lightDir[i].xyz, litAngleScale, litAngleOffset);
}
finalColor += SNL * cc_lightColor[i].rgb * cc_lightColor[i].w * illum * att * (diffuseContrib + lspec);
}
finalColor = finalColor * s.occlusion;
return vec4(finalColor, 0.0);
}
#else
#if CC_RECEIVE_SHADOW
#include <cc-shadow-map-fs>
#endif
vec4 CCStandardShading (StandardSurface s) {
// Calculate diffuse & specular
vec3 diffuse = s.albedo.rgb * (1.0 - s.metallic);
vec3 specular = mix(vec3(0.04), s.albedo.rgb, s.metallic);
vec3 N = normalize(s.normal);
vec3 V = normalize(cc_cameraPos.xyz - s.position);
float NV = max(abs(dot(N, V)), 0.001);
specular = BRDFApprox(specular, s.roughness, NV);
vec3 L = normalize(-cc_mainLitDir.xyz);
vec3 H = normalize(L+V);
float NH = max(dot(N, H), 0.0);
float NL = max(dot(N, L), 0.001);
vec3 finalColor = NL * cc_mainLitColor.rgb * cc_mainLitColor.w;
#if USE_LIGHTMAP && !USE_BATCHING && !CC_FORWARD_ADD
vec4 lightmap = texture(cc_lightingMap, v_luv);
finalColor = lightmap.a * lightmap.rgb + (1.0 - lightmap.a) * finalColor;
#endif
vec3 diffuseContrib = diffuse / PI;
// Cook-Torrance Microfacet Specular BRDF
vec3 specularContrib = specular * CalcSpecular(s.roughness, NH, H, N);
finalColor *= (diffuseContrib + specularContrib);
float fAmb = 0.5 - N.y * 0.5;
vec3 ambDiff = mix(cc_ambientSky.rgb, cc_ambientGround.rgb, fAmb) * cc_ambientSky.w;
finalColor += (ambDiff.rgb * diffuse);
#if CC_USE_IBL
vec3 R = normalize(reflect(-V, N));
vec4 envmap = fragTextureLod(cc_environment, R, s.roughness * cc_ambientGround.w);
#if CC_USE_IBL == IBL_RGBE
vec3 env = unpackRGBE(envmap);
#else
vec3 env = SRGBToLinear(envmap.rgb);
#endif
finalColor += env * cc_ambientSky.w * specular;
#endif
finalColor = finalColor * s.occlusion;
#if CC_USE_HDR
s.emissive *= cc_exposure.w;
#endif
finalColor += s.emissive;
#if CC_RECEIVE_SHADOW
vec4 shadow = vec4(1.0);
float pcf = cc_shadowPCF.x + 0.001;
if (pcf > 2.0) {shadow = CCGetShadowFactorX9();}
if (2.0 > pcf && pcf > 1.0) {shadow = CCGetShadowFactorX5();}
if (1.0 > pcf && pcf > 0.0) {shadow = CCGetShadowFactorX1();}
finalColor = shadow.rgb * shadow.a + finalColor * (1.0 - shadow.a);
#endif
return vec4(finalColor, s.albedo.a);
}
#endif