I followed this tutorial.
When I implement it in my code (Raytracing), and apply it on a sphere, I get a uni-color sphere, with one stripe of darker pixel on it. When I change the random float generator, I got the basic linear noise, which isn't my goal. Can you explain what I missed?
Here is my code:
#include <stdlib.h>
#include <math.h>
float noise(int x, int y)
{
int n;
n = x + y * 57;
n = pow((n << 13), n);
return (1.0 - ( (n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0);
}
float interpolate(float a, float b, float x)
{
float pi_mod;
float f_unk;
pi_mod = x * 3.1415927;
f_unk = (1 - cos(pi_mod)) * 0.5;
return (a * (1 - f_unk) + b * x);
}
float smooth_noise(int x, int y)
{
float corners;
float center;
float sides;
corners = (noise(x - 1, y - 1) + noise(x + 1, y - 1) +
noise(x - 1, x + 1) + noise(x + 1, y + 1)) / 16;
sides = (noise(x - 1, y) + noise(x + 1, y) + noise(x, y - 1) +
noise(x, y + 1)) / 8;
center = noise(x, y) / 4;
return (corners + sides + center);
}
float noise_handler(float x, float y)
{
int int_val[2];
float frac_val[2];
float value[4];
float res[2];
int_val[0] = (int)x;
int_val[1] = (int)y;
frac_val[0] = x - int_val[0];
frac_val[1] = y - int_val[1];
value[0] = smooth_noise(int_val[0], int_val[1]);
value[1] = smooth_noise(int_val[0] + 1, int_val[1]);
value[2] = smooth_noise(int_val[0], int_val[1] + 1);
value[3] = smooth_noise(int_val[0] + 1, int_val[1] + 1);
res[0] = interpolate(value[0], value[1], frac_val[0]);
res[1] = interpolate(value[2], value[3], frac_val[0]);
return (interpolate(res[0], res[1], frac_val[1]));
}
float perlin_two(float x, float y)
{
float total;
float per;
float amp;
int hz;
int i;
int octave;
total = 0.0;
per = 0.5;
octave = 10;
i = 0;
while (i < octave)
{
hz = pow(2, i);
amp = pow(per, (float)i);
total += noise_handler(x * (float)hz, y * (float)hz) * amp;
i += 1;
}
return (total);
}
EDIT: I spot an error in the Noise function (I consider the XOR operand like a power function ... Now I get a barcode, as if the y parameter was ignored in the operations ...
Had to implement this in C recently and this post helped get me started. One fix for the noise function as previously stated.
float noise(int x, int y) {
int n;
n = x + y * 57;
n = (n << 13) ^ n;
return (1.0 - ( (n * ((n * n * 15731) + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0);
}
Most importantly, is that Fractal Brownian Motion is really important when implementing Perlin Noise for use in a height map. Instead of following the pseudo code by Hugo Elias, I used this Google Code Snippet.
float perlin_two(float x, float y, float gain, int octaves, int hgrid) {
int i;
float total = 0.0f;
float frequency = 1.0f/(float)hgrid;
float amplitude = gain;
float lacunarity = 2.0;
for (i = 0; i < octaves; ++i)
{
total += noise_handler((float)x * frequency, (float)y * frequency) * amplitude;
frequency *= lacunarity;
amplitude *= gain;
}
return (total);
}
Before I did this, I'd had the same issue with uniform 'stripping' or just complete random looking height maps.
You got to debug & rework probably all your variable types; do the math in pen & paper or in a debugger and check the range of the values. e.g. here
noise(int x, int y) {
int n = x + y * 57;
n = pow((n << 13), n); ...
}
n
will either underflow or overflow for almost all non-zero values. Good random values can't be produced with any random method, which is what these formulas look like.
Check also this topic for some reference code.
User contributions licensed under CC BY-SA 3.0