diff --git a/engine/src/core-data/Common/MatDefs/Post/FXAA.frag b/engine/src/core-data/Common/MatDefs/Post/FXAA.frag new file mode 100644 index 000000000..679e9d2cf --- /dev/null +++ b/engine/src/core-data/Common/MatDefs/Post/FXAA.frag @@ -0,0 +1,73 @@ +#extension GL_EXT_gpu_shader4 : enable +uniform sampler2D m_Texture; +uniform vec2 g_Resolution; +varying vec2 texCoord; +uniform float m_VxOffset; +uniform float m_SpanMax; +uniform float m_ReduceMul; +varying vec4 posPos; +#define FxaaInt2 ivec2 +#define FxaaFloat2 vec2 +#define FxaaTexLod0(t, p) texture2DLod(t, p, 0.0) +#define FxaaTexOff(t, p, o, r) texture2DLodOffset(t, p, 0.0, o) +vec3 FxaaPixelShader( + vec4 posPos, // Output of FxaaVertexShader interpolated across screen. + sampler2D tex, // Input texture. + vec2 rcpFrame) // Constant {1.0/frameWidth, 1.0/frameHeight}. +{ +/*---------------------------------------------------------*/ + #define FXAA_REDUCE_MIN (1.0/128.0) + //#define FXAA_REDUCE_MUL (1.0/8.0) + //#define FXAA_SPAN_MAX 8.0 +/*---------------------------------------------------------*/ + vec3 rgbNW = FxaaTexLod0(tex, posPos.zw).xyz; + vec3 rgbNE = FxaaTexOff(tex, posPos.zw, FxaaInt2(1,0), rcpFrame.xy).xyz; + vec3 rgbSW = FxaaTexOff(tex, posPos.zw, FxaaInt2(0,1), rcpFrame.xy).xyz; + vec3 rgbSE = FxaaTexOff(tex, posPos.zw, FxaaInt2(1,1), rcpFrame.xy).xyz; + vec3 rgbM = FxaaTexLod0(tex, posPos.xy).xyz; +/*---------------------------------------------------------*/ + vec3 luma = vec3(0.299, 0.587, 0.114); + float lumaNW = dot(rgbNW, luma); + float lumaNE = dot(rgbNE, luma); + float lumaSW = dot(rgbSW, luma); + float lumaSE = dot(rgbSE, luma); + float lumaM = dot(rgbM, luma); +/*---------------------------------------------------------*/ + float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE))); + float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE))); +/*---------------------------------------------------------*/ + vec2 dir; + dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE)); + dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE)); +/*---------------------------------------------------------*/ + float dirReduce = max( + (lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * m_ReduceMul), + FXAA_REDUCE_MIN); + float rcpDirMin = 1.0/(min(abs(dir.x), abs(dir.y)) + dirReduce); + dir = min(FxaaFloat2( m_SpanMax, m_SpanMax), + max(FxaaFloat2(-m_SpanMax, -m_SpanMax), + dir * rcpDirMin)) * rcpFrame.xy; +/*--------------------------------------------------------*/ + vec3 rgbA = (1.0/2.0) * ( + FxaaTexLod0(tex, posPos.xy + dir * (1.0/3.0 - 0.5)).xyz + + FxaaTexLod0(tex, posPos.xy + dir * (2.0/3.0 - 0.5)).xyz); + vec3 rgbB = rgbA * (1.0/2.0) + (1.0/4.0) * ( + FxaaTexLod0(tex, posPos.xy + dir * (0.0/3.0 - 0.5)).xyz + + FxaaTexLod0(tex, posPos.xy + dir * (3.0/3.0 - 0.5)).xyz); + float lumaB = dot(rgbB, luma); + if((lumaB < lumaMin) || (lumaB > lumaMax)) return rgbA; + return rgbB; } +vec4 PostFX(sampler2D tex, vec2 uv, float time) +{ + vec4 c = vec4(0.0); + vec2 rcpFrame = vec2(1.0/g_Resolution.x, 1.0/g_Resolution.y); + c.rgb = FxaaPixelShader(posPos, tex, rcpFrame); + //c.rgb = 1.0 - texture2D(tex, posPos.xy).rgb; + c.a = 1.0; + return c; +} +void main() +{ + vec2 uv = texCoord.st; + gl_FragColor = PostFX(m_Texture, uv, 0.0); +} \ No newline at end of file diff --git a/engine/src/core-data/Common/MatDefs/Post/FXAA.j3md b/engine/src/core-data/Common/MatDefs/Post/FXAA.j3md new file mode 100644 index 000000000..88401f529 --- /dev/null +++ b/engine/src/core-data/Common/MatDefs/Post/FXAA.j3md @@ -0,0 +1,20 @@ +MaterialDef FXAA { + MaterialParameters { + Int NumSamples + Texture2D Texture + Float SubPixelShif + Float VxOffset + Float SpanMax + Float ReduceMul + } + Technique { + VertexShader GLSL100: Common/MatDefs/Post/FXAA.vert + FragmentShader GLSL120: Common/MatDefs/Post/FXAA.frag + WorldParameters { + WorldViewProjectionMatrix + Resolution + } + } + Technique FixedFunc { + } +} \ No newline at end of file diff --git a/engine/src/core-data/Common/MatDefs/Post/FXAA.vert b/engine/src/core-data/Common/MatDefs/Post/FXAA.vert new file mode 100644 index 000000000..659492634 --- /dev/null +++ b/engine/src/core-data/Common/MatDefs/Post/FXAA.vert @@ -0,0 +1,15 @@ +uniform mat4 g_WorldViewProjectionMatrix; +uniform vec2 g_Resolution; +attribute vec4 inPosition; +attribute vec2 inTexCoord; +varying vec2 texCoord; +uniform float m_SubPixelShif; +varying vec4 posPos; +void main() { + gl_Position = inPosition * 2.0 - 1.0; //vec4(pos, 0.0, 1.0); + texCoord = inTexCoord; + vec2 rcpFrame = vec2(1.0/g_Resolution.x, 1.0/g_Resolution.y); + posPos.xy = inTexCoord.xy; + posPos.zw = inTexCoord.xy - + (rcpFrame * (0.5 + m_SubPixelShif)); +} \ No newline at end of file diff --git a/engine/src/desktop-fx/com/jme3/post/filters/FXAAFilter.java b/engine/src/desktop-fx/com/jme3/post/filters/FXAAFilter.java new file mode 100644 index 000000000..27de14569 --- /dev/null +++ b/engine/src/desktop-fx/com/jme3/post/filters/FXAAFilter.java @@ -0,0 +1,95 @@ +package com.jme3.post.filters; + +import com.jme3.asset.AssetManager; +import com.jme3.material.Material; +import com.jme3.post.Filter; +import com.jme3.renderer.RenderManager; +import com.jme3.renderer.ViewPort; + +/** + * http://www.geeks3d.com/20110405/fxaa-fast-approximate-anti-aliasing-demo-glsl-opengl-test-radeon-geforce/3/ + * http://developer.download.nvidia.com/assets/gamedev/files/sdk/11/FXAA_WhitePaper.pdf + * + * @author Phate666 (adapted to jme3) + * + */ +public class FXAAFilter extends Filter { + + private float subPixelShif = 1.0f / 4.0f; + private float vxOffset = 0.0f; + private float spanMax = 8.0f; + private float reduceMul = 1.0f / 8.0f; + + public FXAAFilter() { + super("FXAAFilter"); + } + + @Override + protected void initFilter(AssetManager manager, + RenderManager renderManager, ViewPort vp, int w, int h) { + material = new Material(manager, "Common/MatDefs/Post/FXAA.j3md"); + material.setFloat("SubPixelShif", subPixelShif); + material.setFloat("VxOffset", vxOffset); + material.setFloat("SpanMax", spanMax); + material.setFloat("ReduceMul", reduceMul); + } + + @Override + protected Material getMaterial() { + return material; + } + + public void setSpanMax(float spanMax) { + this.spanMax = spanMax; + if (material != null) { + material.setFloat("SpanMax", this.spanMax); + } + } + + /** + * set to 0.0f for higher quality + * + * @param subPixelShift + */ + public void setSubPixelShift(float subPixelShift) { + subPixelShif = subPixelShift; + if (material != null) { + material.setFloat("SubPixelShif", subPixelShif); + } + } + + /** + * set to 0.0f for higher quality + * + * @param reduceMul + */ + public void setReduceMul(float reduceMul) { + this.reduceMul = reduceMul; + if (material != null) { + material.setFloat("ReduceMul", this.reduceMul); + } + } + + public void setVxOffset(float vxOffset) { + this.vxOffset = vxOffset; + if (material != null) { + material.setFloat("VxOffset", this.vxOffset); + } + } + + public float getReduceMul() { + return reduceMul; + } + + public float getSpanMax() { + return spanMax; + } + + public float getSubPixelShif() { + return subPixelShif; + } + + public float getVxOffset() { + return vxOffset; + } +} \ No newline at end of file