par_bluenoise.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563
  1. // BLUENOISE :: https://github.com/prideout/par
  2. // Generator for infinite 2D point sequences using Recursive Wang Tiles.
  3. //
  4. // In addition to this source code, you'll need to download one of the following
  5. // tilesets, the first being 2 MB while the other is 257 KB. The latter cheats
  6. // by referencing the point sequence from the first tile for all 8 tiles. This
  7. // obviously produces poor results, but in many contexts, it isn't noticeable.
  8. //
  9. // https://prideout.net/assets/bluenoise.bin
  10. // https://prideout.net/assets/bluenoise.trimmed.bin
  11. //
  12. // The code herein is an implementation of the algorithm described in:
  13. //
  14. // Recursive Wang Tiles for Real-Time Blue Noise
  15. // Johannes Kopf, Daniel Cohen-Or, Oliver Deussen, Dani Lischinski
  16. // ACM Transactions on Graphics 25, 3 (Proc. SIGGRAPH 2006)
  17. //
  18. // If you use this software for research purposes, please cite the above paper
  19. // in any resulting publication.
  20. //
  21. // EXAMPLE
  22. //
  23. // Generate point samples whose density is guided by a 512x512 grayscale image:
  24. //
  25. // int npoints;
  26. // float* points;
  27. // int maxpoints = 1e6;
  28. // float density = 30000;
  29. // par_bluenoise_context* ctx;
  30. // ctx = par_bluenoise_from_file("bluenoise.bin", maxpoints);
  31. // par_bluenoise_density_from_gray(ctx, source_pixels, 512, 512, 1);
  32. // points = par_bluenoise_generate(ctx, density, &npoints);
  33. // ... Draw points here. Each point is a three-tuple of (X Y RANK).
  34. // par_bluenoise_free(ctx);
  35. //
  36. // Distributed under the MIT License, see bottom of file.
  37. #ifndef PAR_BLUENOISE_H
  38. #define PAR_BLUENOISE_H
  39. #ifdef __cplusplus
  40. extern "C" {
  41. #endif
  42. // -----------------------------------------------------------------------------
  43. // BEGIN PUBLIC API
  44. // -----------------------------------------------------------------------------
  45. typedef unsigned char par_byte;
  46. // Encapsulates a tile set and an optional density function.
  47. typedef struct par_bluenoise_context_s par_bluenoise_context;
  48. // Creates a bluenoise context using the given tileset. The first argument is
  49. // the file path the bin file. The second argument is the maximum number of
  50. // points that you expect to ever be generated.
  51. par_bluenoise_context* par_bluenoise_from_file(char const* path, int maxpts);
  52. // Creates a bluenoise context using the given tileset. The first and second
  53. // arguments describe a memory buffer containing the contents of the bin file.
  54. // The third argument is the maximum number of points that you expect to ever
  55. // be generated.
  56. par_bluenoise_context* par_bluenoise_from_buffer(
  57. par_byte const* buffer, int nbytes, int maxpts);
  58. // Sets up a scissoring rectangle using the given lower-left and upper-right
  59. // coordinates. By default the scissor encompasses [-0.5, -0.5] - [0.5, 0.5],
  60. // which is the entire sampling domain for the two "generate" methods.
  61. void par_bluenoise_set_viewport(
  62. par_bluenoise_context*, float left, float bottom, float right, float top);
  63. // Sets up a reference window size. The only purpose of this is to ensure
  64. // that apparent density remains constant when the window gets resized.
  65. // Clients should call this *before* calling par_bluenoise_set_viewport.
  66. void par_bluenoise_set_window(par_bluenoise_context*, int width, int height);
  67. // Frees all memory associated with the given bluenoise context.
  68. void par_bluenoise_free(par_bluenoise_context* ctx);
  69. // Copies a grayscale image into the bluenoise context to guide point density.
  70. // Darker regions generate a higher number of points. The given bytes-per-pixel
  71. // value is the stride between pixels.
  72. void par_bluenoise_density_from_gray(par_bluenoise_context* ctx,
  73. const unsigned char* pixels, int width, int height, int bpp);
  74. // Creates a binary mask to guide point density. The given bytes-per-pixel
  75. // value is the stride between pixels, which must be 4 or less.
  76. void par_bluenoise_density_from_color(par_bluenoise_context* ctx,
  77. const unsigned char* pixels, int width, int height, int bpp,
  78. unsigned int background_color, int invert);
  79. // Generates samples using Recursive Wang Tiles. This is really fast!
  80. // The returned pointer is a list of three-tuples, where XY are in [-0.5, +0.5]
  81. // and Z is a rank value that can be used to create a progressive ordering.
  82. // The caller should not free the returned pointer.
  83. float* par_bluenoise_generate(
  84. par_bluenoise_context* ctx, float density, int* npts);
  85. // Generates an ordered sequence of tuples with the specified sequence length.
  86. // This is slower than the other "generate" method because it uses a dumb
  87. // backtracking method to determine a reasonable density value, and it
  88. // automatically sorts the output by rank. The dims argument must be 2 or more;
  89. // it represents the desired stride (in floats) between consecutive verts in the
  90. // returned data buffer.
  91. float* par_bluenoise_generate_exact(
  92. par_bluenoise_context* ctx, int npts, int dims);
  93. // Performs an in-place sort of 3-tuples, based on the 3rd component, then
  94. // replaces the 3rd component with an index.
  95. void par_bluenoise_sort_by_rank(float* pts, int npts);
  96. #ifndef PAR_PI
  97. #define PAR_PI (3.14159265359)
  98. #define PAR_MIN(a, b) (a > b ? b : a)
  99. #define PAR_MAX(a, b) (a > b ? a : b)
  100. #define PAR_CLAMP(v, lo, hi) PAR_MAX(lo, PAR_MIN(hi, v))
  101. #define PAR_SWAP(T, A, B) { T tmp = B; B = A; A = tmp; }
  102. #define PAR_SQR(a) ((a) * (a))
  103. #endif
  104. #ifndef PAR_MALLOC
  105. #define PAR_MALLOC(T, N) ((T*) malloc(N * sizeof(T)))
  106. #define PAR_CALLOC(T, N) ((T*) calloc(N * sizeof(T), 1))
  107. #define PAR_REALLOC(T, BUF, N) ((T*) realloc(BUF, sizeof(T) * (N)))
  108. #define PAR_FREE(BUF) free(BUF)
  109. #endif
  110. #ifdef __cplusplus
  111. }
  112. #endif
  113. // -----------------------------------------------------------------------------
  114. // END PUBLIC API
  115. // -----------------------------------------------------------------------------
  116. #ifdef PAR_BLUENOISE_IMPLEMENTATION
  117. #include <stdio.h>
  118. #include <stdlib.h>
  119. #include <assert.h>
  120. #include <math.h>
  121. #include <string.h>
  122. #define PAR_MINI(a, b) ((a < b) ? a : b)
  123. #define PAR_MAXI(a, b) ((a > b) ? a : b)
  124. typedef struct {
  125. float x;
  126. float y;
  127. } par_vec2;
  128. typedef struct {
  129. float x;
  130. float y;
  131. float rank;
  132. } par_vec3;
  133. typedef struct {
  134. int n, e, s, w;
  135. int nsubtiles, nsubdivs, npoints, nsubpts;
  136. int** subdivs;
  137. par_vec2* points;
  138. par_vec2* subpts;
  139. } par_tile;
  140. struct par_bluenoise_context_s {
  141. par_vec3* points;
  142. par_tile* tiles;
  143. float global_density;
  144. float left, bottom, right, top;
  145. int ntiles, nsubtiles, nsubdivs;
  146. int npoints;
  147. int maxpoints;
  148. int density_width;
  149. int density_height;
  150. unsigned char* density;
  151. float mag;
  152. int window_width;
  153. int window_height;
  154. int abridged;
  155. };
  156. static float sample_density(par_bluenoise_context* ctx, float x, float y)
  157. {
  158. unsigned char* density = ctx->density;
  159. if (!density) {
  160. return 1;
  161. }
  162. int width = ctx->density_width;
  163. int height = ctx->density_height;
  164. y = 1 - y;
  165. x -= 0.5;
  166. y -= 0.5;
  167. float tx = x * PAR_MAXI(width, height);
  168. float ty = y * PAR_MAXI(width, height);
  169. x += 0.5;
  170. y += 0.5;
  171. tx += width / 2;
  172. ty += height / 2;
  173. int ix = PAR_CLAMP((int) tx, 0, width - 2);
  174. int iy = PAR_CLAMP((int) ty, 0, height - 2);
  175. return density[iy * width + ix] / 255.0f;
  176. }
  177. static void recurse_tile(
  178. par_bluenoise_context* ctx, par_tile* tile, float x, float y, int level)
  179. {
  180. float left = ctx->left, right = ctx->right;
  181. float top = ctx->top, bottom = ctx->bottom;
  182. float mag = ctx->mag;
  183. float tileSize = 1.f / powf(ctx->nsubtiles, level);
  184. if (x + tileSize < left || x > right || y + tileSize < bottom || y > top) {
  185. return;
  186. }
  187. float depth = powf(ctx->nsubtiles, 2 * level);
  188. float threshold = mag / depth * ctx->global_density - tile->npoints;
  189. int ntests = PAR_MINI(tile->nsubpts, threshold);
  190. float factor = 1.f / mag * depth / ctx->global_density;
  191. for (int i = 0; i < ntests; i++) {
  192. float px = x + tile->subpts[i].x * tileSize;
  193. float py = y + tile->subpts[i].y * tileSize;
  194. if (px < left || px > right || py < bottom || py > top) {
  195. continue;
  196. }
  197. if (sample_density(ctx, px, py) < (i + tile->npoints) * factor) {
  198. continue;
  199. }
  200. ctx->points[ctx->npoints].x = px - 0.5;
  201. ctx->points[ctx->npoints].y = py - 0.5;
  202. ctx->points[ctx->npoints].rank = (level + 1) + i * factor;
  203. ctx->npoints++;
  204. if (ctx->npoints >= ctx->maxpoints) {
  205. return;
  206. }
  207. }
  208. const float scale = tileSize / ctx->nsubtiles;
  209. if (threshold <= tile->nsubpts) {
  210. return;
  211. }
  212. level++;
  213. for (int ty = 0; ty < ctx->nsubtiles; ty++) {
  214. for (int tx = 0; tx < ctx->nsubtiles; tx++) {
  215. int tileIndex = tile->subdivs[0][ty * ctx->nsubtiles + tx];
  216. par_tile* subtile = &ctx->tiles[tileIndex];
  217. recurse_tile(ctx, subtile, x + tx * scale, y + ty * scale, level);
  218. }
  219. }
  220. }
  221. void par_bluenoise_set_window(par_bluenoise_context* ctx, int width, int height)
  222. {
  223. ctx->window_width = width;
  224. ctx->window_height = height;
  225. }
  226. void par_bluenoise_set_viewport(par_bluenoise_context* ctx, float left,
  227. float bottom, float right, float top)
  228. {
  229. // Transform [-.5, +.5] to [0, 1]
  230. left = ctx->left = left + 0.5;
  231. right = ctx->right = right + 0.5;
  232. bottom = ctx->bottom = bottom + 0.5;
  233. top = ctx->top = top + 0.5;
  234. // Determine magnification factor BEFORE clamping.
  235. float scale = 1000 * (top - bottom) / ctx->window_height;
  236. ctx->mag = powf(scale, -2);
  237. // The density function is only sampled in [0, +1].
  238. ctx->left = PAR_CLAMP(left, 0, 1);
  239. ctx->right = PAR_CLAMP(right, 0, 1);
  240. ctx->bottom = PAR_CLAMP(bottom, 0, 1);
  241. ctx->top = PAR_CLAMP(top, 0, 1);
  242. }
  243. float* par_bluenoise_generate(
  244. par_bluenoise_context* ctx, float density, int* npts)
  245. {
  246. ctx->global_density = density;
  247. ctx->npoints = 0;
  248. float left = ctx->left;
  249. float right = ctx->right;
  250. float bottom = ctx->bottom;
  251. float top = ctx->top;
  252. float mag = ctx->mag;
  253. int ntests = PAR_MINI(ctx->tiles[0].npoints, mag * ctx->global_density);
  254. float factor = 1.f / mag / ctx->global_density;
  255. for (int i = 0; i < ntests; i++) {
  256. float px = ctx->tiles[0].points[i].x;
  257. float py = ctx->tiles[0].points[i].y;
  258. if (px < left || px > right || py < bottom || py > top) {
  259. continue;
  260. }
  261. if (sample_density(ctx, px, py) < (i + 1) * factor) {
  262. continue;
  263. }
  264. ctx->points[ctx->npoints].x = px - 0.5;
  265. ctx->points[ctx->npoints].y = py - 0.5;
  266. ctx->points[ctx->npoints].rank = i * factor;
  267. ctx->npoints++;
  268. if (ctx->npoints >= ctx->maxpoints) {
  269. break;
  270. }
  271. }
  272. recurse_tile(ctx, &ctx->tiles[0], 0, 0, 0);
  273. *npts = ctx->npoints;
  274. return &ctx->points->x;
  275. }
  276. #define freadi() \
  277. *((int*) ptr); \
  278. ptr += sizeof(int)
  279. #define freadf() \
  280. *((float*) ptr); \
  281. ptr += sizeof(float)
  282. static par_bluenoise_context* par_bluenoise_create(
  283. char const* filepath, int nbytes, int maxpts)
  284. {
  285. par_bluenoise_context* ctx = PAR_MALLOC(par_bluenoise_context, 1);
  286. ctx->maxpoints = maxpts;
  287. ctx->points = PAR_MALLOC(par_vec3, maxpts);
  288. ctx->density = 0;
  289. ctx->abridged = 0;
  290. par_bluenoise_set_window(ctx, 1024, 768);
  291. par_bluenoise_set_viewport(ctx, -.5, -.5, .5, .5);
  292. char* buf = 0;
  293. if (nbytes == 0) {
  294. FILE* fin = fopen(filepath, "rb");
  295. assert(fin);
  296. fseek(fin, 0, SEEK_END);
  297. nbytes = (int) ftell(fin);
  298. fseek(fin, 0, SEEK_SET);
  299. buf = PAR_MALLOC(char, nbytes);
  300. int consumed = (int) fread(buf, nbytes, 1, fin);
  301. assert(consumed == 1);
  302. fclose(fin);
  303. }
  304. char const* ptr = buf ? buf : filepath;
  305. int ntiles = ctx->ntiles = freadi();
  306. int nsubtiles = ctx->nsubtiles = freadi();
  307. int nsubdivs = ctx->nsubdivs = freadi();
  308. par_tile* tiles = ctx->tiles = PAR_MALLOC(par_tile, ntiles);
  309. for (int i = 0; i < ntiles; i++) {
  310. tiles[i].n = freadi();
  311. tiles[i].e = freadi();
  312. tiles[i].s = freadi();
  313. tiles[i].w = freadi();
  314. tiles[i].subdivs = PAR_MALLOC(int*, nsubdivs);
  315. for (int j = 0; j < nsubdivs; j++) {
  316. int* subdiv = PAR_MALLOC(int, PAR_SQR(nsubtiles));
  317. for (int k = 0; k < PAR_SQR(nsubtiles); k++) {
  318. subdiv[k] = freadi();
  319. }
  320. tiles[i].subdivs[j] = subdiv;
  321. }
  322. tiles[i].npoints = freadi();
  323. tiles[i].points = PAR_MALLOC(par_vec2, tiles[i].npoints);
  324. for (int j = 0; j < tiles[i].npoints; j++) {
  325. tiles[i].points[j].x = freadf();
  326. tiles[i].points[j].y = freadf();
  327. }
  328. tiles[i].nsubpts = freadi();
  329. tiles[i].subpts = PAR_MALLOC(par_vec2, tiles[i].nsubpts);
  330. for (int j = 0; j < tiles[i].nsubpts; j++) {
  331. tiles[i].subpts[j].x = freadf();
  332. tiles[i].subpts[j].y = freadf();
  333. }
  334. // The following hack allows for an optimization whereby
  335. // the first tile's point set is re-used for every other tile.
  336. // This goes against the entire purpose of Recursive Wang Tiles,
  337. // but in many applications the qualatitive loss is not
  338. // observable, and the footprint savings are huge (10x).
  339. if (tiles[i].npoints == 0) {
  340. ctx->abridged = 1;
  341. tiles[i].npoints = tiles[0].npoints;
  342. tiles[i].points = tiles[0].points;
  343. tiles[i].nsubpts = tiles[0].nsubpts;
  344. tiles[i].subpts = tiles[0].subpts;
  345. }
  346. }
  347. free(buf);
  348. return ctx;
  349. }
  350. par_bluenoise_context* par_bluenoise_from_file(char const* path, int maxpts)
  351. {
  352. return par_bluenoise_create(path, 0, maxpts);
  353. }
  354. par_bluenoise_context* par_bluenoise_from_buffer(
  355. par_byte const* buffer, int nbytes, int maxpts)
  356. {
  357. return par_bluenoise_create((char const*) buffer, nbytes, maxpts);
  358. }
  359. void par_bluenoise_density_from_gray(par_bluenoise_context* ctx,
  360. const unsigned char* pixels, int width, int height, int bpp)
  361. {
  362. ctx->density_width = width;
  363. ctx->density_height = height;
  364. ctx->density = PAR_MALLOC(unsigned char, width * height);
  365. unsigned char* dst = ctx->density;
  366. for (int j = 0; j < height; j++) {
  367. for (int i = 0; i < width; i++) {
  368. *dst++ = 255 - (*pixels);
  369. pixels += bpp;
  370. }
  371. }
  372. }
  373. void par_bluenoise_density_from_color(par_bluenoise_context* ctx,
  374. const unsigned char* pixels, int width, int height, int bpp,
  375. unsigned int background_color, int invert)
  376. {
  377. unsigned int bkgd = background_color;
  378. ctx->density_width = width;
  379. ctx->density_height = height;
  380. ctx->density = PAR_MALLOC(unsigned char, width * height);
  381. unsigned char* dst = ctx->density;
  382. unsigned int mask = 0x000000ffu;
  383. if (bpp > 1) {
  384. mask |= 0x0000ff00u;
  385. }
  386. if (bpp > 2) {
  387. mask |= 0x00ff0000u;
  388. }
  389. if (bpp > 3) {
  390. mask |= 0xff000000u;
  391. }
  392. assert(bpp <= 4);
  393. for (int j = 0; j < height; j++) {
  394. for (int i = 0; i < width; i++) {
  395. unsigned int val = (*((unsigned int*) pixels)) & mask;
  396. val = invert ? (val == bkgd) : (val != bkgd);
  397. *dst++ = val ? 255 : 0;
  398. pixels += bpp;
  399. }
  400. }
  401. }
  402. void par_bluenoise_free(par_bluenoise_context* ctx)
  403. {
  404. free(ctx->points);
  405. for (int t = 0; t < ctx->ntiles; t++) {
  406. for (int s = 0; s < ctx->nsubdivs; s++) {
  407. free(ctx->tiles[t].subdivs[s]);
  408. }
  409. free(ctx->tiles[t].subdivs);
  410. if (t == 0 || !ctx->abridged) {
  411. free(ctx->tiles[t].points);
  412. free(ctx->tiles[t].subpts);
  413. }
  414. }
  415. free(ctx->tiles);
  416. free(ctx->density);
  417. }
  418. int cmp(const void* a, const void* b)
  419. {
  420. const par_vec3* v1 = (const par_vec3*) a;
  421. const par_vec3* v2 = (const par_vec3*) b;
  422. if (v1->rank < v2->rank) {
  423. return -1;
  424. }
  425. if (v1->rank > v2->rank) {
  426. return 1;
  427. }
  428. return 0;
  429. }
  430. void par_bluenoise_sort_by_rank(float* floats, int npts)
  431. {
  432. par_vec3* vecs = (par_vec3*) floats;
  433. qsort(vecs, npts, sizeof(vecs[0]), cmp);
  434. for (int i = 0; i < npts; i++) {
  435. vecs[i].rank = i;
  436. }
  437. }
  438. float* par_bluenoise_generate_exact(
  439. par_bluenoise_context* ctx, int npts, int stride)
  440. {
  441. assert(stride >= 2);
  442. int maxpoints = npts * 2;
  443. if (ctx->maxpoints < maxpoints) {
  444. free(ctx->points);
  445. ctx->maxpoints = maxpoints;
  446. ctx->points = PAR_MALLOC(par_vec3, maxpoints);
  447. }
  448. int ngenerated = 0;
  449. int nprevious = 0;
  450. int ndesired = npts;
  451. float density = 2048;
  452. while (ngenerated < ndesired) {
  453. par_bluenoise_generate(ctx, density, &ngenerated);
  454. // Might be paranoid, but break if something fishy is going on:
  455. if (ngenerated == nprevious) {
  456. return 0;
  457. }
  458. // Perform crazy heuristic to approach a nice density:
  459. if (ndesired / ngenerated >= 2) {
  460. density *= 2;
  461. } else {
  462. density += density / 10;
  463. }
  464. nprevious = ngenerated;
  465. }
  466. par_bluenoise_sort_by_rank(&ctx->points->x, ngenerated);
  467. if (stride != 3) {
  468. int nbytes = sizeof(float) * stride * ndesired;
  469. float* pts = PAR_MALLOC(float, stride * ndesired);
  470. float* dst = pts;
  471. const float* src = &ctx->points->x;
  472. for (int i = 0; i < ndesired; i++, src++) {
  473. *dst++ = *src++;
  474. *dst++ = *src++;
  475. if (stride > 3) {
  476. *dst++ = *src;
  477. dst += stride - 3;
  478. }
  479. }
  480. memcpy(ctx->points, pts, nbytes);
  481. free(pts);
  482. }
  483. return &ctx->points->x;
  484. }
  485. #undef PAR_MINI
  486. #undef PAR_MAXI
  487. #endif // PAR_BLUENOISE_IMPLEMENTATION
  488. #endif // PAR_BLUENOISE_H
  489. // par_bluenoise is distributed under the MIT license:
  490. //
  491. // Copyright (c) 2019 Philip Rideout
  492. //
  493. // Permission is hereby granted, free of charge, to any person obtaining a copy
  494. // of this software and associated documentation files (the "Software"), to deal
  495. // in the Software without restriction, including without limitation the rights
  496. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  497. // copies of the Software, and to permit persons to whom the Software is
  498. // furnished to do so, subject to the following conditions:
  499. //
  500. // The above copyright notice and this permission notice shall be included in
  501. // all copies or substantial portions of the Software.
  502. //
  503. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  504. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  505. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  506. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  507. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  508. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  509. // SOFTWARE.