# Faster Rendering Techniques in P3D?

**URL:** https://discourse.processing.org/t/faster-rendering-techniques-in-p3d/31465
**Category:** Libraries
**Created:** [July 27, 2021, 6:20pm UTC](https://discourse.processing.org/t/faster-rendering-techniques-in-p3d/31465 "2021-07-27T18:20:01Z")
**Posts on this page:** 17
**Page:** 1

<div class="post-metadata">

### Author: ![CosmicCrowMC](https://avatars.discourse-cdn.com/v4/letter/c/ba8739/32.png) [@CosmicCrowMC](https://discourse.processing.org/u/CosmicCrowMC)
#### Post date: [July 27, 2021, 6:20pm UTC](https://discourse.processing.org/t/faster-rendering-techniques-in-p3d/31465/1 "2021-07-27T18:20:02Z")

</div>

I’ve made a very large 3D game with Processing, and for the past few months, I’ve dealt with pretty shotty performance, considering only 2,000 or so quads are being drawn at any given time. With enough workarounds, I’ve been able to maintain 60 FPS on my GTX 1070, but the game is getting so large that I keep having to sacrifice more and more to maintain a smooth framerate.

The bulk of the game’s drawing is done by a drawWall() function that looks something like this: (I’ve shortened it to get to the point)

```auto
void drawWall(float x, float y, float z, float thickness, float width, float height, PImage texture) {
beginShape();
vertex(x,y,z,0,0);
vertex(x+width,y,z,1,0);
vertex(x+width,y+height,z,1,1);
vertex(x,y+height,z,0,1);
endShape();
beginShape();
vertex(x+width,y,z,0,0);
vertex(x+width,y,z+thickness,1,0);
vertex(x+width,y+height,z+thickness,1,1);
vertex(x+width,y+height,z,0,1);
endShape();
beginShape();
vertex(x,y,z+thickness,0,0);
vertex(x+width,y,z+thickness,1,0);
vertex(x+width,y+height,z+thickness,1,1);
vertex(x,y+height,z+thickness,0,1);
endShape();
beginShape();
vertex(x,y,z,0,0);
vertex(x,y,z+thickness,1,0);
vertex(x,y+height,z+thickness,1,1);
vertex(x,y+height,z,0,1);
endShape();
}

```

This basic example is a 3D wall being drawn with width, thickness, and height. There aren’t any quads drawn on the top or bottom to make it a full cuboid because those parts are invisible when the walls go from the floor to the ceiling.

So is there any way to do that more efficiently? I read [this article](https://discourse.processing.org/t/is-p3d-inherently-slow-and-or-is-there-a-fast-alternative/22889) about P3D alternatives, and while I was able to get raw OpenGL 2 to work (and it definitely had much better performance), I don’t know how to incorporate Processing’s operations such as pushMatrix(), popMatrix(), translate(), rotate(), and scale().

What I’m really looking for are alternative methods of drawing shapes that save on performance but don’t force me to remove all of Processing’s 3D operations listed before. Any ideas?

---

<div class="post-metadata">

### Author: ![CosmicCrowMC](https://avatars.discourse-cdn.com/v4/letter/c/ba8739/32.png) [@CosmicCrowMC](https://discourse.processing.org/u/CosmicCrowMC)
#### Post date: [July 27, 2021, 6:39pm UTC](https://discourse.processing.org/t/faster-rendering-techniques-in-p3d/31465/2 "2021-07-27T18:39:29Z")

</div>

I’ll also mention that I found some articles about glPushMatrix, glPopMatrix, glTranslate, etc, which would still require a lot of code-rewriting, but it’d be worth it in the end. No idea how to implement them because I don’t know the necessary libraries I need to import! 😅 [Here’s a good example of what I’m talking about.](https://www.programcreek.com/java-api-examples/?class=javax.media.opengl.GL&method=glPushMatrix)

---

<div class="post-metadata">

### Author: ![CosmicCrowMC](https://avatars.discourse-cdn.com/v4/letter/c/ba8739/32.png) [@CosmicCrowMC](https://discourse.processing.org/u/CosmicCrowMC)
#### Post date: [July 27, 2021, 6:57pm UTC](https://discourse.processing.org/t/faster-rendering-techniques-in-p3d/31465/3 "2021-07-27T18:57:21Z")

</div>

Alright, now I’m slapping myself in the face. Starting with beginShape(QUAD); has SIGNIFICANTLY improved performance. Other tips for performance improvements would still be appreciated, but this alone has made performance 4 times better.

---

<div class="post-metadata">

### Author: ![quark](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/quark/32/26_2.png) [@quark](https://discourse.processing.org/u/quark)
#### Post date: [July 28, 2021, 6:35am UTC](https://discourse.processing.org/t/faster-rendering-techniques-in-p3d/31465/4 "2021-07-28T06:35:53Z")

</div>

You might also try using `noStroke()`. I have found OpenGL slower when drawing lines than filling shapes.

---

<div class="post-metadata">

### Author: ![neilcsmith](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/neilcsmith/32/144_2.png) [@neilcsmith](https://discourse.processing.org/u/neilcsmith)
#### Post date: [July 28, 2021, 3:19pm UTC](https://discourse.processing.org/t/faster-rendering-techniques-in-p3d/31465/5 "2021-07-28T15:19:47Z")

</div>

> [@CosmicCrowMC](#):
>
> Starting with beginShape(QUAD); has SIGNIFICANTLY improved performance.

What exactly do you mean? Replacing each `beginShape()` with `beginShape(QUADS)` ? Because you should be able to have one begin / end shape wrapping all the vertex calls I think.

---

<div class="post-metadata">

### Author: ![glv](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/glv/32/18785_2.png) [@glv](https://discourse.processing.org/u/glv)
#### Post date: [July 29, 2021, 9:14pm UTC](https://discourse.processing.org/t/faster-rendering-techniques-in-p3d/31465/6 "2021-07-29T21:14:59Z")

</div>

Hello,

> [@CosmicCrowMC](#):
>
> Starting with beginShape(QUAD); has SIGNIFICANTLY improved performance.

I get a similar improvement:

```auto
beginShape(); //frameRate around 25

beginShape(QUADS) // frameRate around 60

```

Tested with `15*15*15` = 3375 textured cubes

I used your shapes, made a cube and added some textures:

 ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/d/db922e68ddbb2df548de6bbe39ef0673ef35704e.jpeg)

I also cleaned up the code a bit but did not see any change:

```auto
  float xw = x + width;
  float yw = y + width; 
  float xt = z + thickness;
 
  beginShape(p);
  texture(img);
  vertex(x, y, z, 0, 0);
  vertex(xw, y, z, v, 0);
  vertex(xw, yw, z, v, v);
  vertex(x, yw, z, 0, v);
  endShape();

// And so on...

```

`:)`

---

<div class="post-metadata">

### Author: ![neilcsmith](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/neilcsmith/32/144_2.png) [@neilcsmith](https://discourse.processing.org/u/neilcsmith)
#### Post date: [July 30, 2021, 9:01am UTC](https://discourse.processing.org/t/faster-rendering-techniques-in-p3d/31465/7 "2021-07-30T09:01:54Z")

</div>

Is that with a single beginShape()? Could you share the full code for this? Am interested in doing some performance comparisons.

---

<div class="post-metadata">

### Author: ![glv](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/glv/32/18785_2.png) [@glv](https://discourse.processing.org/u/glv)
#### Post date: [August 4, 2021, 12:17pm UTC](https://discourse.processing.org/t/faster-rendering-techniques-in-p3d/31465/8 "2021-08-04T12:17:53Z")

</div>

> [@neilcsmith](#):
>
> Am interested in doing some performance comparisons.

Here you go:

> **Code**
>
> ```auto
> // Texture Cube 
> // v1.0.0
> // GLV 2021-07-29
> 
> //drawWall() courtesy of CosmicCrowMC:
> //https://discourse.processing.org/t/faster-rendering-techniques-in-p3d/31465
> 
> PImage img;
> 
> final int DEFAULT = 20; // default beginShape() parameter
> 
> int w = 25; // width of cube
> int w2;
> int n = 15; // number of cubes along each axis
> int p; // beginShape() parameter
> boolean t; // toggles parameter 
> 
> void setup() 
> {
> size(800, 800, P3D);
> noFill();
> noStroke();
> img = loadImage("https://upload.wikimedia.org/wikipedia/commons/thumb/2/2e/Processing_3_logo.png/240px-Processing_3_logo.png");
> img.resize(w, w);
>   
> textureMode(NORMAL);
>   
> String s = "Press t to toggle between beginShape() and beginShape(QUAD)";
> println(s);
>   
> //hint(ENABLE_DEPTH_SORT); // frameRates < 15 with this!
> hint(DISABLE_DEPTH_TEST); // cool effect! Watch a few rotations.
> }
> 
> void draw() 
> {
> background(255, 255, 0);
> lights();
> translate(width/2, height/2, -25);
> rotateY(frameCount*TAU/500);
> w2 = w+5; // Add space between cubes
> float offset = -n*w2/2;
> translate(offset, offset, offset);
>   
> for(int z=0; z<n; z++)
> {
> for(int y=0; y<n; y++)
> {
> for(int x=0; x<n; x++)
> {
> drawWall(x*w2, y*w2, z*w2, w, w, w);
> }  
> }
> }    
> if (frameCount%15 == 0) println(frameRate); 
>   
> if (t)
> p = DEFAULT;
> else
> p = QUAD;
> 
> }
> 
> void drawWall(int x, float y, float z, float thickness, float width, float height) 
> {
> float xw = x + width;
> float yw = y + width; 
> float xt = z + thickness;
>  
> beginShape(p);
> texture(img);
> vertex(x, y, z, 0, 0);
> vertex(xw, y, z, 1, 0);
> vertex(xw, yw, z, 1, 1);
> vertex(x, yw, z, 0, 1);
> endShape();
>   
> beginShape(p);
> texture(img);
> vertex(xw, y, z, 0, 0);
> vertex(xw, y, xt, 1, 0);
> vertex(xw, yw, xt, 1, 1);
> vertex(xw, yw, z, 0, 1);
> endShape();
>   
> beginShape(p);
> texture(img);
> vertex(x, y, xt, 0, 0);
> vertex(xw, y, xt, 1, 0);
> vertex(xw, yw, xt, 1, 1);
> vertex(x, yw, xt, 0, 1);
> endShape();
>   
> beginShape(p);
> texture(img);
> vertex(x, y, z, 0, 0);
> vertex(x, y, xt, 1, 0);
> vertex(x, yw, xt, 1, 1);
> vertex(x, yw, z, 0, 1);
> endShape();
> }
>   
> void keyPressed()
> {
> if (key == 't') 
> t = !t;
> if (t) 
> println("beginShape()");
> else
> println("beginShape(QUAD)");
> }
>   
> 
> ```

I am sharing this as an example of` beginShape()` vs `beginShape(QUAD)` in the context of this topic to explore this:

> [@CosmicCrowMC](#):
>
> Alright, now I’m slapping myself in the face. Starting with beginShape(QUAD); has SIGNIFICANTLY improved performance

And @CosmicCrowMC is ok with me using his drawWall() function for this example.

`:)`

 ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/8/84554709ed4528c181e45486de3d50fe930ab103.jpeg)

---

<div class="post-metadata">

### Author: ![neilcsmith](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/neilcsmith/32/144_2.png) [@neilcsmith](https://discourse.processing.org/u/neilcsmith)
#### Post date: [August 4, 2021, 2:06pm UTC](https://discourse.processing.org/t/faster-rendering-techniques-in-p3d/31465/9 "2021-08-04T14:06:59Z")

</div>

@glv thanks! What I meant in comment above is that you can do this instead -

```java
void draw() {
  ...
  beginShape(QUADS);
  texture(img);
  for(int z=0; z<n; z++) {
    for(int y=0; y<n; y++) {
      for(int x=0; x<n; x++) {
        drawWall(x*w2, y*w2, z*w2, w, w, w);
      }  
    }
  }
  endShape();
  ...
  }

void drawWall(int x, float y, float z, float thickness, float width, float height) {
  float xw = x + width;
  float yw = y + width; 
  float xt = z + thickness;
 
  vertex(x, y, z, 0, 0);
  vertex(xw, y, z, 1, 0);
  vertex(xw, yw, z, 1, 1);
  vertex(x, yw, z, 0, 1);
  
  vertex(xw, y, z, 0, 0);
  vertex(xw, y, xt, 1, 0);
  vertex(xw, yw, xt, 1, 1);
  vertex(xw, yw, z, 0, 1);
  
  vertex(x, y, xt, 0, 0);
  vertex(xw, y, xt, 1, 0);
  vertex(xw, yw, xt, 1, 1);
  vertex(x, yw, xt, 0, 1);
  
  vertex(x, y, z, 0, 0);
  vertex(x, y, xt, 1, 0);
  vertex(x, yw, xt, 1, 1);
  vertex(x, yw, z, 0, 1);
}

```

With your default sketch I don’t see much difference - I had to increase the number of cubes to see quite a difference (eg. w = 15, n = 25). Then it’s 40 fps vs 60 fps. Can’t use this with default (`POLYGON`) and `beginShape()` - renders differently … and crashes.

Incidentally, `QUAD` is theoretically not a valid value for `beginShape(..)` - should be `QUADS` - which is a good clue you can draw more than one at a time. It just so happens, the OpenGL backend treats `QUAD` the same.

---

<div class="post-metadata">

### Author: ![glv](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/glv/32/18785_2.png) [@glv](https://discourse.processing.org/u/glv)
#### Post date: [August 5, 2021, 11:44am UTC](https://discourse.processing.org/t/faster-rendering-techniques-in-p3d/31465/10 "2021-08-05T11:44:46Z")

</div>

Hello,

Thanks for your insight.

> [@neilcsmith](#):
>
> It just so happens, the OpenGL backend treats `QUAD` the same.

Can you provide a reference to this?  
I do like to delve into the technical details.

That may be a good thing!  
I have seen QUAD used in place of QUADS in some other examples including a published book.

I am curious if this applies to:  
POINT, LINE, TRIANGLE and QUAD

If they are used in `beginShape()` in place of:  
POINTS, LINES, TRIANGLES and QUADS

I have explored here so far:

- [Khronos OpenGL® Registry - The Khronos Group Inc](https://www.khronos.org/registry/OpenGL/index_gl.php)
- [GitHub - processing/processing: Source code for the Processing Core and Development Environment (PDE)](https://github.com/processing/processing)
- [processing/core/src/processing/core/PConstants.java at master · processing/processing · GitHub](https://github.com/processing/processing/blob/master/core/src/processing/core/PConstants.java#L292)

> **Code to print some constants**
>
> ```auto
> //https://processing.org/reference/beginShape_.html lists 7
>  
> println(POINTS, LINES, TRIANGLES, TRIANGLE_FAN, TRIANGLE_STRIP, QUADS, QUAD_STRIP); // 7
> println();
> 
> //http://www.songho.ca/opengl/gl_overview.html lists 10
> 
> //println(GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_LINE_LOOP, GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_QUADS, GL_QUAD_STRIP, GL_POLYGON);
> println(POINTS, LINES, LINE_STRIP, LINE_LOOP, TRIANGLES, TRIANGLE_STRIP, TRIANGLE_FAN, QUADS, QUAD_STRIP, POLYGON); // 10
> println();
> 
> println(POINTS, LINES, TRIANGLES, QUADS);
> println(POINT, LINE, TRIANGLE, QUAD);
> println();
> 
> // This lists much more:
> //https://github.com/processing/processing/blob/master/core/src/processing/core/PConstants.java#L292
> 
> ```

`:)`

---

<div class="post-metadata">

### Author: ![neilcsmith](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/neilcsmith/32/144_2.png) [@neilcsmith](https://discourse.processing.org/u/neilcsmith)
#### Post date: [August 5, 2021, 1:03pm UTC](https://discourse.processing.org/t/faster-rendering-techniques-in-p3d/31465/11 "2021-08-05T13:03:36Z")

</div>

> [@glv](#):
>
> Can you provide a reference to this?

The [docs](https://processing.org/reference/beginShape_.html) specifically mention the allowed values being “Either POINTS, LINES, TRIANGLES, TRIANGLE\_FAN, TRIANGLE\_STRIP, QUADS, or QUAD\_STRIP” - also at

> <https://github.com/processing/processing/blob/master/core/src/processing/core/PGraphics.java#L1227>

QUAD is 16 and QUADS is 17. However in PGraphicsOpenGL you can see -

> <https://github.com/processing/processing/blob/master/core/src/processing/opengl/PGraphicsOpenGL.java#L2246>

> [@glv](#):
>
> I am curious if this applies to:  
> POINT, LINE, TRIANGLE and QUAD

By the look of it, TRIANGLE yes, the others no.

---

<div class="post-metadata">

### Author: ![raron](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/raron/32/13651_2.png) [@raron](https://discourse.processing.org/u/raron)
#### Post date: [August 7, 2021, 11:26am UTC](https://discourse.processing.org/t/faster-rendering-techniques-in-p3d/31465/12 "2021-08-07T11:26:52Z")

</div>

Interesting.

Saw this thread a while ago, and wanted to test if a fixed/static(?) shape improves the speed. Like done from the reference page for [createShape](https://www.processing.org/reference/createShape_.html).

I finally got around to it, and It did **not**! Maybe it’s all the translations that really slows it down more than an eventual gain from not having to re-make all the shapes in every frame? Idk. Or maybe I do it in a very inefficient way.

Posting it here in case others find it interesting, even if the thread is marked solved.

> **Click to (un) expand**
>
> ```auto
> // Static shape test
> // 2021-08-07 - Mod by raron
> // Built on:
> 
> // Texture Cube
> // v1.0.0
> // GLV 2021-07-29
> 
> // drawWall() courtesy of CosmicCrowMC:
> //https://discourse.processing.org/t/faster-rendering-techniques-in-p3d/31465
> 
> PImage img;
> 
> final int DEFAULT = 20; // default beginShape() parameter
> 
> int w = 25; // width of cube
> int w2 = w+5; // Add space between cubes
> int n = 15; // number of cubes along each axis
> int p; // beginShape() parameter
> boolean t; // toggles parameter
> 
> // For the static shape test:
> int sp = QUADS; // shape's createShape() parameter
> boolean s; // toggles shape method
> PShape testcube, wall1, wall2, wall3, wall4;
> 
> void setup()
> {
> size(800, 800, P3D);
> noFill();
> noStroke();
> img = loadImage("https://upload.wikimedia.org/wikipedia/commons/thumb/2/2e/Processing_3_logo.png/240px-Processing_3_logo.png");
> img.resize(w, w);
> 
> textureMode(NORMAL);
> 
> String s1 = "Press t to toggle between beginShape() and beginShape(QUAD)";
> String s2 = "Press s to toggle between createShape() and shape()";
> println(s1);
> println(s2);
> println();
> 
> //hint(ENABLE_DEPTH_SORT); // frameRates < 15 with this!
> //hint(DISABLE_DEPTH_TEST); // cool effect! Watch a few rotations.
> 
> makeCube(0, 0, 0, w, w, w);
> }
> 
> void draw()
> {
> background(255, 255, 0);
> lights();
> translate(width/2, height/2, -25);
> rotateY(frameCount*TAU/500);
> float offset = -n*w2/2;
> translate(offset, offset, offset);
> 
> for(int z=0; z<n; z++)
> {
> for(int y=0; y<n; y++)
> {
> for(int x=0; x<n; x++)
> {
> if (!s) {
> drawWall(x*w2, y*w2, z*w2, w, w, w);
> } else {
> pushMatrix();
> translate(x*w2, y*w2, z*w2);
> shape(testcube);
> popMatrix();
> }
> }
> }
> }
> 
> if (frameCount%15 == 0) println(frameRate);
> 
> if (t)
> p = DEFAULT;
> else
> p = QUAD;
> 
> }
> 
> void drawWall(int x, float y, float z, float thickness, float width, float height)
> {
> float xw = x + width;
> float yw = y + height;
> float xt = z + thickness;
> 
> beginShape(p);
> texture(img);
> vertex(x, y, z, 0, 0);
> vertex(xw, y, z, 1, 0);
> vertex(xw, yw, z, 1, 1);
> vertex(x, yw, z, 0, 1);
> endShape();
> 
> beginShape(p);
> texture(img);
> vertex(xw, y, z, 0, 0);
> vertex(xw, y, xt, 1, 0);
> vertex(xw, yw, xt, 1, 1);
> vertex(xw, yw, z, 0, 1);
> endShape();
> 
> beginShape(p);
> texture(img);
> vertex(x, y, xt, 0, 0);
> vertex(xw, y, xt, 1, 0);
> vertex(xw, yw, xt, 1, 1);
> vertex(x, yw, xt, 0, 1);
> endShape();
> 
> beginShape(p);
> texture(img);
> vertex(x, y, z, 0, 0);
> vertex(x, y, xt, 1, 0);
> vertex(x, yw, xt, 1, 1);
> vertex(x, yw, z, 0, 1);
> endShape();
> }
> 
> void makeCube(int x, float y, float z, float thickness, float width, float height)
> {
> wall1 = createShape();
> wall2 = createShape();
> wall3 = createShape();
> wall4 = createShape();
> 
> float xw = x + width;
> float yw = y + height;
> float xt = z + thickness;
> 
> wall1.beginShape(sp);
> wall1.texture(img);
> wall1.vertex(x, y, z, 0, 0);
> wall1.vertex(xw, y, z, 1, 0);
> wall1.vertex(xw, yw, z, 1, 1);
> wall1.vertex(x, yw, z, 0, 1);
> wall1.endShape(CLOSE);
> 
> wall2.beginShape(sp);
> wall2.texture(img);
> wall2.vertex(xw, y, z, 0, 0);
> wall2.vertex(xw, y, xt, 1, 0);
> wall2.vertex(xw, yw, xt, 1, 1);
> wall2.vertex(xw, yw, z, 0, 1);
> wall2.endShape(CLOSE);
> 
> wall3.beginShape(sp);
> wall3.texture(img);
> wall3.vertex(x, y, xt, 0, 0);
> wall3.vertex(xw, y, xt, 1, 0);
> wall3.vertex(xw, yw, xt, 1, 1);
> wall3.vertex(x, yw, xt, 0, 1);
> wall3.endShape(CLOSE);
> 
> wall4.beginShape(sp);
> wall4.texture(img);
> wall4.vertex(x, y, z, 0, 0);
> wall4.vertex(x, y, xt, 1, 0);
> wall4.vertex(x, yw, xt, 1, 1);
> wall4.vertex(x, yw, z, 0, 1);
> wall4.endShape(CLOSE);
> 
> testcube = createShape(GROUP);
> testcube.addChild(wall1);
> testcube.addChild(wall2);
> testcube.addChild(wall3);
> testcube.addChild(wall4);
> }
> 
> void keyPressed()
> {
> if (key == 't') t = !t;
> if (key == 's') s = !s;
> println();
> println();
> if (t) println("beginShape()");
> else println("beginShape(QUAD)");
> if (s) println("shape()");
> else println("createshape()");
> println();
> }
> 
> ```

---

<div class="post-metadata">

### Author: ![neilcsmith](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/neilcsmith/32/144_2.png) [@neilcsmith](https://discourse.processing.org/u/neilcsmith)
#### Post date: [August 7, 2021, 12:05pm UTC](https://discourse.processing.org/t/faster-rendering-techniques-in-p3d/31465/13 "2021-08-07T12:05:02Z")

</div>

The translation methods on a retained PShape are definitely slow - eg. [P3D performance with 62500 boxes - #8 by neilcsmith](https://discourse.processing.org/t/p3d-performance-with-62500-boxes/3821/8)

Although if you do transforms globally I can’t remember it being so much of a problem.

---

<div class="post-metadata">

### Author: ![glv](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/glv/32/18785_2.png) [@glv](https://discourse.processing.org/u/glv)
#### Post date: [August 7, 2021, 12:48pm UTC](https://discourse.processing.org/t/faster-rendering-techniques-in-p3d/31465/14 "2021-08-07T12:48:55Z")

</div>

Hello,

> [@raron](#):
>
> Saw this thread a while ago, and wanted to test if a fixed/static(?) shape improves the speed.

I was doing the same! This aligns with another project I am working on as well.  
When this happens I call it “electromagnetic waves propagating through space”.

Here is what I came up with:

> **Click here to see code**
>
> ```auto
> // Texture Cube 
> // v1.0.0
> // GLV 2021-08-06
> 
> // Inspired by:
> //https://discourse.processing.org/t/faster-rendering-techniques-in-p3d/31465
> 
> // Cube faces rebuilt from scratch.
> // Entire shape built in setup()
> 
> PImage img1, img2, img3, img4;
> 
> int w = 30; // width of cube
> int n = 10; // number of cubes along each axis
> int sp = 5; // space between cubes
> 
> int p = QUADS;
> 
> PShape front, right, left, back;
> PShape cube, borg, borg2;
> 
> void setup() 
> {
> size(800, 800, P3D);
>   
> noFill();
> noStroke();
> noSmooth();
>   
> img1 = loadImage("https://media.digikey.com/Renders/Riedon%20Renders/TO-220-2.jpg");
> img1.resize(w, w);
>   
> img2 = loadImage("https://media.digikey.com/Renders/Stackpole%20Renders/CF%2027k.jpg");
> img2.resize(w, w);
>   
> img3 = loadImage("https://media.digikey.com/Renders/TE%20Connectivity/220m-Ohm-5%25-ROX,-Neohm.jpg");
> img3.resize(w, w);
>   
> img4 = loadImage("https://upload.wikimedia.org/wikipedia/commons/thumb/2/2e/Processing_3_logo.png/240px-Processing_3_logo.png");
> //img4 = loadImage("https://media.digikey.com/Photos/Illinois%20Capacitor/CKH-Series_12-17%28HT%29.jpg");
> img4.resize(w, w);
>   
> textureMode(NORMAL);
> borg2 = createShape(GROUP); 
>   
> int w2 = w + sp; // Add a fixed space between cubes
> int o = n*w2/2; // Offset to center cube
>   
> for(int z=0; z<n; z++)
> {
> for(int y=0; y<n; y++)
> {
> for(int x=0; x<n; x++)
> {      
> cubeShape(x*w2-o, y*w2-o, z*w2-o, w, w, w);
> }  
> }
> } 
>  
> println("Cube count: ", n*n*n);
> }
> 
> void draw() 
> {
> background(255);
>   
> translate(width/2, height/2, 0);
> 
> float angX = map(mouseY, 0, width, -TAU/2, TAU/2);
> rotateX(angX);
>   
> float angY = map(mouseX, 0, width, -TAU/2, TAU/2);
> rotateY(angY);
>   
> shape(borg2, 0, 0);
>   
> if (frameCount%15 == 0) println(frameRate);   
> }
>   
> void cubeShape(int x, int y, int z, int wx, int wy, int wz)
> {
> int sx = x + wx;
> int sy = y + wy;
> int sz = z + wz;
>   
> borg = createShape();
>   
> //front
> borg.beginShape(p);
> borg.texture(img1);
> borg.vertex( x, y, sz, 0, 0); 
> borg.vertex(sx, y, sz, 1, 0);
> borg.vertex(sx, sy, sz, 1, 1);
> borg.vertex( x, sy, sz, 0, 1);  
> borg.endShape(p); 
> borg2.addChild(borg);
>   
> borg = createShape();
> //right
> borg.beginShape(p);
> borg.texture(img2);
> borg.vertex( sx, y, sz, 0, 0);
> borg.vertex( sx, y, z, 1, 0);
> borg.vertex( sx, sy, z, 1, 1);
> borg.vertex( sx, sy, sz, 0, 1);  
> borg.endShape(p);  
> borg2.addChild(borg);
>   
> borg = createShape();
> //back
> borg.beginShape(p);
> borg.texture(img3);
> borg.vertex( sx, y, z, 0, 0);
> borg.vertex( x, y, z, 1, 0);
> borg.vertex( x, sy, z, 1, 1);
> borg.vertex( sx, sy, z, 0, 1);  
> borg.endShape(p); 
> borg2.addChild(borg);
>   
> borg = createShape();
> //left
> borg.beginShape(p);
> borg.texture(img4);
> borg.vertex( x, y, z, 0, 0);
> borg.vertex( x, y, sz, 1, 0);
> borg.vertex( x, sy, sz, 1, 1);
> borg.vertex( x, sy, z, 0, 1);  
> borg.endShape(p);
> borg2.addChild(borg);
> }  
> 
> ```

I built the entire shape in setup().

On my PC I get 60 fps with 10x10x10 (1000) cubes… anything over that the fps go down.

 ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/6/634c500fdc2d20759d66e59c01f2095710e99407.jpeg)

`:)`

---

<div class="post-metadata">

### Author: ![raron](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/raron/32/13651_2.png) [@raron](https://discourse.processing.org/u/raron)
#### Post date: [August 7, 2021, 1:12pm UTC](https://discourse.processing.org/t/faster-rendering-techniques-in-p3d/31465/16 "2021-08-07T13:12:40Z")

</div>

Better!

Ah, I did it in a rather impractical way after all, just making one cube static. Not sure what I was thinking.

Btw, I get multiple NPE errors when running your code in Linux Mint, but it works great in Windows 10.

EDIT: Messed up the posting… reposting.

---

<div class="post-metadata">

### Author: ![raron](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/raron/32/13651_2.png) [@raron](https://discourse.processing.org/u/raron)
#### Post date: [August 7, 2021, 2:27pm UTC](https://discourse.processing.org/t/faster-rendering-techniques-in-p3d/31465/17 "2021-08-07T14:27:07Z")

</div>

Finally!

Coding late (it’s late for me :P) makes for the most obvious but hidden logical errors 🙂 No wonder I got bad FPS, as I drew the whole cube multiple times from the inner loop lol. (plus my previous not-optimal brainfart method…).

Thanks glv, wouldn’t have figured this out without your code! I was really puzzled.  
(plus for the Borg name 🖖 )

Now I get the expected correct result in that the static shape performs much better! At least for more complex / larger objects. 15625 cubes (25 \* 25 \* 25) gave me 37ish FPS after some initial stutter, with createshape. But with the one fixed shape just below 60 FPS.

Ofc, the drawback is that you can’t do dynamic deformation like when collisiding objects, when using pre-made shapes.

Modified code:

> **Click to (un) expand**
>
> ```auto
> // Static shape test 2
> // 2021-08-07 - Mod by raron (fixed the static cube shape now)
> // Built on:
> 
> // Texture Cube
> // v1.0.0
> // GLV 2021-07-29
> 
> // drawWall() courtesy of CosmicCrowMC:
> //https://discourse.processing.org/t/faster-rendering-techniques-in-p3d/31465
> 
> PImage img;
> 
> final int DEFAULT = 20; // default beginShape() parameter
> 
> int w = 15; // width of cube
> int n = 25; // number of cubes along each axis
> int w2 = w+5; // Add space between cubes
> int p; // beginShape() parameter
> boolean t; // toggles parameter
> 
> // For the static shape test:
> int sp = QUADS; // shape parameter
> boolean s; // toggles shape method
> PShape testcube, wall;
> 
> void setup()
> {
> size(800, 800, P3D);
> noFill();
> noStroke();
> noSmooth();
> 
> img = loadImage("https://upload.wikimedia.org/wikipedia/commons/thumb/2/2e/Processing_3_logo.png/240px-Processing_3_logo.png");
> img.resize(w, w);
> 
> println("Press t to toggle between beginShape() and beginShape(QUAD)");
> println("Press s to toggle between createShape() and shape()");
> println();
> println(" Cubicles: " + n*n*n);
> println();
> 
> textureMode(NORMAL);
> //hint(ENABLE_DEPTH_SORT); // frameRates < 15 with this!
> //hint(DISABLE_DEPTH_TEST); // cool effect! Watch a few rotations.
> 
> testcube = createShape(GROUP);
> 
> for(int z=0; z<n; z++)
> {
> for(int y=0; y<n; y++)
> {
> for(int x=0; x<n; x++)
> {
> makeCubicle(x*w2, y*w2, z*w2, w, w, w);
> }
> }
> }
> }
> 
> void draw()
> {
> background(255, 255, 0);
> lights();
> translate(width/2, height/2, -25);
> rotateY(frameCount*TAU/500);
> float offset = -n*w2/2;
> translate(offset, offset, offset);
> 
> if (!s) {
> for(int z=0; z<n; z++)
> {
> for(int y=0; y<n; y++)
> {
> for(int x=0; x<n; x++)
> {
> drawWall(x*w2, y*w2, z*w2, w, w, w);
> }
> }
> }
> } else {
> shape(testcube);
> }
> 
> if (frameCount%15 == 0) println(frameRate);
> 
> if (t)
> p = DEFAULT;
> else
> p = QUAD;
> 
> }
> 
> void drawWall(int x, float y, float z, float thickness, float width, float height)
> {
> float xw = x + width;
> float yw = y + height;
> float xt = z + thickness;
> 
> beginShape(p);
> texture(img);
> vertex(x, y, z, 0, 0);
> vertex(xw, y, z, 1, 0);
> vertex(xw, yw, z, 1, 1);
> vertex(x, yw, z, 0, 1);
> endShape();
> 
> beginShape(p);
> texture(img);
> vertex(xw, y, z, 0, 0);
> vertex(xw, y, xt, 1, 0);
> vertex(xw, yw, xt, 1, 1);
> vertex(xw, yw, z, 0, 1);
> endShape();
> 
> beginShape(p);
> texture(img);
> vertex(x, y, xt, 0, 0);
> vertex(xw, y, xt, 1, 0);
> vertex(xw, yw, xt, 1, 1);
> vertex(x, yw, xt, 0, 1);
> endShape();
> 
> beginShape(p);
> texture(img);
> vertex(x, y, z, 0, 0);
> vertex(x, y, xt, 1, 0);
> vertex(x, yw, xt, 1, 1);
> vertex(x, yw, z, 0, 1);
> endShape();
> }
> 
> void makeCubicle(int x, float y, float z, float thickness, float width, float height)
> {
> float xw = x + width;
> float yw = y + height;
> float xt = z + thickness;
> 
> wall = createShape();
> wall.beginShape(sp);
> wall.texture(img);
> wall.vertex(x, y, z, 0, 0);
> wall.vertex(xw, y, z, 1, 0);
> wall.vertex(xw, yw, z, 1, 1);
> wall.vertex(x, yw, z, 0, 1);
> wall.endShape(sp);
> testcube.addChild(wall);
> 
> wall = createShape();
> wall.beginShape(sp);
> wall.texture(img);
> wall.vertex(xw, y, z, 0, 0);
> wall.vertex(xw, y, xt, 1, 0);
> wall.vertex(xw, yw, xt, 1, 1);
> wall.vertex(xw, yw, z, 0, 1);
> wall.endShape(sp);
> testcube.addChild(wall);
> 
> wall = createShape();
> wall.beginShape(sp);
> wall.texture(img);
> wall.vertex(x, y, xt, 0, 0);
> wall.vertex(xw, y, xt, 1, 0);
> wall.vertex(xw, yw, xt, 1, 1);
> wall.vertex(x, yw, xt, 0, 1);
> wall.endShape(sp);
> testcube.addChild(wall);
> 
> wall = createShape();
> wall.beginShape(sp);
> wall.texture(img);
> wall.vertex(x, y, z, 0, 0);
> wall.vertex(x, y, xt, 1, 0);
> wall.vertex(x, yw, xt, 1, 1);
> wall.vertex(x, yw, z, 0, 1);
> wall.endShape(sp);
> testcube.addChild(wall);
> }
> 
> void keyPressed()
> {
> if (key == 't') t = !t;
> if (key == 's') s = !s;
> println();
> println();
> if (t) println("beginShape()");
> else println("beginShape(QUAD)");
> if (s) println("static shape()");
> else println("dynamic createshape()");
> println();
> }
> 
> ```

Btw, replacing the images in your code above fixed it for my linux box as well, and I get the same results on my computer (maybe a tad less at 58-59 FPS).

---

<div class="post-metadata">

### Author: ![glv](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/glv/32/18785_2.png) [@glv](https://discourse.processing.org/u/glv)
#### Post date: [August 7, 2021, 2:37pm UTC](https://discourse.processing.org/t/faster-rendering-techniques-in-p3d/31465/18 "2021-08-07T14:37:41Z")

</div>

> [@raron](#):
>
> Thanks glv, wouldn’t have figured this out without your code!

You would have!

It took some persistence on my part and I did this after a good nap.

I have many versions of this (one very similar to yours) and learned quite a bit in the process.

I have a dynamic version that updates cube faces (images) as well.  
It is a much smaller cube count and larger images and works for the that purpose.

That was fun!

`:)`
