# 3D Perlin noise in Processing

**URL:** https://discourse.processing.org/t/3d-perlin-noise-in-processing/37770
**Category:** Coding Questions
**Created:** [June 30, 2022, 6:05pm UTC](https://discourse.processing.org/t/3d-perlin-noise-in-processing/37770 "2022-06-30T18:05:32Z")
**Posts on this page:** 1
**Showing post:** 15

<div class="post-metadata">

### Author: ![mnse](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/mnse/32/16520_2.png) [@mnse](https://discourse.processing.org/u/mnse)
#### Post date: [July 2, 2022, 4:02pm UTC](https://discourse.processing.org/t/3d-perlin-noise-in-processing/37770/15 "2022-07-02T16:02:05Z")

</div>

Hi again,

Well, as the day is slowly coming to an end and I’ve had some thoughts about whether to post or not, I’ve come to the decision that I will post it after all.  
There are many pros and cons that could be listed, but none of them weigh so heavily that there would be a right or wrong.  
Reasons are …  
My code is just one of many examples and is far from an all-encompassing implementation. There are many things that can be worked out in addition to this on the topic.  
I’ve now added lots of comments to the code, to not offer this as a simple copy/paste solution, but rather that one can get an idea of what concrete was done here and most importantly why.  
(took longer than to code it. 😁)

If you disagree with my decision, you are free to flag the post. 😉

> **Code+Image**
>
> ```auto
> // a class to representing a point on our grid.
> // This should/would/could be done better by defining it as faces (of a triangle mesh).
> // but would it keep as simple as possible 
> class GridPoint {
> float x, y, v;
> public GridPoint(float px, float py, float pv) {
> x = px; // x-pos of the grid point
> y = py; // y-pos of the grid point
> v = pv; // height of the grid point
> }
> }
> 
> //helper variables
> float halfWidth, halfHeight;
> boolean mode = false;
> // storage of out grid
> int rows, cols;
> GridPoint[][] grid;
> // image used for texture and heightmap
> PImage img;
> 
> void setup() {
> size(800, 800, P3D);
> halfWidth = width/2.;
> halfHeight = height/2.;
> initGrid(10.);
> // use textureMode IMAGE as the grid is not normalized
> textureMode(IMAGE);
> }
> 
> void initGrid(float scl) {
> // load the image, used for texture and heightmap.
> // usually more than one picture will be used. One for heightmap, one for normalmap and one with the texture.
> // for simplicity it has the same size than our grid to not make the code more math intensive.
> // to get this work our image is somehow a bit blurred (like noise is), otherwise the mesh isn't smooth enough
> img = loadImage("image.png");
> img.loadPixels();
> // initialize our gridpoints
> rows = floor(height/scl);
> cols = floor(width/scl);
> grid= new GridPoint[rows][cols];
> for (int y = 0; y < rows; y++) {
> for (int x = 0; x < cols; x++) {
> int sx = floor(x*scl);
> int sy = floor(y*scl);
> // set x and y coordinates (center origin) and the height of the current point.
> // height is the normalized brightness value [0..1] of the pixel color from the image.
> // Subtract 0.5 to align it to center [-0.5..0.5]
> // scaling it by 50, so the range is [50.0*(-0.5)..50.0*(0.5)]
> grid[y][x] = new GridPoint(-halfWidth+sx+scl/2, -halfHeight+sy+scl/2, 50.*(brightness(img.get(sx, sy))/255-0.5));
> }
> }
> }
> 
> void draw() {
> background(0);
> // set the origin to the center of the screen, and move it 400px far away on z-axis
> translate(halfWidth, halfHeight, -400);
> 
> // switch between mesh and texured mode
> if (frameCount % int(TAU*100.) == 0) {
> mode = !mode;
> }
> 
> if (mode) {
> // if textured mode no strokes and a light from viewpoint to object
> noStroke();
> directionalLight(255, 255, 255, 0, 0, -1);
> } else {
> // if mesh mode only show strokes
> noFill();
> stroke(128);
> strokeWeight(0.5);
> }
> 
> // apply the rotation after lighting, otherwhile the light gets also rotated, which we not want.
> // tipping 30degree back on X-axis
> rotateX(radians(30));
> // tipping left/right a bit per frame from -PI/4 - +PI/4 on Y-axis
> rotateY(sin(frameCount/100.)*QUARTER_PI);
> 
> // build the surface/terrain by triangle strips to display it
> for (int y = 0; y < rows-1; y ++) {
> beginShape(TRIANGLE_STRIP);
> if (mode) {
> // on textured mode set the texture
> texture(img);
> }
> // common triangle strips
> for (int x = 0; x < cols; x++) {
> GridPoint ca = grid[y][x];
> GridPoint cb = grid[y+1][x];
> vertex(ca.x, ca.y, ca.v, ca.x+halfWidth, ca.y+halfHeight);
> if (mode) {
> // on textured mode we need to set the normal vector, so the light knows how to behave on hittng the surface
> // usually there are better calculation than this cheap hack
> // comment it out to see the difference if normals are messed up
> PVector na = new PVector(ca.x-cb.x, ca.y-cb.y, 0).sub(new PVector(ca.x-cb.x, ca.y-cb.y, 1)).normalize();
> normal(na.x, na.y, na.z);
> }
> vertex(cb.x, cb.y, cb.v, cb.x+halfWidth, cb.y+halfHeight);
> if (mode) {
> // on textured mode we need to set the normal vector, so the light knows how to behave on hittng the surface
> // usually there are better calculation than this cheap hack
> // comment it out to see the difference if normals are messed up
> PVector nb = new PVector(cb.x-ca.x, cb.y-ca.y, 0).sub(new PVector(cb.x-ca.x, cb.y-ca.y, 1)).normalize();
> normal(nb.x, nb.y, nb.z);
> }
> }
> endShape();
> }
> }
> 
> ```
> 
> Image used for code above [800x800]px
> 
> ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/3X/f/4/f4caec351570dd0737c869958933719cc66d44c6.png)

Result:  
 ![output](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/3X/a/3/a327ebc0df7dcabc3654e4fb89a32842db5876f3.webp)

Cheers  
— mnse

---

_[View the full topic](https://discourse.processing.org/t/3d-perlin-noise-in-processing/37770)._
