Mercurial
annotate mrjunejune/src/blog/optimizing-grass-rendering/index.md @ 169:295ac2e5ec00
[MrJuneJune] Created separate target for generating html from md.
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Mon, 19 Jan 2026 17:33:18 -0800 |
| parents | 7a4e942814bc |
| children |
| rev | line source |
|---|---|
|
169
295ac2e5ec00
[MrJuneJune] Created separate target for generating html from md.
MrJuneJune <me@mrjunejune.com>
parents:
113
diff
changeset
|
1 --- |
|
295ac2e5ec00
[MrJuneJune] Created separate target for generating html from md.
MrJuneJune <me@mrjunejune.com>
parents:
113
diff
changeset
|
2 title: Optimizing Random Placement with Colour Noise |
|
295ac2e5ec00
[MrJuneJune] Created separate target for generating html from md.
MrJuneJune <me@mrjunejune.com>
parents:
113
diff
changeset
|
3 description: Comparing white noise and blue noise for natural object placement in game development, with optimization techniques for real-time rendering. |
|
295ac2e5ec00
[MrJuneJune] Created separate target for generating html from md.
MrJuneJune <me@mrjunejune.com>
parents:
113
diff
changeset
|
4 --- |
|
295ac2e5ec00
[MrJuneJune] Created separate target for generating html from md.
MrJuneJune <me@mrjunejune.com>
parents:
113
diff
changeset
|
5 |
|
100
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
6 # Optimizing Random Placement with Colour Noise |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
7 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
8 ### Introduction |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
9 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
10 When it comes to placing objects like grass in a scene, achieving a balance between randomness and natural-looking distribution is a challenge. Too much randomness, like white noise, results in unnatural clustering or gaps. On the other hand, a completely uniform pattern can look artificial. Nature strikes a balance, often governed by constraints such as nutrient availability or environmental factors. |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
11 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
12 In this blog, I’ll walk you through how I tackled this problem by comparing white noise and blue noise for object placement. I’ll also explore an optimization technique inspired by Casey Muratori’s insights to improve performance, making it feasible for rendering grass in real-time applications. |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
13 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
14 ### Understanding White Noise vs. Blue Noise |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
15 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
16 White noise is completely random: each point is placed without consideration of others. While this randomness is simple to implement, it results in visually chaotic patterns with undesirable clumping. |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
17 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
18 Blue noise introduces spatial constraints, ensuring a minimum distance between points. This results in a more natural, evenly spaced pattern—perfect for simulating real-world distributions like grass or tree placement. |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
19 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
20 To visualize this difference, I implemented functions to generate both white and blue noise patterns and compared their results. |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
21 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
22 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
23 ### Implementation Highlights |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
24 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
25 #### White Noise |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
26 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
27 The **whiteNoiseRandom** function generates points completely randomly within a bounding box: |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
28 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
29 ```cpp |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
30 void whiteNoiseRandom(Vector2& top_left_corner, Vector2& bottom_right_corner, const int& sides, const float& inner_radius, Vector2 positions[], int& i) { |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
31 std::random_device rd; |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
32 std::mt19937 gen(rd()); |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
33 std::uniform_real_distribution<float> random_float(0, 1); |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
34 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
35 Vector2 start_point = { |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
36 (random_float(gen) * (bottom_right_corner.x - top_left_corner.x)) + top_left_corner.x , |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
37 (random_float(gen) * (bottom_right_corner.y - top_left_corner.y)) + top_left_corner.y |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
38 }; |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
39 positions[i] = { start_point.x, start_point.y }; |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
40 } |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
41 ``` |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
42 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
43 This is computationally the most efficient as there is no constraints on where it can be placed which mean it will often lead to clumping together. |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
44 |
|
113
7a4e942814bc
[MrJuneJune] Fixed static assets
June Park <parkjune1995@gmail.com>
parents:
100
diff
changeset
|
45 <div class="center"> <img src="/public/white-noise-grass.png" /> </div> |
|
100
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
46 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
47 Above image is okay, but lacks realism. We can do better. |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
48 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
49 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
50 #### Blue Noise |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
51 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
52 Blue noise requires additional checks to maintain a minimum distance between points, implemented as follows: |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
53 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
54 ```cpp |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
55 void blueNoiseRandom(Vector2& top_left_corner, Vector2& bottom_right_corner, const int& sides, const float& inner_radius, Vector2 positions[], int& i) { |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
56 std::random_device rd; |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
57 std::mt19937 gen(rd()); |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
58 std::uniform_real_distribution<float> random_float(0, 1); |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
59 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
60 int attempts = 0; |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
61 const int max_attempts = sides * sides; |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
62 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
63 while (attempts < max_attempts) { |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
64 Vector2 start_point = { random_float(gen) * sides, random_float(gen) * sides }; |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
65 if (x >= top_left_corner.x && x < bottom_right_corner.y && y >= top_left_corner.y && y < bottom_right_corner.y) { |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
66 bool added = true; |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
67 for (int j = 0; j < i; j++) { |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
68 float dx = x - positions[j].x; |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
69 float dy = y - positions[j].y; |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
70 if (std::sqrt(dx * dx + dy * dy) < inner_radius) { |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
71 added = false; |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
72 break; |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
73 } |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
74 } |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
75 if (added) { |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
76 positions[i] = { start_point.x, start_point.y }; |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
77 break; |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
78 } |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
79 } |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
80 attempts++; |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
81 } |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
82 } |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
83 ``` |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
84 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
85 As you can see from below image, this approach improves visual quality... |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
86 |
|
113
7a4e942814bc
[MrJuneJune] Fixed static assets
June Park <parkjune1995@gmail.com>
parents:
100
diff
changeset
|
87 <div class="center"> <img src="/public/blue-noise-random.png" /> </div> |
|
100
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
88 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
89 ...but at the cost of computational complexity. As the number of points increases, available space becomes limited, requiring more attempts to place a point. This can take several seconds, which isn’t ideal. |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
90 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
91 <video width="100%" controls> |
|
113
7a4e942814bc
[MrJuneJune] Fixed static assets
June Park <parkjune1995@gmail.com>
parents:
100
diff
changeset
|
92 <source src="/public/slow-blue.mp4" type="video/mp4" /> |
|
100
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
93 </video> |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
94 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
95 ** It takes around 8 seconds for 800 points in 1000 x 800 with 30 radius which means it should be able to add 100 more points in theory ** |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
96 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
97 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
98 ### Optimizing Blue Noise Generation |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
99 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
100 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
101 While researching approaches, I came across Casey Muratori’s work on Witness, where he introduced a local sampling optimization. Instead of evaluating the entire grid for each point, checks are limited to a smaller region around the current point. This reduces redundant calculations, especially in dense scenes. Here’s my implementation: |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
102 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
103 ```cpp |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
104 void blueNoiseCircle(Vector2& top_left_corner, Vector2& bottom_right_corner, const int& sides, const float& inner_radius, const float& outer_radius, |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
105 Vector2& starting_point, Vector2 positions[], int& i){ |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
106 float center_x = starting_point.x; |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
107 float center_y = starting_point.y; |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
108 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
109 std::random_device rd; |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
110 std::mt19937 gen(rd()); |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
111 std::uniform_real_distribution<float> angle_dist(0, 2 * M_PI); |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
112 std::uniform_real_distribution<float> radius_dist(0, 1); |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
113 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
114 bool added = false; |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
115 int attempts = 0; |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
116 const int max_attempts = outer_radius*outer_radius*PI - inner_radius*inner_radius*PI; |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
117 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
118 while (attempts <= max_attempts) { |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
119 float theta = angle_dist(gen); |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
120 float random_scale = radius_dist(gen); |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
121 float radius = std::sqrt(random_scale * (outer_radius * outer_radius - |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
122 inner_radius * inner_radius) + |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
123 inner_radius * inner_radius); |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
124 float x = center_x + radius * std::cos(theta); |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
125 float y = center_y + radius * std::sin(theta); |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
126 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
127 added = true; |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
128 if (x > 0 && x < sides && y > 0 && y < sides) { |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
129 for (int j = 0; j < i; j++) { |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
130 Vector2 current_point = positions[j]; |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
131 float dx = x - current_point.x; |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
132 float dy = y - current_point.y; |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
133 if (std::sqrt(dx * dx + dy * dy) < inner_radius) { |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
134 added = false; |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
135 break; |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
136 } |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
137 } |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
138 if (added) { |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
139 positions[i] = { x, y }; |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
140 break; |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
141 } |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
142 } |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
143 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
144 attempts++; |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
145 } |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
146 if (!added) { |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
147 blueNoiseRandom(top_left_corner, bottom_right_corner, sides, inner_radius, positions, i); |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
148 } |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
149 } |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
150 ``` |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
151 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
152 <video width="100%" controls> |
|
113
7a4e942814bc
[MrJuneJune] Fixed static assets
June Park <parkjune1995@gmail.com>
parents:
100
diff
changeset
|
153 <source src="/public/fast-blue.mp4" type="video/mp4" /> |
|
100
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
154 </video> |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
155 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
156 ** It only took 2 seconds or so. It slows down at the end since it probably needed to look for one or two points using random number ** |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
157 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
158 |
|
113
7a4e942814bc
[MrJuneJune] Fixed static assets
June Park <parkjune1995@gmail.com>
parents:
100
diff
changeset
|
159 <div class="center"> <img src="/public/blue-noises-optimal.png" /> </div> |
|
100
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
160 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
161 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
162 ### Conclusion |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
163 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
164 If you're working on object placement for games, simulations, or any graphics project, understanding the balance between randomness and natural constraints is crucial. Blue noise offers a compelling way to achieve this balance, and with optimizations, it becomes practical for real-time rendering. |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
165 |
|
65e5a5b89a4e
[Seobeo] Migrated everything to this page.
June Park <parkjune1995@gmail.com>
parents:
diff
changeset
|
166 You can find the full source code for my implementation on [GitHub](https://github.com/MrJuneJune/blog_sample_codes/tree/main/performance_tests/noises). |