Add 1 pixel of padding between adjacent images in a texture. The
padding should be the same colour as the border colour.
pyglet.resource.image/TextureAtlas don't currently do this because
this kind of image manipulation isn't really supported by pyglet; and
it's easy to pad the images yourself. The following monkey patch will
also automatically add padding, but is only correct if your images
have 0 alpha at the border:
def _texture_atlas_add(self, img):
pad = 1
x, y = self.allocator.alloc(img.width + pad * 2, img.height + pad * 2)
self.texture.blit_into(img, x + pad, y + pad, 0)
region = self.texture.get_region(x + pad, y + pad, img.width, img.height)
return region
pyglet.image.atlas.TextureAtlas.add = _texture_atlas_add
Alex.
I can't see those images (domain doesn't seem to be hosted); but I'll
believe what you say.
Be aware that with a TextureAtlas of non-power-of-2 dimensions, you
may have inadvertantly created a rectangular texture -- these do not
support texture coordinate wrapping, so you would never see artifacts
on the images so long as you only had one image in the atlas.
If you've ruled out that possibility; then great! Using 1-pixel
borders should work -- I believe I've tried this before and still had
artefacts, but must have had some other problem. Not sure why you're
getting black borders in my code but not yours; perhaps you could post
a complete example I can reproduce.
Alex.
When OpenGL draws the edge pixels of each tile, it samples the edge
texel of that tile, and combines it with the adjacent texel ("bilinear
filtering"). Depending on how you're loading your images with pyglet,
you're likely to have just zeroed data (black) outside of the tile
image, which is why you're getting dark borders.
You need to ensure there's enough data for OpenGL to sample, even at
the edges. You can do this by creating tile images of size 34x34 for
when you intend to draw images at 32x32. Then use get_region (or
fiddle with the texture coordinates yourself) to draw the part of the
image from 1x1 to 33x33.
Ideally pyglet would be able to automatically "inflate" the borders of
images like this to save you a trip into your image editor; but the
current lack of pixel-level operations on images would make this quite
a pain to implement.
Alex.
That's it.
> or having a transparent background?
> what i do want is that the bilinear scaling filter combines the texels
> of the current with the neighboring tile instead of taking the next
> colors in the source texture.
> isn't this a common task?
Bilinear filtering is in texture fetch, not a raster op -- the only
way to do it is to draw your tiles at 1:1 scale with no rotation, copy
the framebuffer into a texture, then redraw that texture with the
desired transformation and bilinear filtering.
Alex.
Yep. The fixed_resolution.py example demonstrates this (albeit with
filtering deliberately disabled). There are also faster paths for
newer hardware using framebuffer objects (AFAIK cocos2d has an
implementation of this that you could use/borrow).
Alex.
Simply grab the framebuffer image after drawing just the batch and
before drawing anything else. If you need to, you can then clear the
framebuffer and draw the complete scene using that captured image as a
texture.
Alex.