strings.ts 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556
  1. function strings_error0(): string {
  2. return tr("Error: .arm file expected");
  3. }
  4. function strings_error1(): string {
  5. return tr("Error: Unknown asset format");
  6. }
  7. function strings_error2(): string {
  8. return tr("Error: Could not locate texture");
  9. }
  10. function strings_error3(): string {
  11. return tr("Error: Failed to read mesh data");
  12. }
  13. function strings_error5(): string {
  14. return tr("Error: Check internet connection to access the cloud");
  15. }
  16. function strings_info0(): string {
  17. return tr("Info: Asset already imported");
  18. }
  19. function strings_graphics_api(): string {
  20. ///if krom_direct3d11
  21. return "Direct3D11";
  22. ///elseif krom_direct3d12
  23. return "Direct3D12";
  24. ///elseif krom_metal
  25. return "Metal";
  26. ///elseif krom_vulkan
  27. return "Vulkan";
  28. ///else
  29. return "OpenGL";
  30. ///end
  31. }
  32. let str_tex_checker: string = " \
  33. vec3 tex_checker(const vec3 co, const vec3 col1, const vec3 col2, const float scale) { \
  34. // Prevent precision issues on unit coordinates \
  35. vec3 p = (co + 0.000001 * 0.999999) * scale; \
  36. float xi = abs(floor(p.x)); \
  37. float yi = abs(floor(p.y)); \
  38. float zi = abs(floor(p.z)); \
  39. bool check = ((mod(xi, 2.0) == mod(yi, 2.0)) == bool(mod(zi, 2.0))); \
  40. return check ? col1 : col2; \
  41. } \
  42. float tex_checker_f(const vec3 co, const float scale) { \
  43. vec3 p = (co + 0.000001 * 0.999999) * scale; \
  44. float xi = abs(floor(p.x)); \
  45. float yi = abs(floor(p.y)); \
  46. float zi = abs(floor(p.z)); \
  47. return float((mod(xi, 2.0) == mod(yi, 2.0)) == bool(mod(zi, 2.0))); \
  48. } \
  49. ";
  50. // Created by inigo quilez - iq/2013
  51. // License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
  52. let str_tex_voronoi: string = " \
  53. vec4 tex_voronoi(const vec3 x, textureArg(snoise256)) { \
  54. vec3 p = floor(x); \
  55. vec3 f = fract(x); \
  56. float id = 0.0; \
  57. float res = 100.0; \
  58. for (int k = -1; k <= 1; k++) \
  59. for (int j = -1; j <= 1; j++) \
  60. for (int i = -1; i <= 1; i++) { \
  61. vec3 b = vec3(float(i), float(j), float(k)); \
  62. vec3 pb = p + b; \
  63. vec3 r = vec3(b) - f + texture(snoise256, (pb.xy + vec2(3.0, 1.0) * pb.z + 0.5) / 256.0).xyz; \
  64. float d = dot(r, r); \
  65. if (d < res) { \
  66. id = dot(p + b, vec3(1.0, 57.0, 113.0)); \
  67. res = d; \
  68. } \
  69. } \
  70. vec3 col = 0.5 + 0.5 * cos(id * 0.35 + vec3(0.0, 1.0, 2.0)); \
  71. return vec4(col, sqrt(res)); \
  72. } \
  73. ";
  74. // By Morgan McGuire @morgan3d, http://graphicscodex.com Reuse permitted under the BSD license.
  75. // https://www.shadertoy.com/view/4dS3Wd
  76. let str_tex_noise: string = " \
  77. float hash(float n) { return fract(sin(n) * 1e4); } \
  78. float tex_noise_f(vec3 x) { \
  79. const vec3 step = vec3(110, 241, 171); \
  80. vec3 i = floor(x); \
  81. vec3 f = fract(x); \
  82. float n = dot(i, step); \
  83. vec3 u = f * f * (3.0 - 2.0 * f); \
  84. return mix(mix(mix(hash(n + dot(step, vec3(0, 0, 0))), hash(n + dot(step, vec3(1, 0, 0))), u.x), \
  85. mix(hash(n + dot(step, vec3(0, 1, 0))), hash(n + dot(step, vec3(1, 1, 0))), u.x), u.y), \
  86. mix(mix(hash(n + dot(step, vec3(0, 0, 1))), hash(n + dot(step, vec3(1, 0, 1))), u.x), \
  87. mix(hash(n + dot(step, vec3(0, 1, 1))), hash(n + dot(step, vec3(1, 1, 1))), u.x), u.y), u.z); \
  88. } \
  89. float tex_noise(vec3 p) { \
  90. p *= 1.25; \
  91. float f = 0.5 * tex_noise_f(p); p *= 2.01; \
  92. f += 0.25 * tex_noise_f(p); p *= 2.02; \
  93. f += 0.125 * tex_noise_f(p); p *= 2.03; \
  94. f += 0.0625 * tex_noise_f(p); \
  95. return 1.0 - f; \
  96. } \
  97. ";
  98. // Based on noise created by Nikita Miropolskiy, nikat/2013
  99. // Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
  100. let str_tex_musgrave: string = " \
  101. vec3 random3(const vec3 c) { \
  102. float j = 4096.0 * sin(dot(c, vec3(17.0, 59.4, 15.0))); \
  103. vec3 r; \
  104. r.z = fract(512.0 * j); \
  105. j *= 0.125; \
  106. r.x = fract(512.0 * j); \
  107. j *= 0.125; \
  108. r.y = fract(512.0 * j); \
  109. return r - 0.5; \
  110. } \
  111. float tex_musgrave_f(const vec3 p) { \
  112. const float F3 = 0.3333333; \
  113. const float G3 = 0.1666667; \
  114. vec3 s = floor(p + dot(p, vec3(F3, F3, F3))); \
  115. vec3 x = p - s + dot(s, vec3(G3, G3, G3)); \
  116. vec3 e = step(vec3(0.0, 0.0, 0.0), x - x.yzx); \
  117. vec3 i1 = e * (1.0 - e.zxy); \
  118. vec3 i2 = 1.0 - e.zxy * (1.0 - e); \
  119. vec3 x1 = x - i1 + G3; \
  120. vec3 x2 = x - i2 + 2.0 * G3; \
  121. vec3 x3 = x - 1.0 + 3.0 * G3; \
  122. vec4 w, d; \
  123. w.x = dot(x, x); \
  124. w.y = dot(x1, x1); \
  125. w.z = dot(x2, x2); \
  126. w.w = dot(x3, x3); \
  127. w = max(0.6 - w, 0.0); \
  128. d.x = dot(random3(s), x); \
  129. d.y = dot(random3(s + i1), x1); \
  130. d.z = dot(random3(s + i2), x2); \
  131. d.w = dot(random3(s + 1.0), x3); \
  132. w *= w; \
  133. w *= w; \
  134. d *= w; \
  135. return clamp(dot(d, vec4(52.0, 52.0, 52.0, 52.0)), 0.0, 1.0); \
  136. } \
  137. ";
  138. let str_hue_sat: string = " \
  139. vec3 hsv_to_rgb(const vec3 c) { \
  140. const vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); \
  141. vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); \
  142. return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); \
  143. } \
  144. vec3 rgb_to_hsv(const vec3 c) { \
  145. const vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0); \
  146. vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g)); \
  147. vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r)); \
  148. float d = q.x - min(q.w, q.y); \
  149. float e = 1.0e-10; \
  150. return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x); \
  151. } \
  152. vec3 hue_sat(const vec3 col, const vec4 shift) { \
  153. vec3 hsv = rgb_to_hsv(col); \
  154. hsv.x += shift.x; \
  155. hsv.y *= shift.y; \
  156. hsv.z *= shift.z; \
  157. return mix(hsv_to_rgb(hsv), col, shift.w); \
  158. } \
  159. ";
  160. // https://twitter.com/Donzanoid/status/903424376707657730
  161. let str_wavelength_to_rgb: string = " \
  162. vec3 wavelength_to_rgb(const float t) { \
  163. vec3 r = t * 2.1 - vec3(1.8, 1.14, 0.3); \
  164. return 1.0 - r * r; \
  165. } \
  166. ";
  167. let str_tex_magic: string = " \
  168. vec3 tex_magic(const vec3 p) { \
  169. float a = 1.0 - (sin(p.x) + sin(p.y)); \
  170. float b = 1.0 - sin(p.x - p.y); \
  171. float c = 1.0 - sin(p.x + p.y); \
  172. return vec3(a, b, c); \
  173. } \
  174. float tex_magic_f(const vec3 p) { \
  175. vec3 c = tex_magic(p); \
  176. return (c.x + c.y + c.z) / 3.0; \
  177. } \
  178. ";
  179. let str_tex_brick: string = " \
  180. float tex_brick_noise(int n) { \
  181. int nn; \
  182. n = (n >> 13) ^ n; \
  183. nn = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff; \
  184. return 0.5f * float(nn) / 1073741824.0; \
  185. } \
  186. vec3 tex_brick(vec3 p, const vec3 c1, const vec3 c2, const vec3 c3) { \
  187. vec3 brickSize = vec3(0.9, 0.49, 0.49); \
  188. vec3 mortarSize = vec3(0.05, 0.1, 0.1); \
  189. p /= brickSize / 2; \
  190. if (fract(p.y * 0.5) > 0.5) p.x += 0.5; \
  191. float col = floor(p.x / (brickSize.x + (mortarSize.x * 2.0))); \
  192. float row = p.y; \
  193. p = fract(p); \
  194. vec3 b = step(p, 1.0 - mortarSize); \
  195. float tint = min(max(tex_brick_noise((int(col) << 16) + (int(row) & 0xFFFF)), 0.0), 1.0); \
  196. return mix(c3, mix(c1, c2, tint), b.x * b.y * b.z); \
  197. } \
  198. float tex_brick_f(vec3 p) { \
  199. p /= vec3(0.9, 0.49, 0.49) / 2; \
  200. if (fract(p.y * 0.5) > 0.5) p.x += 0.5; \
  201. p = fract(p); \
  202. vec3 b = step(p, vec3(0.95, 0.9, 0.9)); \
  203. return mix(1.0, 0.0, b.x * b.y * b.z); \
  204. } \
  205. ";
  206. let str_tex_wave: string = " \
  207. float tex_wave_f(const vec3 p) { \
  208. return 1.0 - sin((p.x + p.y) * 10.0); \
  209. } \
  210. ";
  211. let str_brightcontrast: string = " \
  212. vec3 brightcontrast(const vec3 col, const float bright, const float contr) { \
  213. float a = 1.0 + contr; \
  214. float b = bright - contr * 0.5; \
  215. return max(a * col + b, 0.0); \
  216. } \
  217. ";
  218. ///if arm_voxels
  219. let str_trace_ao: string = " \
  220. float traceConeAO(sampler3D voxels, const vec3 origin, vec3 dir, const float aperture, const float maxDist, const float offset) { \
  221. const ivec3 voxelgiResolution = ivec3(256, 256, 256); \
  222. const float voxelgiStep = 1.0; \
  223. const float VOXEL_SIZE = (2.0 / voxelgiResolution.x) * voxelgiStep; \
  224. dir = normalize(dir); \
  225. float sampleCol = 0.0; \
  226. float dist = offset; \
  227. float diam = dist * aperture; \
  228. vec3 samplePos; \
  229. while (sampleCol < 1.0 && dist < maxDist) { \
  230. samplePos = dir * dist + origin; \
  231. float mip = max(log2(diam * voxelgiResolution.x), 0); \
  232. float mipSample = textureLod(voxels, samplePos * 0.5 + vec3(0.5, 0.5, 0.5), mip).r; \
  233. sampleCol += (1 - sampleCol) * mipSample; \
  234. dist += max(diam / 2, VOXEL_SIZE); \
  235. diam = dist * aperture; \
  236. } \
  237. return sampleCol; \
  238. } \
  239. vec3 tangent(const vec3 n) { \
  240. vec3 t1 = cross(n, vec3(0, 0, 1)); \
  241. vec3 t2 = cross(n, vec3(0, 1, 0)); \
  242. if (length(t1) > length(t2)) return normalize(t1); \
  243. else return normalize(t2); \
  244. } \
  245. float traceAO(const vec3 origin, const vec3 normal, const float vrange, const float voffset) { \
  246. const float angleMix = 0.5f; \
  247. const float aperture = 0.55785173935; \
  248. vec3 o1 = normalize(tangent(normal)); \
  249. vec3 o2 = normalize(cross(o1, normal)); \
  250. vec3 c1 = 0.5f * (o1 + o2); \
  251. vec3 c2 = 0.5f * (o1 - o2); \
  252. float MAX_DISTANCE = 1.73205080757 * 2.0 * vrange; \
  253. const ivec3 voxelgiResolution = ivec3(256, 256, 256); \
  254. const float voxelgiStep = 1.0; \
  255. const float VOXEL_SIZE = (2.0 / voxelgiResolution.x) * voxelgiStep; \
  256. float offset = 1.5 * VOXEL_SIZE * 2.5 * voffset; \
  257. float col = traceConeAO(voxels, origin, normal, aperture, MAX_DISTANCE, offset); \
  258. col += traceConeAO(voxels, origin, mix(normal, o1, angleMix), aperture, MAX_DISTANCE, offset); \
  259. col += traceConeAO(voxels, origin, mix(normal, o2, angleMix), aperture, MAX_DISTANCE, offset); \
  260. col += traceConeAO(voxels, origin, mix(normal, -c1, angleMix), aperture, MAX_DISTANCE, offset); \
  261. col += traceConeAO(voxels, origin, mix(normal, -c2, angleMix), aperture, MAX_DISTANCE, offset); \
  262. col += traceConeAO(voxels, origin, mix(normal, -o1, angleMix), aperture, MAX_DISTANCE, offset); \
  263. col += traceConeAO(voxels, origin, mix(normal, -o2, angleMix), aperture, MAX_DISTANCE, offset); \
  264. col += traceConeAO(voxels, origin, mix(normal, c1, angleMix), aperture, MAX_DISTANCE, offset); \
  265. col += traceConeAO(voxels, origin, mix(normal, c2, angleMix), aperture, MAX_DISTANCE, offset); \
  266. return col / 9.0; \
  267. } \
  268. ";
  269. ///end
  270. let str_cotangent_frame: string = " \
  271. mat3 cotangentFrame(const vec3 n, const vec3 p, const vec2 duv1, const vec2 duv2) { \
  272. vec3 dp1 = dFdx(p); \
  273. vec3 dp2 = dFdy(p); \
  274. vec3 dp2perp = cross(dp2, n); \
  275. vec3 dp1perp = cross(n, dp1); \
  276. vec3 t = dp2perp * duv1.x + dp1perp * duv2.x; \
  277. vec3 b = dp2perp * duv1.y + dp1perp * duv2.y; \
  278. float invmax = inversesqrt(max(dot(t, t), dot(b, b))); \
  279. return mat3(t * invmax, b * invmax, n); \
  280. } \
  281. mat3 cotangentFrame(const vec3 n, const vec3 p, const vec2 texCoord) { \
  282. return cotangentFrame(n, p, dFdx(texCoord), dFdy(texCoord)); \
  283. } \
  284. ";
  285. let str_octahedron_wrap: string = " \
  286. vec2 octahedronWrap(const vec2 v) { \
  287. return (1.0 - abs(v.yx)) * (vec2(v.x >= 0.0 ? 1.0 : -1.0, v.y >= 0.0 ? 1.0 : -1.0)); \
  288. } \
  289. ";
  290. let str_pack_float_int16: string = " \
  291. float packFloatInt16(const float f, const uint i) { \
  292. const float prec = float(1 << 16); \
  293. const float maxi = float(1 << 4); \
  294. const float precMinusOne = prec - 1.0; \
  295. const float t1 = ((prec / maxi) - 1.0) / precMinusOne; \
  296. const float t2 = (prec / maxi) / precMinusOne; \
  297. return t1 * f + t2 * float(i); \
  298. } \
  299. ";
  300. ///if arm_skin
  301. let str_get_skinning_dual_quat: string = " \
  302. void getSkinningDualQuat(const ivec4 bone, vec4 weight, out vec4 A, inout vec4 B) { \
  303. ivec4 bonei = bone * 2; \
  304. mat4 matA = mat4( \
  305. skinBones[bonei.x], \
  306. skinBones[bonei.y], \
  307. skinBones[bonei.z], \
  308. skinBones[bonei.w]); \
  309. mat4 matB = mat4( \
  310. skinBones[bonei.x + 1], \
  311. skinBones[bonei.y + 1], \
  312. skinBones[bonei.z + 1], \
  313. skinBones[bonei.w + 1]); \
  314. weight.xyz *= sign(mul(matA, matA[3])).xyz; \
  315. A = mul(weight, matA); \
  316. B = mul(weight, matB); \
  317. float invNormA = 1.0 / length(A); \
  318. A *= invNormA; \
  319. B *= invNormA; \
  320. } \
  321. ";
  322. ///end
  323. let str_create_basis: string = " \
  324. void createBasis(vec3 normal, out vec3 tangent, out vec3 binormal) { \
  325. tangent = normalize(cameraRight - normal * dot(cameraRight, normal)); \
  326. binormal = cross(tangent, normal); \
  327. } \
  328. ";
  329. function str_sh_irradiance(): string {
  330. ///if krom_metal
  331. return "vec3 shIrradiance(const vec3 nor, constant vec4 shirr[7]) { \
  332. const float c1 = 0.429043; \
  333. const float c2 = 0.511664; \
  334. const float c3 = 0.743125; \
  335. const float c4 = 0.886227; \
  336. const float c5 = 0.247708; \
  337. vec3 cl00 = vec3(shirr[0].x, shirr[0].y, shirr[0].z); \
  338. vec3 cl1m1 = vec3(shirr[0].w, shirr[1].x, shirr[1].y); \
  339. vec3 cl10 = vec3(shirr[1].z, shirr[1].w, shirr[2].x); \
  340. vec3 cl11 = vec3(shirr[2].y, shirr[2].z, shirr[2].w); \
  341. vec3 cl2m2 = vec3(shirr[3].x, shirr[3].y, shirr[3].z); \
  342. vec3 cl2m1 = vec3(shirr[3].w, shirr[4].x, shirr[4].y); \
  343. vec3 cl20 = vec3(shirr[4].z, shirr[4].w, shirr[5].x); \
  344. vec3 cl21 = vec3(shirr[5].y, shirr[5].z, shirr[5].w); \
  345. vec3 cl22 = vec3(shirr[6].x, shirr[6].y, shirr[6].z); \
  346. return ( \
  347. c1 * cl22 * (nor.y * nor.y - (-nor.z) * (-nor.z)) + \
  348. c3 * cl20 * nor.x * nor.x + \
  349. c4 * cl00 - \
  350. c5 * cl20 + \
  351. 2.0 * c1 * cl2m2 * nor.y * (-nor.z) + \
  352. 2.0 * c1 * cl21 * nor.y * nor.x + \
  353. 2.0 * c1 * cl2m1 * (-nor.z) * nor.x + \
  354. 2.0 * c2 * cl11 * nor.y + \
  355. 2.0 * c2 * cl1m1 * (-nor.z) + \
  356. 2.0 * c2 * cl10 * nor.x \
  357. ); \
  358. } \
  359. ";
  360. ///else
  361. return "vec3 shIrradiance(const vec3 nor, const vec4 shirr[7]) { \
  362. const float c1 = 0.429043; \
  363. const float c2 = 0.511664; \
  364. const float c3 = 0.743125; \
  365. const float c4 = 0.886227; \
  366. const float c5 = 0.247708; \
  367. vec3 cl00 = vec3(shirr[0].x, shirr[0].y, shirr[0].z); \
  368. vec3 cl1m1 = vec3(shirr[0].w, shirr[1].x, shirr[1].y); \
  369. vec3 cl10 = vec3(shirr[1].z, shirr[1].w, shirr[2].x); \
  370. vec3 cl11 = vec3(shirr[2].y, shirr[2].z, shirr[2].w); \
  371. vec3 cl2m2 = vec3(shirr[3].x, shirr[3].y, shirr[3].z); \
  372. vec3 cl2m1 = vec3(shirr[3].w, shirr[4].x, shirr[4].y); \
  373. vec3 cl20 = vec3(shirr[4].z, shirr[4].w, shirr[5].x); \
  374. vec3 cl21 = vec3(shirr[5].y, shirr[5].z, shirr[5].w); \
  375. vec3 cl22 = vec3(shirr[6].x, shirr[6].y, shirr[6].z); \
  376. return ( \
  377. c1 * cl22 * (nor.y * nor.y - (-nor.z) * (-nor.z)) + \
  378. c3 * cl20 * nor.x * nor.x + \
  379. c4 * cl00 - \
  380. c5 * cl20 + \
  381. 2.0 * c1 * cl2m2 * nor.y * (-nor.z) + \
  382. 2.0 * c1 * cl21 * nor.y * nor.x + \
  383. 2.0 * c1 * cl2m1 * (-nor.z) * nor.x + \
  384. 2.0 * c2 * cl11 * nor.y + \
  385. 2.0 * c2 * cl1m1 * (-nor.z) + \
  386. 2.0 * c2 * cl10 * nor.x \
  387. ); \
  388. } \
  389. ";
  390. ///end
  391. }
  392. let str_envmap_equirect: string = " \
  393. vec2 envMapEquirect(const vec3 normal, const float angle) { \
  394. const float PI = 3.1415926535; \
  395. const float PI2 = PI * 2.0; \
  396. float phi = acos(normal.z); \
  397. float theta = atan2(-normal.y, normal.x) + PI + angle; \
  398. return vec2(theta / PI2, phi / PI); \
  399. } \
  400. ";
  401. // Linearly Transformed Cosines
  402. // https://eheitzresearch.wordpress.com/415-2/
  403. let str_ltc_evaluate: string = " \
  404. float integrateEdge(vec3 v1, vec3 v2) { \
  405. float cosTheta = dot(v1, v2); \
  406. float theta = acos(cosTheta); \
  407. float res = cross(v1, v2).z * ((theta > 0.001) ? theta / sin(theta) : 1.0); \
  408. return res; \
  409. } \
  410. float ltcEvaluate(vec3 N, vec3 V, float dotNV, vec3 P, mat3 Minv, vec3 points0, vec3 points1, vec3 points2, vec3 points3) { \
  411. vec3 T1 = normalize(V - N * dotNV); \
  412. vec3 T2 = cross(N, T1); \
  413. Minv = mul(transpose(mat3(T1, T2, N)), Minv); \
  414. vec3 L0 = mul((points0 - P), Minv); \
  415. vec3 L1 = mul((points1 - P), Minv); \
  416. vec3 L2 = mul((points2 - P), Minv); \
  417. vec3 L3 = mul((points3 - P), Minv); \
  418. vec3 L4 = vec3(0.0, 0.0, 0.0); \
  419. int n = 0; \
  420. int config = 0; \
  421. if (L0.z > 0.0) config += 1; \
  422. if (L1.z > 0.0) config += 2; \
  423. if (L2.z > 0.0) config += 4; \
  424. if (L3.z > 0.0) config += 8; \
  425. if (config == 0) {} \
  426. else if (config == 1) { \
  427. n = 3; \
  428. L1 = -L1.z * L0 + L0.z * L1; \
  429. L2 = -L3.z * L0 + L0.z * L3; \
  430. } \
  431. else if (config == 2) { \
  432. n = 3; \
  433. L0 = -L0.z * L1 + L1.z * L0; \
  434. L2 = -L2.z * L1 + L1.z * L2; \
  435. } \
  436. else if (config == 3) { \
  437. n = 4; \
  438. L2 = -L2.z * L1 + L1.z * L2; \
  439. L3 = -L3.z * L0 + L0.z * L3; \
  440. } \
  441. else if (config == 4) { \
  442. n = 3; \
  443. L0 = -L3.z * L2 + L2.z * L3; \
  444. L1 = -L1.z * L2 + L2.z * L1; \
  445. } \
  446. else if (config == 5) { n = 0; } \
  447. else if (config == 6) { \
  448. n = 4; \
  449. L0 = -L0.z * L1 + L1.z * L0; \
  450. L3 = -L3.z * L2 + L2.z * L3; \
  451. } \
  452. else if (config == 7) { \
  453. n = 5; \
  454. L4 = -L3.z * L0 + L0.z * L3; \
  455. L3 = -L3.z * L2 + L2.z * L3; \
  456. } \
  457. else if (config == 8) { \
  458. n = 3; \
  459. L0 = -L0.z * L3 + L3.z * L0; \
  460. L1 = -L2.z * L3 + L3.z * L2; \
  461. L2 = L3; \
  462. } \
  463. else if (config == 9) { \
  464. n = 4; \
  465. L1 = -L1.z * L0 + L0.z * L1; \
  466. L2 = -L2.z * L3 + L3.z * L2; \
  467. } \
  468. else if (config == 10) { n = 0; } \
  469. else if (config == 11) { \
  470. n = 5; \
  471. L4 = L3; \
  472. L3 = -L2.z * L3 + L3.z * L2; \
  473. L2 = -L2.z * L1 + L1.z * L2; \
  474. } \
  475. else if (config == 12) { \
  476. n = 4; \
  477. L1 = -L1.z * L2 + L2.z * L1; \
  478. L0 = -L0.z * L3 + L3.z * L0; \
  479. } \
  480. else if (config == 13) { \
  481. n = 5; \
  482. L4 = L3; \
  483. L3 = L2; \
  484. L2 = -L1.z * L2 + L2.z * L1; \
  485. L1 = -L1.z * L0 + L0.z * L1; \
  486. } \
  487. else if (config == 14) { \
  488. n = 5; \
  489. L4 = -L0.z * L3 + L3.z * L0; \
  490. L0 = -L0.z * L1 + L1.z * L0; \
  491. } \
  492. else if (config == 15) { n = 4; } \
  493. if (n == 0) return 0.0; \
  494. if (n == 3) L3 = L0; \
  495. if (n == 4) L4 = L0; \
  496. L0 = normalize(L0); \
  497. L1 = normalize(L1); \
  498. L2 = normalize(L2); \
  499. L3 = normalize(L3); \
  500. L4 = normalize(L4); \
  501. float sum = 0.0; \
  502. sum += integrateEdge(L0, L1); \
  503. sum += integrateEdge(L1, L2); \
  504. sum += integrateEdge(L2, L3); \
  505. if (n >= 4) sum += integrateEdge(L3, L4); \
  506. if (n == 5) sum += integrateEdge(L4, L0); \
  507. return max(0.0, -sum); \
  508. } \
  509. ";
  510. let str_get_pos_from_depth: string = " \
  511. vec3 get_pos_from_depth(vec2 uv, mat4 invVP, textureArg(gbufferD)) { \
  512. #if defined(HLSL) || defined(METAL) || defined(SPIRV) \
  513. float depth = textureLod(gbufferD, vec2(uv.x, 1.0 - uv.y), 0.0).r; \
  514. #else \
  515. float depth = textureLod(gbufferD, uv, 0.0).r; \
  516. #endif \
  517. vec4 wpos = vec4(uv * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0); \
  518. wpos = mul(wpos, invVP); \
  519. return wpos.xyz / wpos.w; \
  520. } \
  521. ";
  522. let str_get_nor_from_depth: string = " \
  523. vec3 get_nor_from_depth(vec3 p0, vec2 uv, mat4 invVP, vec2 texStep, textureArg(gbufferD)) { \
  524. vec3 p1 = get_pos_from_depth(uv + vec2(texStep.x * 4.0, 0.0), invVP, texturePass(gbufferD)); \
  525. vec3 p2 = get_pos_from_depth(uv + vec2(0.0, texStep.y * 4.0), invVP, texturePass(gbufferD)); \
  526. return normalize(cross(p2 - p0, p1 - p0)); \
  527. } \
  528. ";