I would like to create a heat haze effect for a 2D game I am making.

Do You have ideas or suggestions, how to get that effect. I am using Libgdx(OpenGL 2.0).

Thank You in advance!

  • 1
    \$\begingroup\$ You should post a picture or screenshot demonstrating the effect. \$\endgroup\$ – Katu Jul 24 '13 at 21:32
  • 1
    \$\begingroup\$ Welcome to gamedev.SE. This site generally discourages "how-to" questions, and instead prefers questions with specific technical or design problems. If you are interested in learning how to proceed, what to study, or for advice, you should try visiting Game Development Chat. But...I just realized that will be difficult for you, since you don't have the requisite 20 reputation. \$\endgroup\$ – Seth Battin Jul 24 '13 at 22:53
  • 3
    \$\begingroup\$ Ok, try reading this: code.google.com/p/libgdx/wiki/OpenGLShader What you want is to distort your game screen in some kind of wavy pattern. That could be accomplished with a fragment shader as part of a post-processing system. Good luck \$\endgroup\$ – Seth Battin Jul 24 '13 at 22:56

I used this solution to make a water distortion effect. You could use the sin waves vertically instead of horizontally to possibly achieve your effect. I draw what might get distorted onto a FrameBuffer. I make regions of the buffer texture that will be redrawn with a distortion shader applied. GdxGame.java

void create(){
    scaleX =  Gdx.graphics.getWidth() / gs.cam.viewportWidth ; //floats that convert the width and height in world
    scaleY =   Gdx.graphics.getHeight() / gs.cam.viewportHeight;//to width and height on screen
    //The above floats need to be recalculated on screen resize, and the frame buffer will also need to be recreated
    batch = new SpriteBatch();
    shader = new ShaderProgram(Gdx.files.internal("data/vertexShader.glsl").readString(),Gdx.files.internal("data/fragmentShader.glsl").readString());
    coords = new Vector3(0,0,0);
    heatRegions = new ArrayList<TextureRegion>();
    heatCoords = new ArrayList<Vector2>();
    heatDimensions = new ArrayList<Vector2>();
    idt = new Matrix4();
    time = 0f; //makes the effect move over time
    /*This is a bad way to store your regions. I assume some object generates heat waves, 
    so use it's x and y and width and height, also have it store it's own distortionRegion
    instead of storing ArrayLists*/
    //Create a FrameBuffer to draw the objects that will be distorted to. 
    try {//This try-catch block is because some Androids don't support Format.RGBA8888
            frameBuffer = new FrameBuffer(Format.RGBA8888, Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), false);
        }catch (GdxRuntimeException e){ 
            frameBuffer = new FrameBuffer(Format.RGB565, Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), false);

    heatRegions.add(new TextureRegion(frameBuffer.getColorBufferTexture()));
    heatCoords.add(new Vector2(0,0));
    heatDimensions.add(new Vector2(32,32));

public void render(){
    float dt = Gdx.graphics.getDeltaTime();
    time += dt ;
    float angle = time * (2 * MathUtils.PI);
    if (angle > (2 * MathUtils.PI))
        angle -= (2 * MathUtils.PI);

    Gdx.gl20.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
    shader.setUniformf("timedelta", -angle);

    //Draw the objects that will be rendered BEHIND the heat wave to the FrameBuffer so that they will get distorted
    //Draw the buffer to screen
    g.draw(frameBuffer.getColorBufferTexture(), -1, 1, 2, -2); //IIRC, you need to vertically flip it. If I remembered wrong, then do -1, -1, 2, 2
    //Now we will actually use the effect by drawing our heat regions
    for(int i = 0; i < heatRegions.size(); i++){
        TextureRegion region = heatRegions.get(i); 
        coords.set(heatCoords.get(i).x, heatCoords.get(i).y,0);//
        coords.project(cam.combined); //get screen coordinates for the coords
        //cut out the area to distort
        region.setRegion(coords.x, coords.y,
                        heatDimensions.get(i).x * scaleX,heatDimensions.get(i).y * scaleY); 
        //draw it with the distortion shader applied
        batch.draw(region, coords.x, coords.y, 
                        heatDimensions.get(i).x * scaleX,heatDimensions.get(i).y * scaleY);


GLSL Shaders Formatted as Java Strings

public static String waterFragmentShader = "#ifdef GL_ES\n"
        + "precision mediump float;\n"
        + "#endif\n"
        + "varying vec4 v_color;\n"
        + "varying vec2 v_texCoords;\n"
        + "uniform sampler2D u_texture;\n"
        + "uniform sampler2D u_texture2;\n"
        + "uniform float timedelta;\n"
        + "uniform vec2 sss;\n"
        + "uniform vec2 u_maxclamp;\n"
        + "void main()                                  \n"
        + "{                                            \n"
        + "  vec2 displacement = texture2D(u_texture2, v_texCoords/4.0).xy;\n" //
        + "  float t=v_texCoords.y +displacement.y*0.7-0.15+  (sin(v_texCoords.x * 40.0+timedelta) * 0.003); \n" //swap the x & y stuff here to make the waves vertical instead of horizontal
        + "  gl_FragColor = v_color * texture2D(u_texture, vec2(v_texCoords.x,t ));\n"
        + "}";

public static String vertexShader = 
        "attribute vec4 a_position;    \n"
        + "attribute vec2 a_texCoord0;\n"
        + "uniform mat4 u_projTrans;\n"
        + "varying vec4 v_color;" 
        + "varying vec2 v_texCoords;"
        + "void main()                  \n"
        + "{                            \n"
        + "   v_color = vec4(1, 1, 1, 1); \n"
        + "   v_texCoords = a_texCoord0; \n"
        + "   gl_Position =  u_projTrans * a_position;  \n"
        + "}";

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.