par_bluenoise.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527
  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. // http://github.prideout.net/assets/bluenoise.bin
  10. // http://github.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. // -----------------------------------------------------------------------------
  37. // BEGIN PUBLIC API
  38. // -----------------------------------------------------------------------------
  39. typedef unsigned char par_byte;
  40. // Encapsulates a tile set and an optional density function.
  41. typedef struct par_bluenoise_context_s par_bluenoise_context;
  42. // Creates a bluenoise context using the given tileset. The first argument is
  43. // the file path the bin file. The second argument is the maximum number of
  44. // points that you expect to ever be generated.
  45. par_bluenoise_context* par_bluenoise_from_file(char const* path, int maxpts);
  46. // Creates a bluenoise context using the given tileset. The first and second
  47. // arguments describe a memory buffer containing the contents of the bin file.
  48. // The third argument is the maximum number of points that you expect to ever
  49. // be generated.
  50. par_bluenoise_context* par_bluenoise_from_buffer(
  51. par_byte const* buffer, int nbytes, int maxpts);
  52. // Sets up a scissoring rectangle using the given lower-left and upper-right
  53. // coordinates. By default the scissor encompasses [-0.5, -0.5] - [0.5, 0.5],
  54. // which is the entire sampling domain for the two "generate" methods.
  55. void par_bluenoise_set_viewport(
  56. par_bluenoise_context*, float left, float bottom, float right, float top);
  57. // Sets up a reference window size. The only purpose of this is to ensure
  58. // that apparent density remains constant when the window gets resized.
  59. // Clients should call this *before* calling par_bluenoise_set_viewport.
  60. void par_bluenoise_set_window(par_bluenoise_context*, int width, int height);
  61. // Frees all memory associated with the given bluenoise context.
  62. void par_bluenoise_free(par_bluenoise_context* ctx);
  63. // Copies a grayscale image into the bluenoise context to guide point density.
  64. // Darker regions generate a higher number of points. The given bytes-per-pixel
  65. // value is the stride between pixels.
  66. void par_bluenoise_density_from_gray(par_bluenoise_context* ctx,
  67. const unsigned char* pixels, int width, int height, int bpp);
  68. // Creates a binary mask to guide point density. The given bytes-per-pixel
  69. // value is the stride between pixels, which must be 4 or less.
  70. void par_bluenoise_density_from_color(par_bluenoise_context* ctx,
  71. const unsigned char* pixels, int width, int height, int bpp,
  72. unsigned int background_color, int invert);
  73. // Generates samples using Recursive Wang Tiles. This is really fast!
  74. // The returned pointer is a list of three-tuples, where XY are in [-0.5, +0.5]
  75. // and Z is a rank value that can be used to create a progressive ordering.
  76. // The caller should not free the returned pointer.
  77. float* par_bluenoise_generate(
  78. par_bluenoise_context* ctx, float density, int* npts);
  79. // Generates an ordered sequence of tuples with the specified sequence length.
  80. // This is slower than the other "generate" method because it uses a dumb
  81. // backtracking method to determine a reasonable density value, and it
  82. // automatically sorts the output by rank. The dims argument must be 2 or more;
  83. // it represents the desired stride (in floats) between consecutive verts in the
  84. // returned data buffer.
  85. float* par_bluenoise_generate_exact(
  86. par_bluenoise_context* ctx, int npts, int dims);
  87. // Performs an in-place sort of 3-tuples, based on the 3rd component, then
  88. // replaces the 3rd component with an index.
  89. void par_bluenoise_sort_by_rank(float* pts, int npts);
  90. #ifndef PAR_HELPERS
  91. #define PAR_HELPERS 1
  92. #define PAR_PI (3.14159265359)
  93. #define PAR_MIN(a, b) (a > b ? b : a)
  94. #define PAR_MAX(a, b) (a > b ? a : b)
  95. #define PAR_CLAMP(v, lo, hi) PAR_MAX(lo, PAR_MIN(hi, v))
  96. #define PAR_MALLOC(T, N) ((T*) malloc(N * sizeof(T)))
  97. #define PAR_CALLOC(T, N) ((T*) calloc(N * sizeof(T), 1))
  98. #define PAR_REALLOC(T, BUF, N) ((T*) realloc(BUF, sizeof(T) * N))
  99. #define PAR_FREE(BUF) free(BUF)
  100. #define PAR_SWAP(T, A, B) { T tmp = B; B = A; A = tmp; }
  101. #define PAR_SQR(a) (a * a)
  102. #endif
  103. // -----------------------------------------------------------------------------
  104. // END PUBLIC API
  105. // -----------------------------------------------------------------------------
  106. #ifdef PAR_BLUENOISE_IMPLEMENTATION
  107. #include <stdio.h>
  108. #include <stdlib.h>
  109. #include <assert.h>
  110. #include <math.h>
  111. #include <string.h>
  112. #define PAR_MINI(a, b) ((a < b) ? a : b)
  113. #define PAR_MAXI(a, b) ((a > b) ? a : b)
  114. typedef struct {
  115. float x;
  116. float y;
  117. } par_vec2;
  118. typedef struct {
  119. float x;
  120. float y;
  121. float rank;
  122. } par_vec3;
  123. typedef struct {
  124. int n, e, s, w;
  125. int nsubtiles, nsubdivs, npoints, nsubpts;
  126. int** subdivs;
  127. par_vec2* points;
  128. par_vec2* subpts;
  129. } par_tile;
  130. struct par_bluenoise_context_s {
  131. par_vec3* points;
  132. par_tile* tiles;
  133. float global_density;
  134. float left, bottom, right, top;
  135. int ntiles, nsubtiles, nsubdivs;
  136. int npoints;
  137. int maxpoints;
  138. int density_width;
  139. int density_height;
  140. unsigned char* density;
  141. float mag;
  142. int window_width;
  143. int window_height;
  144. int abridged;
  145. };
  146. static float sample_density(par_bluenoise_context* ctx, float x, float y)
  147. {
  148. unsigned char* density = ctx->density;
  149. if (!density) {
  150. return 1;
  151. }
  152. int width = ctx->density_width;
  153. int height = ctx->density_height;
  154. y = 1 - y;
  155. x -= 0.5;
  156. y -= 0.5;
  157. float tx = x * PAR_MAXI(width, height);
  158. float ty = y * PAR_MAXI(width, height);
  159. x += 0.5;
  160. y += 0.5;
  161. tx += width / 2;
  162. ty += height / 2;
  163. int ix = PAR_CLAMP((int) tx, 0, width - 2);
  164. int iy = PAR_CLAMP((int) ty, 0, height - 2);
  165. return density[iy * width + ix] / 255.0f;
  166. }
  167. static void recurse_tile(
  168. par_bluenoise_context* ctx, par_tile* tile, float x, float y, int level)
  169. {
  170. float left = ctx->left, right = ctx->right;
  171. float top = ctx->top, bottom = ctx->bottom;
  172. float mag = ctx->mag;
  173. float tileSize = 1.f / powf(ctx->nsubtiles, level);
  174. if (x + tileSize < left || x > right || y + tileSize < bottom || y > top) {
  175. return;
  176. }
  177. float depth = powf(ctx->nsubtiles, 2 * level);
  178. float threshold = mag / depth * ctx->global_density - tile->npoints;
  179. int ntests = PAR_MINI(tile->nsubpts, threshold);
  180. float factor = 1.f / mag * depth / ctx->global_density;
  181. for (int i = 0; i < ntests; i++) {
  182. float px = x + tile->subpts[i].x * tileSize;
  183. float py = y + tile->subpts[i].y * tileSize;
  184. if (px < left || px > right || py < bottom || py > top) {
  185. continue;
  186. }
  187. if (sample_density(ctx, px, py) < (i + tile->npoints) * factor) {
  188. continue;
  189. }
  190. ctx->points[ctx->npoints].x = px - 0.5;
  191. ctx->points[ctx->npoints].y = py - 0.5;
  192. ctx->points[ctx->npoints].rank = (level + 1) + i * factor;
  193. ctx->npoints++;
  194. if (ctx->npoints >= ctx->maxpoints) {
  195. return;
  196. }
  197. }
  198. const float scale = tileSize / ctx->nsubtiles;
  199. if (threshold <= tile->nsubpts) {
  200. return;
  201. }
  202. level++;
  203. for (int ty = 0; ty < ctx->nsubtiles; ty++) {
  204. for (int tx = 0; tx < ctx->nsubtiles; tx++) {
  205. int tileIndex = tile->subdivs[0][ty * ctx->nsubtiles + tx];
  206. par_tile* subtile = &ctx->tiles[tileIndex];
  207. recurse_tile(ctx, subtile, x + tx * scale, y + ty * scale, level);
  208. }
  209. }
  210. }
  211. void par_bluenoise_set_window(par_bluenoise_context* ctx, int width, int height)
  212. {
  213. ctx->window_width = width;
  214. ctx->window_height = height;
  215. }
  216. void par_bluenoise_set_viewport(par_bluenoise_context* ctx, float left,
  217. float bottom, float right, float top)
  218. {
  219. // Transform [-.5, +.5] to [0, 1]
  220. left = ctx->left = left + 0.5;
  221. right = ctx->right = right + 0.5;
  222. bottom = ctx->bottom = bottom + 0.5;
  223. top = ctx->top = top + 0.5;
  224. // Determine magnification factor BEFORE clamping.
  225. float scale = 1000 * (top - bottom) / ctx->window_height;
  226. ctx->mag = powf(scale, -2);
  227. // The density function is only sampled in [0, +1].
  228. ctx->left = PAR_CLAMP(left, 0, 1);
  229. ctx->right = PAR_CLAMP(right, 0, 1);
  230. ctx->bottom = PAR_CLAMP(bottom, 0, 1);
  231. ctx->top = PAR_CLAMP(top, 0, 1);
  232. }
  233. float* par_bluenoise_generate(
  234. par_bluenoise_context* ctx, float density, int* npts)
  235. {
  236. ctx->global_density = density;
  237. ctx->npoints = 0;
  238. float left = ctx->left;
  239. float right = ctx->right;
  240. float bottom = ctx->bottom;
  241. float top = ctx->top;
  242. float mag = ctx->mag;
  243. int ntests = PAR_MINI(ctx->tiles[0].npoints, mag * ctx->global_density);
  244. float factor = 1.f / mag / ctx->global_density;
  245. for (int i = 0; i < ntests; i++) {
  246. float px = ctx->tiles[0].points[i].x;
  247. float py = ctx->tiles[0].points[i].y;
  248. if (px < left || px > right || py < bottom || py > top) {
  249. continue;
  250. }
  251. if (sample_density(ctx, px, py) < (i + 1) * factor) {
  252. continue;
  253. }
  254. ctx->points[ctx->npoints].x = px - 0.5;
  255. ctx->points[ctx->npoints].y = py - 0.5;
  256. ctx->points[ctx->npoints].rank = i * factor;
  257. ctx->npoints++;
  258. if (ctx->npoints >= ctx->maxpoints) {
  259. break;
  260. }
  261. }
  262. recurse_tile(ctx, &ctx->tiles[0], 0, 0, 0);
  263. *npts = ctx->npoints;
  264. return &ctx->points->x;
  265. }
  266. #define freadi() \
  267. *((int*) ptr); \
  268. ptr += sizeof(int)
  269. #define freadf() \
  270. *((float*) ptr); \
  271. ptr += sizeof(float)
  272. static par_bluenoise_context* par_bluenoise_create(
  273. char const* filepath, int nbytes, int maxpts)
  274. {
  275. par_bluenoise_context* ctx = PAR_MALLOC(par_bluenoise_context, 1);
  276. ctx->maxpoints = maxpts;
  277. ctx->points = PAR_MALLOC(par_vec3, maxpts);
  278. ctx->density = 0;
  279. ctx->abridged = 0;
  280. par_bluenoise_set_window(ctx, 1024, 768);
  281. par_bluenoise_set_viewport(ctx, -.5, -.5, .5, .5);
  282. char* buf = 0;
  283. if (nbytes == 0) {
  284. FILE* fin = fopen(filepath, "rb");
  285. assert(fin);
  286. fseek(fin, 0, SEEK_END);
  287. nbytes = (int) ftell(fin);
  288. fseek(fin, 0, SEEK_SET);
  289. buf = PAR_MALLOC(char, nbytes);
  290. int consumed = (int) fread(buf, nbytes, 1, fin);
  291. assert(consumed == nbytes);
  292. fclose(fin);
  293. }
  294. char const* ptr = buf ? buf : filepath;
  295. int ntiles = ctx->ntiles = freadi();
  296. int nsubtiles = ctx->nsubtiles = freadi();
  297. int nsubdivs = ctx->nsubdivs = freadi();
  298. par_tile* tiles = ctx->tiles = PAR_MALLOC(par_tile, ntiles);
  299. for (int i = 0; i < ntiles; i++) {
  300. tiles[i].n = freadi();
  301. tiles[i].e = freadi();
  302. tiles[i].s = freadi();
  303. tiles[i].w = freadi();
  304. tiles[i].subdivs = PAR_MALLOC(int*, nsubdivs);
  305. for (int j = 0; j < nsubdivs; j++) {
  306. int* subdiv = PAR_MALLOC(int, PAR_SQR(nsubtiles));
  307. for (int k = 0; k < PAR_SQR(nsubtiles); k++) {
  308. subdiv[k] = freadi();
  309. }
  310. tiles[i].subdivs[j] = subdiv;
  311. }
  312. tiles[i].npoints = freadi();
  313. tiles[i].points = PAR_MALLOC(par_vec2, tiles[i].npoints);
  314. for (int j = 0; j < tiles[i].npoints; j++) {
  315. tiles[i].points[j].x = freadf();
  316. tiles[i].points[j].y = freadf();
  317. }
  318. tiles[i].nsubpts = freadi();
  319. tiles[i].subpts = PAR_MALLOC(par_vec2, tiles[i].nsubpts);
  320. for (int j = 0; j < tiles[i].nsubpts; j++) {
  321. tiles[i].subpts[j].x = freadf();
  322. tiles[i].subpts[j].y = freadf();
  323. }
  324. // The following hack allows for an optimization whereby
  325. // the first tile's point set is re-used for every other tile.
  326. // This goes against the entire purpose of Recursive Wang Tiles,
  327. // but in many applications the qualatitive loss is not
  328. // observable, and the footprint savings are huge (10x).
  329. if (tiles[i].npoints == 0) {
  330. ctx->abridged = 1;
  331. tiles[i].npoints = tiles[0].npoints;
  332. tiles[i].points = tiles[0].points;
  333. tiles[i].nsubpts = tiles[0].nsubpts;
  334. tiles[i].subpts = tiles[0].subpts;
  335. }
  336. }
  337. free(buf);
  338. return ctx;
  339. }
  340. par_bluenoise_context* par_bluenoise_from_file(char const* path, int maxpts)
  341. {
  342. return par_bluenoise_create(path, 0, maxpts);
  343. }
  344. par_bluenoise_context* par_bluenoise_from_buffer(
  345. par_byte const* buffer, int nbytes, int maxpts)
  346. {
  347. return par_bluenoise_create((char const*) buffer, nbytes, maxpts);
  348. }
  349. void par_bluenoise_density_from_gray(par_bluenoise_context* ctx,
  350. const unsigned char* pixels, int width, int height, int bpp)
  351. {
  352. ctx->density_width = width;
  353. ctx->density_height = height;
  354. ctx->density = PAR_MALLOC(unsigned char, width * height);
  355. unsigned char* dst = ctx->density;
  356. for (int j = 0; j < height; j++) {
  357. for (int i = 0; i < width; i++) {
  358. *dst++ = 255 - (*pixels);
  359. pixels += bpp;
  360. }
  361. }
  362. }
  363. void par_bluenoise_density_from_color(par_bluenoise_context* ctx,
  364. const unsigned char* pixels, int width, int height, int bpp,
  365. unsigned int background_color, int invert)
  366. {
  367. unsigned int bkgd = background_color;
  368. ctx->density_width = width;
  369. ctx->density_height = height;
  370. ctx->density = PAR_MALLOC(unsigned char, width * height);
  371. unsigned char* dst = ctx->density;
  372. unsigned int mask = 0x000000ffu;
  373. if (bpp > 1) {
  374. mask |= 0x0000ff00u;
  375. }
  376. if (bpp > 2) {
  377. mask |= 0x00ff0000u;
  378. }
  379. if (bpp > 3) {
  380. mask |= 0xff000000u;
  381. }
  382. assert(bpp <= 4);
  383. for (int j = 0; j < height; j++) {
  384. for (int i = 0; i < width; i++) {
  385. unsigned int val = (*((unsigned int*) pixels)) & mask;
  386. val = invert ? (val == bkgd) : (val != bkgd);
  387. *dst++ = val ? 255 : 0;
  388. pixels += bpp;
  389. }
  390. }
  391. }
  392. void par_bluenoise_free(par_bluenoise_context* ctx)
  393. {
  394. free(ctx->points);
  395. for (int t = 0; t < ctx->ntiles; t++) {
  396. for (int s = 0; s < ctx->nsubdivs; s++) {
  397. free(ctx->tiles[t].subdivs[s]);
  398. }
  399. free(ctx->tiles[t].subdivs);
  400. if (t == 0 || !ctx->abridged) {
  401. free(ctx->tiles[t].points);
  402. free(ctx->tiles[t].subpts);
  403. }
  404. }
  405. free(ctx->tiles);
  406. free(ctx->density);
  407. }
  408. int cmp(const void* a, const void* b)
  409. {
  410. const par_vec3* v1 = (const par_vec3*) a;
  411. const par_vec3* v2 = (const par_vec3*) b;
  412. if (v1->rank < v2->rank) {
  413. return -1;
  414. }
  415. if (v1->rank > v2->rank) {
  416. return 1;
  417. }
  418. return 0;
  419. }
  420. void par_bluenoise_sort_by_rank(float* floats, int npts)
  421. {
  422. par_vec3* vecs = (par_vec3*) floats;
  423. qsort(vecs, npts, sizeof(vecs[0]), cmp);
  424. for (int i = 0; i < npts; i++) {
  425. vecs[i].rank = i;
  426. }
  427. }
  428. float* par_bluenoise_generate_exact(
  429. par_bluenoise_context* ctx, int npts, int stride)
  430. {
  431. assert(stride >= 2);
  432. int maxpoints = npts * 2;
  433. if (ctx->maxpoints < maxpoints) {
  434. free(ctx->points);
  435. ctx->maxpoints = maxpoints;
  436. ctx->points = PAR_MALLOC(par_vec3, maxpoints);
  437. }
  438. int ngenerated = 0;
  439. int nprevious = 0;
  440. int ndesired = npts;
  441. float density = 2048;
  442. while (ngenerated < ndesired) {
  443. par_bluenoise_generate(ctx, density, &ngenerated);
  444. // Might be paranoid, but break if something fishy is going on:
  445. if (ngenerated == nprevious) {
  446. return 0;
  447. }
  448. // Perform crazy heuristic to approach a nice density:
  449. if (ndesired / ngenerated >= 2) {
  450. density *= 2;
  451. } else {
  452. density += density / 10;
  453. }
  454. nprevious = ngenerated;
  455. }
  456. par_bluenoise_sort_by_rank(&ctx->points->x, ngenerated);
  457. if (stride != 3) {
  458. int nbytes = sizeof(float) * stride * ndesired;
  459. float* pts = PAR_MALLOC(float, stride * ndesired);
  460. float* dst = pts;
  461. const float* src = &ctx->points->x;
  462. for (int i = 0; i < ndesired; i++, src++) {
  463. *dst++ = *src++;
  464. *dst++ = *src++;
  465. if (stride > 3) {
  466. *dst++ = *src;
  467. dst += stride - 3;
  468. }
  469. }
  470. memcpy(ctx->points, pts, nbytes);
  471. free(pts);
  472. }
  473. return &ctx->points->x;
  474. }
  475. #undef PAR_MINI
  476. #undef PAR_MAXI
  477. #endif