Android OpenGL - ES 纹理渗色

发布于 2024-09-28 08:22:19 字数 2269 浏览 0 评论 0原文

我正在编写一个小应用程序,目前可以生成随机纹理图。

我将这张地图绘制为一组 10 x 15 的“四边形”,它们实际上都是三角形带。我使用“map”来获取一个int,然后将其作为textureAtlas 中该正方形的纹理位置。例如 0 是左下角的“图块”。该图集大小为 128 x 128,分为 32 像素图块。

然而,我似乎得到了一些奇怪的伪影,其中一个图块的纹理正在渗透到下一个图块。我想知道这是否是图像本身的问题,但据我所知,像素恰好位于它们应该在的位置。然后我查看了我指定的纹理坐标,但它们看起来都很精确(0.0、0.25、0.5、0.75、1.0 - 将其分成我期望的 4 行和列)。

奇怪的是,如果我在模拟器上运行它,我不会得到任何工件。

我是否缺少一个会导致 1 像素渗色的设置?它似乎也只是垂直的 - 这可能与在手机上我在该方向上“拉伸”图像有关,因为手机的屏幕在该方向上比正常情况下大。

我像这样加载纹理:

//Get a new ID
    int id = newTextureID(gl);

    //We will need to flip the texture vertically
    Matrix flip = new Matrix();
    flip.postScale(1f, -1f);

    //Load up and flip the texture
    Bitmap temp = BitmapFactory.decodeResource(context.getResources(), resource);

    //Store the widths for the texturemap
    int width = temp.getWidth();
    int height = temp.getHeight();
    Bitmap bmp = Bitmap.createBitmap(temp, 0, 0, width, height, flip, true);
    temp.recycle();

    //Bind
    gl.glBindTexture(GL10.GL_TEXTURE_2D, id);

    //Set params
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR);

    //Push onto the GPU
    GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bmp, 0);

    TextureAtlas atlas = new TextureAtlas(id, width, height, tileSize);
    return atlas;

然后像这样渲染它:

gl.glBindTexture(GL10.GL_TEXTURE_2D, currentAtlas.textureID);
    //Enable the vertices buffer for writing and to be used during our rendering
    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
    //Specify the location and data format of an array of vertex coordinates to use
    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);

    //Enable the texture buffer
    gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
    gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
    gl.glDrawElements(GL10.GL_TRIANGLES, indices.length, GL10.GL_UNSIGNED_SHORT, indexBuffer);

我会拍照,但我不确定如何从手机获取屏幕盖...

如果有人知道我如何捕获当前帧并可能放置如果它有助于解释发生了什么,我会这样做!

期待您的回复。

编辑:这是一个屏幕截图 - 请注意,我以横向方式运行该应用程序,但帽子是纵向的。还要原谅可怕的纹理:D它们只是一个占位符/乱搞。

ScreenCap

I am writing a small app that at the moment generates a random map of textures.

I am drawing this map as a 10 x 15 group of "quads" which are infact all triangle strips. I use the "map" to grab an int which I then take as the location of the texture for this square in the textureAtlas. so for example 0 is the bottom left "tile". The atlas is 128 x 128 and split into 32 pixel tiles.

However I seem to be getting some odd artifacts where the texture from the one tile is creeping in to the next tile. I wondered if it was the image itself but as far as I can tell the pixels are exactly where they should be. I then looked at the texture coords I was specifying but they all look exact (0.0, 0.25, 0.5, 0.75, 1.0 - splitting it into the 4 rows and columns I would expect).

The odd thing is if I run it on the emulator I do not get any artifacts.

Is there a setting I am missing which would cause bleeding of 1 pixel? It seemed to only be vertical too - this could be related to on the phone I am "stretching" the image in that direction as the phone's screen is larger than normal in that direction.

I load the texture like so:

//Get a new ID
    int id = newTextureID(gl);

    //We will need to flip the texture vertically
    Matrix flip = new Matrix();
    flip.postScale(1f, -1f);

    //Load up and flip the texture
    Bitmap temp = BitmapFactory.decodeResource(context.getResources(), resource);

    //Store the widths for the texturemap
    int width = temp.getWidth();
    int height = temp.getHeight();
    Bitmap bmp = Bitmap.createBitmap(temp, 0, 0, width, height, flip, true);
    temp.recycle();

    //Bind
    gl.glBindTexture(GL10.GL_TEXTURE_2D, id);

    //Set params
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR);

    //Push onto the GPU
    GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bmp, 0);

    TextureAtlas atlas = new TextureAtlas(id, width, height, tileSize);
    return atlas;

I then render it like so:

gl.glBindTexture(GL10.GL_TEXTURE_2D, currentAtlas.textureID);
    //Enable the vertices buffer for writing and to be used during our rendering
    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
    //Specify the location and data format of an array of vertex coordinates to use
    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);

    //Enable the texture buffer
    gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
    gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
    gl.glDrawElements(GL10.GL_TRIANGLES, indices.length, GL10.GL_UNSIGNED_SHORT, indexBuffer);

I would take a picture, but I am unsure how to get a screen cap from the phone...

If anyone knows of how I can capture the current frame and perhaps put it out into a file I will do that if it helps explain what is going on!

Look forward to your response.

Edit: Here is a screencap - note I run the app in landscape but cap is in portrait. Also excuse the horrible textures :D they were merely a place holder / messing around.

ScreenCap

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

疑心病 2024-10-05 08:22:19

好吧,在与朋友交谈后,我设法解决了这个小问题。

事实证明,如果您希望获得精确的像素完美纹理,则必须将纹理的边缘指定为像素的一半。

为此,我只需在纹理坐标的测量中添加半个像素或减去半个像素。

就像这样:

//Top Left
            textureCoords[textPlace] = xAdjust*currentAtlas.texSpaceWidth + currentAtlas.halfPixelAdjust;        textPlace++;
            textureCoords[textPlace] = (yAdjust+1)*currentAtlas.texSpaceHeight - currentAtlas.halfPixelAdjust;    textPlace++;

这只是在加载纹理图集时计算的:

(float)(0.5 * ((1.0f / numberOfTilesInAtlasRow) / pixelsPerTile));

尽管如果每个图块的高度与宽度不同(这可能会发生),您将需要单独计算它们。

这已经解决了所有的工件,所以我可以继续。希望它对其他人有帮助!

Well, after speaking to a friend I managed to solve this little problem.

It turns out that if you wish to have exact pixel perfect textures you have to specify the edge of the texture to be halfway into the pixel.

To do this I simply added half a pixel or subtracted half a pixel to the measurement for the texture coords.

Like so:

//Top Left
            textureCoords[textPlace] = xAdjust*currentAtlas.texSpaceWidth + currentAtlas.halfPixelAdjust;        textPlace++;
            textureCoords[textPlace] = (yAdjust+1)*currentAtlas.texSpaceHeight - currentAtlas.halfPixelAdjust;    textPlace++;

This was simply calculated when loading the texture atlas:

(float)(0.5 * ((1.0f / numberOfTilesInAtlasRow) / pixelsPerTile));

Although if the height was different to the width of each tile (which could happen) you would need to calculate them individually.

This has solved all the artifacts so I can continue on. Hope it helps someone else!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文