在Java中将图像转换为缓冲区

时间:2013-03-19 16:16:49

标签: java opengl-es libgdx

我正在尝试在我正在开发的游戏中实现一些简单的3D功能。我正在利用 LibGDX游戏引擎来实现这个目标,因为它似乎很好地与OpenGL ES集成,但是由于我无法弄清楚如何创建一个简单的{{1来自Java中的图像的对象。

问题

我的目标是让一个立方体在3D空间中旋转,上面有一些纹理。问题是,虽然我设法渲染立方体并让它旋转,但我似乎找不到任何关于如何将图像实际解码为Buffer以便纹理立方体的教程,代码示例或文档。我已经找到了很多说明如何在Android中执行此操作的示例,但这限制了您必须在Android SDK中使用Buffer方法,这对我来说不是一个选项,因为我试图允许我的代码可移植到许多平台。

正是出于这个原因,我得出的结论是,我必须找到一种方法将图像(BitmapFactory.decodeResource(<your_image here>)文件)解码为.bmp,以便利用{{1我发现用OpenGL ES打包的方法。

我到目前为止所做的事

我已经尝试了许多替代方案来尝试寻找解决方案,其中一些包括:

  • 利用LibGDX软件包附带的Buffer类中嵌入的Gdx.gl10.glTexImage2D()方法。
  • 尝试使用Java ImageIO包解码图像。
  • 使用其他解码工具,例如image4j库。

一些代码

以下是我用于渲染多维数据集的一些代码。为了清楚起见,省略了许多OpenGL“切换翻转”,所以如果你认为我错过了什么,请发表评论,我会确认它是否只是在另一个班级的另一部分。

我知道这段代码会过于扼要筛选,所以我尽力在必要时对其进行评论。

请注意,此代码表示我当前的实现,并且是与下面的“调试信息”部分相关联的代码。

Texture.bind()

我的问题

如何将图像直接解码为Java中的Texture?如果无法做到这一点,那么我该如何尝试在LibGDX中构建我的3D对象呢?我还应该咨询其他资源吗?

调试信息

最后更新时间:2013年3月19日美国东部时间下午12:45

以下是与我的应用程序的当前调试过程相关的一些信息。随着我逐步解决这个问题,我将对此进行更新:

  • 目前,当我运行我的应用程序时,收到错误public void draw(){ // This is used to hold the OpenGL pointer to the texture int[] textures = new int[1]; // Tells the GPU to render the vertices in a clockwise manner Gdx.gl10.glFrontFace(GL10.GL_CW); // Informs OpenGL of the location of the vertices Gdx.gl10.glVertexPointer(3, GL10.GL_FLOAT, 0, mVertexBuffer); // Bind the texture pointer in OpenGL to the texture Gdx.gl10.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]); // This is the function I found in LibGDX that I think I am supposed to use? mTexture.bind(); // Some "switch-flipping" in OpenGL Gdx.gl10.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST); Gdx.gl10.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); Gdx.gl10.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE); Gdx.gl10.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE); Gdx.gl10.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE, GL10.GL_REPLACE); // This tells OpenGL to assign my Texture to the 3D Image Gdx.gl10.glTexImage2D(GL10.GL_TEXTURE_2D, 0, GL10.GL_RGB, 256, 256, 0, GL10.GL_RGB, GL10.GL_UNSIGNED_BYTE, mTexture); // Finally, this draws the objects to the screen Gdx.gl.glDrawElements(GL10.GL_TRIANGLES, 6, GL10.GL_UNSIGNED_BYTE, mIndexBuffer); } ,也许这个实现是正确的,我只是在其他地方遗漏了一些语法?
  • 我目前正在调查我在筛选一些论坛后发现的this其他资源。
  • 这里似乎Buffer对象是正确的路线。我会尝试继续这个实现并更新我的结果!我以前无法找到它,因为它被LibGDX团队认为是“弃用”,所以我不确定这是否会很快被替换。

补充资料

回答我的问题时应该考虑的一些事项是:

  • 应该注意的是,我使用LibGDX Game Engine进行此操作,因此,我还将在论坛上发布有关此问题的信息。

  • 此外,似乎有很多方法可以从图片中获取Invalid memory access of location 0x0 rip=0x11dc77564,但是无法从Mesh中提取BufferedImage。我只是忽略了这里明显的东西吗? Buffer真的应该是我需要的吗?

  • 我不希望在构建路径中包含Android SDK并使用简单的BufferedImage方法。

  • 出于兼容性原因,我目前正在尝试使用OpenGL ES 1.0实现此目的。

1 个答案:

答案 0 :(得分:2)

我认为你想避免原始的OpenGL纹理和缓冲API,并坚持使用Libgdx MeshTexture包装器。他们隐藏了一堆OpenGL细节。当然,如果您有兴趣了解OpenGL的详细信息,这将无济于事。 (但也许你可以使用Libgdx API,然后查看它们的来源,看看到底发生了什么)。

第一步是确保您的Mesh(或您的原始mVertexBuffer OpenGL顶点列表(如果您没有使用Mesh)包含有效(u,v)纹理坐标与每个顶点。这些坐标将在渲染时引用“当前”纹理。见https://code.google.com/p/libgdx/wiki/MeshColorTexture#Texture

首先,定义网格以包含每个顶点的纹理信息:

mesh = new Mesh(true, 3, 3, 
            new VertexAttribute(Usage.Position, 3, "a_position"),
            new VertexAttribute(Usage.ColorPacked, 4, "a_color"),
            new VertexAttribute(Usage.TextureCoordinates, 2, "a_texCoords"));

(此网格物体也有颜色数据,但如果您不想混合原始颜色数据,则可以不使用“a_color”。)

另一个准备步骤是将纹理文件加载到Libgdx纹理中。假设文件打包在标准的“资产”位置,您应该只能使用相对路径加载它:

Texture texture = new Texture("path/to/image.bmp");

Libgdx通常可以加载和解析BMP,PNG和JPEG文件格式。对于其他格式,我认为您需要自己创建一个Pixmap对象,然后将其插入Texture

其次,确保每个顶点都有与之关联的(u,v)纹理坐标:

mesh.setVertices(new float[] { -0.5f, -0.5f, 0, Color.toFloatBits(255, 0, 0, 255), 0, 1,
                                0.5f, -0.5f, 0, Color.toFloatBits(0, 255, 0, 255), 1, 1
                                0, 0.5f, 0, Color.toFloatBits(0, 0, 255, 255), 0.5f, 0 });

上面的每一行定义了每个顶点的“(x,y,z,rgba,u,v)”。 (“rgba”是整个颜色压成一个浮子。)

此时您已经定义了Mesh Color信息和纹理(u,v)坐标。

第二步是在render调用期间绑定纹理,因此Mesh中的(u,v)坐标可以引用:

texture.bind();
mesh.render(GL10.GL_TRIANGLES, 0, 3);

您不需要直接使用任何OpenGL纹理或顶点API。