Depth Sorting and PShape

Am I doing something wrong or hint(ENABLE_DEPTH_SORT); only works with beginShape() and endShape() and not with PShape. If I am not wrong, and this is a issue, how can I do depth sort myself on PShapes ?

Screenshot, red = PShape, blue = not PShape like : beginShape(), box(), line() …

The code, using QueasyCam library :

import queasycam.*;

QueasyCam cam;

PShape box;
PShape sphere;

public void setup() {
  fullScreen(P3D);
  
  cam = new QueasyCam(this);
  
  box = createShape(BOX, 100.0f);
  sphere = createShape(SPHERE, 50.0f);
  
  box.setStroke(false);
  box.setFill(color(255, 0, 0, 100));
  
  sphere.setStroke(false);
  sphere.setFill(color(255, 0, 0, 100));
}

public void draw() {
  background(255);
  
  // Just to be sure
  hint(ENABLE_DEPTH_TEST);
  hint(ENABLE_DEPTH_MASK);
  
  // Magic line that should all correct
  hint(ENABLE_DEPTH_SORT);
  
  shape(box);
  
  pushMatrix();
  translate(0, 0, 200);
  shape(sphere);
  popMatrix();
  
  pushMatrix();
  translate(200, 0, 0);
  noStroke();
  fill(0, 0, 255, 100);
  box(100);
  popMatrix();
  
  pushMatrix();
  translate(200, 0, 200);
  noStroke();
  fill(0, 0, 255, 100);
  sphere(50);
  popMatrix();
}

Also, weird lag when going in between the 4 shapes, dont know why.

Thank you !

Does someone know how to solve this issue ?

I could not install QueasyCam (it fails) so I tried with PeasyCam

import peasy.*;

PeasyCam cam;

PShape box;
PShape sphere;

public void setup() {
  fullScreen(P3D);
  
  cam = new PeasyCam(this, 400);
  
  box = createShape(BOX, 100.0f);
  sphere = createShape(SPHERE, 50.0f);
  
  box.setStroke(false);
  box.setFill(color(255, 0, 0, 100));
  
  sphere.setStroke(false);
  sphere.setFill(color(255, 0, 0, 100));
  
  noStroke();
  fill(0, 0, 255, 100);
}

public void draw() {
  background(255);
  
  // Just to be sure
  hint(ENABLE_DEPTH_TEST);
  hint(ENABLE_DEPTH_MASK);
  
  // Magic line that should all correct
  hint(ENABLE_DEPTH_SORT);
  
  for(int i=0; i<2; i++) {
    translate(0, 0, i*200);
    pushMatrix();
    translate(100, 100, 0);
    sphere(50);
    translate(-200, 0, 0);
    box(100);   
    translate(0, -200, 0);
    shape(box);
    translate(200, 0, 0);
    shape(sphere);
    popMatrix();
  }  
}

For me too the shapes created with createShape behave different from those drawn directly.
But even when dealing only with shapes drawn directly the transparency works only sometimes, depending on the rotation.
2018-10-08-215604_500x500_scrot 2018-10-08-215643_500x500_scrot

To use QueasyCam you can also paste the source code in a new tab : https://github.com/jrc03c/queasycam/blob/master/src/template/library/QueasyCam.java

But same problem with QueasyCam in some angles hint(ENABLE_DEPTH_SORT); doesent work properly PShape or not :confused: I thought at least it worked 100% without PShape

Don’t you want to be disabling the depth test to get this to work correctly?

I modified this program for testing transparency and hints and it seems like things are fine (as @neilcsmith suggests) when all three hints are disabled.

import peasy.*;
PeasyCam cam;
boolean b[] = new boolean[3];
PShape shp1, shp2;

void setup() {
  size(800, 600, P3D);
  cam = new PeasyCam(this, 400);
  hint(DISABLE_DEPTH_TEST);
  hint(DISABLE_DEPTH_SORT);
  hint(DISABLE_DEPTH_MASK);
  shp1 = createShape(SPHERE, 90);
  shp1.setStroke(false);
  shp1.setFill(color(255, 40, 20, 100));
  shp2 = createShape(BOX, 180);
  shp2.setStroke(false);
  shp2.setFill(color(255, 40, 20, 100));
}

void draw() {
  background(255);

  cam.beginHUD();
  fill(0);
  text("DEPTH_TEST " + b[0], 20, 20);
  text("DEPTH_SORT " + b[1], 20, 40);
  text("DEPTH_MASK " + b[2], 20, 60);
  text("<- use the mouse to toggle settings", 200, 40);
  cam.endHUD();
  
  for (int x = -200; x<=200; x+=200) {
    for (int y = -200; y<=200; y+=200) {
      pushMatrix();
      translate(x, 0, y);
      shape((x+y)/200 % 2 == 0 ? shp1 : shp2);
      popMatrix();
    }
  }
}
void mousePressed() {
  int id = mouseY / 20;
  if (id < b.length) {
    b[id] ^= true; // same as b[id] = !b[id]
  }
  hint(b[0] ? ENABLE_DEPTH_TEST : DISABLE_DEPTH_TEST);
  hint(b[1] ? ENABLE_DEPTH_SORT : DISABLE_DEPTH_SORT);
  hint(b[2] ? ENABLE_DEPTH_MASK : DISABLE_DEPTH_MASK);
}

That wasn’t quite what I suggested! There are still times you might want to depth sort to do the painter’s algorithm, although sometimes the output will be fine without. I’m just not sure when you’d want to depth test and depth sort together.

You’re right. Sorry, I was rewriting the sentence and left it in the wrong state.

1 Like

Wow ! At first i thought it worked well… but if you add opaque objects you see it doesent work. I also tried enabling per object depth mask but still doesent work.

Any solutions ?

PeasyCam cam;
boolean b[] = new boolean[3];
PShape shp1, shp2;

void setup() {
  size(800, 600, P3D);
  cam = new PeasyCam(this, 400);
  hint(DISABLE_DEPTH_TEST);
  hint(DISABLE_DEPTH_SORT);
  hint(DISABLE_DEPTH_MASK);
  shp1 = createShape(SPHERE, 90);
  shp1.setStroke(false);
  shp1.setFill(color(100));
  shp2 = createShape(BOX, 180);
  shp2.setStroke(false);
  shp2.setFill(color(255, 40, 20, 100));
}

void draw() {
  background(255);

  cam.beginHUD();
  fill(0);
  text("DEPTH_TEST " + b[0], 20, 20);
  text("DEPTH_SORT " + b[1], 20, 40);
  text("DEPTH_MASK " + b[2], 20, 60);
  text("<- use the mouse to toggle settings", 200, 40);
  cam.endHUD();
  
  for(int i=0; i<2; i++) {
    for (int x = -200; x<=200; x+=200) {
      for (int y = -200; y<=200; y+=200) {
        pushMatrix();
        translate(x, i*300, y);
        // per object depth mask
        // hint((x+y)/200 % 2 == 0 ? ENABLE_DEPTH_MASK : DISABLE_DEPTH_MASK);
        shape((x+y)/200 % 2 == 0 ? shp1 : shp2);
        popMatrix();
      }
    }
  }
}
void mousePressed() {
  int id = mouseY / 20;
  if (id < b.length) {
    b[id] ^= true; // same as b[id] = !b[id]
  }
  hint(b[0] ? ENABLE_DEPTH_TEST : DISABLE_DEPTH_TEST);
  hint(b[1] ? ENABLE_DEPTH_SORT : DISABLE_DEPTH_SORT);
  hint(b[2] ? ENABLE_DEPTH_MASK : DISABLE_DEPTH_MASK);
}```

Maybe ideas here?

Update: I wonder if the faces are single sided and they should be made double sided? And if that’s the case, can it be done by tweaking the shader?

And also in https://www.khronos.org/opengl/wiki/Transparency_Sorting

Thinking about it I’m not sure disabling the depth test is correct. Draw solid objects with depth mask enabled, then draw depth sorted translucent objects with depth mask disabled?

@hamoid yes but not in the shader and by default it is double sided. Anything that can be done in OpenGL can be done in processing so :

import peasy.*;
import com.jogamp.opengl.GL2ES2;
import com.jogamp.opengl.GL;

PeasyCam cam;
boolean b[] = new boolean[3];
PShape shp1, shp2;

PGL pgl;
GL2ES2 gl;

void setup() {
  size(800, 600, P3D);
  cam = new PeasyCam(this, 400);
  hint(DISABLE_DEPTH_TEST);
  hint(DISABLE_DEPTH_SORT);
  hint(DISABLE_DEPTH_MASK);
  shp1 = createShape(SPHERE, 90);
  shp1.setStroke(false);
  shp1.setFill(color(100));
  shp2 = createShape(BOX, 180);
  shp2.setStroke(false);
  shp2.setFill(color(255, 40, 20, 100));
}

void draw() {
  background(255);

  cam.beginHUD();
  fill(0);
  text("DEPTH_TEST " + b[0], 20, 20);
  text("DEPTH_SORT " + b[1], 20, 40);
  text("DEPTH_MASK " + b[2], 20, 60);
  text("<- use the mouse to toggle settings", 200, 40);
  cam.endHUD();
  
  pgl = beginPGL();  
  gl = ((PJOGL)pgl).gl.getGL2ES2();
  
  // OpenGL Code
  gl.glEnable(GL.GL_CULL_FACE);
  gl.glCullFace(GL.GL_FRONT); // GL_BACK, GL_FRONT_AND_BACK
  
  for(int i=0; i<2; i++) {
    for (int x = -200; x<=200; x+=200) {
      for (int y = -200; y<=200; y+=200) {
        pushMatrix();
        translate(x, i*300, y);
        // hint((x+y)/200 % 2 == 0 ? ENABLE_DEPTH_MASK : DISABLE_DEPTH_MASK);
        shape((x+y)/200 % 2 == 0 ? shp1 : shp2);
        popMatrix();
      }
    }
  }
  
  endPGL();
}
void mousePressed() {
  int id = mouseY / 20;
  if (id < b.length) {
    b[id] ^= true; // same as b[id] = !b[id]
  }
  hint(b[0] ? ENABLE_DEPTH_TEST : DISABLE_DEPTH_TEST);
  hint(b[1] ? ENABLE_DEPTH_SORT : DISABLE_DEPTH_SORT);
  hint(b[2] ? ENABLE_DEPTH_MASK : DISABLE_DEPTH_MASK);
}

@neilcsmith could you make a quick exemple, i tried to do that but I failed.

This seems to work correctly? Enabling / Disabling depth sort doesn’t change anything, although I think it might if the translucent shapes were different colours / opacities? :confused:

import peasy.*;

PeasyCam cam;
PShape shp1, shp2;

void setup() {
 size(800, 600, P3D);
 cam = new PeasyCam(this, 400);
 shp1 = createShape(SPHERE, 90);
 shp1.setStroke(false);
 shp1.setFill(color(100));
 shp2 = createShape(BOX, 180);
 shp2.setStroke(false);
 shp2.setFill(color(255, 40, 20, 100));
}

void draw() {
 background(255);
 
 // All opaque
 
 hint(ENABLE_DEPTH_MASK);
 //hint(DISABLE_DEPTH_SORT);
  
 for(int i=0; i<2; i++) {
   for (int x = -200; x<=200; x+=200) {
     for (int y = -200; y<=200; y+=200) {
       pushMatrix();
       translate(x, i*300, y);
       if ((x+y)/200 % 2 == 0) {
         shape(shp1);
       }
       popMatrix();
     }
   }
 }
 
 // All transparent
 
 hint(DISABLE_DEPTH_MASK);
 //hint(ENABLE_DEPTH_SORT);
 
 for(int i=0; i<2; i++) {
   for (int x = -200; x<=200; x+=200) {
     for (int y = -200; y<=200; y+=200) {
       pushMatrix();
       translate(x, i*300, y);
       if ((x+y)/200 % 2 != 0) {
         shape(shp2);
       }
       popMatrix();
     }
   }
 }
 
}

1 Like

Yeah wow ! It actually works, I also tried different colors, seems to work well. :smiley:

But… when you move the camera, maybe its just me, but it display weird artefacts :

Actually : It works !!! :smiley: :tada::tada: @neilcsmith thank you very much :smiley: I’ts been so long since i wanted to solve this problem. You’re the best !!

I had processing 3.3.6, in 3.4.0 no artefacts !

The solution, supports transparent & opaque PShapes to be rendered correctly (exemple) :

import com.jogamp.opengl.GL2ES2;
import com.jogamp.opengl.GL;

PeasyCam cam;
PShape shp1, shp2;

void setup() {
 size(800, 600, P3D);
 cam = new PeasyCam(this, 400);
 shp1 = createShape(SPHERE, 90);
 shp1.setStroke(false);
 shp1.setFill(color(100));
 shp2 = createShape(BOX, 180);
 shp2.setStroke(false);
 shp2.setFill(color(255, 40, 20, 100));
}

void draw() {
 background(255);
 
 // All opaque
 
 hint(ENABLE_DEPTH_MASK);
 //hint(DISABLE_DEPTH_SORT);
  
 for(int i=0; i<2; i++) {
   for (int x = -200; x<=200; x+=200) {
     for (int y = -200; y<=200; y+=200) {
       pushMatrix();
       translate(x, i*300, y);
       if ((x+y)/200 % 2 == 0) {
         shp1.setFill(true);
         shp1.setFill(color(x+200, y+200, i*100));
         shape(shp1);
       }
       popMatrix();
     }
   }
 }
 
 // All transparent
 
 hint(DISABLE_DEPTH_MASK);
 //hint(ENABLE_DEPTH_SORT);
 
 for(int i=0; i<2; i++) {
   for (int x = -200; x<=200; x+=200) {
     for (int y = -200; y<=200; y+=200) {
       pushMatrix();
       translate(x, i*300, y);
       if ((x+y)/200 % 2 != 0) {
         shp2.setFill(true);
         shp2.setFill(color( 255-(x+200), 255-(y+200), 255-(i*100), 100 ));
         shape(shp2);
       }
       popMatrix();
     }
   }
 }
}```
1 Like