VignetteFilter

I’ve been looking for it but I haven’t found anything on the forum nor in the code. The only thing that comes close is the OldFilm filter of the shader blow project and I only wanted to have the vignetting effect.
Thus I took pieces from here and there to achieve a simple vignette effect. The original is from ShaderLesson3 · mattdesl/lwjgl-basics Wiki · GitHub

So if anyone is looking for something similar in the future they don’t need to put it together by themselves. If you think it’s worth it then I’d be more than happy if you add it to the core effects collection as well.

VignetteFilter.java
[java]

import com.jme3.asset.AssetManager;
import com.jme3.material.Material;
import com.jme3.math.Vector2f;
import com.jme3.post.Filter;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;

/**

private Material material;

private float radius = 0.75f;
private float softness = 0.5f;
private float strength = 0.5f;

public VignetteFilter() {
super(VignetteFilter.class.getSimpleName());
}

@Override
protected void initFilter(AssetManager assetManager, RenderManager arg1, ViewPort arg2, int w, int h) {
material = new Material(assetManager, “MatDefs/Post/Vignette.j3md”);
material.setVector2(“Resolution”, new Vector2f(w, h));
material.setFloat(“Radius”, radius);
material.setFloat(“Softness”, softness);
material.setFloat(“Strength”, strength);
}

@Override
protected Material getMaterial() {
return material;
}

public float getRadius() {
return radius;
}

/**

  • The radius of the vignette. Where a value of 0.5 will lead to a circle fitting the screen.
  • @param radius
    */
    public void setRadius(float radius) {
    checkFloatArgument(radius, 0, 1, “radius”);
    this.radius = radius;
    }

public float getSoftness() {
return softness;
}

/**

  • The softness of the vignette’s edge. A value between 0 and 1.
  • @param softness
    */
    public void setSoftness(float softness) {
    checkFloatArgument(softness, 0, 1, “softness”);
    this.softness = softness;
    }

public float getStrength() {
return strength;
}

/**

  • The strength vignette. A value between 0 and 1. Where a value of 0 will result in no visible effect.
  • @param strength
    */
    public void setStrength(float strength) {
    checkFloatArgument(strength, 0, 1, “strength”);
    this.strength = strength;
    }

private static void checkFloatArgument(float value, float min, float max, String name) {
if (value < min || value > max) {
throw new IllegalArgumentException(name + " was " + value + " but should be between " + min + " and " + max);
}
}
}
[/java]

Vignette.j3md
[java]
MaterialDef Vignette {

MaterialParameters {
    Int NumSamples
    Int NumSamplesDepth
    Texture2D Texture
    
    Vector2 Resolution;
    Float Radius;
    Float Softness;
    Float Strength;
}

Technique {
    VertexShader GLSL100:   Common/MatDefs/Post/Post.vert
    FragmentShader GLSL100: MatDefs/Post/Vignette.frag

    WorldParameters {
    }
}

}
[/java]

Vignette.frag
[java]

uniform sampler2D m_Texture;
varying vec2 texCoord;

uniform vec2 m_Resolution;
uniform float m_Radius ;
uniform float m_Softness;
uniform float m_Strength;

void main() {
vec4 texColor = texture2D(m_Texture, texCoord);
vec2 position = (gl_FragCoord.xy / m_Resolution.xy) - vec2(0.5);
float len = length(position);
float vignette = smoothstep(m_Radius, m_Radius-m_Softness, len);
texColor.rgb = mix(texColor.rgb, texColor.rgb * vignette, m_Strength);
gl_FragColor = texColor;
}
[/java]

4 Likes

Since I am unable/incompetent to edit my original post. Here the update including the serialization:

VignetteFilter.java

import com.jme3.asset.AssetManager;
import com.jme3.export.InputCapsule;
import com.jme3.export.JmeExporter;
import com.jme3.export.JmeImporter;
import com.jme3.export.OutputCapsule;
import com.jme3.material.Material;
import com.jme3.math.Vector2f;
import com.jme3.post.Filter;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;

/**

private static final float DEFAULT_STRENTH = 0.5f;
private static final float DEFAULT_SOFTNESS = 0.5f;
private static final float DEFAULT_RADIUS = 0.75f;

private Material material;

private float radius = DEFAULT_RADIUS;
private float softness = DEFAULT_SOFTNESS;
private float strength = DEFAULT_STRENTH;

public VignetteFilter() {
super(VignetteFilter.class.getSimpleName());
}

@Override
protected void initFilter(AssetManager assetManager, RenderManager arg1, ViewPort arg2, int w, int h) {
material = new Material(assetManager, “MatDefs/Post/Vignette.j3md”);
material.setVector2(“Resolution”, new Vector2f(w, h));
material.setFloat(“Radius”, radius);
material.setFloat(“Softness”, softness);
material.setFloat(“Strength”, strength);
}

@Override
protected Material getMaterial() {
return material;
}

public float getRadius() {
return radius;
}

/**

  • The radius of the vignette. Where a value of 0.5 will lead to a circle fitting the screen.
  • @param radius
    */
    public void setRadius(float radius) {
    checkFloatArgument(radius, 0, 1, “radius”);
    this.radius = radius;
    }

public float getSoftness() {
return softness;
}

/**

  • The softness of the vignette’s edge. A value between 0 and 1.
  • @param softness
    */
    public void setSoftness(float softness) {
    checkFloatArgument(softness, 0, 1, “softness”);
    this.softness = softness;
    }

public float getStrength() {
return strength;
}

/**

  • The strength vignette. A value between 0 and 1. Where a value of 0 will result in no visible effect.
  • @param strength
    */
    public void setStrength(float strength) {
    checkFloatArgument(strength, 0, 1, “strength”);
    this.strength = strength;
    }

private static void checkFloatArgument(float value, float min, float max, String name) {
if (value < min || value > max) {
throw new IllegalArgumentException(name + " was " + value + " but should be between " + min + " and " + max);
}
}

@Override
public void write(JmeExporter ex) throws IOException {
super.write(ex);
OutputCapsule oc = ex.getCapsule(this);
oc.write(radius, “radius”, DEFAULT_RADIUS);
oc.write(softness, “softness”, DEFAULT_SOFTNESS);
oc.write(strength, “strength”, DEFAULT_STRENTH);
}

@Override
public void read(JmeImporter im) throws IOException {
super.read(im);
InputCapsule ic = im.getCapsule(this);
radius = ic.readFloat(“radius”, DEFAULT_RADIUS);
softness = ic.readFloat(“softness”, DEFAULT_SOFTNESS);
strength = ic.readFloat(“strength”, DEFAULT_STRENTH);
}
}

How does it look ? can you post a without / with screenshot? Cause I does not really know what a vignette is :slight_smile:

We have OldFilm filter. https://wiki.jmonkeyengine.org/legacy/doku.php/sdk:plugin:shaderblow#old_film_effect_filter

Also, we can add your filter to ShaderBlow. @H what do you think about this filter?

@EmpirePhoenix
This is a screenshot from my game Wasteland with and without the filter. The effect is very subtle and leads the visual focus more to the center. I think just like bloom this is a pretty popular effect in games and movie productions.


@mifth
Sure if you like you can add it to your ShaderBlow collection. However, it might also be something for the core effects.
The OldFilm filter also includes a vignette but I didn’t find it in the code. The google-code project which I’ve found didn’t include vignetting.

@mifth said: We have OldFilm filter. https://wiki.jmonkeyengine.org/legacy/doku.php/sdk:plugin:shaderblow#old_film_effect_filter

Also, we can add your filter to ShaderBlow. @H what do you think about this filter?


Setting colorDensity = 0, noiseDensity = 0 and scratchDensity = 0 on Old Film effect filter from shaderblow you will get the vignette effect but over a grayscale image.

The code section that calculates the vignette effect is:
// Apply vignetting
// Max distance from center to corner is ~0.7. Scale that to 1.0.
float d = distance(vec2(0.5, 0.5), texCoord) * 1.414213;
float vignetting = clamp((m_OuterVignetting - d) / (m_OuterVignetting - m_InnerVignetting), 0.0, 1.0);
finalColour.xyz *= vignetting;

Check the full code for more details.

We can modify old film effect filter to display image real color (avoid grayscale transformation) if colorDensity == 0. Or we can add this filter, no problem with that.

@H said: We can modify old film effect filter to display image real color (avoid grayscale transformation) if colorDensity == 0.
It's done. Changes commited. It was really easy ;-P
@H said: It's done. Changes commited. It was really easy ;-P

Cool! Glad you did it. Now we have VignetteFilter! :slight_smile:
Fot better performance we need to use #ifdef things. I’ll refactor it a bit when i get some free time.