Почему этот SpriteBatch работает в C#, а не в Java?
У меня есть версии SpriteBatch, написанные на двух разных языках:
Java: http://pastebin.com/7gwHBTXi C#: http://pastebin.com/cTFn26H8
У них одинаковый код, и оба они выполняют следующие вызовы в простой программе:
Джава:
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);
Контекст OpenGL для них одинаков (3.3).
Тем не менее, версия C# делает то, что должна (рисовать белый прямоугольник), а версия Java ничего не делает (только зеленый фон). Может кто-нибудь сказать, пожалуйста, в чем разница? Что не работает? Спасибо. Я застрял на этом в течение трех недель.
1 ответ
Итак, я нашел проблему на самом деле. Это связано с тем, как Java управляет памятью, и с тем фактом, что Java в этом отношении является кучей мусора. Причина, по которой он работает в C#, а не в Java, заключается в том, что C# предоставляет доступ к указателям, в то время как в Java наиболее близки буферы NIO. Чтобы звонки OpenGL работали, необходимо указывать физические указатели, но буферы могут предоставлять физические или виртуальные указатели в зависимости от их конструкции. Короче говоря, замена "ByteBuffer.allocateDirect" на "BufferUtils.createByteBuffer" решает проблему. Хотя я бы предпочел вместо этого исправить Java: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);
}