/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.jme3.post;
import com.jme3.asset.AssetManager;
import com.jme3.material.Material;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.post.Filter;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.renderer.queue.RenderQueue;
import com.jme3.texture.Image.Format;
/**
* A Cartoon Screen Space Ambient Occlusion filter with instance rendering capabilities.
* @author reden - phr00t - https://github.com/phr00t
* @author Julien Seinturier - (c) 2016 - JOrigin project - <a href="http://www.jorigin.org">http:/www.jorigin.org</a>
*
*/
public class CartoonSSAO extends Filter{
private Pass normalPass;
private Vector3f frustumCorner;
private Vector2f frustumNearFar;
private boolean useOutline = true;
private float downsample = 1f, applyDistance = 0.0005f;
private boolean instancedRendering = false;
RenderManager renderManager;
ViewPort viewPort;
/**
* Create a Screen Space Ambient Occlusion Filter.
* @param instancedRendering <code>true</code> if this filter has to use instance rendering and <code>false</code> (default) otherwise.
*/
public CartoonSSAO(boolean instancedRendering) {
super("CartoonSSAO");
this.instancedRendering = instancedRendering;
}
/**
* Create a Screen Space Ambient Occlusion Filter.
* @param downsample factor to divide resolution by for filter, >1 increases speed but degrades quality.
* @param instancedRendering <code>true</code> if this filter has to use instance rendering and <code>false</code> (default) otherwise.
*/
public CartoonSSAO(float downsample, boolean instancedRendering) {
this(instancedRendering);
this.downsample = downsample;
}
/**
* Create a Screen Space Ambient Occlusion Filter from the given one (by copy).
* @param cloneFrom the original filter.
*/
public CartoonSSAO(CartoonSSAO cloneFrom) {
this(cloneFrom.downsample, cloneFrom.instancedRendering);
}
@Override
protected boolean isRequiresDepthTexture() {
return true;
}
@Override
protected void postQueue(RenderQueue renderQueue) {
PreNormalCaching.getPreNormals(renderManager, normalPass, viewPort);
}
/**
* Set if outline has to be enabled.
* @param set <code>true</code> if the outline has to be enabled and <code>false</code> otherwise.
* @see #isOutlineEnabled()
*/
public void setOutlineEnabled(boolean set) {
useOutline = set;
if( material != null ) {
if( useOutline ) {
material.clearParam("disableOutline");
} else {
material.setBoolean("disableOutline", true);
}
}
}
/**
* Is outline rendering is enabled.
* @return <code>true</code> if the outline is enabled and <code>false</code> otherwise.
* @see #setOutlineEnabled(boolean)
*/
public boolean isOutlineEnabled() {
return useOutline;
}
/**
* Set the down sampling value.
* @param downsample the down sampling value.
* @see #getDownsampling()
*/
public void setDownsampling(float downsample) {
this.downsample = downsample;
}
/**
* Get the down sampling value.
* @return the down sampling value.
* @see #setDownsampling(float)
*/
public float getDownsampling() {
return this.downsample;
}
@Override
protected Material getMaterial() {
return material;
}
/**
* Set the distance of the material.
* @param dist the distance of the material.
*/
public void setDistance(float dist) {
applyDistance = dist;
if( material != null ) material.setFloat("Distance", dist);
}
@Override
protected void initFilter(AssetManager manager, RenderManager renderManager, ViewPort vp, int w, int h) {
this.renderManager = renderManager;
this.viewPort = vp;
int screenWidth = Math.round(w / downsample);
int screenHeight = Math.round(h / downsample);
normalPass = new Pass();
normalPass.init(renderManager.getRenderer(), screenWidth, screenHeight, Format.RGBA8, Format.Depth);
frustumNearFar = new Vector2f();
float farY = (vp.getCamera().getFrustumTop() / vp.getCamera().getFrustumNear()) * vp.getCamera().getFrustumFar();
float farX = farY * ((float) screenWidth / (float) screenHeight);
frustumCorner = new Vector3f(farX, farY, vp.getCamera().getFrustumFar());
frustumNearFar.x = vp.getCamera().getFrustumNear();
frustumNearFar.y = vp.getCamera().getFrustumFar();
//ssao Pass
material = new Material(manager, "Common/MatDefs/VR/CartoonSSAO.j3md");
material.setTexture("Normals", normalPass.getRenderedTexture());
material.setVector3("FrustumCorner", frustumCorner);
material.setVector2("FrustumNearFar", frustumNearFar);
material.setFloat("Distance", applyDistance);
if( useOutline == false ) material.setBoolean("disableOutline", true);
if( instancedRendering ) material.setBoolean("useInstancing", true);
}
}