@pspeed, sure
MotionBlurFilter.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);
}
}
MotionBlur.j3md
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
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
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(texCoord*2.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);
}