When I compress textures into PVRTC it bleeds from one side to the other. Is there a way to fix that? I’ve read recommendations of adding borders, but that doesn’t work for me, because I would have to rescale the image, which means loosing some quality.
Why is there this limitation? I though problem is only in the tool that does compression, or is it hardware design (i.e. uncompression) that causes this problem?
It is the PVRTC compression format which causes it to bleed, this is true for any GPU compression format. You can read more about why it is so in PVRTextureCompression documentation.
Are you trying to compress textures with hard edges ? Then you have to leave borders there is no way around this.
GPU Compression formats are designed so that texture data is not unpacked when stored on the GPU, this is very friendly for memory bandwidth which is one of the most precious resources on mobile SOC.
A PNG(32bpp) image of 1024x1024 is 1024x1024x4 = 4,194,304 bytes which is 4MB.
A PVRTC(4bpp) image of 1024x1024 is 1024x1024/2 = 524,288 bytes which is 0.5MB.
A PVRTC(4bpp) image of 2048x2048 is 2048x2048/2 = 2,097,152 bytes which is 2MB.
If you cannot leave borders you may want to double the texture size and then leave borders , this is still a lot more efficient than using an uncompressed texture format.
> It is the PVRTC compression format which causes it to bleed, this is true for any GPU compression format.
> You can read more about why it is so in PVRTextureCompression documentation.
Could you point me to more specific part in the documentation? I’m having hard time understanding which part specifically causes this bleeding and why it is impossible to solve it. For example ETC compression doesn’t have this problem. Why does PVRTC have it?
PVRTC doesn’t use “blocks” in the traditional [URL=https://en.wikipedia.org/wiki/Block_Truncation_Coding]Block Truncation Coding[/URL] sense in the way ETC or S3TC/DXTC do, i.e. where each 4x4 block of texels is compressed completely independently of any other block.
Most of the time, the pixels on either side of these artificial block boundaries are usually very similar. PVRTC aims to make use of this correlation by not actually using blocks - instead it shares information between overlapping neighbourhoods of pixels.
A problem can occur at the edge of the textures. When PVRTC1 was developed, to save costs in the really small (in terms of gates) mobile devices of circa 2000, it was assumed that the textures would typically tile seamlessly and so the left edge shares information with the right and, similarly, the top edge with the bottom. Usually this is not much of an issue unless the boundaries are completely different which unfortunately may be the case for your textures.
PVRTC2 was developed not long after and, amongst other benefits, is able to locally relax this interpolation rule but unfortunately is not exposed by the drivers in some popular devices.
Really great info, Simon. Quick follow-up:
On devices for which it is exposed, what is the procedure for disabling the implicit GL_REPEAT wrap filtering, both on the texgen side as well as the realtime side?
On the texgen side are there any special arguments to provide to force CLAMP instead of REPEAT filtering?
On the realtime side, is it sufficient to specify a GL_CLAMP* wrap filter instead of GL_REPEAT?
Currently there is no interface to the compressor to force the disabling of the toroidal wrapping (it’s not really GL_REPEAT, per se).
Instead -provided the quality is setting for the compressor is set high enough** - the compressor will try options with/without the interpolation and choose whichever scores better from an RMSE/PSNR point of view. Note also the interpolation can be turned off away from the borders as well.
For example the following is a 32x32 test image that has both continuous and discontinuous regions.
This has been compressed with both PVRTC1 and PVRTC2:
[attachment file=“leaf-test-TC1-scale.png”] … [attachment file=“leaf-test-TC2-scale.png”]
With PVRTC2 most of the green areas are being treated as ‘continuous’ by the compressor but it switches to other modes around the red/blue stripes etc.
Also, just for fun, I tried the same with DXT1
Having said this, it would be useful to add a feature to force the discontinuous mode at the edges of a texture so that they can more easily be assembled “on the fly” into atlases at runtime.
I need to confirm this, but IIRC the lowest quality doesn’t try the “don’t wrap” modes*
***This may change in future versions
Thanks, Simon. Your response was very helpful!