4
\$\begingroup\$

I'm using libGDX and currently have a simple shader that does a passthrough, except for randomly shifting the vertex positions. This shift is a vec2 uniform that I set within my code's render() loop. It's declared in my vertex shader as uniform vec2 u_random.

I have two different kind of Sprites -- let's called them SpriteA and SpriteB. Both are drawn within the same SpriteBatch's begin()/end() calls. Prior to drawing each sprite in my scene, I check the type of the sprite.

  • If sprite instance of SpriteA: I set the uniform u_random value to Vector2.Zero, meaning that I don't want any vertex changes for it.
  • If sprite instance of SpriteB, I set the uniform u_random to Vector2(MathUtils.random(), MathUtils.random().

The expected behavior was that all the SpriteA objects in my scene won't experience any jittering, while all SpriteB objects would be jittering about their positions.

However, what I'm experiencing is that both SpriteA and SpriteB are jittering, leading me to believe that the u_random uniform is not actually being set per Sprite, and being applied to all sprites. What is the reason for this? And how can I fix this such that the vertex shader correctly accepts the uniform value set to affect each sprite individually?

passthrough.vsh

attribute vec4 a_color;
attribute vec3 a_position;
attribute vec2 a_texCoord0;

uniform mat4 u_projTrans;
uniform vec2 u_random;

varying vec4 v_color;
varying vec2 v_texCoord;

void main() {

    v_color = a_color;
    v_texCoord = a_texCoord0;

    vec3 temp_position = vec3( a_position.x + u_random.x, a_position.y + u_random.y, a_position.z);

    gl_Position = u_projTrans * vec4(temp_position, 1.0);

}

Java Code

this.batch.begin();
this.batch.setShader(shader);

for (Sprite sprite : sprites)
{
    Vector2 v = Vector2.Zero;
    if (sprite instanceof SpriteB)
    {
        v.x = MathUtils.random(-1, 1);
        v.y = MathUtils.random(-1, 1);
    }

    shader.setUniformf("u_random", v);

    sprite.draw(this.batch);
}

this.batch.end();
\$\endgroup\$
  • 1
    \$\begingroup\$ You almost certainly don't want to actually do this. Changing a uniform for every quad/sprite is going to severely impact the throughput of your renderer. Much of the GPU will be sitting idle while you're drawing one measly sprite at a time. The whole point of a "sprite batch" is to draw as many sprites at the same time with as few draw calls or state changes as possible. If you need random data in your shader, use a noise texture or a noise function. stackoverflow.com/questions/4200224/… \$\endgroup\$ – Sean Middleditch May 23 '14 at 21:22
  • \$\begingroup\$ @SeanMiddleditch Thanks for your input. Would you suggest that uniforms be used and set for things that are global and affect all sprites within in a SpriteBatch instead? For example, setting the position of the light? Anyway, to relate back to the question, efficiency/throughput aside, why does the uniform get set for the entire batch and not per Sprite. Does it look to be that the SpriteBatch is somehow not being flushed per Sprite? \$\endgroup\$ – midasmax May 23 '14 at 21:27
  • 1
    \$\begingroup\$ I don't know anything about libgdx, so I can't say anything particularly about the question other than that you're asking how to do something you shouldn't try to do in the first place (which may be why it's broken/unsupported/difficult). You may just have to restart the whole batch every time you want to modify the shader (e.g. for every sprite) depending on how libgdx's wrappers works. \$\endgroup\$ – Sean Middleditch May 24 '14 at 0:24
2
\$\begingroup\$

i think you first have to call it like this:

shader.begin();
shader.setUniformf("u_random", v);
shader.end();

because otherwise the uniform wont be set each time.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Thanks for the suggestion. Setting shader.begin() and shader.end() within the SpriteBatch's begin() and end() always results in a white screen. Trying to set it before batch.begin() is not possible either since it will require me to end() the batch after each sprite is drawn, which defeats the purpose of the batch I suppose. \$\endgroup\$ – midasmax May 23 '14 at 18:11

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.