lm_compute.glsl 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738
  1. #[versions]
  2. primary = "#define MODE_DIRECT_LIGHT";
  3. secondary = "#define MODE_BOUNCE_LIGHT";
  4. dilate = "#define MODE_DILATE";
  5. unocclude = "#define MODE_UNOCCLUDE";
  6. light_probes = "#define MODE_LIGHT_PROBES";
  7. #[compute]
  8. #version 450
  9. #VERSION_DEFINES
  10. // One 2D local group focusing in one layer at a time, though all
  11. // in parallel (no barriers) makes more sense than a 3D local group
  12. // as this can take more advantage of the cache for each group.
  13. #ifdef MODE_LIGHT_PROBES
  14. layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
  15. #else
  16. layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
  17. #endif
  18. #include "lm_common_inc.glsl"
  19. #ifdef MODE_LIGHT_PROBES
  20. layout(set = 1, binding = 0, std430) restrict buffer LightProbeData {
  21. vec4 data[];
  22. }
  23. light_probes;
  24. layout(set = 1, binding = 1) uniform texture2DArray source_light;
  25. layout(set = 1, binding = 2) uniform texture2DArray source_direct_light; //also need the direct light, which was omitted
  26. layout(set = 1, binding = 3) uniform texture2D environment;
  27. #endif
  28. #ifdef MODE_UNOCCLUDE
  29. layout(rgba32f, set = 1, binding = 0) uniform restrict image2DArray position;
  30. layout(rgba32f, set = 1, binding = 1) uniform restrict readonly image2DArray unocclude;
  31. #endif
  32. #if defined(MODE_DIRECT_LIGHT) || defined(MODE_BOUNCE_LIGHT)
  33. layout(rgba16f, set = 1, binding = 0) uniform restrict writeonly image2DArray dest_light;
  34. layout(set = 1, binding = 1) uniform texture2DArray source_light;
  35. layout(set = 1, binding = 2) uniform texture2DArray source_position;
  36. layout(set = 1, binding = 3) uniform texture2DArray source_normal;
  37. layout(rgba16f, set = 1, binding = 4) uniform restrict image2DArray accum_light;
  38. #endif
  39. #ifdef MODE_BOUNCE_LIGHT
  40. layout(rgba32f, set = 1, binding = 5) uniform restrict image2DArray bounce_accum;
  41. layout(set = 1, binding = 6) uniform texture2D environment;
  42. #endif
  43. #ifdef MODE_DIRECT_LIGHT
  44. layout(rgba32f, set = 1, binding = 5) uniform restrict writeonly image2DArray primary_dynamic;
  45. #endif
  46. #ifdef MODE_DILATE
  47. layout(rgba16f, set = 1, binding = 0) uniform restrict writeonly image2DArray dest_light;
  48. layout(set = 1, binding = 1) uniform texture2DArray source_light;
  49. #endif
  50. layout(push_constant, std430) uniform Params {
  51. ivec2 atlas_size; // x used for light probe mode total probes
  52. uint ray_count;
  53. uint ray_to;
  54. vec3 world_size;
  55. float bias;
  56. vec3 to_cell_offset;
  57. uint ray_from;
  58. vec3 to_cell_size;
  59. uint light_count;
  60. int grid_size;
  61. int atlas_slice;
  62. ivec2 region_ofs;
  63. mat3x4 env_transform;
  64. }
  65. params;
  66. //check it, but also return distance and barycentric coords (for uv lookup)
  67. bool ray_hits_triangle(vec3 from, vec3 dir, float max_dist, vec3 p0, vec3 p1, vec3 p2, out float r_distance, out vec3 r_barycentric) {
  68. const float EPSILON = 0.00001;
  69. const vec3 e0 = p1 - p0;
  70. const vec3 e1 = p0 - p2;
  71. vec3 triangle_normal = cross(e1, e0);
  72. float n_dot_dir = dot(triangle_normal, dir);
  73. if (abs(n_dot_dir) < EPSILON) {
  74. return false;
  75. }
  76. const vec3 e2 = (p0 - from) / n_dot_dir;
  77. const vec3 i = cross(dir, e2);
  78. r_barycentric.y = dot(i, e1);
  79. r_barycentric.z = dot(i, e0);
  80. r_barycentric.x = 1.0 - (r_barycentric.z + r_barycentric.y);
  81. r_distance = dot(triangle_normal, e2);
  82. return (r_distance > params.bias) && (r_distance < max_dist) && all(greaterThanEqual(r_barycentric, vec3(0.0)));
  83. }
  84. const uint RAY_MISS = 0;
  85. const uint RAY_FRONT = 1;
  86. const uint RAY_BACK = 2;
  87. const uint RAY_ANY = 3;
  88. uint trace_ray(vec3 p_from, vec3 p_to
  89. #if defined(MODE_BOUNCE_LIGHT) || defined(MODE_LIGHT_PROBES)
  90. ,
  91. out uint r_triangle, out vec3 r_barycentric
  92. #endif
  93. #if defined(MODE_UNOCCLUDE)
  94. ,
  95. out float r_distance, out vec3 r_normal
  96. #endif
  97. ) {
  98. /* world coords */
  99. vec3 rel = p_to - p_from;
  100. float rel_len = length(rel);
  101. vec3 dir = normalize(rel);
  102. vec3 inv_dir = 1.0 / dir;
  103. /* cell coords */
  104. vec3 from_cell = (p_from - params.to_cell_offset) * params.to_cell_size;
  105. vec3 to_cell = (p_to - params.to_cell_offset) * params.to_cell_size;
  106. //prepare DDA
  107. vec3 rel_cell = to_cell - from_cell;
  108. ivec3 icell = ivec3(from_cell);
  109. ivec3 iendcell = ivec3(to_cell);
  110. vec3 dir_cell = normalize(rel_cell);
  111. vec3 delta = min(abs(1.0 / dir_cell), params.grid_size); // use params.grid_size as max to prevent infinity values
  112. ivec3 step = ivec3(sign(rel_cell));
  113. vec3 side = (sign(rel_cell) * (vec3(icell) - from_cell) + (sign(rel_cell) * 0.5) + 0.5) * delta;
  114. uint iters = 0;
  115. while (all(greaterThanEqual(icell, ivec3(0))) && all(lessThan(icell, ivec3(params.grid_size))) && iters < 1000) {
  116. uvec2 cell_data = texelFetch(usampler3D(grid, linear_sampler), icell, 0).xy;
  117. if (cell_data.x > 0) { //triangles here
  118. uint hit = RAY_MISS;
  119. float best_distance = 1e20;
  120. for (uint i = 0; i < cell_data.x; i++) {
  121. uint tidx = grid_indices.data[cell_data.y + i];
  122. //Ray-Box test
  123. Triangle triangle = triangles.data[tidx];
  124. vec3 t0 = (triangle.min_bounds - p_from) * inv_dir;
  125. vec3 t1 = (triangle.max_bounds - p_from) * inv_dir;
  126. vec3 tmin = min(t0, t1), tmax = max(t0, t1);
  127. if (max(tmin.x, max(tmin.y, tmin.z)) > min(tmax.x, min(tmax.y, tmax.z))) {
  128. continue; //ray box failed
  129. }
  130. //prepare triangle vertices
  131. vec3 vtx0 = vertices.data[triangle.indices.x].position;
  132. vec3 vtx1 = vertices.data[triangle.indices.y].position;
  133. vec3 vtx2 = vertices.data[triangle.indices.z].position;
  134. #if defined(MODE_UNOCCLUDE) || defined(MODE_BOUNCE_LIGHT) || defined(MODE_LIGHT_PROBES)
  135. vec3 normal = -normalize(cross((vtx0 - vtx1), (vtx0 - vtx2)));
  136. bool backface = dot(normal, dir) >= 0.0;
  137. #endif
  138. float distance;
  139. vec3 barycentric;
  140. if (ray_hits_triangle(p_from, dir, rel_len, vtx0, vtx1, vtx2, distance, barycentric)) {
  141. #ifdef MODE_DIRECT_LIGHT
  142. return RAY_ANY; //any hit good
  143. #endif
  144. #if defined(MODE_UNOCCLUDE) || defined(MODE_BOUNCE_LIGHT) || defined(MODE_LIGHT_PROBES)
  145. if (!backface) {
  146. // the case of meshes having both a front and back face in the same plane is more common than
  147. // expected, so if this is a front-face, bias it closer to the ray origin, so it always wins over the back-face
  148. distance = max(params.bias, distance - params.bias);
  149. }
  150. if (distance < best_distance) {
  151. hit = backface ? RAY_BACK : RAY_FRONT;
  152. best_distance = distance;
  153. #if defined(MODE_UNOCCLUDE)
  154. r_distance = distance;
  155. r_normal = normal;
  156. #endif
  157. #if defined(MODE_BOUNCE_LIGHT) || defined(MODE_LIGHT_PROBES)
  158. r_triangle = tidx;
  159. r_barycentric = barycentric;
  160. #endif
  161. }
  162. #endif
  163. }
  164. }
  165. #if defined(MODE_UNOCCLUDE) || defined(MODE_BOUNCE_LIGHT) || defined(MODE_LIGHT_PROBES)
  166. if (hit != RAY_MISS) {
  167. return hit;
  168. }
  169. #endif
  170. }
  171. if (icell == iendcell) {
  172. break;
  173. }
  174. bvec3 mask = lessThanEqual(side.xyz, min(side.yzx, side.zxy));
  175. side += vec3(mask) * delta;
  176. icell += ivec3(vec3(mask)) * step;
  177. iters++;
  178. }
  179. return RAY_MISS;
  180. }
  181. // https://www.reedbeta.com/blog/hash-functions-for-gpu-rendering/
  182. uint hash(uint value) {
  183. uint state = value * 747796405u + 2891336453u;
  184. uint word = ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u;
  185. return (word >> 22u) ^ word;
  186. }
  187. uint random_seed(ivec3 seed) {
  188. return hash(seed.x ^ hash(seed.y ^ hash(seed.z)));
  189. }
  190. // generates a random value in range [0.0, 1.0)
  191. float randomize(inout uint value) {
  192. value = hash(value);
  193. return float(value / 4294967296.0);
  194. }
  195. const float PI = 3.14159265f;
  196. // http://www.realtimerendering.com/raytracinggems/unofficial_RayTracingGems_v1.4.pdf (chapter 15)
  197. vec3 generate_hemisphere_uniform_direction(inout uint noise) {
  198. float noise1 = randomize(noise);
  199. float noise2 = randomize(noise) * 2.0 * PI;
  200. float factor = sqrt(1 - (noise1 * noise1));
  201. return vec3(factor * cos(noise2), factor * sin(noise2), noise1);
  202. }
  203. vec3 generate_hemisphere_cosine_weighted_direction(inout uint noise) {
  204. float noise1 = randomize(noise);
  205. float noise2 = randomize(noise) * 2.0 * PI;
  206. return vec3(sqrt(noise1) * cos(noise2), sqrt(noise1) * sin(noise2), sqrt(1.0 - noise1));
  207. }
  208. float get_omni_attenuation(float distance, float inv_range, float decay) {
  209. float nd = distance * inv_range;
  210. nd *= nd;
  211. nd *= nd; // nd^4
  212. nd = max(1.0 - nd, 0.0);
  213. nd *= nd; // nd^2
  214. return nd * pow(max(distance, 0.0001), -decay);
  215. }
  216. void main() {
  217. #ifdef MODE_LIGHT_PROBES
  218. int probe_index = int(gl_GlobalInvocationID.x);
  219. if (probe_index >= params.atlas_size.x) { //too large, do nothing
  220. return;
  221. }
  222. #else
  223. ivec2 atlas_pos = ivec2(gl_GlobalInvocationID.xy) + params.region_ofs;
  224. if (any(greaterThanEqual(atlas_pos, params.atlas_size))) { //too large, do nothing
  225. return;
  226. }
  227. #endif
  228. #ifdef MODE_DIRECT_LIGHT
  229. vec3 normal = texelFetch(sampler2DArray(source_normal, linear_sampler), ivec3(atlas_pos, params.atlas_slice), 0).xyz;
  230. if (length(normal) < 0.5) {
  231. return; //empty texel, no process
  232. }
  233. vec3 position = texelFetch(sampler2DArray(source_position, linear_sampler), ivec3(atlas_pos, params.atlas_slice), 0).xyz;
  234. //go through all lights
  235. //start by own light (emissive)
  236. vec3 static_light = vec3(0.0);
  237. vec3 dynamic_light = vec3(0.0);
  238. #ifdef USE_SH_LIGHTMAPS
  239. vec4 sh_accum[4] = vec4[](
  240. vec4(0.0, 0.0, 0.0, 1.0),
  241. vec4(0.0, 0.0, 0.0, 1.0),
  242. vec4(0.0, 0.0, 0.0, 1.0),
  243. vec4(0.0, 0.0, 0.0, 1.0));
  244. #endif
  245. for (uint i = 0; i < params.light_count; i++) {
  246. vec3 light_pos;
  247. float dist;
  248. float attenuation;
  249. float soft_shadowing_disk_size;
  250. if (lights.data[i].type == LIGHT_TYPE_DIRECTIONAL) {
  251. vec3 light_vec = lights.data[i].direction;
  252. light_pos = position - light_vec * length(params.world_size);
  253. dist = length(params.world_size);
  254. attenuation = 1.0;
  255. soft_shadowing_disk_size = lights.data[i].size;
  256. } else {
  257. light_pos = lights.data[i].position;
  258. dist = distance(position, light_pos);
  259. if (dist > lights.data[i].range) {
  260. continue;
  261. }
  262. soft_shadowing_disk_size = lights.data[i].size / dist;
  263. attenuation = get_omni_attenuation(dist, 1.0 / lights.data[i].range, lights.data[i].attenuation);
  264. if (lights.data[i].type == LIGHT_TYPE_SPOT) {
  265. vec3 rel = normalize(position - light_pos);
  266. float cos_spot_angle = lights.data[i].cos_spot_angle;
  267. float cos_angle = dot(rel, lights.data[i].direction);
  268. if (cos_angle < cos_spot_angle) {
  269. continue; //invisible, dont try
  270. }
  271. float scos = max(cos_angle, cos_spot_angle);
  272. float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - cos_spot_angle));
  273. attenuation *= 1.0 - pow(spot_rim, lights.data[i].inv_spot_attenuation);
  274. }
  275. }
  276. vec3 light_dir = normalize(light_pos - position);
  277. attenuation *= max(0.0, dot(normal, light_dir));
  278. if (attenuation <= 0.0001) {
  279. continue; //no need to do anything
  280. }
  281. float penumbra = 0.0;
  282. if (lights.data[i].size > 0.0) {
  283. vec3 light_to_point = -light_dir;
  284. vec3 aux = light_to_point.y < 0.777 ? vec3(0.0, 1.0, 0.0) : vec3(1.0, 0.0, 0.0);
  285. vec3 light_to_point_tan = normalize(cross(light_to_point, aux));
  286. vec3 light_to_point_bitan = normalize(cross(light_to_point, light_to_point_tan));
  287. const uint shadowing_rays_check_penumbra_denom = 2;
  288. uint shadowing_ray_count = params.ray_count;
  289. uint hits = 0;
  290. uint noise = random_seed(ivec3(atlas_pos, 43573547 /* some prime */));
  291. vec3 light_disk_to_point = light_to_point;
  292. for (uint j = 0; j < shadowing_ray_count; j++) {
  293. // Optimization:
  294. // Once already traced an important proportion of rays, if all are hits or misses,
  295. // assume we're not in the penumbra so we can infer the rest would have the same result
  296. if (j == shadowing_ray_count / shadowing_rays_check_penumbra_denom) {
  297. if (hits == j) {
  298. // Assume totally lit
  299. hits = shadowing_ray_count;
  300. break;
  301. } else if (hits == 0) {
  302. // Assume totally dark
  303. hits = 0;
  304. break;
  305. }
  306. }
  307. float r = randomize(noise);
  308. float a = randomize(noise) * 2.0 * PI;
  309. vec2 disk_sample = (r * vec2(cos(a), sin(a))) * soft_shadowing_disk_size * lights.data[i].shadow_blur;
  310. light_disk_to_point = normalize(light_to_point + disk_sample.x * light_to_point_tan + disk_sample.y * light_to_point_bitan);
  311. if (trace_ray(position - light_disk_to_point * params.bias, position - light_disk_to_point * dist) == RAY_MISS) {
  312. hits++;
  313. }
  314. }
  315. penumbra = float(hits) / float(shadowing_ray_count);
  316. } else {
  317. if (trace_ray(position + light_dir * params.bias, light_pos) == RAY_MISS) {
  318. penumbra = 1.0;
  319. }
  320. }
  321. vec3 light = lights.data[i].color * lights.data[i].energy * attenuation * penumbra;
  322. if (lights.data[i].static_bake) {
  323. static_light += light;
  324. #ifdef USE_SH_LIGHTMAPS
  325. float c[4] = float[](
  326. 0.282095, //l0
  327. 0.488603 * light_dir.y, //l1n1
  328. 0.488603 * light_dir.z, //l1n0
  329. 0.488603 * light_dir.x //l1p1
  330. );
  331. for (uint j = 0; j < 4; j++) {
  332. sh_accum[j].rgb += light * c[j] * (1.0 / 3.0);
  333. }
  334. #endif
  335. } else {
  336. dynamic_light += light;
  337. }
  338. }
  339. vec3 albedo = texelFetch(sampler2DArray(albedo_tex, linear_sampler), ivec3(atlas_pos, params.atlas_slice), 0).rgb;
  340. vec3 emissive = texelFetch(sampler2DArray(emission_tex, linear_sampler), ivec3(atlas_pos, params.atlas_slice), 0).rgb;
  341. dynamic_light *= albedo; //if it will bounce, must multiply by albedo
  342. dynamic_light += emissive;
  343. //keep for lightprobes
  344. imageStore(primary_dynamic, ivec3(atlas_pos, params.atlas_slice), vec4(dynamic_light, 1.0));
  345. dynamic_light += static_light * albedo; //send for bounces
  346. dynamic_light *= params.env_transform[2][3]; // exposure_normalization
  347. imageStore(dest_light, ivec3(atlas_pos, params.atlas_slice), vec4(dynamic_light, 1.0));
  348. #ifdef USE_SH_LIGHTMAPS
  349. //keep for adding at the end
  350. imageStore(accum_light, ivec3(atlas_pos, params.atlas_slice * 4 + 0), sh_accum[0]);
  351. imageStore(accum_light, ivec3(atlas_pos, params.atlas_slice * 4 + 1), sh_accum[1]);
  352. imageStore(accum_light, ivec3(atlas_pos, params.atlas_slice * 4 + 2), sh_accum[2]);
  353. imageStore(accum_light, ivec3(atlas_pos, params.atlas_slice * 4 + 3), sh_accum[3]);
  354. #else
  355. static_light *= params.env_transform[2][3]; // exposure_normalization
  356. imageStore(accum_light, ivec3(atlas_pos, params.atlas_slice), vec4(static_light, 1.0));
  357. #endif
  358. #endif
  359. #ifdef MODE_BOUNCE_LIGHT
  360. vec3 normal = texelFetch(sampler2DArray(source_normal, linear_sampler), ivec3(atlas_pos, params.atlas_slice), 0).xyz;
  361. if (length(normal) < 0.5) {
  362. return; //empty texel, no process
  363. }
  364. vec3 position = texelFetch(sampler2DArray(source_position, linear_sampler), ivec3(atlas_pos, params.atlas_slice), 0).xyz;
  365. vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0);
  366. vec3 tangent = normalize(cross(v0, normal));
  367. vec3 bitangent = normalize(cross(tangent, normal));
  368. mat3 normal_mat = mat3(tangent, bitangent, normal);
  369. #ifdef USE_SH_LIGHTMAPS
  370. vec4 sh_accum[4] = vec4[](
  371. vec4(0.0, 0.0, 0.0, 1.0),
  372. vec4(0.0, 0.0, 0.0, 1.0),
  373. vec4(0.0, 0.0, 0.0, 1.0),
  374. vec4(0.0, 0.0, 0.0, 1.0));
  375. #endif
  376. vec3 light_average = vec3(0.0);
  377. float active_rays = 0.0;
  378. uint noise = random_seed(ivec3(params.ray_from, atlas_pos));
  379. for (uint i = params.ray_from; i < params.ray_to; i++) {
  380. vec3 ray_dir = normal_mat * generate_hemisphere_cosine_weighted_direction(noise);
  381. uint tidx;
  382. vec3 barycentric;
  383. vec3 light = vec3(0.0);
  384. uint trace_result = trace_ray(position + ray_dir * params.bias, position + ray_dir * length(params.world_size), tidx, barycentric);
  385. if (trace_result == RAY_FRONT) {
  386. //hit a triangle
  387. vec2 uv0 = vertices.data[triangles.data[tidx].indices.x].uv;
  388. vec2 uv1 = vertices.data[triangles.data[tidx].indices.y].uv;
  389. vec2 uv2 = vertices.data[triangles.data[tidx].indices.z].uv;
  390. vec3 uvw = vec3(barycentric.x * uv0 + barycentric.y * uv1 + barycentric.z * uv2, float(triangles.data[tidx].slice));
  391. light = textureLod(sampler2DArray(source_light, linear_sampler), uvw, 0.0).rgb;
  392. active_rays += 1.0;
  393. } else if (trace_result == RAY_MISS) {
  394. if (params.env_transform[0][3] == 0.0) { // Use env_transform[0][3] to indicate when we are computing the first bounce
  395. // Did not hit a triangle, reach out for the sky
  396. vec3 sky_dir = normalize(mat3(params.env_transform) * ray_dir);
  397. vec2 st = vec2(
  398. atan(sky_dir.x, sky_dir.z),
  399. acos(sky_dir.y));
  400. if (st.x < 0.0)
  401. st.x += PI * 2.0;
  402. st /= vec2(PI * 2.0, PI);
  403. light = textureLod(sampler2D(environment, linear_sampler), st, 0.0).rgb;
  404. }
  405. active_rays += 1.0;
  406. }
  407. light_average += light;
  408. #ifdef USE_SH_LIGHTMAPS
  409. float c[4] = float[](
  410. 0.282095, //l0
  411. 0.488603 * ray_dir.y, //l1n1
  412. 0.488603 * ray_dir.z, //l1n0
  413. 0.488603 * ray_dir.x //l1p1
  414. );
  415. for (uint j = 0; j < 4; j++) {
  416. sh_accum[j].rgb += light * c[j] * (8.0 / float(params.ray_count));
  417. }
  418. #endif
  419. }
  420. vec3 light_total;
  421. if (params.ray_from == 0) {
  422. light_total = vec3(0.0);
  423. } else {
  424. vec4 accum = imageLoad(bounce_accum, ivec3(atlas_pos, params.atlas_slice));
  425. light_total = accum.rgb;
  426. active_rays += accum.a;
  427. }
  428. light_total += light_average;
  429. #ifdef USE_SH_LIGHTMAPS
  430. for (int i = 0; i < 4; i++) {
  431. vec4 accum = imageLoad(accum_light, ivec3(atlas_pos, params.atlas_slice * 4 + i));
  432. accum.rgb += sh_accum[i].rgb;
  433. imageStore(accum_light, ivec3(atlas_pos, params.atlas_slice * 4 + i), accum);
  434. }
  435. #endif
  436. if (params.ray_to == params.ray_count) {
  437. if (active_rays > 0) {
  438. light_total /= active_rays;
  439. }
  440. imageStore(dest_light, ivec3(atlas_pos, params.atlas_slice), vec4(light_total, 1.0));
  441. #ifndef USE_SH_LIGHTMAPS
  442. vec4 accum = imageLoad(accum_light, ivec3(atlas_pos, params.atlas_slice));
  443. accum.rgb += light_total;
  444. imageStore(accum_light, ivec3(atlas_pos, params.atlas_slice), accum);
  445. #endif
  446. } else {
  447. imageStore(bounce_accum, ivec3(atlas_pos, params.atlas_slice), vec4(light_total, active_rays));
  448. }
  449. #endif
  450. #ifdef MODE_UNOCCLUDE
  451. //texel_size = 0.5;
  452. //compute tangents
  453. vec4 position_alpha = imageLoad(position, ivec3(atlas_pos, params.atlas_slice));
  454. if (position_alpha.a < 0.5) {
  455. return;
  456. }
  457. vec3 vertex_pos = position_alpha.xyz;
  458. vec4 normal_tsize = imageLoad(unocclude, ivec3(atlas_pos, params.atlas_slice));
  459. vec3 face_normal = normal_tsize.xyz;
  460. float texel_size = normal_tsize.w;
  461. vec3 v0 = abs(face_normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0);
  462. vec3 tangent = normalize(cross(v0, face_normal));
  463. vec3 bitangent = normalize(cross(tangent, face_normal));
  464. vec3 base_pos = vertex_pos + face_normal * params.bias; //raise a bit
  465. vec3 rays[4] = vec3[](tangent, bitangent, -tangent, -bitangent);
  466. float min_d = 1e20;
  467. for (int i = 0; i < 4; i++) {
  468. vec3 ray_to = base_pos + rays[i] * texel_size;
  469. float d;
  470. vec3 norm;
  471. if (trace_ray(base_pos, ray_to, d, norm) == RAY_BACK) {
  472. if (d < min_d) {
  473. vertex_pos = base_pos + rays[i] * d + norm * params.bias * 10.0; //this bias needs to be greater than the regular bias, because otherwise later, rays will go the other side when pointing back.
  474. min_d = d;
  475. }
  476. }
  477. }
  478. position_alpha.xyz = vertex_pos;
  479. imageStore(position, ivec3(atlas_pos, params.atlas_slice), position_alpha);
  480. #endif
  481. #ifdef MODE_LIGHT_PROBES
  482. vec3 position = probe_positions.data[probe_index].xyz;
  483. vec4 probe_sh_accum[9] = vec4[](
  484. vec4(0.0),
  485. vec4(0.0),
  486. vec4(0.0),
  487. vec4(0.0),
  488. vec4(0.0),
  489. vec4(0.0),
  490. vec4(0.0),
  491. vec4(0.0),
  492. vec4(0.0));
  493. uint noise = random_seed(ivec3(params.ray_from, probe_index, 49502741 /* some prime */));
  494. for (uint i = params.ray_from; i < params.ray_to; i++) {
  495. vec3 ray_dir = generate_hemisphere_uniform_direction(noise);
  496. if (bool(i & 1)) {
  497. //throw to both sides, so alternate them
  498. ray_dir.z *= -1.0;
  499. }
  500. uint tidx;
  501. vec3 barycentric;
  502. vec3 light;
  503. uint trace_result = trace_ray(position + ray_dir * params.bias, position + ray_dir * length(params.world_size), tidx, barycentric);
  504. if (trace_result == RAY_FRONT) {
  505. vec2 uv0 = vertices.data[triangles.data[tidx].indices.x].uv;
  506. vec2 uv1 = vertices.data[triangles.data[tidx].indices.y].uv;
  507. vec2 uv2 = vertices.data[triangles.data[tidx].indices.z].uv;
  508. vec3 uvw = vec3(barycentric.x * uv0 + barycentric.y * uv1 + barycentric.z * uv2, float(triangles.data[tidx].slice));
  509. light = textureLod(sampler2DArray(source_light, linear_sampler), uvw, 0.0).rgb;
  510. light += textureLod(sampler2DArray(source_direct_light, linear_sampler), uvw, 0.0).rgb;
  511. } else if (trace_result == RAY_MISS) {
  512. //did not hit a triangle, reach out for the sky
  513. vec3 sky_dir = normalize(mat3(params.env_transform) * ray_dir);
  514. vec2 st = vec2(
  515. atan(sky_dir.x, sky_dir.z),
  516. acos(sky_dir.y));
  517. if (st.x < 0.0)
  518. st.x += PI * 2.0;
  519. st /= vec2(PI * 2.0, PI);
  520. light = textureLod(sampler2D(environment, linear_sampler), st, 0.0).rgb;
  521. }
  522. {
  523. float c[9] = float[](
  524. 0.282095, //l0
  525. 0.488603 * ray_dir.y, //l1n1
  526. 0.488603 * ray_dir.z, //l1n0
  527. 0.488603 * ray_dir.x, //l1p1
  528. 1.092548 * ray_dir.x * ray_dir.y, //l2n2
  529. 1.092548 * ray_dir.y * ray_dir.z, //l2n1
  530. //0.315392 * (ray_dir.x * ray_dir.x + ray_dir.y * ray_dir.y + 2.0 * ray_dir.z * ray_dir.z), //l20
  531. 0.315392 * (3.0 * ray_dir.z * ray_dir.z - 1.0), //l20
  532. 1.092548 * ray_dir.x * ray_dir.z, //l2p1
  533. 0.546274 * (ray_dir.x * ray_dir.x - ray_dir.y * ray_dir.y) //l2p2
  534. );
  535. for (uint j = 0; j < 9; j++) {
  536. probe_sh_accum[j].rgb += light * c[j];
  537. }
  538. }
  539. }
  540. if (params.ray_from > 0) {
  541. for (uint j = 0; j < 9; j++) { //accum from existing
  542. probe_sh_accum[j] += light_probes.data[probe_index * 9 + j];
  543. }
  544. }
  545. if (params.ray_to == params.ray_count) {
  546. for (uint j = 0; j < 9; j++) { //accum from existing
  547. probe_sh_accum[j] *= 4.0 / float(params.ray_count);
  548. }
  549. }
  550. for (uint j = 0; j < 9; j++) { //accum from existing
  551. light_probes.data[probe_index * 9 + j] = probe_sh_accum[j];
  552. }
  553. #endif
  554. #ifdef MODE_DILATE
  555. vec4 c = texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos, params.atlas_slice), 0);
  556. //sides first, as they are closer
  557. c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(-1, 0), params.atlas_slice), 0);
  558. c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(0, 1), params.atlas_slice), 0);
  559. c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(1, 0), params.atlas_slice), 0);
  560. c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(0, -1), params.atlas_slice), 0);
  561. //endpoints second
  562. c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(-1, -1), params.atlas_slice), 0);
  563. c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(-1, 1), params.atlas_slice), 0);
  564. c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(1, -1), params.atlas_slice), 0);
  565. c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(1, 1), params.atlas_slice), 0);
  566. //far sides third
  567. c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(-2, 0), params.atlas_slice), 0);
  568. c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(0, 2), params.atlas_slice), 0);
  569. c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(2, 0), params.atlas_slice), 0);
  570. c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(0, -2), params.atlas_slice), 0);
  571. //far-mid endpoints
  572. c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(-2, -1), params.atlas_slice), 0);
  573. c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(-2, 1), params.atlas_slice), 0);
  574. c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(2, -1), params.atlas_slice), 0);
  575. c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(2, 1), params.atlas_slice), 0);
  576. c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(-1, -2), params.atlas_slice), 0);
  577. c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(-1, 2), params.atlas_slice), 0);
  578. c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(1, -2), params.atlas_slice), 0);
  579. c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(1, 2), params.atlas_slice), 0);
  580. //far endpoints
  581. c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(-2, -2), params.atlas_slice), 0);
  582. c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(-2, 2), params.atlas_slice), 0);
  583. c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(2, -2), params.atlas_slice), 0);
  584. c = c.a > 0.5 ? c : texelFetch(sampler2DArray(source_light, linear_sampler), ivec3(atlas_pos + ivec2(2, 2), params.atlas_slice), 0);
  585. imageStore(dest_light, ivec3(atlas_pos, params.atlas_slice), c);
  586. #endif
  587. }