0
\$\begingroup\$

This question already has an answer here:

I'm working on a simple 3d game using the Processing Java environment. I want to optimise my code so I can draw many many 'objects' (the world is made up of many different shaped objects that live inside the volume of a cube) without the framerate dropping. How can I detect which faces cannot be seen and stop drawing them? I have tried this code:

pgl = (PJOGL) beginPGL();  
gl = pgl.gl.getGL2ES2();
gl.glEnable(GL.GL_CULL_FACE);
gl.glCullFace(GL.GL_BACK);

which does do backface culling but it is not all that I want. I want to stop rendering any face that the camera cannot see, i.e. inside faces etc.

The code used to draw the objects (just a simple cube for testing) is as follows:

    noFill();
    noStroke();
    noSmooth();
    push();
    lights();
    translate(this.x * this.size, this.y * this.size, this.z * this.size);
    beginShape(QUADS);
    texture(this.texture_image);
    vertex(-this.size / 2, -this.size / 2, this.size / 2, 0, 0);
    vertex( this.size / 2, -this.size / 2, this.size / 2, this.size / 2, 0);
    vertex( this.size / 2, this.size / 2, this.size / 2, this.size / 2, this.size / 2);
    vertex(-this.size / 2, this.size / 2, this.size / 2, 0, this.size / 2);

    // -Z "back" face
    vertex( this.size / 2, -this.size / 2, -this.size / 2, 0, 0);
    vertex(-this.size / 2, -this.size / 2, -this.size / 2, this.size / 2, 0);
    vertex(-this.size / 2, this.size / 2, -this.size / 2, this.size / 2, this.size / 2);
    vertex( this.size / 2, this.size / 2, -this.size / 2, 0, this.size / 2);

    // +Y "bottom" face
    vertex(-this.size / 2, this.size / 2, this.size / 2, 0, 0);
    vertex( this.size / 2, this.size / 2, this.size / 2, this.size / 2, 0);
    vertex( this.size / 2, this.size / 2, -this.size / 2, this.size / 2, this.size / 2);
    vertex(-this.size / 2, this.size / 2, -this.size / 2, 0, this.size / 2);

    // -Y "top" face
    vertex(-this.size / 2, -this.size / 2, -this.size / 2, 0, 0);
    vertex( this.size / 2, -this.size / 2, -this.size / 2, this.size / 2, 0);
    vertex( this.size / 2, -this.size / 2, this.size / 2, this.size / 2, this.size / 2);
    vertex(-this.size / 2, -this.size / 2, this.size / 2, 0, this.size / 2);

    // +X "right" face
    vertex( this.size / 2, -this.size / 2, this.size / 2, 0, 0);
    vertex( this.size / 2, -this.size / 2, -this.size / 2, this.size / 2, 0);
    vertex( this.size / 2, this.size / 2, -this.size / 2, this.size / 2, this.size / 2);
    vertex( this.size / 2, this.size / 2, this.size / 2, 0, this.size / 2);

    // -X "left" face
    vertex(-this.size / 2, -this.size / 2, -this.size / 2, 0, 0);
    vertex(-this.size / 2, -this.size / 2, this.size / 2, this.size / 2, 0);
    vertex(-this.size / 2, this.size / 2, this.size / 2, this.size / 2, this.size / 2);
    vertex(-this.size / 2, this.size / 2, -this.size / 2, 0, this.size / 2);

    endShape();
    pop();

Sorry for the long code.

Thanks in advance.

\$\endgroup\$

marked as duplicate by Maximus Minimus, DMGregory Apr 25 at 16:20

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • \$\begingroup\$ In what specific way does the code you've shown fail to work? It looks like pretty typical back face culling. \$\endgroup\$ – DMGregory Apr 16 at 9:37
  • \$\begingroup\$ @DMGregory It works for back face culling but I want to stop rendering anything that the camera cannot see. I understand that this is a difficult task but was wondering if Processing/OGL had any inbuilt features to help with it. \$\endgroup\$ – Jachdich Apr 16 at 9:40
  • \$\begingroup\$ @DMGregory see my recent edit \$\endgroup\$ – Jachdich Apr 16 at 9:41
  • \$\begingroup\$ Are you talking about frustum culling? Occlusion culling? Or something else? What is an "inside face" if it's not already handled by back face culling? \$\endgroup\$ – DMGregory Apr 16 at 9:42
  • 1
    \$\begingroup\$ Ohhh, you're building your objects out of cube-shaped voxels? The usual solution there is to group them into chunks, pre-processed to contain only outside faces. When you say "it needs to be there for other reasons" that sounds like a detail you should explain in your question. It's unclear why a face that's not drawn needs to be submitted to the GPU at all. Maybe you're using a different definition of "be there" meaning something other than "included in the vertex buffer used for drawing"? \$\endgroup\$ – DMGregory Apr 16 at 9:59
0
\$\begingroup\$

It not always beneficial to cull absolutely everything, not even in voxel games. Loading new geometry or dealing with faces as separate objects can really cost a lot of computational power, especially given how 3 of those sides gets culled by backface culling automatically 100% of the time.

What you could do instead is to render only what's roughly in front of the player and rendering everything starting from the players position and going outward. That way the blocks will obstruct everything coming after them and depth culling will kick in reducing the time spent in the fragment shader to close to zero.

You can combine that with instanced rendering (and possibly geometry buffers) and you'll get a pretty fast system

\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.