Help Needed with Texture Atlas Tilting(iPhone6s -Power VR 7 Series)

We have received feedback that there is a rendering artifact with regard to terrain on iPhone6S

Devices I test on personally

  • iPhone6
  • iPad Air2
  • iPad4
  • iPad2
  • iPhone5(The issue occured on this device).

You can look at the screenshots to best understand the problem.
Terrain Texture atlas

  • 4096x4096
  • Anisotrophic 2x
  • Custom tiling per texture in pixel shader
  • 8 different types(1024x1024 with 64 pixel border so upto 6 mips)
  • 1334x750 rendering resolution

I solved the issue on iPhone5(By not including the highest Mip and disabling Anisotrophic filtering).
But that is not such a nice option for iPhone6s(Since the GPU is much more capable).
I want to include the fix for this for our new Update 1.2

If anyone have an iPhone6s with access to the App directories, Can you PM me, I can send over a Promo code.You can try certain graphic settings and have access to pixel shaders
which may help me solve the issue.

The issue does not crop up in PVRVFrame.


[attachment file=“Editor.png”]

[attachment file=“iPhone6sArtifact.png”]

[attachment file=“iPhone6sArtifact2.png”]

Hi Ganesh,

[blockquote]The issue does not crop up in PVRVFrame.[/blockquote]
The most common reason for issues like this occurring on device and not in emulation is shader precision. All shader calculations are promoted to 32-bit in PVRVFrame. On device the GPU will try to honour the requested precision. For example, on most Series6 and newer GPUs the compiler will try to execute lowp and mediump calculations at 16-bit precision.

If you are using precision modifiers, can you try using highp throughout the terrain shaders? If this resolves the problem, you can then gradually add back in lowp and mediump qualifiers until you identify the calculation that requires higher precision than you are currently requesting.

Hello Joe

That is the problem I don’t have iPhone6s.

I think I was not clear in my earlier post sorry
The issue only comes up in iPhone6s and iPhone 5
On the other devices like iPhone 6 and iPadair2
This error is not there.

I fixed the issue in iPhone5 by dropping anisotropic filtering and dropping the base mop level


Ah, I see. Unfortunately, our team doesn’t have an iPhone 6S so we won’t be able to help you reproduce this issue :frowning:

Hello Joe,
Thanks for the quick response.
I have been considering about the Shader precision error,and just want to run a code by you to make sure all calculations for texcoord calculations are happening in highp.

This is the code which is already on the device.

float selectMipMap(highp vec2 texture_coordinate)
    // The OpenGL Graphics System: A Specification 4.2
    //  - chapter 3.9.11, equation 3.21
    highp vec2  dx_vtc        = dFdx(texture_coordinate);
    highp vec2  dy_vtc        = dFdy(texture_coordinate);
    highp float delta_max_sqr = max(dot(dx_vtc, dx_vtc), dot(dy_vtc, dy_vtc));
    return 0.5 * log2(delta_max_sqr); // == log2(sqrt(delta_max_sqr));
//This is terrain texture blending code
vec4 control = sampleTexture2D(ControlTextureMap,l_controlMapTexCoords);
float blendWeight = dot(,BlendWeightUnpack);

highp vec2 tileTexCoords = fract[l_texCoords.xy] * 0.234375 + vec2[0.0078125];
highp vec2 texCoords1 = vec2[control.x * 3.75,0.25 * float[control.x > 0.2]] + tileTexCoords.xy;
highp vec2 texCoords2 = vec2[control.y * 3.75,0.25 * float[control.y > 0.2]] + tileTexCoords.xy;

float mip = selectMipMap[l_texCoords.xy * 512.0];
vec3 colorSample1 = sampleTexture2DLod[TextureMap,texCoords1,mip].rgb;
vec3 colorSample2 = sampleTexture2DLod[TextureMap,texCoords2,mip].rgb;

vec3 colorSample = mix[colorSample2,colorSample1,blendWeight];
colorSample.rgb *= colorSample.rgb;//gamma correction

texCoords1 = texCoords1 + vec2[0.0,0.5];
texCoords2 = texCoords2 + vec2[0.0,0.5];

vec3 detailSample1,detailSample2,detailSample;
detailSample1 = sampleTexture2DLod(TextureMap,texCoords1,mip).rgb;
detailSample2 = sampleTexture2DLod(TextureMap,texCoords2,mip).rgb;
detailSample = mix(detailSample2,detailSample1,blendWeight);
roughness = detailSample.b;
const float DETAIL_SCALE = 2.0;
vec2 detailNormal = (2.0 *  DETAIL_SCALE) * detailSample.rg - DETAIL_SCALE;
Normal = Normal + l_tangent * detailNormal.x + l_bitTangent * detailNormal.y;

My questions is in the highlighted text the +vec2’s are they in mediump or highp?. The code path for iPhone6s(Power VR 7 Series) is MANUAL_MIPS.


On a side note do you have development kits which are available for purchasing. The one available in Store is only Powervr SGX540.
If possible i would love to buy one with the latest Power VR 7 Series development board.


Just an update. I have managed to solve this issue on iPhone6s.Had to buy it :frowning:
on iPhone6s(Power VR 7 Series). Even after manually selecting a mipmap, I also disabled anisotropic filtering for that texture.

Since manually selecting a mipmap means that anisotropic filtering should automatically not work, Properly disable anisotropic filtering removed the seams.


Hi Ganesh,

[blockquote]My questions is in the highlighted text the +vec2’s are they in mediump or highp?[/blockquote]
In section 4.5.3 of the GLSL ES 1.0 specification, it states:

[blockquote]The fragment language has the following predeclared globally scoped default precision statements:

precision mediump int;
precision lowp sampler2D;
precision lowp samplerCube;

The fragment language has no default precision qualifier for floating point types. Hence for float, floating
point vector and matrix variable declarations, either the declaration must include a precision qualifier or
the default float precision must have been previously declared.[/blockquote]

This means that the default precision of floating point values in GLSL ES 1.0 is implementation specific.

I don’t have a clear understanding of why your application selects mips manually instead of relying on OpenGL ES filtering modes. Can you expand on this?

[blockquote]If possible i would love to buy one with the latest Power VR 7 Series development board.[/blockquote]
Development boards tend to come from our customers rather than from us directly. I’m not aware of any PowerVR Series7 development boards.

Hello Joe,
I manually select the mip only on few select devices ,where the seam issue is prominent,
Actually even after allowing for a 64 pixel border, between each terrain texture, you will still have a very small seam when the part of the terrain texture repeats.

Since the GPU does not care whether it is an atlas or a single texture,
So a texture coordinate which wraps from 0.25 to 0.0 (assuming the first tile) will make the GPU think that I should fetch all samples from 0.0 to 0.25 so it ends up selecting higher mip levels even when very close to camera, for this reason selecting manual mips completely eliminates the seam, but I only use this when required.

For devices where the seam is not so visible I dont select mipmaps, it actually has preprocessor directives compilation, I just posted the shader I used for the issue which is iPhone6s, also with manual mip selection i can force GPU to use better mip levels to simulate anisotrophic filtering.

You can read more about this issue here

Note that one of the solutions is to use tex2DGrad functions but i found this function unacceptably slow on the devices I tested on.

Best Regards,

Hello Joe,

To add to the conversation above, Just a an absolute wishful thinking,
Is it possible to specify custom texture wrapping logic in Power VR devices , like instead of the standard 0.0 to 1.0 wrapping logic , is it possible to have like from 0.0 to 0.25 , then back to 0.0, With this I think anisotrophic filtering can be achieved with custom wrapping logic and very helpful for Texture atlases, but this is actually not so significant with texture arrays. I had to use Texture atlas to provide support for devices with OpenGLES 2.0.

The fact that TBDR saves so much memory bandwidth with it’s amazing technology and implementation, This can be value addition.

Just being wishful :slight_smile:

Best Regards,