Jump to content
  • Advertisement
Sign in to follow this  

A perlin noise function on the GPU

This topic is 2770 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

As an idle thought, I've written my perlin noise function in NVidia FX Composer. However, there's a slight problem...Outputting data. I'm limited to a GeForce 8800GT, so I'm using Shader Model 3.0. No dynamic array indexing, which means I can't just output to an array stored in the effect file. And Google doesn't seem to know about modifying a texture.

I suppose I could output the perlin noise to the screen and take a screenshot, but that's not really what I'm after...

Share this post


Link to post
Share on other sites
Advertisement
Ok, I solved that, I think. Just output to a surface I create. However, I've got a new problem. In FX Composer, my code compiles fine. Try to load it as a SlimDX Effect and I get X3000 "Unexpected Token" on this: I've bolded the unexpected token.

uint MercenneOnce(uint seed)
{
return (1812433253 * (seed - (seed * (uint)pow(2, 30))) + 1); // 0x6c078965
}

float Noise2D(int x, int y)
{
int n = x + y * 1376312627;
n = (1 - ((n * (n * n * 15727 + 789181) + (int)1376312627) - (int)0x7fffffff) / (int)1073741827);
return MercenneOnce(n / 4294967295) * 2.0;
}

How is that unexpected?

Share this post


Link to post
Share on other sites
Alright, my GPU Perlin functions are returning the maximum float value as a negative and I don't know why.


texture Data;

/* uint MercenneOnce(uint seed)
{
return (uint)abs((1812433253 * ((int)seed - (int)(seed * (int)pow(2, 30))) + 1)); // 0x6c078965
} */

int MercenneOnce(int seed)
{
return (1812433253 * (seed - (seed * (int)pow(2, 30))) + 1); // 0x6c078965
}

float Noise2D(int x, int y)
{
int n = x + y * 1376312627;
n = (1 - ((n * (n * n * 15727 + 789181) + (int)1376312627) - (int)0x7fffffff) / (int)1073741827);
// uint n2 = (uint)n / 4294967295;
// return MercenneOnce((uint)abs( (uint)abs(n) / 2147483647.0)) * 2.0;
// return MercenneOnce((uint)abs( n )) * 2.0;
// return n / 2147483647.0;
return MercenneOnce(n) / 2147483647.0;
// return 1.0;
}

float SmoothedNoise2D(int x, int y)
{
float corners = (Noise2D(x - 1, y - 1) + Noise2D(x + 1, y - 1) + Noise2D(x - 1, y + 1) + Noise2D(x + 1, y + 1)) / 16;
float sides = (Noise2D(x - 1, y) + Noise2D(x + 1, y) + Noise2D(x, y - 1) + Noise2D(x, y + 1)) / 8;
float center = Noise2D(x, y) / 4;

return corners + sides + center;
}

float CosineInterpolate(float a, float b, float interpolation)
{
float f = (1 - cos(interpolation * 3.1415926535897932384626433832795)) * .5;

return a * (1 - f) + b * f;
}

float InterpolatedNoise2D(float x, float y)
{
int integer_X = (int)x;
float fractional_X = x - integer_X;

int integer_Y = (int)y;
float fractional_Y = y - integer_Y;

float v1 = SmoothedNoise2D(integer_X, integer_Y);
float v2 = SmoothedNoise2D(integer_X + 1, integer_Y);
float v3 = SmoothedNoise2D(integer_X, integer_Y + 1);
float v4 = SmoothedNoise2D(integer_X + 1, integer_Y + 1);

float i1 = CosineInterpolate(v1, v2, fractional_X);
float i2 = CosineInterpolate(v3, v4, fractional_X);

return CosineInterpolate(i1, i2, fractional_Y);
}


float PerlinNoise2D(float x, float y, float persistance, int octaves, int shift)
{
float total = 0;
float p = persistance;
int n = octaves;

for (int i = 0; i < n; ++i)
{
float frequency = pow(2, i + shift);
float amplitude = pow(p, i + shift);

total = total + InterpolatedNoise2D(x * frequency, y * frequency) * amplitude;
}

return total / persistance;
}

struct VertexShader_Input
{
float4 Position : Position0;
};

struct VertexShader_Output
{
float4 Position : Position0;
float3 Pos : TexCoord0;
float4 Color : Color;
};

VertexShader_Output mainVS(VertexShader_Input input)
{
VertexShader_Output output;
output.Position = input.Position;
output.Pos = input.Position.xyz;
// data[(int)output.Pos.x][(int)output.Pos.z] = PerlinNoise2D(output.Pos.x / 512.0, output.Pos.z / 512.0, 5, 5, 0);
output.Color = float4(1.0, 1.0, 1.0, 1.0) * (PerlinNoise2D(output.Pos.x / 512.0, output.Pos.z / 512.0, 5, 5, 0));
return output;
}

float4 mainPS(VertexShader_Output input) : COLOR
{

return input.Color;
}

technique technique0 {
pass p0 {
// CullMode = None;
VertexShader = compile vs_3_0 mainVS();
PixelShader = compile ps_3_0 mainPS();
}
}

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!