blob: 953f10a66f2462122ca9dea69263f3e9295501f9 [file] [log] [blame]
/*
* Copyright (c) 2009-2010 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.jme3.post.filters;
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.Vector3f;
import com.jme3.post.Filter;
import com.jme3.renderer.Camera;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import java.io.IOException;
/**
* LightScattering filters creates rays comming from a light sources
* This is often reffered as god rays.
*
* @author Rémy Bouquet aka Nehon
*/
public class LightScatteringFilter extends Filter {
private Vector3f lightPosition;
private Vector3f screenLightPos = new Vector3f();
private int nbSamples = 50;
private float blurStart = 0.02f;
private float blurWidth = 0.9f;
private float lightDensity = 1.4f;
private boolean adaptative = true;
Vector3f viewLightPos = new Vector3f();
private boolean display = true;
private float innerLightDensity;
/**
* creates a lightScaterring filter
*/
public LightScatteringFilter() {
super("Light Scattering");
}
/**
* Creates a lightScatteringFilter
* @param lightPosition
*/
public LightScatteringFilter(Vector3f lightPosition) {
this();
this.lightPosition = lightPosition;
}
@Override
protected boolean isRequiresDepthTexture() {
return true;
}
@Override
protected Material getMaterial() {
material.setVector3("LightPosition", screenLightPos);
material.setInt("NbSamples", nbSamples);
material.setFloat("BlurStart", blurStart);
material.setFloat("BlurWidth", blurWidth);
material.setFloat("LightDensity", innerLightDensity);
material.setBoolean("Display", display);
return material;
}
@Override
protected void postQueue(RenderManager renderManager, ViewPort viewPort) {
getClipCoordinates(lightPosition, screenLightPos, viewPort.getCamera());
// screenLightPos.x = screenLightPos.x / viewPort.getCamera().getWidth();
// screenLightPos.y = screenLightPos.y / viewPort.getCamera().getHeight();
viewPort.getCamera().getViewMatrix().mult(lightPosition, viewLightPos);
//System.err.println("viewLightPos "+viewLightPos);
display = screenLightPos.x < 1.6f && screenLightPos.x > -0.6f && screenLightPos.y < 1.6f && screenLightPos.y > -0.6f && viewLightPos.z < 0;
//System.err.println("camdir "+viewPort.getCamera().getDirection());
//System.err.println("lightPos "+lightPosition);
//System.err.println("screenLightPos "+screenLightPos);
if (adaptative) {
innerLightDensity = Math.max(lightDensity - Math.max(screenLightPos.x, screenLightPos.y), 0.0f);
} else {
innerLightDensity = lightDensity;
}
}
private Vector3f getClipCoordinates(Vector3f worldPosition, Vector3f store, Camera cam) {
float w = cam.getViewProjectionMatrix().multProj(worldPosition, store);
store.divideLocal(w);
store.x = ((store.x + 1f) * (cam.getViewPortRight() - cam.getViewPortLeft()) / 2f + cam.getViewPortLeft());
store.y = ((store.y + 1f) * (cam.getViewPortTop() - cam.getViewPortBottom()) / 2f + cam.getViewPortBottom());
store.z = (store.z + 1f) / 2f;
return store;
}
@Override
protected void initFilter(AssetManager manager, RenderManager renderManager, ViewPort vp, int w, int h) {
material = new Material(manager, "Common/MatDefs/Post/LightScattering.j3md");
}
/**
* returns the blur start of the scattering
* see {@link setBlurStart(float blurStart)}
* @return
*/
public float getBlurStart() {
return blurStart;
}
/**
* sets the blur start<br>
* at which distance from the light source the effect starts default is 0.02
* @param blurStart
*/
public void setBlurStart(float blurStart) {
this.blurStart = blurStart;
}
/**
* returns the blur width<br>
* see {@link setBlurWidth(float blurWidth)}
* @return
*/
public float getBlurWidth() {
return blurWidth;
}
/**
* sets the blur width default is 0.9
* @param blurWidth
*/
public void setBlurWidth(float blurWidth) {
this.blurWidth = blurWidth;
}
/**
* retiurns the light density<br>
* see {@link setLightDensity(float lightDensity)}
*
* @return
*/
public float getLightDensity() {
return lightDensity;
}
/**
* sets how much the effect is visible over the rendered scene default is 1.4
* @param lightDensity
*/
public void setLightDensity(float lightDensity) {
this.lightDensity = lightDensity;
}
/**
* returns the light position
* @return
*/
public Vector3f getLightPosition() {
return lightPosition;
}
/**
* sets the light position
* @param lightPosition
*/
public void setLightPosition(Vector3f lightPosition) {
this.lightPosition = lightPosition;
}
/**
* returns the nmber of samples for the radial blur
* @return
*/
public int getNbSamples() {
return nbSamples;
}
/**
* sets the number of samples for the radial blur default is 50
* the higher the value the higher the quality, but the slower the performances.
* @param nbSamples
*/
public void setNbSamples(int nbSamples) {
this.nbSamples = nbSamples;
}
@Override
public void write(JmeExporter ex) throws IOException {
super.write(ex);
OutputCapsule oc = ex.getCapsule(this);
oc.write(lightPosition, "lightPosition", Vector3f.ZERO);
oc.write(nbSamples, "nbSamples", 50);
oc.write(blurStart, "blurStart", 0.02f);
oc.write(blurWidth, "blurWidth", 0.9f);
oc.write(lightDensity, "lightDensity", 1.4f);
oc.write(adaptative, "adaptative", true);
}
@Override
public void read(JmeImporter im) throws IOException {
super.read(im);
InputCapsule ic = im.getCapsule(this);
lightPosition = (Vector3f) ic.readSavable("lightPosition", Vector3f.ZERO);
nbSamples = ic.readInt("nbSamples", 50);
blurStart = ic.readFloat("blurStart", 0.02f);
blurWidth = ic.readFloat("blurWidth", 0.9f);
lightDensity = ic.readFloat("lightDensity", 1.4f);
adaptative = ic.readBoolean("adaptative", true);
}
}