1
\$\begingroup\$

I want to use a shader as a background for a mobile game. I'm using libgdx for my project. I've never written glsl before, but here's my attempt so far:

http://glslsandbox.com/e#22332.13

On desktop the code runs fine, but on mobile it can be a bit slow sometimes. I have read that using built in functions reduces branching, so I tried to use mix and smoothstep instead of if statements.

I'm also not sure if I am rendering the shader correctly in the first place.

First I'm creating a TextureRegion:

fbo = new TextureRegion(new FrameBuffer(Pixmap.Format.RGB888, width, height, false).getColorBufferTexture());

Then I create a rectangle mesh, and render the shader as 2 triangles on the mesh. The device/window resolution is also passed to the shader as a uniform.

Then I am calling batch.setShader(background); and finally batch.draw(fbo, 0, 0, width, height);

Is there a better way I can achieve this?

Code from the link above:

#ifdef GL_ES
precision mediump float;
#endif

uniform float time;
uniform vec2 mouse;
uniform vec2 resolution;
//created 1/15/2015 by alex booth

const vec3 sky_top_color = vec3(90.0/255.0, 200.0/255.0, 190.0/255.0);
const vec3 sky_bot_color = vec3(235.0/255.0, 235.0/255.0, 215.0/255.0);

const vec3 hill_1_color = vec3(170.0/255.0, 210.0/255.0, 205.0/255.0);
const vec3 hill_2_color = vec3(150.0/255.0, 190.0/255.0, 185.0/255.0);
const vec3 hill_3_color = vec3(110.0/255.0, 142.0/255.0, 135.0/255.0); 

void main(void) {
    vec2 pos = (gl_FragCoord.xy / resolution.xy);

    float hill_1 = 0.060*sin(pos.x*6.0+time*0.100)*sin(time*0.10)+0.55;
    float hill_2 = 0.075*sin(pos.x*6.0-time*0.090)*sin(time*0.12)+0.45;
    float hill_3 = 0.100*sin(pos.x*6.0+time*0.095)*sin(time*0.14)+0.30;

    //sky, far, middle, and closest
    vec3 color = mix(sky_bot_color, sky_top_color, smoothstep(hill_1, 1.0, pos.y));
    color = mix(color, hill_1_color, smoothstep(hill_1 + 0.004, hill_1, pos.y));
    color = mix(color, hill_2_color, smoothstep(hill_2 + 0.004, hill_2, pos.y));
    gl_FragColor = vec4(mix(color, hill_3_color, smoothstep(hill_3 + 0.004, hill_3, pos.y)), 1.0);
}
\$\endgroup\$
1
\$\begingroup\$

What makes you think this is the shader code that is slow ? In most machines nowadays, and especially mobile devices, the bottlenecks are not these purely calculation-fed (ALU loaded) shaders, but memory bandwidth.

Memory bandwidth is used by framebuffers being fed to shaders as textures, or by the ROPs writing to the render target. Especially bad when render targets are multiple, or floating formats. This of course incrases with the sequare of the resolution and we know mobile devices have SUPER HIGH DPI. capitals intended.

What I suggest is to use half the resolution of your hardware native screen resolution + good antialiasing techniques like SMAA. This should accelerate wonders.

Tip: if you want to prove that you are going to accelerate something by optimizing this specific shader, make it return hardcoded red, and check your FPS.

\$\endgroup\$
  • \$\begingroup\$ I rendered the shader at 640x360 to the framebuffer and scaled it up when drawing it to the screen. I'm getting 60 fps on mobile again and it still looks good when scaled up to 1920x1080. Thanks for the help. \$\endgroup\$ – Alex Jan 22 '15 at 7:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.