lighting.shader 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  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 8 // 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. uniform vec4 u_lights_data[LIGHT_SIZE * MAX_NUM_LIGHTS]; // 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. vec3 calc_lighting(mat3 tbn
  144. , vec3 n
  145. , vec3 v
  146. , vec3 frag_pos
  147. , vec3 camera_frag_pos
  148. , vec3 camera_pos
  149. , vec4 shadow_pos0
  150. , vec4 shadow_pos1
  151. , vec4 shadow_pos2
  152. , vec4 shadow_pos3
  153. , vec4 shadow_local
  154. , vec3 albedo
  155. , float metallic
  156. , float roughness
  157. , float ao
  158. , vec3 emission
  159. , vec3 f0
  160. )
  161. {
  162. vec3 radiance = ao * toLinearAccurate(ambient_color) * albedo;
  163. int loffset = 0;
  164. int num_dir = int(u_lights_num.x);
  165. int num_omni = int(u_lights_num.y);
  166. int num_spot = int(u_lights_num.z);
  167. vec3 sun_color = vec3(1, 1, 1);
  168. if (num_dir > 0) {
  169. // Brightest directional light (index == 0) generates cascaded shadow maps.
  170. vec3 light_color = u_lights_data[loffset + 0].rgb;
  171. float intensity = u_lights_data[loffset + 0].w;
  172. vec3 direction = u_lights_data[loffset + 2].xyz;
  173. float shadow_bias = u_lights_data[loffset + 3].r;
  174. float atlas_u = u_lights_data[loffset + 3].g;
  175. float atlas_v = u_lights_data[loffset + 3].b;
  176. float atlas_size = u_lights_data[loffset + 3].a;
  177. loffset += LIGHT_SIZE;
  178. sun_color = light_color;
  179. vec3 local_radiance = calc_dir_light(n
  180. , v
  181. , toLinearAccurate(light_color)
  182. , intensity
  183. , mul(direction, tbn)
  184. , albedo
  185. , metallic
  186. , roughness
  187. , f0
  188. );
  189. vec2 shadow0 = shadow_pos0.xy/shadow_pos0.w;
  190. vec2 shadow1 = shadow_pos1.xy/shadow_pos1.w;
  191. vec2 shadow2 = shadow_pos2.xy/shadow_pos2.w;
  192. vec2 shadow3 = shadow_pos3.xy/shadow_pos3.w;
  193. bool atlas0 = all(lessThan(shadow0, vec2_splat(1.0))) && all(greaterThan(shadow0, vec2_splat(0.0)));
  194. bool atlas1 = all(lessThan(shadow1, vec2_splat(1.0))) && all(greaterThan(shadow1, vec2_splat(0.0)));
  195. bool atlas2 = all(lessThan(shadow2, vec2_splat(1.0))) && all(greaterThan(shadow2, vec2_splat(0.0)));
  196. bool atlas3 = all(lessThan(shadow3, vec2_splat(1.0))) && all(greaterThan(shadow3, vec2_splat(0.0)));
  197. if (atlas0)
  198. local_radiance *= PCF(u_cascaded_shadow_map, shadow_pos0, shadow_bias, sun_sm_texel_size, vec3(atlas_u , atlas_v , atlas_size));
  199. else if (atlas1)
  200. local_radiance *= PCF(u_cascaded_shadow_map, shadow_pos1, shadow_bias, sun_sm_texel_size, vec3(atlas_u + atlas_size, atlas_v , atlas_size));
  201. else if (atlas2)
  202. local_radiance *= PCF(u_cascaded_shadow_map, shadow_pos2, shadow_bias, sun_sm_texel_size, vec3(atlas_u , atlas_v + atlas_size, atlas_size));
  203. else if (atlas3)
  204. local_radiance *= PCF(u_cascaded_shadow_map, shadow_pos3, shadow_bias, sun_sm_texel_size, vec3(atlas_u + atlas_size, atlas_v + atlas_size, atlas_size));
  205. radiance += local_radiance;
  206. }
  207. // Others directional lights just add to radiance.
  208. for (int di = 1; di < num_dir; ++di, loffset += LIGHT_SIZE) {
  209. vec3 light_color = u_lights_data[loffset + 0].rgb;
  210. float intensity = u_lights_data[loffset + 0].w;
  211. vec3 direction = u_lights_data[loffset + 2].xyz;
  212. float shadow_bias = u_lights_data[loffset + 3].r;
  213. radiance += calc_dir_light(n
  214. , v
  215. , toLinearAccurate(light_color)
  216. , intensity
  217. , mul(direction, tbn)
  218. , albedo
  219. , metallic
  220. , roughness
  221. , f0
  222. );
  223. }
  224. for (int oi = 0; oi < num_omni; ++oi, loffset += LIGHT_SIZE) {
  225. vec3 light_color = u_lights_data[loffset + 0].rgb;
  226. float intensity = u_lights_data[loffset + 0].w;
  227. vec3 position = u_lights_data[loffset + 1].xyz;
  228. float range = u_lights_data[loffset + 1].w;
  229. float shadow_bias = u_lights_data[loffset + 3].r;
  230. vec3 local_radiance = calc_omni_light(n
  231. , v
  232. , frag_pos
  233. , toLinearAccurate(light_color)
  234. , intensity
  235. , mul(position, tbn)
  236. , range
  237. , albedo
  238. , metallic
  239. , roughness
  240. , f0
  241. );
  242. radiance += apply_distance_fading(local_radiance, position, camera_pos);
  243. }
  244. for (int si = 0; si < num_spot; ++si, loffset += LIGHT_SIZE) {
  245. vec3 light_color = u_lights_data[loffset + 0].rgb;
  246. float intensity = u_lights_data[loffset + 0].w;
  247. vec3 position = u_lights_data[loffset + 1].xyz;
  248. float range = u_lights_data[loffset + 1].w;
  249. vec3 direction = u_lights_data[loffset + 2].xyz;
  250. float spot_angle = u_lights_data[loffset + 2].w;
  251. float shadow_bias = u_lights_data[loffset + 3].r;
  252. float atlas_u = u_lights_data[loffset + 3].g;
  253. float atlas_v = u_lights_data[loffset + 3].b;
  254. float atlas_size = u_lights_data[loffset + 3].a;
  255. vec4 axis_x = u_lights_data[loffset + 4];
  256. vec4 axis_y = u_lights_data[loffset + 5];
  257. vec4 axis_z = u_lights_data[loffset + 6];
  258. vec4 axis_t = u_lights_data[loffset + 7];
  259. vec3 local_radiance = calc_spot_light(n
  260. , v
  261. , frag_pos
  262. , toLinearAccurate(light_color)
  263. , intensity
  264. , mul(direction, tbn)
  265. , spot_angle
  266. , mul(position, tbn)
  267. , range
  268. , albedo
  269. , metallic
  270. , roughness
  271. , f0
  272. );
  273. mat4 mvp = mtxFromCols(axis_x, axis_y, axis_z, axis_t);
  274. vec4 shadow_pos0 = mul(mvp, shadow_local);
  275. local_radiance *= PCF(u_local_lights_shadow_map, shadow_pos0, shadow_bias, local_lights_sm_texel_size, vec3(atlas_u, atlas_v, atlas_size));
  276. radiance += apply_distance_fading(local_radiance, position, camera_pos);
  277. }
  278. return apply_fog(emission + radiance, length(camera_frag_pos), sun_color);
  279. }
  280. #endif
  281. """
  282. }
  283. fog = {
  284. code = """
  285. uniform vec4 u_fog_data[2];
  286. #define fog_color u_fog_data[0].rgb
  287. #define fog_density u_fog_data[0].w
  288. #define fog_range_min u_fog_data[1].x
  289. #define fog_range_max u_fog_data[1].y
  290. #define fog_sun_blend u_fog_data[1].z
  291. #define fog_enabled u_fog_data[1].w
  292. vec3 apply_fog(vec3 radiance, float d, vec3 sun_color)
  293. {
  294. if (fog_enabled == 0.0)
  295. return radiance;
  296. if (d < fog_range_min || d > fog_range_max)
  297. return radiance;
  298. float d2 = d - fog_range_min;
  299. float f = exp(-fog_density * d2);
  300. return mix(mix(fog_color, sun_color, fog_sun_blend), radiance, f);
  301. }
  302. """
  303. }
  304. }