[WIP] Atmospheric Scattering and Motion Blur

This is a short wip of two shader effect I’d like to contribute to this project with.

http://www.youtube.com/watch?v=7cBiBwUT8aU



Atmospheric scattering as a dynamic skydome and post process scattering filter and motion blur as a post processing filter effect.

6 Likes

Very nice! The motion blur looks like in Resident Evil 5 :smiley:



http://www.youtube.com/watch?v=dyZs37KUjfA

You motion blur looks very nice. :slight_smile:

Good job!



What’s the basic logic behind Atmospheric scattering? Is it a light gradient overlay?



You might want to do a little benchmark with both the motion blur we have right now :stuck_out_tongue: Yours one looks very cool!

The use of this motionblur implementation is sadly rather limited. It depends on camera movement and does not handle camera rotation or moving objects really well. I think it could be used in some flight or car simulation where camera rotation is not that negligible.



@iamcreasy



I’m using Hoffman and Preetham model for areal perspective. The sky is rendered as a small sphere before everything else is rendered. The sky colors are calculated in real time inside the vertex shader and then interpolated. Colors are based on optical density (essentially how much air a given light ray has travelled through) and the angle sun. I have plenty of references if someone is interrested.

some basic reference would be great :slight_smile:

http://developer.amd.com/media/gpu_assets/GDC_02_HoffmanPreetham.pdf

http://developer.amd.com/media/gpu_assets/ATI-LightScattering.pdf



The basics can be found in the links above.



Following article helped me understanding even though the implementation it’s not the same :slight_smile:

1 Like

For the motion blur… do you have a basic estimate on what the frame hit is?

Unlit HelloTerrain and atmospheric scattering, MotionBlur stats:



16 samples ~390 fps

8 samples ~420 fps

1 sample ~420 fps

No filter ~620 fps



@2560x1440, 32bpp, 8xAA



I think most of the cost is due to an extra post processing filter.

Yeah, very reasonable.

Any chance we can see the code? It might be worth incorporating into the core post processing effects.



…and also, I’m interesting in potentially using the motion blur in Mythruna. :slight_smile: Seems like it would be good for flying.

@pspeed, sure :slight_smile:



MotionBlurFilter.java

[java]

package motionblur;





import com.jme3.asset.AssetManager;

import com.jme3.material.Material;

import com.jme3.math.FastMath;

import com.jme3.math.Matrix4f;

import com.jme3.post.Filter;

import com.jme3.renderer.RenderManager;

import com.jme3.renderer.ViewPort;

import com.jme3.texture.FrameBuffer;



/*

  • To change this template, choose Tools | Templates
  • and open the template in the editor.

    */

    /**

    *
  • @author kwando

    */

    public class MotionBlurFilter extends Filter {



    private float strength;

    private float blendAmount;



    private ViewPort vp;

    private Matrix4f lastProjectionMatrix;

    private Matrix4f currentProjectionMatrix;



    @Override

    protected void initFilter(AssetManager manager, RenderManager renderManager, ViewPort vp, int w, int h) {

    material = new Material(manager, "MatDefs/2D/MotionBlur.j3md");

    this.vp = vp;

    setStrength(1.3f);

    setBlendAmount(1f);

    }



    @Override

    protected Material getMaterial() {

    return material;

    }



    @Override

    protected boolean isRequiresDepthTexture() {

    return true;

    }



    public float getStrength() {

    return strength;

    }



    public void setStrength(float strength) {

    material.setFloat("Strength", strength);

    this.strength = strength;

    }



    public float getBlendAmount() {

    return blendAmount;

    }



    public void setBlendAmount(float blendAmount) {

    blendAmount = FastMath.clamp(blendAmount, 0f, 1f);

    material.setFloat("BlendAmount", blendAmount);

    this.blendAmount = blendAmount;

    }



    @Override

    protected void postFrame(RenderManager renderManager, ViewPort viewPort, FrameBuffer prevFilterBuffer, FrameBuffer sceneBuffer) {

    lastProjectionMatrix = currentProjectionMatrix;

    currentProjectionMatrix = vp.getCamera().getViewProjectionMatrix().clone();

    if (lastProjectionMatrix == null) {

    lastProjectionMatrix = currentProjectionMatrix;

    }

    material.setMatrix4("ViewProjectionInverse", currentProjectionMatrix.invert());

    material.setMatrix4("LastViewProjection", lastProjectionMatrix);

    }

    }

    [/java]



    MotionBlur.j3md
Code:
MaterialDef MotionBlur {
MaterialParameters {
    Texture2D Texture
    Texture2D DepthTexture
    Matrix4 ViewProjectionInverse
    Matrix4 LastViewProjection
    Float Strength
    Float BlendAmount
}

Technique {
    VertexShader GLSL100:   Shaders/2D/MotionBlur.vert
    FragmentShader GLSL100: Shaders/2D/MotionBlur.frag

    WorldParameters {
        FrameRate
    }
}

}

Shaders
Vertex Shader
Code:
attribute vec4 inPosition; attribute vec2 inTexCoord; varying vec2 texCoord;

void main() {
gl_Position = inPosition * 2.0 - 1.0; //vec4(pos, 0.0, 1.0);
texCoord = inTexCoord;
}

Fragment Shader
Code:
uniform sampler2D m_DepthTexture; uniform sampler2D m_Texture; uniform mat4 m_ViewProjectionInverse; uniform mat4 m_LastViewProjection; uniform float g_FrameRate; uniform float m_Strength; uniform float m_BlendAmount;

varying vec2 texCoord;

void main() {
float z = texture2D(m_DepthTexture, texCoord).r;
vec4 H = vec4(texCoord2.0-1.0, z * 2.0 -1.0, 1.0);
vec4 D = m_ViewProjectionInverse
H;
vec4 worldPos = D / D.w;
vec4 color = worldPos;

vec4 currentPos = H;
vec4 previousPos = m_LastViewProjection * worldPos;
previousPos = previousPos / previousPos.w;

vec2 velocity = (currentPos - previousPos).xy*-45.0/g_FrameRate * m_Strength;

vec4 realColor = color = texture2D(m_Texture, texCoord);
int samples = 16;
vec2 deltaTc = velocity/float(samples);
vec2 tc = texCoord + deltaTc;
for(int i = 0; i < samples; i++){
    tc.x = clamp(tc.x, 0.0, 1.0);
    tc.y = clamp(tc.y, 0.0, 1.0);
    vec4 cColor = texture2D(m_Texture, tc);
    color += cColor;
    tc += deltaTc;
}
gl_FragColor = mix(realColor,(color / float(samples + 1)), m_BlendAmount);

}

3 Likes
@kwando said:

I'm using Hoffman and Preetham model for areal perspective. The sky is rendered as a small sphere before everything else is rendered. The sky colors are calculated in real time inside the vertex shader and then interpolated. Colors are based on optical density (essentially how much air a given light ray has travelled through) and the angle sun. I have plenty of references if someone is interrested.


This is very nice. What prompted you to create the atmospheric scattering shader if i may ask? Are you interested in atmospheric rendering generally, or is it mostly shaders & filters?

@kwando , thanks for sharing!



Any chance for this cool shader to be in the JME-Core?



@kwando , I did a shader library “ShaderBlow”. If you want you can be a developer there. I can add you as a member or as a committer, as you wish. http://code.google.com/p/jme-glsl-shaders/

@mifth said:
Any chance for this cool shader to be in the JME-Core?


Yeah, that was the main reason I asked. I defer to @nehon on this stuff, though. He is the post-processing expert. :)

I’m on it :wink:



At first glance this effect is very nice!

@androlo said:
This is very nice. What prompted you to create the atmospheric scattering shader if i may ask? Are you interested in atmospheric rendering generally, or is it mostly shaders & filters?

I was looking for some nice shader effects to implement as a part of a course in "High Performance Computer Graphics" and I found the scattering a neat candidate (together with motion blur and parallax occlusion mapping).

If time allows I would like to implement another scattering shader based on another approach :)
@nehon said:
I'm on it ;)

At first glance this effect is very nice!


As I mentioned earlier the effects currently has some limits.. but used wisely it can enhance the realism quite a bit :)
http://http.developer.nvidia.com/GPUGems3/gpugems3_ch27.html <-- shader is based on this info, there are also some suggestion to make it more versatile :)

The graphics group at my university is currently doing research in the field of motion blur, if I find time I might talk to them and get hold on some other way to implement it.

Very nice!

I think JME becomes the strongest open-source engine with the strongest community.

@kwando said:
I was looking for some nice shader effects to implement as a part of a course in "High Performance Computer Graphics" and I found the scattering a neat candidate (together with motion blur and parallax occlusion mapping).

I don't know if you tried it but the lighting material has a steep parallax option. I never get the difference between steep parallax mapping and parallax occlusion mapping, so it might be of interest for you.
check this thread
http://hub.jmonkeyengine.org/groups/development-discussion-jme3/forum/topic/steep-parallax-mapping/

About the motion blur, it seems to be frame rate dependent (at high frame rate it not visible). But it seems you did account for it in the shader when computing the velocity.

vec2 velocity = (currentPos - previousPos).xy*-45.0/g_FrameRate * m_Strength;

Is it normal or something is messy on my end?