Simplex Noise Texture Lookups?

Started by
15 comments, last by unbird 10 years, 11 months ago

I tried that before but I get no output using it as a texture, and it doesnt change the terrain either :(

Advertisement

If you're interested in a non-texture method for Perlin simplex noize, I found this code here: https://github.com/ashima/webgl-noise/wiki. I've used it in a pixel shader to generate really nice fine-grained noise when using screen X,Y as a parameter to the method.


float3 permute(float3 x) { return fmod(((x*34.0)+1.0)*x, 289.0); }

// Perlin simplex noise
float snoise(float2 v)
{
  const float4 C = float4(0.211324865405187, 0.366025403784439, -0.577350269189626, 0.024390243902439);
  float2 i  = floor(v + dot(v, C.yy) );
  float2 x0 = v -   i + dot(i, C.xx);
  float2 i1;
  i1 = (x0.x > x0.y) ? float2(1.0, 0.0) : float2(0.0, 1.0);
//  i1.x = step( x0.y, x0.x ); // x0.x > x0.y ? 1.0 : 0.0
//  i1.y = 1.0 - i1.x;
  float4 x12 = x0.xyxy + C.xxzz;
  x12.xy -= i1;
  i = fmod(i, 289.0);
  float3 p = permute( permute( i.y + float3(0.0, i1.y, 1.0 )) + i.x + float3(0.0, i1.x, 1.0 ));
  float3 m = max(0.5 - float3(dot(x0,x0), dot(x12.xy,x12.xy), dot(x12.zw,x12.zw)), 0.0);
  m = m*m ;
  m = m*m ;
  float3 x = 2.0 * frac(p * C.www) - 1.0;
  float3 h = abs(x) - 0.5;
  float3 ox = floor(x + 0.5);
  float3 a0 = x - ox;
  m *= 1.79284291400159 - 0.85373472095314 * ( a0*a0 + h*h );
  float3 g;
  g.x  = a0.x  * x0.x  + h.x  * x0.y;
  g.yz = a0.yz * x12.xz + h.yz * x12.yw;
  return 130.0 * dot(m, g);
}

SampleLevel ? Wait, are you sampling in the vertex shader ? Then you need to set the texture to this stage:

deviceContext->VSSetShaderResources(0, 1, &PermTextureSRV);

Also: Check with PIX/Graphics Debugger if your setup is correct (textures bound, texture data, render target and viewport correctly set, etc.)

@Scoob Droolins : Wow, Permute with ALU instructions alone. I'm surprised. I once tried that - and failed. Produced quite some noticable non-randomness. Thanks for sharing.

Ah of course! its now changing the terrain which is good. I'm still trying to figure out what to pass in as co-ordinates though and for some reason when I use for example 0 which should point to 151, the array for the gradient doesn't get an out of bounds error which it should if the value is not between 0-11. I thought that maybe the value was just a fraction of that value or something so I tried adding 100 to gi0 after the look up so it would break out but it didnt, but it does if I set it to 100, whats going on?

Now you lost me, I can't quite follow. What array ? You now (should) have a texture which wraps, you won't get an "out of bounds" here. Again: Texture co-ordinates are normalized (0..1). Then again: With a proper perlin noise in place you can feed it any scale (aka frequency) you like. That's the whole beauty of perlin noise.

Can you post your (complete) shader code and what you feed it (your terrain mesh) ?

PS: Maybe playing with perlin alone, i.e. decoupled from your terrain stuff and generate some textures first (this time in the pixel shader) would be a good idea. It's also easier to check if it actually produces correct results.

Edit: Sorry, now I get it (was too late yesterday and reading more carefully helps tongue.png). So you still have an array for the gradients. Not sure what the shader produces with out of bounds, but it probably won't wrap automatically. Static arrays may get translated to a sequence of "ifs" (in assembly movc IIRC). So wrap manually or use a texture for the gradient too.

By the way: It "breaks" with a constant value of 100, since then the compiler can check that at compile time. Well, that's just my guess without seeing code.

Yeah the array is for the gradient but it only has 12 values in it, so if you tried passing 13 for example, it wouldn't work and I pass the values that are obtained through the texture lookup into it.

I've been messing about with it some more and I've used some if statements to try and debug it a little and find out what values are getting returned from the texture. A few things I've noticed are that if I make a texture of 10 width using:

float data[10] = {10,10,10,10,10,10,10,10,10,10};

and set it up the same way as I posted before with R32 Floats then some interesting things happen. If I sample to the first point in the texture using 0.1 as the co-ord and change the 10 to other numbers to see what value I'm getting then using 1 returns ~5.5 instead of 1 and using 4 returns exactly 7 instead of 4. Any idea why this is?

Sounds like linear sampling instead of point. And 0.1 is actually the second texel - or rather somewhere close, since 0.1 cannot be exactly represented with floats. The first texel is at 0.0.

This topic is closed to new replies.

Advertisement