lighting.shader 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. include = [
  2. "core/shaders/common.shader"
  3. "core/shaders/shadow_map.shader"
  4. ]
  5. bgfx_shaders = {
  6. lighting = {
  7. includes = [ "shadow_mapping" "fog" ]
  8. code = """
  9. #if !defined(NO_LIGHT)
  10. # define LIGHT_SIZE 22 // In vec4 units.
  11. # define MAX_NUM_LIGHTS 32
  12. # define MAX_NUM_CASCADES 4
  13. uniform vec4 u_lights_num; // num_dir, num_omni, num_spot
  14. SAMPLER2D(u_lights_data, 12); // dir_0, .., dir_n-1, omni_0, .., omni_n-1, spot_0, .., spot_n-1
  15. uniform mat4 u_cascaded_lights[MAX_NUM_CASCADES]; // View-proj-crop matrices for cascaded shadow maps.
  16. uniform vec4 u_shadow_maps_texel_sizes;
  17. # define sun_sm_texel_size u_shadow_maps_texel_sizes.xy
  18. # define local_lights_sm_texel_size u_shadow_maps_texel_sizes.zw
  19. SAMPLER2DSHADOW(u_cascaded_shadow_map, 10);
  20. SAMPLER2DSHADOW(u_local_lights_shadow_map, 11);
  21. uniform vec4 u_local_lights_params;
  22. # define local_lights_distance_culling u_local_lights_params.x
  23. # define local_lights_distance_culling_fade u_local_lights_params.y
  24. # define local_lights_distance_culling_cutoff u_local_lights_params.z
  25. uniform vec4 u_lighting_params;
  26. # define ambient_color u_lighting_params.xyz
  27. CONST(float PI) = 3.14159265358979323846;
  28. float length_squared(vec3 a)
  29. {
  30. return dot(a, a);
  31. }
  32. vec3 fresnel(float dot, vec3 f0)
  33. {
  34. float a = clamp(1.0 - dot, 0.0, 1.0);
  35. return f0 + (1.0 - f0) * (a*a*a*a*a);
  36. }
  37. float dist_GGX(float ndoth, float roughness)
  38. {
  39. float r = roughness*roughness;
  40. float rr = r*r;
  41. float d = ((ndoth*ndoth) * (rr - 1.0) + 1.0);
  42. return rr / (PI * (d*d));
  43. }
  44. float geom_schlick_GGX(float ndotv, float roughness)
  45. {
  46. float r = roughness + 1.0;
  47. float k = r*r * (1.0/8.0);
  48. return ndotv / (ndotv * (1.0 - k) + k);
  49. }
  50. float geom_smith(float ndotv, float ndotl, float roughness)
  51. {
  52. float ggx2 = geom_schlick_GGX(ndotv, roughness);
  53. float ggx1 = geom_schlick_GGX(ndotl, roughness);
  54. return ggx1 * ggx2;
  55. }
  56. vec3 calc_radiance(vec3 n, vec3 l, vec3 v, vec3 h, vec3 albedo, vec3 radiance, float metallic, float roughness, vec3 f0)
  57. {
  58. float ndotl = max(0.0, dot(n, l));
  59. float ndotv = max(0.0, dot(n, v));
  60. float ndoth = max(0.0, dot(n, h));
  61. float hdotv = max(0.0, dot(h, v));
  62. vec3 f = fresnel(hdotv, f0);
  63. float ndf = dist_GGX(ndoth, roughness);
  64. float g = geom_smith(ndotv, ndotl, roughness);
  65. // Cook-Torrance BRDF.
  66. vec3 num = ndf * g * f;
  67. float den = 4.0 * ndotv * ndotl + 0.0001;
  68. vec3 specular = num / den;
  69. vec3 ks = f;
  70. vec3 kd = (vec3_splat(1.0) - ks) * (1.0 - metallic);
  71. return (kd * albedo / PI + specular) * radiance * ndotl;
  72. }
  73. vec3 calc_dir_light(vec3 n, vec3 v, vec3 color, float intensity, vec3 direction, vec3 albedo, float metallic, float roughness, vec3 f0)
  74. {
  75. vec3 l = normalize(-direction); // Direction to light.
  76. vec3 h = normalize(v + l); // Half-vector betwen v and l.
  77. vec3 radiance = color * intensity;
  78. return calc_radiance(n, l, v, h, albedo, radiance, metallic, roughness, f0);
  79. }
  80. vec3 calc_omni_light(vec3 n, vec3 v, vec3 frag_pos, vec3 color, float intensity, vec3 position, float range, vec3 albedo, float metallic, float roughness, vec3 f0)
  81. {
  82. vec3 dpos = position - frag_pos;
  83. vec3 l = normalize(dpos); // Direction to light.
  84. vec3 h = normalize(v + l); // Half-vector betwen v and l.
  85. float dd = length_squared(dpos);
  86. float attenuation_std = 1.0 / dd;
  87. float k = 0.15;
  88. float a = 1.0 - dd / (range*range);
  89. float t = clamp(a/k, 0.0, 1.0);
  90. float attenuation = max(mix(0.0, attenuation_std, t), 0.0);
  91. vec3 radiance = color * intensity * attenuation;
  92. return calc_radiance(n, l, v, h, albedo, radiance, metallic, roughness, f0);
  93. }
  94. vec3 calc_spot_light(vec3 n
  95. , vec3 v
  96. , vec3 frag_pos
  97. , vec3 color
  98. , float intensity
  99. , vec3 direction
  100. , float spot_angle
  101. , vec3 position
  102. , float range
  103. , vec3 albedo
  104. , float metallic
  105. , float roughness
  106. , vec3 f0
  107. )
  108. {
  109. vec3 dpos = position - frag_pos;
  110. vec3 l = normalize(dpos); // Direction to light.
  111. vec3 h = normalize(v + l); // Half-vector betwen v and l.
  112. float dd = length_squared(dpos);
  113. float ldotd = dot(l, -direction);
  114. float r = range / ldotd;
  115. float rr = r*r;
  116. float attenuation_std = 1.0 / dd;
  117. float k = 0.03;
  118. if (ldotd >= cos(spot_angle) && dd <= rr) {
  119. float a = ldotd - cos(spot_angle);
  120. float t = clamp(a/k, 0.0, 1.0);
  121. float attenuation = mix(0.0, attenuation_std, t);
  122. vec3 radiance = color * intensity * attenuation;
  123. return calc_radiance(n, l, v, h, albedo, radiance, metallic, roughness, f0);
  124. } else {
  125. return vec3_splat(0.0);
  126. }
  127. }
  128. float fade_smoothstep(float camera_dist, float fade_dist, float cutoff_dist)
  129. {
  130. if (cutoff_dist == fade_dist)
  131. return camera_dist <= fade_dist ? 1.0 : 0.0;
  132. return 1.0 - smoothstep(fade_dist, cutoff_dist, camera_dist);
  133. }
  134. vec3 apply_distance_fading(vec3 radiance, vec3 light_pos, vec3 camera_pos)
  135. {
  136. if (local_lights_distance_culling == 0.0)
  137. return radiance;
  138. float fade_dist = local_lights_distance_culling_fade;
  139. float cutoff_dist = local_lights_distance_culling_cutoff;
  140. float camera_dist = length(light_pos - camera_pos);
  141. return mix(vec3_splat(0.0), radiance, fade_smoothstep(camera_dist, fade_dist, cutoff_dist));
  142. }
  143. vec4 lights_data(int offset)
  144. {
  145. float u = (float(offset) + 0.5) / float(LIGHT_SIZE * MAX_NUM_LIGHTS);
  146. return texture2D(u_lights_data, vec2(u, 0.0));
  147. }
  148. vec3 calc_lighting(mat3 tbn
  149. , vec3 n
  150. , vec3 v
  151. , vec3 frag_pos
  152. , vec3 camera_frag_pos
  153. , vec3 camera_pos
  154. , vec4 shadow_pos0
  155. , vec4 shadow_pos1
  156. , vec4 shadow_pos2
  157. , vec4 shadow_pos3
  158. , vec4 shadow_local
  159. , vec3 albedo
  160. , float metallic
  161. , float roughness
  162. , float ao
  163. , vec3 emission
  164. , vec3 f0
  165. )
  166. {
  167. vec3 radiance = ao * toLinearAccurate(ambient_color) * albedo;
  168. int loffset = 0;
  169. int num_dir = int(u_lights_num.x);
  170. int num_omni = int(u_lights_num.y);
  171. int num_spot = int(u_lights_num.z);
  172. vec3 sun_color = vec3(1, 1, 1);
  173. if (num_dir > 0) {
  174. // Brightest directional light (index == 0) generates cascaded shadow maps.
  175. vec3 light_color = lights_data(loffset + 0).rgb;
  176. float intensity = lights_data(loffset + 0).w;
  177. vec3 direction = lights_data(loffset + 2).xyz;
  178. vec4 atlas_u = lights_data(loffset + 19).xyzw;
  179. vec4 atlas_v = lights_data(loffset + 20).xyzw;
  180. float atlas_size = lights_data(loffset + 21).x;
  181. float shadow_bias = lights_data(loffset + 21).y;
  182. loffset += LIGHT_SIZE;
  183. sun_color = light_color;
  184. vec3 local_radiance = calc_dir_light(n
  185. , v
  186. , toLinearAccurate(light_color)
  187. , intensity
  188. , mul(direction, tbn)
  189. , albedo
  190. , metallic
  191. , roughness
  192. , f0
  193. );
  194. vec2 shadow0 = shadow_pos0.xy/shadow_pos0.w;
  195. vec2 shadow1 = shadow_pos1.xy/shadow_pos1.w;
  196. vec2 shadow2 = shadow_pos2.xy/shadow_pos2.w;
  197. vec2 shadow3 = shadow_pos3.xy/shadow_pos3.w;
  198. bool atlas0 = all(lessThan(shadow0, vec2_splat(1.0))) && all(greaterThan(shadow0, vec2_splat(0.0)));
  199. bool atlas1 = all(lessThan(shadow1, vec2_splat(1.0))) && all(greaterThan(shadow1, vec2_splat(0.0)));
  200. bool atlas2 = all(lessThan(shadow2, vec2_splat(1.0))) && all(greaterThan(shadow2, vec2_splat(0.0)));
  201. bool atlas3 = all(lessThan(shadow3, vec2_splat(1.0))) && all(greaterThan(shadow3, vec2_splat(0.0)));
  202. if (atlas0)
  203. local_radiance *= PCF(u_cascaded_shadow_map, shadow_pos0, shadow_bias, sun_sm_texel_size, vec3(atlas_u.x , atlas_v.x , atlas_size));
  204. else if (atlas1)
  205. local_radiance *= PCF(u_cascaded_shadow_map, shadow_pos1, shadow_bias, sun_sm_texel_size, vec3(atlas_u.x + atlas_size, atlas_v.x , atlas_size));
  206. else if (atlas2)
  207. local_radiance *= PCF(u_cascaded_shadow_map, shadow_pos2, shadow_bias, sun_sm_texel_size, vec3(atlas_u.x , atlas_v.x + atlas_size, atlas_size));
  208. else if (atlas3)
  209. local_radiance *= PCF(u_cascaded_shadow_map, shadow_pos3, shadow_bias, sun_sm_texel_size, vec3(atlas_u.x + atlas_size, atlas_v.x + atlas_size, atlas_size));
  210. radiance += local_radiance;
  211. }
  212. // Others directional lights just add to radiance.
  213. for (int di = 1; di < num_dir; ++di, loffset += LIGHT_SIZE) {
  214. vec3 light_color = lights_data(loffset + 0).rgb;
  215. float intensity = lights_data(loffset + 0).w;
  216. vec3 direction = lights_data(loffset + 2).xyz;
  217. float shadow_bias = lights_data(loffset + 21).y;
  218. radiance += calc_dir_light(n
  219. , v
  220. , toLinearAccurate(light_color)
  221. , intensity
  222. , mul(direction, tbn)
  223. , albedo
  224. , metallic
  225. , roughness
  226. , f0
  227. );
  228. }
  229. for (int oi = 0; oi < num_omni; ++oi, loffset += LIGHT_SIZE) {
  230. vec3 light_color = lights_data(loffset + 0).rgb;
  231. float intensity = lights_data(loffset + 0).w;
  232. vec3 position = lights_data(loffset + 1).xyz;
  233. float range = lights_data(loffset + 1).w;
  234. float cast_shadow = lights_data(loffset + 21).z;
  235. vec3 local_radiance = calc_omni_light(n
  236. , v
  237. , frag_pos
  238. , toLinearAccurate(light_color)
  239. , intensity
  240. , mul(position, tbn)
  241. , range
  242. , albedo
  243. , metallic
  244. , roughness
  245. , f0
  246. );
  247. if (cast_shadow == 1.0) {
  248. // Tetrahedron normals.
  249. CONST(vec3 bn) = vec3( 0.0f, 0.81649661f, -0.57735026f);
  250. CONST(vec3 yn) = vec3( 0.0f, -0.81649661f, -0.57735026f);
  251. CONST(vec3 gn) = vec3(-0.81649661f, 0.0f, 0.57735026f);
  252. CONST(vec3 rn) = vec3( 0.81649661f, 0.0f, 0.57735026f);
  253. vec3 sl = shadow_local.xyz - position; // Transform to light-local space.
  254. // Select tetrahedon face.
  255. float b = dot(sl, bn);
  256. float y = dot(sl, yn);
  257. float g = dot(sl, gn);
  258. float r = dot(sl, rn);
  259. float maximum = max(max(b, y), max(g, r));
  260. vec4 atlas_u = lights_data(loffset + 19);
  261. vec4 atlas_v = lights_data(loffset + 20);
  262. float atlas_size = lights_data(loffset + 21).x;
  263. float shadow_bias = lights_data(loffset + 21).y;
  264. vec4 shadow_pos0;
  265. vec3 col;
  266. vec3 atlas_offset;
  267. if (maximum == b) {
  268. // Tetrahedron mvp matrices.
  269. mat4 bmtx = mtxFromCols(lights_data(loffset + 3)
  270. , lights_data(loffset + 4)
  271. , lights_data(loffset + 5)
  272. , lights_data(loffset + 6)
  273. );
  274. shadow_pos0 = mul(bmtx, shadow_local);
  275. col = vec3(0.1, 0.1, 1);
  276. atlas_offset = vec3(atlas_u.x, atlas_v.x, atlas_size);
  277. } else if (maximum == y) {
  278. mat4 ymtx = mtxFromCols(lights_data(loffset + 7)
  279. , lights_data(loffset + 8)
  280. , lights_data(loffset + 9)
  281. , lights_data(loffset + 10)
  282. );
  283. shadow_pos0 = mul(ymtx, shadow_local);
  284. col = vec3(1, 1, 0);
  285. atlas_offset = vec3(atlas_u.y, atlas_v.y, atlas_size);
  286. } else if (maximum == g) {
  287. mat4 gmtx = mtxFromCols(lights_data(loffset + 11)
  288. , lights_data(loffset + 12)
  289. , lights_data(loffset + 13)
  290. , lights_data(loffset + 14)
  291. );
  292. shadow_pos0 = mul(gmtx, shadow_local);
  293. col = vec3(0, 1, 0);
  294. atlas_offset = vec3(atlas_u.z, atlas_v.z, atlas_size);
  295. } else {
  296. mat4 rmtx = mtxFromCols(lights_data(loffset + 15)
  297. , lights_data(loffset + 16)
  298. , lights_data(loffset + 17)
  299. , lights_data(loffset + 18)
  300. );
  301. shadow_pos0 = mul(rmtx, shadow_local);
  302. col = vec3(1, 0, 0);
  303. atlas_offset = vec3(atlas_u.w, atlas_v.w, atlas_size);
  304. }
  305. local_radiance *= PCF(u_local_lights_shadow_map
  306. , shadow_pos0
  307. , shadow_bias
  308. , local_lights_sm_texel_size / 4.0
  309. , atlas_offset
  310. );
  311. }
  312. radiance += apply_distance_fading(local_radiance, position, camera_pos);
  313. }
  314. for (int si = 0; si < num_spot; ++si, loffset += LIGHT_SIZE) {
  315. vec3 light_color = lights_data(loffset + 0).rgb;
  316. float intensity = lights_data(loffset + 0).w;
  317. vec3 position = lights_data(loffset + 1).xyz;
  318. float range = lights_data(loffset + 1).w;
  319. vec3 direction = lights_data(loffset + 2).xyz;
  320. float spot_angle = lights_data(loffset + 2).w;
  321. float cast_shadow = lights_data(loffset + 21).z;
  322. vec3 local_radiance = calc_spot_light(n
  323. , v
  324. , frag_pos
  325. , toLinearAccurate(light_color)
  326. , intensity
  327. , mul(direction, tbn)
  328. , spot_angle
  329. , mul(position, tbn)
  330. , range
  331. , albedo
  332. , metallic
  333. , roughness
  334. , f0
  335. );
  336. if (cast_shadow == 1.0) {
  337. mat4 mvp = mtxFromCols(lights_data(loffset + 3)
  338. , lights_data(loffset + 4)
  339. , lights_data(loffset + 5)
  340. , lights_data(loffset + 6)
  341. );
  342. vec4 atlas_u = lights_data(loffset + 19);
  343. vec4 atlas_v = lights_data(loffset + 20);
  344. float atlas_size = lights_data(loffset + 21).x;
  345. float shadow_bias = lights_data(loffset + 21).y;
  346. local_radiance *= PCF(u_local_lights_shadow_map
  347. , mul(mvp, shadow_local)
  348. , shadow_bias
  349. , local_lights_sm_texel_size
  350. , vec3(atlas_u.x, atlas_v.x, atlas_size)
  351. );
  352. }
  353. radiance += apply_distance_fading(local_radiance, position, camera_pos);
  354. }
  355. return apply_fog(emission + radiance, length(camera_frag_pos), sun_color);
  356. }
  357. #endif
  358. """
  359. }
  360. fog = {
  361. code = """
  362. uniform vec4 u_fog_data[2];
  363. #define fog_color u_fog_data[0].rgb
  364. #define fog_density u_fog_data[0].w
  365. #define fog_range_min u_fog_data[1].x
  366. #define fog_range_max u_fog_data[1].y
  367. #define fog_sun_blend u_fog_data[1].z
  368. #define fog_enabled u_fog_data[1].w
  369. vec3 apply_fog(vec3 radiance, float d, vec3 sun_color)
  370. {
  371. if (fog_enabled == 0.0)
  372. return radiance;
  373. if (d < fog_range_min || d > fog_range_max)
  374. return radiance;
  375. float d2 = d - fog_range_min;
  376. float f = exp(-fog_density * d2);
  377. return mix(mix(fog_color, sun_color, fog_sun_blend), radiance, f);
  378. }
  379. """
  380. }
  381. }