Search code examples
javac#openglspritebatch

Why does this SpriteBatch work in C# and not in Java?


I have versions of SpriteBatch written in two different languages:

Java: http://pastebin.com/7gwHBTXi C#: http://pastebin.com/cTFn26H8

They have identical code and both make the following calls in a simple program:

Java:

    GL11.glViewport(0, 0, game.getWidth(), game.getHeight());
    GL11.glClearColor(0, 1, 0, 1);
    GL11.glClearDepth(1.0);
    GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);

    sb.Begin();
    sb.Draw(tex, new Vector2(-0.5f, 0.5f), new Vector2(1, -1), Color.White, 0);
    sb.End(SpriteSortMode.None);
    sb.RenderBatch(new Matrix4(), new Matrix4(), BlendState.Opaque, SamplerState.PointWrap, DepthState.None, RasterizerState.CullNone);

C#:

    GL.Viewport(0, 0, game.Width, game.Height);
    GL.ClearColor(0, 1, 0, 1);
    GL.ClearDepth(1.0);
    GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

    sb.Begin();
    sb.Draw(tex, new Vector2(-0.5f, 0.5f), new Vector2(1, -1), Color.White);
    sb.End(SpriteSortMode.None);
    sb.RenderBatch(Matrix4.Identity, Matrix4.Identity, BlendState.Opaque, SamplerState.PointWrap, DepthState.None, RasterizerState.CullNone);

The OpenGL context is the exact same for both of them (3.3).

However, the C# version does what it's supposed to do (draw a white rectangle), but the Java version does nothing (only the green background). Can anyone please tell me what is the difference? What is not working? Thank you. I have been stuck on this for three weeks.


Solution

  • So, I've found the problem actually. It has to do with the way Java manages memory and the fact that Java is a bunch of garbage in that respect. The reason it works in C# and not in Java is because C# gives access to pointers whereas the closest thing that Java has are the NIO Buffers. In order for OpenGL calls to work, physical pointers must be supplied, but Buffers can supply either physical or virtual based on how they are constructed. In short, replacing "ByteBuffer.allocateDirect" with "BufferUtils.createByteBuffer" fixes the problem. Although, I would rather see Java be fixed instead :P.

        private void GenerateBatches() {
            if(glyphs.size() < 1) return;
    
            // Create Arrays
            ByteBuffer bb = BufferUtils.createByteBuffer(6 * glyphs.size() * VertexSpriteBatch.Size);
            SpriteBatchCall call = new SpriteBatchCall(0, glyphs.get(0).Texture, batches);
            glyphs.get(0).VTL.AppendToBuffer(bb);
            glyphs.get(0).VTR.AppendToBuffer(bb);
            glyphs.get(0).VBL.AppendToBuffer(bb);
            glyphs.get(0).VBL.AppendToBuffer(bb);
            glyphs.get(0).VTR.AppendToBuffer(bb);
            glyphs.get(0).VBR.AppendToBuffer(bb);
            emptyGlyphs.add(glyphs.get(0));
    
            int gc = glyphs.size();
            for(int i = 1; i < gc; i++) {
                SpriteGlyph glyph = glyphs.get(i);
                call = call.Append(glyph, batches);
                glyph.VTL.AppendToBuffer(bb);
                glyph.VTR.AppendToBuffer(bb);
                glyph.VBL.AppendToBuffer(bb);
                glyph.VBL.AppendToBuffer(bb);
                glyph.VTR.AppendToBuffer(bb);
                glyph.VBR.AppendToBuffer(bb);
                emptyGlyphs.add(glyphs.get(i));
            }
            bb.flip();
            glyphs = null;
    
            // Set The Buffer Data
            glBindBuffer(BufferTarget.ArrayBuffer, vbo);
            if(gc > glyphCapacity) {
                glyphCapacity = gc * 2;
                glBufferData(
                        BufferTarget.ArrayBuffer,
                        (glyphCapacity * 6) * VertexSpriteBatch.Size,
                        bufUsage
                        );
            }
            glBufferSubData(BufferTarget.ArrayBuffer, 0, bb);
            GLBuffer.Unbind(BufferTarget.ArrayBuffer);
        }