Skip to content

Instantly share code, notes, and snippets.

@9prady9
Last active February 13, 2017 16:28
Show Gist options
  • Save 9prady9/0a3167f5c57ea3ad83e6cad00d4a7bde to your computer and use it in GitHub Desktop.
Save 9prady9/0a3167f5c57ea3ad83e6cad00d4a7bde to your computer and use it in GitHub Desktop.
C++ Program using ArrayFire that show cases Perlin Noise Generation using GPU.
/*******************************************************
* Copyright (c) 2017, ArrayFire
* All rights reserved.
*
* This file is distributed under 3-clause BSD license.
* The complete license agreement can be obtained at:
* http://arrayfire.com/licenses/BSD-3-Clause
********************************************************/
#include <arrayfire.h>
#include <cstdio>
#include <cstdlib>
using namespace af;
array perlin(int w, int h)
{
const float PERSISTENCE = 0.5f;
array base = randu(w, h);
array perlin = constant(0.0f, w, h);
float amp = 1.0f;
float samp = 0.0f;
for (int octave=6; octave>=0; --octave) {
float period = float(1 << octave);
float freq = 1.0f/period;
array x = iota(dim4(w, 1)); // Coloumn Vector
array y = iota(dim4(1, h)); // Row Vector
// Generate horizontal indices to sample data
// for interpolation w.r.t current period
array si0 = (x / period).as(s32) * period;
array si1 = (si0 + period).as(s32) % w;
array hblend = (x - si0) * freq;
hblend = tile(hblend, dim4(1, h)); // tile data along second dimension to enable use in equations that expect matrices
// Generate horizontal indices to sample data
// for interpolation w.r.t current period
array sj0 = (y / period).as(s32) * period;
array sj1 = (sj0 + period).as(s32) % h;
array vblend = (y - sj0) * freq;
vblend = tile(vblend, dim4(w, 1)); // tile data along first dimension to enable use in equations that expect matrices
array top = base(si0, sj0)*(1.0f-hblend) + hblend*base(si1, sj0); // base(array, array)
array bot = base(si0, sj1)*(1.0f-hblend) + hblend*base(si1, sj1); // use indices generated to sample base noise
array blend = top*(1.0f-vblend) + vblend*bot; //interpolate all values
perlin += (amp*blend); //scale by amplitude and add to perlin noise accumulator
samp += amp;
amp *= PERSISTENCE;
}
return perlin/samp;
}
int main(int argc, char *argv[])
{
try {
int device = argc > 1 ? atoi(argv[1]) : 0;
af::setDevice(device);
af::info();
af::Window w(640, 640);
while(!w.close())
w.image(perlin(256, 256));
} catch (af::exception& e) {
fprintf(stderr, "%s\n", e.what());
throw;
}
return 0;
}
@pavanky
Copy link

pavanky commented Feb 13, 2017

@9prady9

  • x,y can go outside the for loop
  • generate x,y as s32
  • period can be int (if x and y are s32)
  • remove .as(s32) for si0, si1, sj0, sj1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment