Skip to main content
Notice removed Draw attention by CommunityBot
Bounty Ended with no winning answer by CommunityBot
Tweeted twitter.com/#!/StackGameDev/status/301771320176287744
Notice added Draw attention by Siddharth
Bounty Started worth 50 reputation by Siddharth

Ripple Effect For Weapon Programmatically and efficiently create a graphical ripple effect?

added 10253 characters in body
Source Link
Siddharth
  • 2k
  • 5
  • 27
  • 55

Edit : I include the image for ripple effect that I think I have to use for weapon fire.enter image description here

Also I include code that I use to create ripple effect. Similar code with some changes I used to create live wallpaper and it work perfectly. But in normal game activity I don't able to find my mistake. So please guide on this

@Override
public Engine onCreateEngine(EngineOptions pEngineOptions) {

    return new org.andengine.engine.Engine(pEngineOptions) {
        private boolean mRenderTextureInitialized;

        private RenderTexture mRenderTexture;
        private UncoloredSprite mRenderTextureSprite;

        @Override
        public void onDrawFrame(final GLState pGLState)
                throws InterruptedException {
            final boolean firstFrame = !this.mRenderTextureInitialized;

            if (firstFrame) {
                this.initRenderTextures(pGLState);
                this.mRenderTextureInitialized = true;
            }

            final int surfaceWidth = this.mCamera.getSurfaceWidth();
            final int surfaceHeight = this.mCamera.getSurfaceHeight();

            this.mRenderTexture.begin(pGLState);
            {
                /* Draw current frame. */
                super.onDrawFrame(pGLState);
            }
            this.mRenderTexture.end(pGLState);

            /* Draw rendered texture with custom shader. */
            {
                pGLState.pushProjectionGLMatrix();
                pGLState.orthoProjectionGLMatrixf(0, surfaceWidth, 0,
                        surfaceHeight, -1, 1);
                {
                    this.mRenderTextureSprite
                            .onDraw(pGLState, this.mCamera);
                }
                pGLState.popProjectionGLMatrix();
            }
        }

        private void initRenderTextures(final GLState pGLState) {
            final int surfaceWidth = this.mCamera.getSurfaceWidth();
            final int surfaceHeight = this.mCamera.getSurfaceHeight();

            this.mRenderTexture = new RenderTexture(RippleEffectDemo.this
                    .getEngine().getTextureManager(), surfaceWidth,
                    surfaceHeight);
            this.mRenderTexture.init(pGLState);

            final ITextureRegion renderTextureTextureRegion = TextureRegionFactory
                    .extractFromTexture(this.mRenderTexture);
            this.mRenderTextureSprite = new UncoloredSprite(0, 0,
                    renderTextureTextureRegion, RippleEffectDemo.this
                            .getEngine().getVertexBufferObjectManager()) {

                @Override
                protected void preDraw(final GLState pGLState,
                        final Camera pCamera) {

                    this.setShaderProgram(RippleShaderProgram.getInstance());

                    super.preDraw(pGLState, pCamera);

                    if (mCurrentWaveLength > 25)
                        mCurrentWaveLength -= 25;
                    else
                        mCurrentWaveLength = 0;

                    float currentTime = -0.001f * mCurrentWaveLength;
                    float aliveTimer = (float) mCurrentWaveLength
                            / (float) mWaveLength;

                    GLES20.glUniform4f(
                            RippleShaderProgram.sUniformResolution,
                            (float) SCREEN_WIDTH, (float) SCREEN_HEIGHT,
                            RippleEffectDemo.this.mDropCenterX,
                            RippleEffectDemo.this.mDropCenterY);
                    GLES20.glUniform2f(RippleShaderProgram.sUniformTime,
                            currentTime, aliveTimer);
                }
            };
        }
    };
}

@Override
public void onCreateResources() {
    this.mBitmapTextureAtlas = new BitmapTextureAtlas(
            this.getTextureManager(), 512, 512);
    this.mBackgroundTextureRegion = BitmapTextureAtlasTextureRegionFactory
            .createFromAsset(this.mBitmapTextureAtlas, this,
                    "badge_large.png", 0, 0);
    this.mBitmapTextureAtlas.load();

    this.getShaderProgramManager().loadShaderProgram(
            RippleShaderProgram.getInstance());
}

@Override
public Scene onCreateScene() {
    final Scene scene = new Scene();

    final int centerX = (int) ((CAMERA_WIDTH - this.mBackgroundTextureRegion
            .getWidth()) / 2);
    final int centerY = (int) ((CAMERA_HEIGHT - this.mBackgroundTextureRegion
            .getHeight()) / 2);

    backgroundSprite = new Sprite(centerX, centerY,
            this.mBackgroundTextureRegion, this.getEngine()
                    .getVertexBufferObjectManager());
    scene.attachChild(backgroundSprite);

    scene.setOnSceneTouchListener(this);

    return scene;
}

protected void onTap(final int pX, final int pY) {
    // we do not support multiple wave
    if (0 == mCurrentWaveLength) {
        // so skip wave, if it is active
        mCurrentWaveLength = mWaveLength;

        this.mDropCenterX = (float) pX;
        this.mDropCenterY = (float) pY;
    }
}

@Override
public void onClick(final ClickDetector pClickDetector,
        final int pPointerID, final float pSceneX, final float pSceneY) {
}

@Override
public boolean onSceneTouchEvent(final Scene pScene,
        final TouchEvent pSceneTouchEvent) {

    if (pSceneTouchEvent.isActionDown()) {
        onTap((int) pSceneTouchEvent.getX(), (int) pSceneTouchEvent.getY());
        return true;
    }

    this.mDropCenterX = pSceneTouchEvent.getMotionEvent().getX()
            / this.mCamera.getSurfaceWidth();
    this.mDropCenterY = pSceneTouchEvent.getMotionEvent().getY()
            / this.mCamera.getSurfaceHeight();

    return true;
}

public static class RippleShaderProgram extends ShaderProgram {
    private static RippleShaderProgram INSTANCE;

    public static final String VERTEXSHADER = "uniform mat4 "
            + ShaderProgramConstants.UNIFORM_MODELVIEWPROJECTIONMATRIX
            + ";\n" + "attribute vec4 "
            + ShaderProgramConstants.ATTRIBUTE_POSITION + ";\n"
            + "attribute vec2 "
            + ShaderProgramConstants.ATTRIBUTE_TEXTURECOORDINATES + ";\n"
            + "varying vec2 "
            + ShaderProgramConstants.VARYING_TEXTURECOORDINATES + ";\n"
            + "void main() {\n" + " "
            + ShaderProgramConstants.VARYING_TEXTURECOORDINATES + " = "
            + ShaderProgramConstants.ATTRIBUTE_TEXTURECOORDINATES + ";\n"
            + " gl_Position = "
            + ShaderProgramConstants.UNIFORM_MODELVIEWPROJECTIONMATRIX
            + " * " + ShaderProgramConstants.ATTRIBUTE_POSITION + ";\n"
            + "}";

    // private static final String UNIFORM_TOUCH_COORDS = "touchCoords";
    private static final String UNIFORM_RESOLUTION = "resolution";
    private static final String UNIFORM_TIME = "time";

    public static final String FRAGMENTSHADER = "precision mediump float;\n"
            +

            "uniform sampler2D "
            + ShaderProgramConstants.UNIFORM_TEXTURE_0
            + ";\n"
            + "varying mediump vec2 "
            + ShaderProgramConstants.VARYING_TEXTURECOORDINATES
            + ";\n"
            + "uniform vec4 "
            + RippleShaderProgram.UNIFORM_RESOLUTION
            + ";\n"
            + "uniform vec2 "
            + RippleShaderProgram.UNIFORM_TIME
            + ";\n"
            +

            "void main() {\n"
            + " vec2 tap = "
            + RippleShaderProgram.UNIFORM_RESOLUTION
            + ".zw;\n"
            + " tap.x = "
            + RippleShaderProgram.UNIFORM_RESOLUTION
            + ".x - tap.x;\n"
            + " vec2 tPos = -1.0 + 2.0 * tap.xy / "
            + RippleShaderProgram.UNIFORM_RESOLUTION
            + ".xy;\n"
            + " vec2 cPos = -1.0 + 2.0 * gl_FragCoord.xy / "
            + RippleShaderProgram.UNIFORM_RESOLUTION
            + ".xy;\n"
            + " cPos = cPos + tPos;\n"
            + " float cLength = length(cPos);\n"
            + " float radius = 18.0 * "
            + RippleShaderProgram.UNIFORM_TIME
            + ".y;\n"
            + " float amplitude = 0.05 * "
            + RippleShaderProgram.UNIFORM_TIME
            + ".y;\n"
            + " vec2 uv = gl_FragCoord.xy/"
            + RippleShaderProgram.UNIFORM_RESOLUTION
            + ".xy"
            + "+(cPos/cLength)*cos(cLength*radius-"
            + RippleShaderProgram.UNIFORM_TIME
            + ".x *4.0)*amplitude;\n"
            + " vec3 col = texture2D("
            + ShaderProgramConstants.UNIFORM_TEXTURE_0
            + ",uv).xyz;\n"
            + " gl_FragColor = vec4(col,1.0); \n" + // color

            "}";

    // ===========================================================
    // Fields
    // ===========================================================

    public static int sUniformModelViewPositionMatrixLocation = ShaderProgramConstants.LOCATION_INVALID;
    public static int sUniformTexture0Location = ShaderProgramConstants.LOCATION_INVALID;
    public static int sUniformResolution = ShaderProgramConstants.LOCATION_INVALID;
    public static int sUniformTime = ShaderProgramConstants.LOCATION_INVALID;

    // ===========================================================
    // Constructors
    // ===========================================================

    private RippleShaderProgram() {
        super(RippleShaderProgram.VERTEXSHADER,
                RippleShaderProgram.FRAGMENTSHADER);
    }

    public static RippleShaderProgram getInstance() {
        if (RippleShaderProgram.INSTANCE == null) {
            RippleShaderProgram.INSTANCE = new RippleShaderProgram();
        }
        return RippleShaderProgram.INSTANCE;
    }

    @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);

        RippleShaderProgram.sUniformModelViewPositionMatrixLocation = this
                .getUniformLocation(ShaderProgramConstants.UNIFORM_MODELVIEWPROJECTIONMATRIX);
        RippleShaderProgram.sUniformTexture0Location = this
                .getUniformLocation(ShaderProgramConstants.UNIFORM_TEXTURE_0);

        RippleShaderProgram.sUniformResolution = this
                .getUniformLocation(RippleShaderProgram.UNIFORM_RESOLUTION);
        RippleShaderProgram.sUniformTime = this
                .getUniformLocation(RippleShaderProgram.UNIFORM_TIME);
    }

    @Override
    public void bind(final GLState pGLState,
            final VertexBufferObjectAttributes pVertexBufferObjectAttributes) {
        GLES20.glDisableVertexAttribArray(ShaderProgramConstants.ATTRIBUTE_COLOR_LOCATION);

        super.bind(pGLState, pVertexBufferObjectAttributes);

        GLES20.glUniformMatrix4fv(
                RippleShaderProgram.sUniformModelViewPositionMatrixLocation,
                1, false, pGLState.getModelViewProjectionGLMatrix(), 0);
        GLES20.glUniform1i(RippleShaderProgram.sUniformTexture0Location, 0);
    }

    @Override
    public void unbind(final GLState pGLState)
            throws ShaderProgramException {
        GLES20.glEnableVertexAttribArray(ShaderProgramConstants.ATTRIBUTE_COLOR_LOCATION);

        super.unbind(pGLState);
    }
}

Edit : I include the image for ripple effect that I think I have to use for weapon fire.enter image description here

Also I include code that I use to create ripple effect. Similar code with some changes I used to create live wallpaper and it work perfectly. But in normal game activity I don't able to find my mistake. So please guide on this

@Override
public Engine onCreateEngine(EngineOptions pEngineOptions) {

    return new org.andengine.engine.Engine(pEngineOptions) {
        private boolean mRenderTextureInitialized;

        private RenderTexture mRenderTexture;
        private UncoloredSprite mRenderTextureSprite;

        @Override
        public void onDrawFrame(final GLState pGLState)
                throws InterruptedException {
            final boolean firstFrame = !this.mRenderTextureInitialized;

            if (firstFrame) {
                this.initRenderTextures(pGLState);
                this.mRenderTextureInitialized = true;
            }

            final int surfaceWidth = this.mCamera.getSurfaceWidth();
            final int surfaceHeight = this.mCamera.getSurfaceHeight();

            this.mRenderTexture.begin(pGLState);
            {
                /* Draw current frame. */
                super.onDrawFrame(pGLState);
            }
            this.mRenderTexture.end(pGLState);

            /* Draw rendered texture with custom shader. */
            {
                pGLState.pushProjectionGLMatrix();
                pGLState.orthoProjectionGLMatrixf(0, surfaceWidth, 0,
                        surfaceHeight, -1, 1);
                {
                    this.mRenderTextureSprite
                            .onDraw(pGLState, this.mCamera);
                }
                pGLState.popProjectionGLMatrix();
            }
        }

        private void initRenderTextures(final GLState pGLState) {
            final int surfaceWidth = this.mCamera.getSurfaceWidth();
            final int surfaceHeight = this.mCamera.getSurfaceHeight();

            this.mRenderTexture = new RenderTexture(RippleEffectDemo.this
                    .getEngine().getTextureManager(), surfaceWidth,
                    surfaceHeight);
            this.mRenderTexture.init(pGLState);

            final ITextureRegion renderTextureTextureRegion = TextureRegionFactory
                    .extractFromTexture(this.mRenderTexture);
            this.mRenderTextureSprite = new UncoloredSprite(0, 0,
                    renderTextureTextureRegion, RippleEffectDemo.this
                            .getEngine().getVertexBufferObjectManager()) {

                @Override
                protected void preDraw(final GLState pGLState,
                        final Camera pCamera) {

                    this.setShaderProgram(RippleShaderProgram.getInstance());

                    super.preDraw(pGLState, pCamera);

                    if (mCurrentWaveLength > 25)
                        mCurrentWaveLength -= 25;
                    else
                        mCurrentWaveLength = 0;

                    float currentTime = -0.001f * mCurrentWaveLength;
                    float aliveTimer = (float) mCurrentWaveLength
                            / (float) mWaveLength;

                    GLES20.glUniform4f(
                            RippleShaderProgram.sUniformResolution,
                            (float) SCREEN_WIDTH, (float) SCREEN_HEIGHT,
                            RippleEffectDemo.this.mDropCenterX,
                            RippleEffectDemo.this.mDropCenterY);
                    GLES20.glUniform2f(RippleShaderProgram.sUniformTime,
                            currentTime, aliveTimer);
                }
            };
        }
    };
}

@Override
public void onCreateResources() {
    this.mBitmapTextureAtlas = new BitmapTextureAtlas(
            this.getTextureManager(), 512, 512);
    this.mBackgroundTextureRegion = BitmapTextureAtlasTextureRegionFactory
            .createFromAsset(this.mBitmapTextureAtlas, this,
                    "badge_large.png", 0, 0);
    this.mBitmapTextureAtlas.load();

    this.getShaderProgramManager().loadShaderProgram(
            RippleShaderProgram.getInstance());
}

@Override
public Scene onCreateScene() {
    final Scene scene = new Scene();

    final int centerX = (int) ((CAMERA_WIDTH - this.mBackgroundTextureRegion
            .getWidth()) / 2);
    final int centerY = (int) ((CAMERA_HEIGHT - this.mBackgroundTextureRegion
            .getHeight()) / 2);

    backgroundSprite = new Sprite(centerX, centerY,
            this.mBackgroundTextureRegion, this.getEngine()
                    .getVertexBufferObjectManager());
    scene.attachChild(backgroundSprite);

    scene.setOnSceneTouchListener(this);

    return scene;
}

protected void onTap(final int pX, final int pY) {
    // we do not support multiple wave
    if (0 == mCurrentWaveLength) {
        // so skip wave, if it is active
        mCurrentWaveLength = mWaveLength;

        this.mDropCenterX = (float) pX;
        this.mDropCenterY = (float) pY;
    }
}

@Override
public void onClick(final ClickDetector pClickDetector,
        final int pPointerID, final float pSceneX, final float pSceneY) {
}

@Override
public boolean onSceneTouchEvent(final Scene pScene,
        final TouchEvent pSceneTouchEvent) {

    if (pSceneTouchEvent.isActionDown()) {
        onTap((int) pSceneTouchEvent.getX(), (int) pSceneTouchEvent.getY());
        return true;
    }

    this.mDropCenterX = pSceneTouchEvent.getMotionEvent().getX()
            / this.mCamera.getSurfaceWidth();
    this.mDropCenterY = pSceneTouchEvent.getMotionEvent().getY()
            / this.mCamera.getSurfaceHeight();

    return true;
}

public static class RippleShaderProgram extends ShaderProgram {
    private static RippleShaderProgram INSTANCE;

    public static final String VERTEXSHADER = "uniform mat4 "
            + ShaderProgramConstants.UNIFORM_MODELVIEWPROJECTIONMATRIX
            + ";\n" + "attribute vec4 "
            + ShaderProgramConstants.ATTRIBUTE_POSITION + ";\n"
            + "attribute vec2 "
            + ShaderProgramConstants.ATTRIBUTE_TEXTURECOORDINATES + ";\n"
            + "varying vec2 "
            + ShaderProgramConstants.VARYING_TEXTURECOORDINATES + ";\n"
            + "void main() {\n" + " "
            + ShaderProgramConstants.VARYING_TEXTURECOORDINATES + " = "
            + ShaderProgramConstants.ATTRIBUTE_TEXTURECOORDINATES + ";\n"
            + " gl_Position = "
            + ShaderProgramConstants.UNIFORM_MODELVIEWPROJECTIONMATRIX
            + " * " + ShaderProgramConstants.ATTRIBUTE_POSITION + ";\n"
            + "}";

    // private static final String UNIFORM_TOUCH_COORDS = "touchCoords";
    private static final String UNIFORM_RESOLUTION = "resolution";
    private static final String UNIFORM_TIME = "time";

    public static final String FRAGMENTSHADER = "precision mediump float;\n"
            +

            "uniform sampler2D "
            + ShaderProgramConstants.UNIFORM_TEXTURE_0
            + ";\n"
            + "varying mediump vec2 "
            + ShaderProgramConstants.VARYING_TEXTURECOORDINATES
            + ";\n"
            + "uniform vec4 "
            + RippleShaderProgram.UNIFORM_RESOLUTION
            + ";\n"
            + "uniform vec2 "
            + RippleShaderProgram.UNIFORM_TIME
            + ";\n"
            +

            "void main() {\n"
            + " vec2 tap = "
            + RippleShaderProgram.UNIFORM_RESOLUTION
            + ".zw;\n"
            + " tap.x = "
            + RippleShaderProgram.UNIFORM_RESOLUTION
            + ".x - tap.x;\n"
            + " vec2 tPos = -1.0 + 2.0 * tap.xy / "
            + RippleShaderProgram.UNIFORM_RESOLUTION
            + ".xy;\n"
            + " vec2 cPos = -1.0 + 2.0 * gl_FragCoord.xy / "
            + RippleShaderProgram.UNIFORM_RESOLUTION
            + ".xy;\n"
            + " cPos = cPos + tPos;\n"
            + " float cLength = length(cPos);\n"
            + " float radius = 18.0 * "
            + RippleShaderProgram.UNIFORM_TIME
            + ".y;\n"
            + " float amplitude = 0.05 * "
            + RippleShaderProgram.UNIFORM_TIME
            + ".y;\n"
            + " vec2 uv = gl_FragCoord.xy/"
            + RippleShaderProgram.UNIFORM_RESOLUTION
            + ".xy"
            + "+(cPos/cLength)*cos(cLength*radius-"
            + RippleShaderProgram.UNIFORM_TIME
            + ".x *4.0)*amplitude;\n"
            + " vec3 col = texture2D("
            + ShaderProgramConstants.UNIFORM_TEXTURE_0
            + ",uv).xyz;\n"
            + " gl_FragColor = vec4(col,1.0); \n" + // color

            "}";

    // ===========================================================
    // Fields
    // ===========================================================

    public static int sUniformModelViewPositionMatrixLocation = ShaderProgramConstants.LOCATION_INVALID;
    public static int sUniformTexture0Location = ShaderProgramConstants.LOCATION_INVALID;
    public static int sUniformResolution = ShaderProgramConstants.LOCATION_INVALID;
    public static int sUniformTime = ShaderProgramConstants.LOCATION_INVALID;

    // ===========================================================
    // Constructors
    // ===========================================================

    private RippleShaderProgram() {
        super(RippleShaderProgram.VERTEXSHADER,
                RippleShaderProgram.FRAGMENTSHADER);
    }

    public static RippleShaderProgram getInstance() {
        if (RippleShaderProgram.INSTANCE == null) {
            RippleShaderProgram.INSTANCE = new RippleShaderProgram();
        }
        return RippleShaderProgram.INSTANCE;
    }

    @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);

        RippleShaderProgram.sUniformModelViewPositionMatrixLocation = this
                .getUniformLocation(ShaderProgramConstants.UNIFORM_MODELVIEWPROJECTIONMATRIX);
        RippleShaderProgram.sUniformTexture0Location = this
                .getUniformLocation(ShaderProgramConstants.UNIFORM_TEXTURE_0);

        RippleShaderProgram.sUniformResolution = this
                .getUniformLocation(RippleShaderProgram.UNIFORM_RESOLUTION);
        RippleShaderProgram.sUniformTime = this
                .getUniformLocation(RippleShaderProgram.UNIFORM_TIME);
    }

    @Override
    public void bind(final GLState pGLState,
            final VertexBufferObjectAttributes pVertexBufferObjectAttributes) {
        GLES20.glDisableVertexAttribArray(ShaderProgramConstants.ATTRIBUTE_COLOR_LOCATION);

        super.bind(pGLState, pVertexBufferObjectAttributes);

        GLES20.glUniformMatrix4fv(
                RippleShaderProgram.sUniformModelViewPositionMatrixLocation,
                1, false, pGLState.getModelViewProjectionGLMatrix(), 0);
        GLES20.glUniform1i(RippleShaderProgram.sUniformTexture0Location, 0);
    }

    @Override
    public void unbind(final GLState pGLState)
            throws ShaderProgramException {
        GLES20.glEnableVertexAttribArray(ShaderProgramConstants.ATTRIBUTE_COLOR_LOCATION);

        super.unbind(pGLState);
    }
}
Source Link
Siddharth
  • 2k
  • 5
  • 27
  • 55

Ripple Effect For Weapon

I was developing tower of defence game for a long time. It was about to complete but I have to create ripple effect for one of the weapon that I have used.

First question I want to ask is that is it feasible to use ripple effect for such purpose? Because suddenly fps goes down.

I have created ripple effect for live wallpaper. But I don't know how to create it for normal game activity.

I was not able to understand many things from it. If any one has some knowledge on this then please provide.