Situation:
I use Vertex Buffer Objects in OpenGL (LWJGL java binding, GL11) to render rectangles. I can render textures (vertices and texture coordinates) without any problems, also adding color to it leads to the desired effect (like making it semi-translucent). Only using vertices and color makes it invisible.
Researchs:
- Disabling alpha test and blending leads to a black rect, which is obviously the vertex and color VBO without alpha testing and blending -> It is rendered.
- Disabling only alpha testing leads to the same result like before.
- Disabling only blending does also not help.
I can’t find any error in my code, neither I can find the source of the problem.
States activated when rendering:
GL_TEXTURE_2D, GL_SMOOTH (Shade Model), GL_DEPTH_TEST, GL_LEQUAL (Depth Func), GL_BACK (Cull Face)
Blend Func: GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA
Alpha Func: GL_GREATER and 0.1F
Projection: glOrtho(0, 1, 1, 0, 0, 1000);
All rectangles are on the Z axis at -1 (I called once glTranslatef(0,0,-1) before rendering the GUI), on the X and Y axis between 0 and 1.
Additionally I have to say that a texture is bound, but this should not be the problem.
Important Code
Note: The Color class basically wraps an RGBA color and has been written by me, so it is not the Color class of the java.awt package.
Note 2: I know that my VertexBufferObject class is not optimized with dynamic draw VBOs, but I could not find time to handle that.
Vertex Buffer Object
private boolean isStatic;
private boolean hasColor;
private boolean hasTexture;
private boolean hasNormals;
private int renderMode;
private int vertices;
private int vertexSize;
private ByteBuffer buffer;
private int vboId;
private boolean isDirty;
public VertexBufferObject (int renderMode, boolean isStatic, boolean hasColor, boolean hasTexture, boolean hasNormals, int vertices) {
this.isStatic = isStatic;
this.hasColor = hasColor;
this.hasTexture = hasTexture;
this.hasNormals = hasNormals;
this.vertices = vertices;
this.renderMode = renderMode;
vertexSize = calculateVertexSize();
}
public void markDirty () {
isDirty = true;
}
public void createBuffer () {
buffer = BufferUtils.createByteBuffer(getVertexSize());
markDirty();
}
public void createVBO () {
buffer.flip();
vboId = ARBVertexBufferObject.glGenBuffersARB();
// Buffer into vbo
ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, vboId);
ARBVertexBufferObject.glBufferDataARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, buffer, (isStatic ? ARBVertexBufferObject.GL_STATIC_DRAW_ARB : ARBVertexBufferObject.GL_DYNAMIC_DRAW_ARB));
// Unbind
ARBVertexBufferObject.glUnmapBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB);
ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, 0);
if (isStatic) buffer = null;
}
public void addVertex (float x, float y, float z) {
buffer.putFloat(x);
buffer.putFloat(y);
buffer.putFloat(z);
}
public void addTextureCoordinates (float u, float v) {
buffer.putFloat(u);
buffer.putFloat(v);
}
public void addColor (Color color) {
addColor(color.getRGBAInt());
}
public void addColor (int rgba) {
buffer.putInt(rgba);
System.out.println(Integer.toBinaryString(rgba));
}
public void addNormal (byte x, byte y, byte z) {
buffer.put(x);
buffer.put(y);
buffer.put(z);
}
public void setVertex (int index, float x, float y, float z) {
index *= vertexSize;
buffer.position(index);
buffer.putFloat(x);
buffer.putFloat(y);
buffer.putFloat(z);
markDirty();
}
public void setTextureCoordinates (int index, float u, float v) {
index *= vertexSize + 12;
buffer.position(index);
buffer.putFloat(u);
buffer.putFloat(v);
markDirty();
}
public void setColor (int index, Color color) {
setColor(index, color.getRGBAInt());
}
public void setColor (int index, int rgba) {
index *= vertexSize + (hasTexture ? 20 : 12);
buffer.position(index);
buffer.putInt(rgba);
markDirty();
}
public void setNormal (int index, byte x, byte y, byte z) {
index *= vertexSize - 3;
buffer.position(index);
buffer.put(x);
buffer.put(y);
buffer.put(z);
markDirty();
}
public void draw () {
draw(0, vertices);
}
public void draw (int start, int vertexNumber) {
if (vboId == 0) return;
ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, vboId);
// Update Dynamic VBO
if (isDirty && !isStatic) {
buffer.position(0);
int vboType = isStatic ? ARBVertexBufferObject.GL_STATIC_DRAW_ARB : ARBVertexBufferObject.GL_DYNAMIC_DRAW_ARB;
ARBVertexBufferObject.glBufferDataARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, 0, vboType);
ARBVertexBufferObject.glBufferDataARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, buffer, vboType);
isDirty = false;
}
// Stride
int stride = 12;
if (hasTexture) stride += 8;
if (hasColor) stride += 4;
if (hasNormals) stride += 3;
// Apply Pointers
GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
GL11.glVertexPointer(3, GL11.GL_FLOAT, stride, 0);
if (hasTexture) {
GL11.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
GL11.glTexCoordPointer(2, GL11.GL_FLOAT, stride, 12);
}
if (hasColor) {
GL11.glEnableClientState(GL11.GL_COLOR_ARRAY);
GL11.glColorPointer(4, GL11.GL_UNSIGNED_BYTE, stride, hasTexture ? 20 : 12);
}
if (hasNormals) {
GL11.glEnableClientState(GL11.GL_NORMAL_ARRAY);
GL11.glNormalPointer(GL11.GL_BYTE, stride, stride - 3);
}
// Draw with specified render mode
GL11.glDrawArrays(renderMode, start, vertexNumber);
// Unbind VBO
if (hasTexture) GL11.glDisableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
if (hasColor) GL11.glDisableClientState(GL11.GL_COLOR_ARRAY);
if (hasNormals) GL11.glDisableClientState(GL11.GL_NORMAL_ARRAY);
GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);
ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, 0);
}
public void destroy () {
ARBVertexBufferObject.glDeleteBuffersARB(vboId);
}
private int calculateVertexSize () {
return vertices * 12 + vertices * (hasTexture ? 8 : 0) + vertices * (hasColor ? 4 : 0) + vertices * (hasNormals ? 4 : 0);
}
ColorFrameRenderer (The Rectangle, basically)
private VertexBufferObject vbo;
private Color color;
public ColorFrameRenderer(int sizeX, int sizeY, Color color) {
super(sizeX, sizeY);
this.color = color;
}
@Override
public void render() {
if (!render) return;
vbo.draw();
}
@Override
public void init() {
vbo = new VertexBufferObject(GL11.GL_QUADS, false, true, false, false, 4);
vbo.createBuffer();
vbo.addVertex(x, y, 0);
vbo.addColor(color);
vbo.addVertex(x, y + sizeY, 0);
vbo.addColor(color);
vbo.addVertex(x + sizeX, y + sizeY, 0);
vbo.addColor(color);
vbo.addVertex(x + sizeX, y, 0);
vbo.addColor(color);
vbo.createVBO();
}
@Override
public void setPosition (float x, float y, float z) {
super.setPosition(x, y, z);
if (vbo != null) {
vbo.setVertex(0, this.x, this.y, 0);
vbo.setVertex(1, this.x, this.y + sizeY, 0);
vbo.setVertex(2, this.x + sizeX, this.y + sizeY, 0);
vbo.setVertex(3, this.x + sizeX, this.y, 0);
}
}
Thanks for any help and advice!
Please understand that I can not provide the whole code due to a more or less secret project it belongs to.
I think that’s your problem there: If you don’t want to texture, disable GL_TEXTURE_…. Otherwise the whole primitive will sample from the last used texture coordinates, possibly a alpha=0 sample.