Salaam I want to design live wallpaper for android with AndEngine, I want to have water ripple effect. How can I do this? Like this.
This is how it works on GLES2. The shader extends through whole screen. You need to tweak it for custom radius.
This code goes into main class/activity:
private float mShockwaveTime = 0f; @Override public Engine onCreateEngine(final EngineOptions pEngineOptions) { return new Engine(pEngineOptions) { private boolean mRenderTextureInitialized; private RenderTexture mRenderTexture; private UncoloredSprite mRenderTextureSprite; @Override public void onDrawFrame(GLState pGLState) throws InterruptedException { if (mShockwaveTime > 0f && mShockwaveTime < 10f) { if (!mRenderTextureInitialized) { initRenderTexture(pGLState); mRenderTextureInitialized = true; } mRenderTexture.begin(pGLState, false, true, Color.TRANSPARENT); { super.onDrawFrame(pGLState); } mRenderTexture.end(pGLState); pGLState.pushProjectionGLMatrix(); pGLState.orthoProjectionGLMatrixf(0, CAMERA_WIDTH, 0, CAMERA_HEIGHT, -1, 1); { mRenderTextureSprite.onDraw(pGLState, mCamera); } pGLState.popProjectionGLMatrix(); } else { super.onDrawFrame(pGLState); } } private void initRenderTexture(GLState pGLState) { mRenderTexture = new RenderTexture(getTextureManager(), mCamera.getSurfaceWidth(), mCamera.getSurfaceHeight(), PixelFormat.RGBA_4444); mRenderTexture.init(pGLState); mRenderTextureSprite = new UncoloredSprite(0f, 0f, TextureRegionFactory.extractFromTexture(mRenderTexture), getVertexBufferObjectManager()) { @Override protected void preDraw(GLState pGLState, Camera pCamera) { super.preDraw(pGLState, pCamera); if (mShockwaveTime > 0f && mShockwaveTime < 10f) GLES20.glUniform1f(ShockwaveShaderProgram.sUniformTimeLocation, mShockwaveTime); } }; mRenderTextureSprite.setShaderProgram(ShockwaveShaderProgram.getInstance()); } }; }
This line goes inside onLoadResources:
this.getShaderProgramManager().loadShaderProgram(ShockwaveShaderProgram.getInstance()); I put shader class code to the end of my main class: public static class ShockwaveShaderProgram extends ShaderProgram { private static ShockwaveShaderProgram instance; public static ShockwaveShaderProgram getInstance() { if (instance == null) instance = new ShockwaveShaderProgram(); return instance; } public static final String FRAGMENTSHADER = "precision lowp float;\n" + "uniform lowp sampler2D " + ShaderProgramConstants.UNIFORM_TEXTURE_0 + ";\n" + "varying mediump vec2 " + ShaderProgramConstants.VARYING_TEXTURECOORDINATES + ";\n" + "uniform vec2 center;\n" + "uniform float time;\n" + "const vec3 params = vec3(10.0, 0.8, 0.02);\n" + "void main() \n" + "{ \n" + " mediump vec2 texCoord = " + ShaderProgramConstants.VARYING_TEXTURECOORDINATES + ";\n" + " float distance = distance(texCoord, center);\n" + " if ( (distance <= (time + params.z)) && (distance >= (time - params.z)) )\n" + " {\n" + " float diff = (distance - time);\n" + " float powDiff = 1.0 - pow(abs(diff*params.x), params.y);\n" + " float diffTime = diff * powDiff;\n" + " vec2 diffUV = normalize(texCoord - center);\n" + " texCoord = texCoord + (diffUV * diffTime);\n" + " }\n" + " gl_FragColor = texture2D(" + ShaderProgramConstants.UNIFORM_TEXTURE_0 + ", texCoord);\n" + "} \n"; private ShockwaveShaderProgram() { super(PositionTextureCoordinatesShaderProgram.VERTEXSHADER, FRAGMENTSHADER); } public static int sUniformModelViewPositionMatrixLocation = ShaderProgramConstants.LOCATION_INVALID; public static int sUniformTexture0Location = ShaderProgramConstants.LOCATION_INVALID; public static int sUniformCenterLocation = ShaderProgramConstants.LOCATION_INVALID; public static int sUniformTimeLocation = ShaderProgramConstants.LOCATION_INVALID; @Override protected void link(final GLState pGLState) throws ShaderProgramLinkException { GLES20.glBindAttribLocation(this.mProgramID, ShaderProgramConstants.ATTRIBUTE_POSITION_LOCATION, ShaderProgramConstants.ATTRIBUTE_POSITION); GLES20.glBindAttribLocation(this.mProgramID, ShaderProgramConstants.ATTRIBUTE_TEXTURECOORDINATES_LOCATION, ShaderProgramConstants.ATTRIBUTE_TEXTURECOORDINATES); super.link(pGLState); ShockwaveShaderProgram.sUniformModelViewPositionMatrixLocation = this.getUniformLocation(ShaderProgramConstants.UNIFORM_MODELVIEWPROJECTIONMATRIX); ShockwaveShaderProgram.sUniformTexture0Location = this.getUniformLocation(ShaderProgramConstants.UNIFORM_TEXTURE_0); ShockwaveShaderProgram.sUniformCenterLocation = this.getUniformLocation("center"); ShockwaveShaderProgram.sUniformTimeLocation = this.getUniformLocation("time"); } @Override public void bind(final GLState pGLState, final VertexBufferObjectAttributes pVertexBufferObjectAttributes) { GLES20.glDisableVertexAttribArray(ShaderProgramConstants.ATTRIBUTE_COLOR_LOCATION); super.bind(pGLState, pVertexBufferObjectAttributes); GLES20.glUniformMatrix4fv(ShockwaveShaderProgram.sUniformModelViewPositionMatrixLocation, 1, false, pGLState.getModelViewProjectionGLMatrix(), 0); GLES20.glUniform1i(ShockwaveShaderProgram.sUniformTexture0Location, 0); GLES20.glUniform2f(ShockwaveShaderProgram.sUniformCenterLocation, 0.5f, 0.5f); } @Override public void unbind(final GLState pGLState) throws ShaderProgramException { GLES20.glEnableVertexAttribArray(ShaderProgramConstants.ATTRIBUTE_COLOR_LOCATION); super.unbind(pGLState); } }
Put this code where you want to trigger it:
mScene.registerUpdateHandler(new TimerHandler(0.08f, true, new ITimerCallback() { @Override public void onTimePassed(TimerHandler pTimerHandler) { mShockwaveTime += 0.02f; if (mShockwaveTime > 1.2f) { mScene.unregisterUpdateHandler(pTimerHandler); mShockwaveTime = 0.0f; } } }));
This is how it works on GLES2. The shader extends through whole screen. You need to tweak it for custom radius.
This code goes into main class/activity:
This line goes inside onLoadResources:
Put this code where you want to trigger it: