Difficulty rendering translucent cubes with ofVbo

EDIT2: Solved by removing gl depth test.
EDIT: I just discovered GL_CULL_FACE, and I have to see if that can fix it.

I was following the icosahedron example in the documentation to try to convert it to a box renderer. So it creates the vbo inserting with setVertexData, setColorData and setIndexData.

I have a method called insert_cube(), which takes a position and edge length, and inserts 8 vertices, 8 colors, and 6 faces (using GL_QUADS). The code is below:

#include "ofApp.h"

vector<ofFloatColor> colors;
vector<glm::vec3>    verts;
vector<ofIndexType>  faces;

ofVbo vbo;
ofEasyCam cam;

void insert_cube(glm::vec3 p, float edge) {
	float l = edge / 2;
	auto v0 = p + glm::vec3( l,  l,  l);
	auto v1 = p + glm::vec3(-l,  l,  l);
	auto v2 = p + glm::vec3(-l,  l, -l);
	auto v3 = p + glm::vec3( l,  l, -l);

	auto v4 = p + glm::vec3( l, -l,  l);
	auto v5 = p + glm::vec3(-l, -l,  l);
	auto v6 = p + glm::vec3(-l, -l, -l);
	auto v7 = p + glm::vec3( l, -l, -l);
	verts.insert(verts.end(), {v0, v1, v2, v3, v4, v5, v6, v7});
	
	ofFloatColor c(1, 1, 1, 0.5);
	colors.insert(colors.end(), { c, c, c, c,  c, c, c, c});

	unsigned int d = verts.size() - 8;
	faces.insert(faces.end(), { d+0, d+1, d+2, d+3 });
	faces.insert(faces.end(), { d+3, d+2, d+6, d+7 });
	faces.insert(faces.end(), { d+7, d+6, d+5, d+4 });
	faces.insert(faces.end(), { d+4, d+5, d+1, d+0 });
	faces.insert(faces.end(), { d+6, d+2, d+1, d+5 });
	faces.insert(faces.end(), { d+3, d+7, d+4, d+0 }); 
}

int cubes = 0;
void ofApp::setup(){
	ofSetBackgroundColor(10); glEnable(GL_DEPTH_TEST);

	insert_cube(glm::vec3(0, 0, 0), 20.0f);   cubes++;
	insert_cube(glm::vec3(0, 0,  50), 20.0f); cubes++;
	insert_cube(glm::vec3(0, 50, 50), 20.0f); cubes++;
	insert_cube(glm::vec3(0, 100, 50), 20.0f); cubes++;

	vbo.setVertexData(verts.data(), 8*cubes, GL_STATIC_DRAW);
	vbo.setColorData(colors.data(), 8*cubes, GL_STATIC_DRAW);
	vbo.setIndexData(faces.data(), (6*4)*cubes, GL_STATIC_DRAW);
}

void ofApp::update(){}

void ofApp::draw(){
	cam.begin();
	glEnable(GL_DEPTH_TEST);
	vbo.drawElements(GL_QUADS, (6*4)*cubes);
	cam.end();
}

For some reason, on 1 side, it is partially translucent:
image

And from the opposite perspective, it’s not transparent at all.
image

I’ve been messing with the clockwise/counterclockwise orientation of the face data, having cut up a cube with paper and labelling the vertices. I’m almost certain I have the orientation of the face data correct, but I still can’t seem to get it to render correctly.

I’ve tried using GL_TRIANGLES, and that resulted in the same image.

Any suggestions for what I might be missing? I have no idea at this point.

Thanks.

I’m attempting to get something like this with ofBox():
image
but using ofBox is too slow for many boxes.

Hi @PHIL528, this post looks like a continuation of a couple of related series of posts in the forum (here and here).

Translucency in 3d is maybe a bit complicated; there are posts in the forum about it. Generally I think it helps to draw the objects from far to near. And I think there are some interactions with ofEnableDepthTest and ofEnableAlphaBlending that I don’t fully understand.

oF has a wonderful way of creating a 3d box with ofBoxPrimitive. An ofBoxPrimitive inherits from of3dPrimitive, so you can use all of the functions in that class too. Importantly for drawing lots of boxes, the ofMesh in an ofBoxPrimitive can be a ofVboMesh. So, my understanding of an ofVboMesh is that it resides in the memeory of the gpu, which is a convenient place to store it if it doesn’t change too often, and/or if you want to draw it quickly and often. The ofBoxPrimitive will use triangles in the ofMesh, and you can set the resolution, colors, add texcoords or map them from a texture, etc.

ofVboMesh::drawInstanced() will draw a ton of boxes. I can easily draw 50,000 boxes on a 2-core Skylake i7 laptop. The app slows to maybe 10fps with 500,000 boxes. You will have to work a bit harder (in the vertex and geometry shader(s)) if you want each box to be a different size or orientation. But its an awesome and simple function if you want to draw a bunch of identical boxes. You can get an ofVboMesh from an ofBoxPrimitive like this:

ofBoxPrimitive box;
// do some things to set up the ofMesh in the box
box.setUseVbo(true);
ofVboMesh vboMesh = box.getMesh();

ofVboMesh::drawInstanced() will draw a whole bunch of boxes centered at 0, 0 in the window. The vertices of each ofVboMesh (24 in total when the resolution of the box is 1) can be modified by a vertex shader, and/or maybe also by a geometry shader. As in the vboMeshDrawInstancedExample project, each set of vertices can be accessed by their unique gl_InstanceID, which is passed into the shader along with the vertices of each of each ofVboMesh. So, with a unique gl_InstanceID, each box can be moved to a unique point in the 3d space with just a few (or several) lines of code and an ofTexture that holds their positions.

Its easy to pass position data to a shader in an ofTexture. I like to allocate an ofFbo with a GL_RGBA16F format (so float values between 0.0 and 1.0 for 4 RGBA channels), draw an ofFloatImage into it, and then use the RGB values for a position. If the positions don’t change, you just have to pass the texture once to the shader. A 200 x 200 image can describe 40,000 unique positions for the same number of boxes. The gpuParticleSystemExample does something very similar. It uses 1 texture for positions, and another for velocities. The really fun part of using textures as data containers is that they can be very quickly updated by the gpu with a shader.

Hope this helps in your quest to draw lots of boxes!

Hi again @PHIL528 , this post and the thread may help explain the transparency aspects of drawing in 3d: Point as texture with depth test enabled - #2 by Drazinut