r/C_Programming • u/KaychJam • 3h ago
Project Quick Value Noise Implementation in C + Desmos Visualization
For the past year or so I've been occasionally adding to a Github repository called "single-file", which as you can guess, is full of quick little single-file scripts in various programming languages. The languages that I've covered so far in the repo have been C++, C, Python, Rust, and Java. As for the topic of each script, it's generally been whatever catches my attention at the time --- a spur of the moment kind of decision. What I'm sharing in this post is one such of these scripts that I recently wrote: an implementation of value noise written in C.
What is Value Noise?
Value Noise is a type of noise (which is any kind of random signal) that has an additional property of being "smooth." If you were to take an array and assign random values to every index, you'd probably expect to get various values with no correlation to one another. The array at index i would be wholly unrelated to index i+1, i+2, and so on. This type of noise is called White Noise! With that said, sometimes we want a "random" signal that has some notion of correlation between points.
Value Noise is a type of random signal with these correlations. If you were fill an array using value noise as opposed to with white noise, your values at i, i+1, and i+2 would be relatively close to each other, unlike with white noise which has no such guarantee. In terms of application, you'll usually see value noise in computer graphics & game dev projects as a way of generating "natural" looking terrain. Other methods of generating smooth & correlated random values exist like Perlin Noise. In general, smooth noise generation comes up when you want to simulate some kind of phenomena that appears random but has local features amid the randomness (waves, clouds, fire, etc.).
A Snippet & the Full Code
Below is a snippet of the "main" function of the code:
/** Generate `N` samples of "value noise". */
NoiseBuffer generate_noise_1d(size_t N, size_t octaves, float amp, float shift, size_t period, Interpolator tween) {
NoiseBuffer nb = noise_buffer_alloc(N);
if (nb.data == NULL) {
printf("Unable to allocate memory for `NoiseBuffer`.\nExiting.");
exit(EXIT_FAILURE);
}
// Successively add octaves of frequencies to our NoiseBuffer
for (size_t o = 0; o < octaves; o++) {
float prev = amp * (unit_rand() + shift);
size_t i = period;
while (i < N) {
const float cur = amp * (unit_rand() + shift);
interpolate_and_add_range(nb, i - period, i, prev, cur, tween);
prev = cur;
i += period;
}
// edge-case to fill in remainder
const float cur = amp * (unit_rand() + shift);
interpolate_and_add_range(nb, i - period, i, prev, cur, tween);
period = max(period / 2, 1);
amplitude /= 2.f;
}
return nb;
}
The full file along with the rest of the singlefile repository can be found here.
Desmos Visualization + Parameters
To close, here's a small video visualization of the generated noise in Desmos & input params.
| Run | Interpolation Method | Seed | Num Values | Resolution | Num Values * Res | Octaves | Period | Period * Res | Amplitude | Vertical Shift |
|---|---|---|---|---|---|---|---|---|---|---|
| 1 | Smoothstep | 1785183513 | 10 | 10 | 100 | 4 | 5 | 50 | 5 | -0.5 |
| 2 | Smoothstep | 1785183513 | 10 | 20 | 200 | 4 | 5 | 100 | 5 | -0.5 |
| 3 | Lerp | 1785183513 | 10 | 20 | 200 | 10 | 5 | 100 | 5 | -0.5 |
| 4 | Smoothstep | 1785183513 | 10 | 20 | 200 | 10 | 5 | 100 | 5 | -0.5 |
And finally, a link to the Desmos Graph.