1

First of all, I'm using this library for post-processing in LibGDX: https://github.com/manuelbua/libgdx-contribs

I added a new custom Effect to it by extending Filter and PostProcessorEffect.

It's a ripple shader, I used this one: https://github.com/julienvillegas/libgdx.info-Shader-Shockwave/blob/master/android/assets/shaders/fragment.glsl

My game is a quite simple board game consisting of one little board and some UI elements around it, consisting of nothing but Stage and Actors.

I use ExtendViewport as the Viewport for the Stage, and set its world size to the size of the board and some extra for the UI elements that are around it, this has worked perfectly so far.

Now for the actual issue, the ripple shader spawns a circular wave - but if my world width is larger than height, it becomes ellipse instead. Only if my world width & height are equal, the ripple is a perfect circle.

How can I fix this?

EDIT: So what I need is to take aspect ratio into account, but I don't know how to do that.

Here's my vertex shader (it's from the post-processing library):

#ifdef GL_ES
    #define PRECISION mediump
    precision PRECISION float;
#else
    #define PRECISION
#endif

attribute vec4 a_position;
attribute vec2 a_texCoord0;
varying vec2 v_texCoords;

void main()
{
    v_texCoords = a_texCoord0;
    gl_Position = a_position;
}

1 Answer 1

2

If you transform the coordinates used to determine the distance in the fragment shader using the aspect-ratio of the window then you ellipse will always be a circle instead.

#ifdef GL_ES
precision highp float;
#endif

uniform sampler2D sceneTex; // 0
uniform vec2 center; // Mouse position
uniform float time; // effect elapsed time

// Add this uniform, it needs to be bound to the float that is the width / height
uniform float aspectRatio; // width / height
//uniform vec3 shockParams; // 10.0, 0.8, 0.1

varying vec2 v_texCoords;

void main()
{
    // get pixel coordinates
    vec2 l_texCoords = v_texCoords;
    vec2 center = vec2(0.5, 0.5);
    vec3 shockParams = vec3(10.0, 0.8, 0.1);

    float offset = (time- floor(time))/time;
    float CurrentTime = (time)*(offset);

    //get distance from center
    //float distance = distance(v_texCoords, center);


    // Take the distance using non-normalized coordinates 
    vec2 texCoordN = vec2(v_texCoords.x, v_texCoords.y / aspectRatio);
    vec2 centerN = vec2(center.x, center.y / aspectRatio);
    float distance = distance(texCoordN, centerN);

    if ( (distance <= (CurrentTime + shockParams.z)) && (distance >= (CurrentTime - shockParams.z)) ) {
        float diff = (distance - CurrentTime);
        float powDiff = 0.0;
        if(distance>0.05){
            powDiff = 1.0 - pow(abs(diff*shockParams.x), shockParams.y);
        }
        float diffTime = diff  * powDiff;
        vec2 diffUV = normalize(v_texCoords-center);
        //Perform the distortion and reduce the effect over time
        l_texCoords = v_texCoords + ((diffUV * diffTime)/(CurrentTime * distance * 40.0));
    }
    gl_FragColor = texture2D(sceneTex, l_texCoords);

}

l_texCoords and center contain normalized coordinates, ranging from (0, 0) to (1, 1), using the passed-in aspectRatio you can turn the coordinates into non-normalized coordinates that respect the aspect ratio.

Sign up to request clarification or add additional context in comments.

1 Comment

Excellent, works like a charm. Thank you!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.