Question

My terrain uses shader which itself uses four different textures. It runs fine on windows and linux machines, but on android it gets only ~25FPS on both galaxies. I thought, that textures are the problem, but no, as it appears the problem is with the part where I divide texture coordinates and use frac to get tiled coordinates. Without it, I get 60FPS.

// Material data.
//uniform vec3 uAmbient;
//uniform vec3 uDiffuse;

//uniform vec3 uLightPos[8];
//uniform vec3 uEyePos;
//uniform vec3 uFogColor;
uniform sampler2D terrain_blend;
uniform sampler2D grass;
uniform sampler2D rock;
uniform sampler2D dirt;

varying vec2 varTexCoords;
//varying vec3 varEyeNormal;
//varying float varFogWeight;

//------------------------------------------------------------------
//  Name: fog
//  Desc: applies calculated fog weight to fog color and mixes with
//  specified color.
//------------------------------------------------------------------
//vec4 fog(vec4 color) {
//  return mix(color, vec4(uFogColor, 1.0), varFogWeight);
//}

void main(void)
{
    /*vec3 N = normalize(varEyeNormal);
    vec3 L = normalize(uLightPos[0]);
    vec3 H = normalize(L + normalize(uEyePos));

    float df = max(0.0, dot(N, L));
    vec3 col = uAmbient + uDiffuse * df;*/

    // Take color information from textures and tile them.
    vec2 tiledCoords = varTexCoords;
    //vec2 tiledCoords = fract(varTexCoords / 0.05); // <========= HERE!!!!!!!!!
    //vec4 colGrass = texture2D(grass, tiledCoords);
    vec4 colGrass = texture2D(grass, tiledCoords);
    //vec4 colDirt = texture2D(dirt, tiledCoords);
    vec4 colDirt = texture2D(dirt, tiledCoords);
    //vec4 colRock = texture2D(rock, tiledCoords);
    vec4 colRock = texture2D(rock, tiledCoords);
    // Take color information from not tiled blend map.
    vec4 colBlend = texture2D(terrain_blend, varTexCoords);
    // Find the inverse of all the blend weights.
    float inverse = 1.0 / (colBlend.r + colBlend.g + colBlend.b);
    // Scale colors by its corresponding weight.
    colGrass *= colBlend.r * inverse;
    colDirt *= colBlend.g * inverse;
    colRock *= colBlend.b * inverse;

    vec4 final = colGrass + colDirt + colRock;

    //final = fog(final);
    gl_FragColor = final;
}

Note: there's some more code for light calculation and fog, but it isn't used. I indicated the line that, when uncommented, causes massive lag. I tried using floor and calculating fractional part manually, but lag is the same. What might be wrong?

EDIT: Now here's what I don't understand.

This:

vec2 tiledCoords = fract(varTexCoords * 2.0);

Runs great.

This:

vec2 tiledCoords = fract(varTexCoords * 10.0);

Runs average on SIII.

This:

vec2 tiledCoords = fract(varTexCoords * 20.0);

Lags...

This:

vec2 tiledCoords = fract(varTexCoords * 100.0);

Well 5FPS is still better than I expected...

So what gives? Why is this happening? To my understanding this shouldn't make any difference. But it does. And a huge one.

Was it helpful?

Solution

I would run your code on a profiler (check Mali-400), but by the looks of it, you are killing the texture cache. For the first pixel computed, all those 4 texture look-ups are fetched but also the contiguous data is also fetched into the texture cache. For the next pixel, you are not accessing data in the cache but looking quite far (10, 20..etc) which completely defies the purpose of such a cache.

This of course a guess, without proper profiling is hard to tell.

EDIT: @harism also pointed you to that direction.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top