【问题标题】:OpenGL: VBO with vertex and color (RGBA) does not show upOpenGL:带有顶点和颜色 (RGBA) 的 VBO 不显示
【发布时间】:2011-09-08 17:33:11
【问题描述】:

情况:

我在 OpenGL(LWJGL Java 绑定,GL11)中使用顶点缓冲区对象来渲染矩形。我可以毫无问题地渲染纹理(顶点和纹理坐标),并且为其添加颜色会产生所需的效果(例如使其半透明)。 仅使用顶点和颜色使其不可见


研究:

  1. 禁用 alpha 测试和混合会导致黑色矩形,这显然是没有 alpha 测试和混合的顶点和颜色 VBO -> 它被渲染了。
  2. 仅禁用 alpha 测试会导致与以前相同的结果。
  3. 仅禁用混合也无济于事。

我在我的代码中找不到任何错误,也找不到问题的根源。


渲染时激活的状态:

GL_TEXTURE_2D、GL_SMOOTH(阴影模型)、GL_DEPTH_TEST、GL_LEQUAL(深度函数)、GL_BACK(剔除面)

混合功能:GL_SRC_ALPHA 和 GL_ONE_MINUS_SRC_ALPHA
Alpha 函数:GL_GREATER 和 0.1F
投影:glOrtho(0, 1, 1, 0, 0, 1000);

所有矩形都在 Z 轴上 -1(我在渲染 GUI 之前调用了一次 glTranslatef(0,0,-1)),在 X 和 Y 轴上介于 0 和 1 之间。
另外我不得不说纹理是绑定的,但这应该不是问题。


重要代码

注意: Color类基本上是包裹了一个RGBA颜色,是我自己写的,所以不是java.awt包的Color类。
注意 2: 我知道我的 VertexBufferObject 类没有使用动态绘制 VBO 进行优化,但我找不到时间来处理它。

顶点缓冲对象

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(基本上是矩形)

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);
    }
}


感谢您的帮助和建议! 请理解,由于它属于或多或少的秘密项目,我无法提供整个代码。

【问题讨论】:

    标签: java opengl colors vbo


    【解决方案1】:

    渲染时激活的状态: GL_TEXTURE_2D

    我认为这是您的问题:如果您不想纹理化,请禁用 GL_TEXTURE_...。否则,整个图元将从上次使用的纹理坐标中采样,可能是 alpha=0 采样。

    【讨论】:

    • 谢谢,这成功了!我实际上认为,不使用纹理坐标会告诉 OpenGL 不要使用纹理;但由于它是一个状态机,我的猜测可能是错误的。
    猜你喜欢
    • 2020-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-19
    相关资源
    最近更新 更多