Documented com.jme3.shadow
git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7631 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
This commit is contained in:
parent
bcef1b1e5c
commit
446275775f
@ -29,7 +29,6 @@
|
|||||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.jme3.shadow;
|
package com.jme3.shadow;
|
||||||
|
|
||||||
import com.jme3.material.Material;
|
import com.jme3.material.Material;
|
||||||
@ -48,29 +47,36 @@ import com.jme3.texture.Image.Format;
|
|||||||
import com.jme3.texture.Texture2D;
|
import com.jme3.texture.Texture2D;
|
||||||
import com.jme3.ui.Picture;
|
import com.jme3.ui.Picture;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BasicShadowRenderer uses standard shadow mapping with one map
|
||||||
|
* it's useful to render shadows in a small scene, but edges might look a bit jagged.
|
||||||
|
*
|
||||||
|
* @author Kirill Vainer
|
||||||
|
*/
|
||||||
public class BasicShadowRenderer implements SceneProcessor {
|
public class BasicShadowRenderer implements SceneProcessor {
|
||||||
|
|
||||||
private RenderManager renderManager;
|
private RenderManager renderManager;
|
||||||
private ViewPort viewPort;
|
private ViewPort viewPort;
|
||||||
|
|
||||||
private FrameBuffer shadowFB;
|
private FrameBuffer shadowFB;
|
||||||
private Texture2D shadowMap;
|
private Texture2D shadowMap;
|
||||||
private Camera shadowCam;
|
private Camera shadowCam;
|
||||||
|
|
||||||
private Material preshadowMat;
|
private Material preshadowMat;
|
||||||
private Material postshadowMat;
|
private Material postshadowMat;
|
||||||
|
|
||||||
private Picture dispPic = new Picture("Picture");
|
private Picture dispPic = new Picture("Picture");
|
||||||
private boolean noOccluders = false;
|
private boolean noOccluders = false;
|
||||||
|
|
||||||
private Vector3f[] points = new Vector3f[8];
|
private Vector3f[] points = new Vector3f[8];
|
||||||
private Vector3f direction = new Vector3f();
|
private Vector3f direction = new Vector3f();
|
||||||
|
|
||||||
public BasicShadowRenderer(AssetManager manager, int size){
|
/**
|
||||||
shadowFB = new FrameBuffer(size,size,1);
|
* Creates a BasicShadowRenderer
|
||||||
shadowMap = new Texture2D(size,size,Format.Depth);
|
* @param manager the asset manager
|
||||||
|
* @param size the size of the shadow map (the map is square)
|
||||||
|
*/
|
||||||
|
public BasicShadowRenderer(AssetManager manager, int size) {
|
||||||
|
shadowFB = new FrameBuffer(size, size, 1);
|
||||||
|
shadowMap = new Texture2D(size, size, Format.Depth);
|
||||||
shadowFB.setDepthTexture(shadowMap);
|
shadowFB.setDepthTexture(shadowMap);
|
||||||
shadowCam = new Camera(size,size);
|
shadowCam = new Camera(size, size);
|
||||||
|
|
||||||
preshadowMat = new Material(manager, "Common/MatDefs/Shadow/PreShadow.j3md");
|
preshadowMat = new Material(manager, "Common/MatDefs/Shadow/PreShadow.j3md");
|
||||||
postshadowMat = new Material(manager, "Common/MatDefs/Shadow/PostShadow.j3md");
|
postshadowMat = new Material(manager, "Common/MatDefs/Shadow/PostShadow.j3md");
|
||||||
@ -78,44 +84,61 @@ public class BasicShadowRenderer implements SceneProcessor {
|
|||||||
|
|
||||||
dispPic.setTexture(manager, shadowMap, false);
|
dispPic.setTexture(manager, shadowMap, false);
|
||||||
|
|
||||||
for (int i = 0; i < points.length; i++){
|
for (int i = 0; i < points.length; i++) {
|
||||||
points[i] = new Vector3f();
|
points[i] = new Vector3f();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initialize(RenderManager rm, ViewPort vp){
|
public void initialize(RenderManager rm, ViewPort vp) {
|
||||||
renderManager = rm;
|
renderManager = rm;
|
||||||
viewPort = vp;
|
viewPort = vp;
|
||||||
|
|
||||||
reshape(vp, vp.getCamera().getWidth(), vp.getCamera().getHeight());
|
reshape(vp, vp.getCamera().getWidth(), vp.getCamera().getHeight());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isInitialized(){
|
public boolean isInitialized() {
|
||||||
return viewPort != null;
|
return viewPort != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the light direction used for this processor
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public Vector3f getDirection() {
|
public Vector3f getDirection() {
|
||||||
return direction;
|
return direction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sets the light direction to use to computs shadows
|
||||||
|
* @param direction
|
||||||
|
*/
|
||||||
public void setDirection(Vector3f direction) {
|
public void setDirection(Vector3f direction) {
|
||||||
this.direction.set(direction).normalizeLocal();
|
this.direction.set(direction).normalizeLocal();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* debug only
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public Vector3f[] getPoints() {
|
public Vector3f[] getPoints() {
|
||||||
return points;
|
return points;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Camera getShadowCamera(){
|
/**
|
||||||
|
* debug only
|
||||||
|
* returns the shadow camera
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Camera getShadowCamera() {
|
||||||
return shadowCam;
|
return shadowCam;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void postQueue(RenderQueue rq){
|
public void postQueue(RenderQueue rq) {
|
||||||
GeometryList occluders = rq.getShadowQueueContent(ShadowMode.Cast);
|
GeometryList occluders = rq.getShadowQueueContent(ShadowMode.Cast);
|
||||||
if (occluders.size() == 0){
|
if (occluders.size() == 0) {
|
||||||
noOccluders = true;
|
noOccluders = true;
|
||||||
return;
|
return;
|
||||||
}else{
|
} else {
|
||||||
noOccluders = false;
|
noOccluders = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,7 +153,7 @@ public class BasicShadowRenderer implements SceneProcessor {
|
|||||||
points);
|
points);
|
||||||
|
|
||||||
Vector3f frustaCenter = new Vector3f();
|
Vector3f frustaCenter = new Vector3f();
|
||||||
for (Vector3f point : points){
|
for (Vector3f point : points) {
|
||||||
frustaCenter.addLocal(point);
|
frustaCenter.addLocal(point);
|
||||||
}
|
}
|
||||||
frustaCenter.multLocal(1f / 8f);
|
frustaCenter.multLocal(1f / 8f);
|
||||||
@ -154,7 +177,7 @@ public class BasicShadowRenderer implements SceneProcessor {
|
|||||||
renderManager.setForcedMaterial(preshadowMat);
|
renderManager.setForcedMaterial(preshadowMat);
|
||||||
|
|
||||||
r.setFrameBuffer(shadowFB);
|
r.setFrameBuffer(shadowFB);
|
||||||
r.clearBuffers(false,true,false);
|
r.clearBuffers(false, true, false);
|
||||||
viewPort.getQueue().renderShadowQueue(ShadowMode.Cast, renderManager, shadowCam, true);
|
viewPort.getQueue().renderShadowQueue(ShadowMode.Cast, renderManager, shadowCam, true);
|
||||||
r.setFrameBuffer(viewPort.getOutputFrameBuffer());
|
r.setFrameBuffer(viewPort.getOutputFrameBuffer());
|
||||||
|
|
||||||
@ -162,12 +185,16 @@ public class BasicShadowRenderer implements SceneProcessor {
|
|||||||
renderManager.setCamera(viewCam, false);
|
renderManager.setCamera(viewCam, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Picture getDisplayPicture(){
|
/**
|
||||||
|
* debug only
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Picture getDisplayPicture() {
|
||||||
return dispPic;
|
return dispPic;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void postFrame(FrameBuffer out){
|
public void postFrame(FrameBuffer out) {
|
||||||
if (!noOccluders){
|
if (!noOccluders) {
|
||||||
postshadowMat.setMatrix4("LightViewProjectionMatrix", shadowCam.getViewProjectionMatrix());
|
postshadowMat.setMatrix4("LightViewProjectionMatrix", shadowCam.getViewProjectionMatrix());
|
||||||
renderManager.setForcedMaterial(postshadowMat);
|
renderManager.setForcedMaterial(postshadowMat);
|
||||||
viewPort.getQueue().renderShadowQueue(ShadowMode.Receive, renderManager, viewPort.getCamera(), true);
|
viewPort.getQueue().renderShadowQueue(ShadowMode.Receive, renderManager, viewPort.getCamera(), true);
|
||||||
@ -186,5 +213,4 @@ public class BasicShadowRenderer implements SceneProcessor {
|
|||||||
dispPic.setWidth(w / 5f);
|
dispPic.setWidth(w / 5f);
|
||||||
dispPic.setHeight(h / 5f);
|
dispPic.setHeight(h / 5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,6 @@
|
|||||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.jme3.shadow;
|
package com.jme3.shadow;
|
||||||
|
|
||||||
import com.jme3.material.Material;
|
import com.jme3.material.Material;
|
||||||
@ -57,36 +56,42 @@ import com.jme3.texture.Texture.ShadowCompareMode;
|
|||||||
import com.jme3.texture.Texture2D;
|
import com.jme3.texture.Texture2D;
|
||||||
import com.jme3.ui.Picture;
|
import com.jme3.ui.Picture;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PssmShadow renderer use Parrallel Split Shadow Mapping technique (pssm)<br>
|
||||||
|
* It splits the view frustum in several parts and compute a shadow map for each one.<br>
|
||||||
|
* splits are distributed so that the closer they are from the camera, the smaller they are to maximize the resolution used of the shadow map.<br>
|
||||||
|
* This result in a better quality shadow than standard shadow mapping.<br>
|
||||||
|
* for more informations on this read this http://http.developer.nvidia.com/GPUGems3/gpugems3_ch10.html<br>
|
||||||
|
*
|
||||||
|
* @author Rémy Bouquet aka Nehon
|
||||||
|
*/
|
||||||
public class PssmShadowRenderer implements SceneProcessor {
|
public class PssmShadowRenderer implements SceneProcessor {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <code>FilterMode</code> specifies how shadows are filtered
|
* <code>FilterMode</code> specifies how shadows are filtered
|
||||||
*/
|
*/
|
||||||
public enum FilterMode {
|
public enum FilterMode {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shadows are not filtered. Nearest sample is used, causing in blocky
|
* Shadows are not filtered. Nearest sample is used, causing in blocky
|
||||||
* shadows.
|
* shadows.
|
||||||
*/
|
*/
|
||||||
Nearest,
|
Nearest,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bilinear filtering is used. Has the potential of being hardware
|
* Bilinear filtering is used. Has the potential of being hardware
|
||||||
* accelerated on some GPUs
|
* accelerated on some GPUs
|
||||||
*/
|
*/
|
||||||
Bilinear,
|
Bilinear,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dither-based sampling is used, very cheap but can look bad
|
* Dither-based sampling is used, very cheap but can look bad
|
||||||
* at low resolutions.
|
* at low resolutions.
|
||||||
*/
|
*/
|
||||||
Dither,
|
Dither,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 4x4 percentage-closer filtering is used. Shadows will be smoother
|
* 4x4 percentage-closer filtering is used. Shadows will be smoother
|
||||||
* at the cost of performance
|
* at the cost of performance
|
||||||
*/
|
*/
|
||||||
PCF4,
|
PCF4,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 8x8 percentage-closer filtering is used. Shadows will be smoother
|
* 8x8 percentage-closer filtering is used. Shadows will be smoother
|
||||||
* at the cost of performance
|
* at the cost of performance
|
||||||
@ -94,19 +99,21 @@ public class PssmShadowRenderer implements SceneProcessor {
|
|||||||
PCF8
|
PCF8
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the shadow comparison mode
|
||||||
|
*/
|
||||||
public enum CompareMode {
|
public enum CompareMode {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shadow depth comparisons are done by using shader code
|
* Shadow depth comparisons are done by using shader code
|
||||||
*/
|
*/
|
||||||
Software,
|
Software,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shadow depth comparisons are done by using the GPU's dedicated
|
* Shadow depth comparisons are done by using the GPU's dedicated
|
||||||
* shadowing pipeline.
|
* shadowing pipeline.
|
||||||
*/
|
*/
|
||||||
Hardware;
|
Hardware;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int nbSplits = 3;
|
private int nbSplits = 3;
|
||||||
private float lambda = 0.65f;
|
private float lambda = 0.65f;
|
||||||
private float shadowIntensity = 0.7f;
|
private float shadowIntensity = 0.7f;
|
||||||
@ -119,21 +126,17 @@ public class PssmShadowRenderer implements SceneProcessor {
|
|||||||
private Camera shadowCam;
|
private Camera shadowCam;
|
||||||
private Material preshadowMat;
|
private Material preshadowMat;
|
||||||
private Material postshadowMat;
|
private Material postshadowMat;
|
||||||
|
|
||||||
private GeometryList splitOccluders = new GeometryList(new OpaqueComparator());
|
private GeometryList splitOccluders = new GeometryList(new OpaqueComparator());
|
||||||
private Matrix4f[] lightViewProjectionsMatrices;
|
private Matrix4f[] lightViewProjectionsMatrices;
|
||||||
private ColorRGBA splits;
|
private ColorRGBA splits;
|
||||||
private float[] splitsArray;
|
private float[] splitsArray;
|
||||||
private boolean noOccluders = false;
|
private boolean noOccluders = false;
|
||||||
|
|
||||||
private Vector3f direction = new Vector3f();
|
private Vector3f direction = new Vector3f();
|
||||||
private AssetManager assetManager;
|
private AssetManager assetManager;
|
||||||
private boolean debug = false;
|
private boolean debug = false;
|
||||||
private float edgesThickness = 1.0f;
|
private float edgesThickness = 1.0f;
|
||||||
|
|
||||||
private FilterMode filterMode;
|
private FilterMode filterMode;
|
||||||
private CompareMode compareMode;
|
private CompareMode compareMode;
|
||||||
|
|
||||||
private Picture[] dispPic;
|
private Picture[] dispPic;
|
||||||
private Vector3f[] points = new Vector3f[8];
|
private Vector3f[] points = new Vector3f[8];
|
||||||
|
|
||||||
@ -154,10 +157,10 @@ public class PssmShadowRenderer implements SceneProcessor {
|
|||||||
dispPic = new Picture[nbSplits];
|
dispPic = new Picture[nbSplits];
|
||||||
lightViewProjectionsMatrices = new Matrix4f[nbSplits];
|
lightViewProjectionsMatrices = new Matrix4f[nbSplits];
|
||||||
splits = new ColorRGBA();
|
splits = new ColorRGBA();
|
||||||
splitsArray = new float[nbSplits+1];
|
splitsArray = new float[nbSplits + 1];
|
||||||
|
|
||||||
//DO NOT COMMENT THIS (it prevent the OSX incomplete read buffer crash)
|
//DO NOT COMMENT THIS (it prevent the OSX incomplete read buffer crash)
|
||||||
dummyTex= new Texture2D(size, size, Format.RGBA8);
|
dummyTex = new Texture2D(size, size, Format.RGBA8);
|
||||||
|
|
||||||
preshadowMat = new Material(manager, "Common/MatDefs/Shadow/PreShadow.j3md");
|
preshadowMat = new Material(manager, "Common/MatDefs/Shadow/PreShadow.j3md");
|
||||||
postshadowMat = new Material(manager, "Common/MatDefs/Shadow/PostShadowPSSM.j3md");
|
postshadowMat = new Material(manager, "Common/MatDefs/Shadow/PostShadowPSSM.j3md");
|
||||||
@ -190,22 +193,28 @@ public class PssmShadowRenderer implements SceneProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFilterMode(FilterMode filterMode){
|
/**
|
||||||
if (filterMode == null)
|
* Sets the filtering mode for shadow edges see {@link FilterMode} for more info
|
||||||
|
* @param filterMode
|
||||||
|
*/
|
||||||
|
public void setFilterMode(FilterMode filterMode) {
|
||||||
|
if (filterMode == null) {
|
||||||
throw new NullPointerException();
|
throw new NullPointerException();
|
||||||
|
}
|
||||||
|
|
||||||
if (this.filterMode == filterMode)
|
if (this.filterMode == filterMode) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.filterMode = filterMode;
|
this.filterMode = filterMode;
|
||||||
postshadowMat.setInt("FilterMode", filterMode.ordinal());
|
postshadowMat.setInt("FilterMode", filterMode.ordinal());
|
||||||
postshadowMat.setFloat("PCFEdge", edgesThickness);
|
postshadowMat.setFloat("PCFEdge", edgesThickness);
|
||||||
if (compareMode == CompareMode.Hardware){
|
if (compareMode == CompareMode.Hardware) {
|
||||||
for (Texture2D shadowMap : shadowMaps){
|
for (Texture2D shadowMap : shadowMaps) {
|
||||||
if (filterMode == FilterMode.Bilinear){
|
if (filterMode == FilterMode.Bilinear) {
|
||||||
shadowMap.setMagFilter(MagFilter.Bilinear);
|
shadowMap.setMagFilter(MagFilter.Bilinear);
|
||||||
shadowMap.setMinFilter(MinFilter.BilinearNoMipMaps);
|
shadowMap.setMinFilter(MinFilter.BilinearNoMipMaps);
|
||||||
}else{
|
} else {
|
||||||
shadowMap.setMagFilter(MagFilter.Nearest);
|
shadowMap.setMagFilter(MagFilter.Nearest);
|
||||||
shadowMap.setMinFilter(MinFilter.NearestNoMipMaps);
|
shadowMap.setMinFilter(MinFilter.NearestNoMipMaps);
|
||||||
}
|
}
|
||||||
@ -213,25 +222,31 @@ public class PssmShadowRenderer implements SceneProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sets the shadow compare mode see {@link CompareMode} for more info
|
||||||
|
* @param compareMode
|
||||||
|
*/
|
||||||
public void setCompareMode(CompareMode compareMode) {
|
public void setCompareMode(CompareMode compareMode) {
|
||||||
if (compareMode == null)
|
if (compareMode == null) {
|
||||||
throw new NullPointerException();
|
throw new NullPointerException();
|
||||||
|
}
|
||||||
|
|
||||||
if (this.compareMode == compareMode)
|
if (this.compareMode == compareMode) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.compareMode = compareMode;
|
this.compareMode = compareMode;
|
||||||
for (Texture2D shadowMap : shadowMaps){
|
for (Texture2D shadowMap : shadowMaps) {
|
||||||
if (compareMode == CompareMode.Hardware){
|
if (compareMode == CompareMode.Hardware) {
|
||||||
shadowMap.setShadowCompareMode(ShadowCompareMode.LessOrEqual);
|
shadowMap.setShadowCompareMode(ShadowCompareMode.LessOrEqual);
|
||||||
if (filterMode == FilterMode.Bilinear){
|
if (filterMode == FilterMode.Bilinear) {
|
||||||
shadowMap.setMagFilter(MagFilter.Bilinear);
|
shadowMap.setMagFilter(MagFilter.Bilinear);
|
||||||
shadowMap.setMinFilter(MinFilter.BilinearNoMipMaps);
|
shadowMap.setMinFilter(MinFilter.BilinearNoMipMaps);
|
||||||
}else{
|
} else {
|
||||||
shadowMap.setMagFilter(MagFilter.Nearest);
|
shadowMap.setMagFilter(MagFilter.Nearest);
|
||||||
shadowMap.setMinFilter(MinFilter.NearestNoMipMaps);
|
shadowMap.setMinFilter(MinFilter.NearestNoMipMaps);
|
||||||
}
|
}
|
||||||
} else{
|
} else {
|
||||||
shadowMap.setShadowCompareMode(ShadowCompareMode.Off);
|
shadowMap.setShadowCompareMode(ShadowCompareMode.Off);
|
||||||
shadowMap.setMagFilter(MagFilter.Nearest);
|
shadowMap.setMagFilter(MagFilter.Nearest);
|
||||||
shadowMap.setMinFilter(MinFilter.NearestNoMipMaps);
|
shadowMap.setMinFilter(MinFilter.NearestNoMipMaps);
|
||||||
@ -280,10 +295,18 @@ public class PssmShadowRenderer implements SceneProcessor {
|
|||||||
return viewPort != null;
|
return viewPort != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the light direction used by the processor
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public Vector3f getDirection() {
|
public Vector3f getDirection() {
|
||||||
return direction;
|
return direction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the light direction to use to compute shadows
|
||||||
|
* @param direction
|
||||||
|
*/
|
||||||
public void setDirection(Vector3f direction) {
|
public void setDirection(Vector3f direction) {
|
||||||
this.direction.set(direction).normalizeLocal();
|
this.direction.set(direction).normalizeLocal();
|
||||||
}
|
}
|
||||||
@ -291,18 +314,20 @@ public class PssmShadowRenderer implements SceneProcessor {
|
|||||||
@SuppressWarnings("fallthrough")
|
@SuppressWarnings("fallthrough")
|
||||||
public void postQueue(RenderQueue rq) {
|
public void postQueue(RenderQueue rq) {
|
||||||
GeometryList occluders = rq.getShadowQueueContent(ShadowMode.Cast);
|
GeometryList occluders = rq.getShadowQueueContent(ShadowMode.Cast);
|
||||||
if (occluders.size() == 0)
|
if (occluders.size() == 0) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
GeometryList receivers = rq.getShadowQueueContent(ShadowMode.Receive);
|
GeometryList receivers = rq.getShadowQueueContent(ShadowMode.Receive);
|
||||||
if (receivers.size() == 0)
|
if (receivers.size() == 0) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Camera viewCam = viewPort.getCamera();
|
Camera viewCam = viewPort.getCamera();
|
||||||
|
|
||||||
float zFar = zFarOverride;
|
float zFar = zFarOverride;
|
||||||
if (zFar == 0) {
|
if (zFar == 0) {
|
||||||
zFar=viewCam.getFrustumFar();
|
zFar = viewCam.getFrustumFar();
|
||||||
// zFar = PssmShadowUtil.computeZFar(occluders, receivers, viewCam);
|
// zFar = PssmShadowUtil.computeZFar(occluders, receivers, viewCam);
|
||||||
}
|
}
|
||||||
// System.out.println("Zfar : "+zFar);
|
// System.out.println("Zfar : "+zFar);
|
||||||
@ -322,7 +347,7 @@ public class PssmShadowRenderer implements SceneProcessor {
|
|||||||
PssmShadowUtil.updateFrustumSplits(splitsArray, viewCam.getFrustumNear(), zFar, lambda);
|
PssmShadowUtil.updateFrustumSplits(splitsArray, viewCam.getFrustumNear(), zFar, lambda);
|
||||||
|
|
||||||
|
|
||||||
switch (splitsArray.length){
|
switch (splitsArray.length) {
|
||||||
case 5:
|
case 5:
|
||||||
splits.a = splitsArray[4];
|
splits.a = splitsArray[4];
|
||||||
case 4:
|
case 4:
|
||||||
@ -345,25 +370,7 @@ public class PssmShadowRenderer implements SceneProcessor {
|
|||||||
ShadowUtil.updateFrustumPoints(viewCam, splitsArray[i], splitsArray[i + 1], 1.0f, points);
|
ShadowUtil.updateFrustumPoints(viewCam, splitsArray[i], splitsArray[i + 1], 1.0f, points);
|
||||||
|
|
||||||
//Updating shadow cam with curent split frustra
|
//Updating shadow cam with curent split frustra
|
||||||
// if(cropShadows){
|
|
||||||
ShadowUtil.updateShadowCamera(occluders, receivers, shadowCam, points, splitOccluders);
|
ShadowUtil.updateShadowCamera(occluders, receivers, shadowCam, points, splitOccluders);
|
||||||
// }else{
|
|
||||||
// ShadowUtil.updateShadowCamera(shadowCam, points);
|
|
||||||
// }
|
|
||||||
//displaying the current splitted frustrum and the associated cropped light frustrums in wireframe.
|
|
||||||
//only for debuging purpose
|
|
||||||
// if (debug) {
|
|
||||||
// viewPort.attachScene(createFrustum(points, i));
|
|
||||||
// Vector3f[] pts = new Vector3f[8];
|
|
||||||
// for (int j = 0; j < pts.length; j++) {
|
|
||||||
// pts[j] = new Vector3f();
|
|
||||||
// }
|
|
||||||
// ShadowUtil.updateFrustumPoints2(shadowCam, pts);
|
|
||||||
// viewPort.attachScene(createFrustum(pts, i));
|
|
||||||
// if (i == nbSplits-1) {
|
|
||||||
// debug = false;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
//saving light view projection matrix for this split
|
//saving light view projection matrix for this split
|
||||||
lightViewProjectionsMatrices[i] = shadowCam.getViewProjectionMatrix().clone();
|
lightViewProjectionsMatrices[i] = shadowCam.getViewProjectionMatrix().clone();
|
||||||
@ -374,8 +381,6 @@ public class PssmShadowRenderer implements SceneProcessor {
|
|||||||
|
|
||||||
// render shadow casters to shadow map
|
// render shadow casters to shadow map
|
||||||
viewPort.getQueue().renderShadowQueue(splitOccluders, renderManager, shadowCam, true);
|
viewPort.getQueue().renderShadowQueue(splitOccluders, renderManager, shadowCam, true);
|
||||||
//viewPort.getQueue().renderShadowQueue(ShadowMode.Cast, renderManager, shadowCam, i == nbSplits - 1);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
occluders.clear();
|
occluders.clear();
|
||||||
//restore setting for future rendering
|
//restore setting for future rendering
|
||||||
@ -387,7 +392,7 @@ public class PssmShadowRenderer implements SceneProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//debug only : displays depth shadow maps
|
//debug only : displays depth shadow maps
|
||||||
public void displayShadowMap(Renderer r) {
|
private void displayShadowMap(Renderer r) {
|
||||||
Camera cam = viewPort.getCamera();
|
Camera cam = viewPort.getCamera();
|
||||||
renderManager.setCamera(cam, true);
|
renderManager.setCamera(cam, true);
|
||||||
int h = cam.getHeight();
|
int h = cam.getHeight();
|
||||||
@ -421,9 +426,10 @@ public class PssmShadowRenderer implements SceneProcessor {
|
|||||||
renderManager.setCamera(cam, false);
|
renderManager.setCamera(cam, false);
|
||||||
|
|
||||||
}
|
}
|
||||||
if (debug)
|
if (debug) {
|
||||||
displayShadowMap(renderManager.getRenderer());
|
displayShadowMap(renderManager.getRenderer());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void preFrame(float tpf) {
|
public void preFrame(float tpf) {
|
||||||
}
|
}
|
||||||
@ -434,6 +440,11 @@ public class PssmShadowRenderer implements SceneProcessor {
|
|||||||
public void reshape(ViewPort vp, int w, int h) {
|
public void reshape(ViewPort vp, int w, int h) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the labda parameter<br>
|
||||||
|
* see {@link setLambda(float lambda)}
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public float getLambda() {
|
public float getLambda() {
|
||||||
return lambda;
|
return lambda;
|
||||||
}
|
}
|
||||||
@ -450,6 +461,11 @@ public class PssmShadowRenderer implements SceneProcessor {
|
|||||||
this.lambda = lambda;
|
this.lambda = lambda;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How far the shadows are rendered in the view
|
||||||
|
* see {@link setShadowZExtend(float zFar)}
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public float getShadowZExtend() {
|
public float getShadowZExtend() {
|
||||||
return zFarOverride;
|
return zFarOverride;
|
||||||
}
|
}
|
||||||
@ -463,6 +479,11 @@ public class PssmShadowRenderer implements SceneProcessor {
|
|||||||
this.zFarOverride = zFar;
|
this.zFarOverride = zFar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the shdaow intensity<br>
|
||||||
|
* see {@link setShadowIntensity(float shadowIntensity)}
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public float getShadowIntensity() {
|
public float getShadowIntensity() {
|
||||||
return shadowIntensity;
|
return shadowIntensity;
|
||||||
}
|
}
|
||||||
@ -479,14 +500,22 @@ public class PssmShadowRenderer implements SceneProcessor {
|
|||||||
postshadowMat.setFloat("ShadowIntensity", shadowIntensity);
|
postshadowMat.setFloat("ShadowIntensity", shadowIntensity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the edges thickness <br>
|
||||||
|
* see {@link setEdgesThickness(int edgesThickness)}
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public int getEdgesThickness() {
|
public int getEdgesThickness() {
|
||||||
return (int) (edgesThickness * 10);
|
return (int) (edgesThickness * 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stes the shadow edges thickness. default is 1, setting it to lower values can help to reduce the jagged effect of the shadow edges
|
||||||
|
* @param edgesThickness
|
||||||
|
*/
|
||||||
public void setEdgesThickness(int edgesThickness) {
|
public void setEdgesThickness(int edgesThickness) {
|
||||||
this.edgesThickness = Math.max(1, Math.min(edgesThickness,10));
|
this.edgesThickness = Math.max(1, Math.min(edgesThickness, 10));
|
||||||
this.edgesThickness *= 0.1f;
|
this.edgesThickness *= 0.1f;
|
||||||
postshadowMat.setFloat("PCFEdge", edgesThickness);
|
postshadowMat.setFloat("PCFEdge", edgesThickness);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +29,6 @@
|
|||||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.jme3.shadow;
|
package com.jme3.shadow;
|
||||||
|
|
||||||
import com.jme3.bounding.BoundingBox;
|
import com.jme3.bounding.BoundingBox;
|
||||||
@ -52,18 +51,6 @@ import static java.lang.Math.*;
|
|||||||
*/
|
*/
|
||||||
public final class PssmShadowUtil {
|
public final class PssmShadowUtil {
|
||||||
|
|
||||||
public static void main(String[] args){
|
|
||||||
float[] splits = new float[5];
|
|
||||||
float[] splitsShader = new float[3];
|
|
||||||
updateFrustumSplits(splits, 1, 1000, 0.5f);
|
|
||||||
System.arraycopy(splits, 1, splitsShader, 0, splitsShader.length);
|
|
||||||
System.out.println(Arrays.toString(splitsShader));
|
|
||||||
|
|
||||||
for (int i = 0; i < splits.length-1; i++){
|
|
||||||
System.out.println(splits[i] + " - " + splits[i+1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the frustum splits stores in <code>splits</code> using PSSM.
|
* Updates the frustum splits stores in <code>splits</code> using PSSM.
|
||||||
*/
|
*/
|
||||||
|
@ -29,7 +29,6 @@
|
|||||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.jme3.shadow;
|
package com.jme3.shadow;
|
||||||
|
|
||||||
import com.jme3.light.DirectionalLight;
|
import com.jme3.light.DirectionalLight;
|
||||||
@ -38,14 +37,19 @@ import com.jme3.light.PointLight;
|
|||||||
import com.jme3.math.Vector3f;
|
import com.jme3.math.Vector3f;
|
||||||
import com.jme3.renderer.Camera;
|
import com.jme3.renderer.Camera;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a camera according to a light
|
||||||
|
* Handy to compute projection matrix of a light
|
||||||
|
* @author Kirill Vainer
|
||||||
|
*/
|
||||||
public class ShadowCamera {
|
public class ShadowCamera {
|
||||||
|
|
||||||
private Vector3f[] points = new Vector3f[8];
|
private Vector3f[] points = new Vector3f[8];
|
||||||
private Light target;
|
private Light target;
|
||||||
|
|
||||||
public ShadowCamera(Light target){
|
public ShadowCamera(Light target) {
|
||||||
this.target = target;
|
this.target = target;
|
||||||
for (int i = 0; i < points.length; i++){
|
for (int i = 0; i < points.length; i++) {
|
||||||
points[i] = new Vector3f();
|
points[i] = new Vector3f();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -53,14 +57,14 @@ public class ShadowCamera {
|
|||||||
/**
|
/**
|
||||||
* Updates the camera view direction and position based on the light
|
* Updates the camera view direction and position based on the light
|
||||||
*/
|
*/
|
||||||
private void updateLightCamera(Camera lightCam){
|
public void updateLightCamera(Camera lightCam) {
|
||||||
if (target.getType() == Light.Type.Directional){
|
if (target.getType() == Light.Type.Directional) {
|
||||||
DirectionalLight dl = (DirectionalLight) target;
|
DirectionalLight dl = (DirectionalLight) target;
|
||||||
lightCam.setParallelProjection(true);
|
lightCam.setParallelProjection(true);
|
||||||
lightCam.setLocation(Vector3f.ZERO);
|
lightCam.setLocation(Vector3f.ZERO);
|
||||||
lightCam.lookAtDirection(dl.getDirection(), Vector3f.UNIT_Y );
|
lightCam.lookAtDirection(dl.getDirection(), Vector3f.UNIT_Y);
|
||||||
lightCam.setFrustum(-1, 1, -1, 1, 1, -1);
|
lightCam.setFrustum(-1, 1, -1, 1, 1, -1);
|
||||||
}else{
|
} else {
|
||||||
PointLight pl = (PointLight) target;
|
PointLight pl = (PointLight) target;
|
||||||
lightCam.setParallelProjection(false);
|
lightCam.setParallelProjection(false);
|
||||||
lightCam.setLocation(pl.getPosition());
|
lightCam.setLocation(pl.getPosition());
|
||||||
@ -68,5 +72,4 @@ public class ShadowCamera {
|
|||||||
lightCam.setFrustumPerspective(45, 1, 1, 300);
|
lightCam.setFrustumPerspective(45, 1, 1, 300);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -29,12 +29,10 @@
|
|||||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.jme3.shadow;
|
package com.jme3.shadow;
|
||||||
|
|
||||||
import com.jme3.bounding.BoundingBox;
|
import com.jme3.bounding.BoundingBox;
|
||||||
import com.jme3.bounding.BoundingVolume;
|
import com.jme3.bounding.BoundingVolume;
|
||||||
import com.jme3.math.FastMath;
|
|
||||||
import com.jme3.math.Matrix4f;
|
import com.jme3.math.Matrix4f;
|
||||||
import com.jme3.math.Transform;
|
import com.jme3.math.Transform;
|
||||||
import com.jme3.math.Vector2f;
|
import com.jme3.math.Vector2f;
|
||||||
@ -58,7 +56,12 @@ import static java.lang.Math.*;
|
|||||||
*/
|
*/
|
||||||
public class ShadowUtil {
|
public class ShadowUtil {
|
||||||
|
|
||||||
public static void updateFrustumPoints2(Camera viewCam, Vector3f[] points){
|
/**
|
||||||
|
* Updates a points arrays with the frustum corners of the provided camera.
|
||||||
|
* @param viewCam
|
||||||
|
* @param points
|
||||||
|
*/
|
||||||
|
public static void updateFrustumPoints2(Camera viewCam, Vector3f[] points) {
|
||||||
int w = viewCam.getWidth();
|
int w = viewCam.getWidth();
|
||||||
int h = viewCam.getHeight();
|
int h = viewCam.getHeight();
|
||||||
float n = viewCam.getFrustumNear();
|
float n = viewCam.getFrustumNear();
|
||||||
@ -160,6 +163,12 @@ public class ShadowUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute bounds of a geomList
|
||||||
|
* @param list
|
||||||
|
* @param transform
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public static BoundingBox computeUnionBound(GeometryList list, Transform transform) {
|
public static BoundingBox computeUnionBound(GeometryList list, Transform transform) {
|
||||||
BoundingBox bbox = new BoundingBox();
|
BoundingBox bbox = new BoundingBox();
|
||||||
for (int i = 0; i < list.size(); i++) {
|
for (int i = 0; i < list.size(); i++) {
|
||||||
@ -173,6 +182,12 @@ public class ShadowUtil {
|
|||||||
return bbox;
|
return bbox;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute bounds of a geomList
|
||||||
|
* @param list
|
||||||
|
* @param mat
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public static BoundingBox computeUnionBound(GeometryList list, Matrix4f mat) {
|
public static BoundingBox computeUnionBound(GeometryList list, Matrix4f mat) {
|
||||||
BoundingBox bbox = new BoundingBox();
|
BoundingBox bbox = new BoundingBox();
|
||||||
BoundingVolume store = null;
|
BoundingVolume store = null;
|
||||||
@ -187,6 +202,11 @@ public class ShadowUtil {
|
|||||||
return bbox;
|
return bbox;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes the bounds of multiple bounding volumes
|
||||||
|
* @param bv
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public static BoundingBox computeUnionBound(List<BoundingVolume> bv) {
|
public static BoundingBox computeUnionBound(List<BoundingVolume> bv) {
|
||||||
BoundingBox bbox = new BoundingBox();
|
BoundingBox bbox = new BoundingBox();
|
||||||
for (int i = 0; i < bv.size(); i++) {
|
for (int i = 0; i < bv.size(); i++) {
|
||||||
@ -196,6 +216,12 @@ public class ShadowUtil {
|
|||||||
return bbox;
|
return bbox;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute bounds from an array of points
|
||||||
|
* @param pts
|
||||||
|
* @param transform
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public static BoundingBox computeBoundForPoints(Vector3f[] pts, Transform transform) {
|
public static BoundingBox computeBoundForPoints(Vector3f[] pts, Transform transform) {
|
||||||
Vector3f min = new Vector3f(Vector3f.POSITIVE_INFINITY);
|
Vector3f min = new Vector3f(Vector3f.POSITIVE_INFINITY);
|
||||||
Vector3f max = new Vector3f(Vector3f.NEGATIVE_INFINITY);
|
Vector3f max = new Vector3f(Vector3f.NEGATIVE_INFINITY);
|
||||||
@ -211,6 +237,12 @@ public class ShadowUtil {
|
|||||||
return new BoundingBox(center, extent.x, extent.y, extent.z);
|
return new BoundingBox(center, extent.x, extent.y, extent.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute bounds from an array of points
|
||||||
|
* @param pts
|
||||||
|
* @param mat
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public static BoundingBox computeBoundForPoints(Vector3f[] pts, Matrix4f mat) {
|
public static BoundingBox computeBoundForPoints(Vector3f[] pts, Matrix4f mat) {
|
||||||
Vector3f min = new Vector3f(Vector3f.POSITIVE_INFINITY);
|
Vector3f min = new Vector3f(Vector3f.POSITIVE_INFINITY);
|
||||||
Vector3f max = new Vector3f(Vector3f.NEGATIVE_INFINITY);
|
Vector3f max = new Vector3f(Vector3f.NEGATIVE_INFINITY);
|
||||||
@ -228,16 +260,10 @@ public class ShadowUtil {
|
|||||||
max.maxLocal(temp);
|
max.maxLocal(temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
// min.x = FastMath.clamp(min.x, -1f, 1f);
|
|
||||||
// max.y = FastMath.clamp(max.y, -1f, 1f);
|
|
||||||
// min.x = FastMath.clamp(min.x, -1f, 1f);
|
|
||||||
// max.y = FastMath.clamp(max.y, -1f, 1f);
|
|
||||||
|
|
||||||
Vector3f center = min.add(max).multLocal(0.5f);
|
Vector3f center = min.add(max).multLocal(0.5f);
|
||||||
Vector3f extent = max.subtract(min).multLocal(0.5f);
|
Vector3f extent = max.subtract(min).multLocal(0.5f);
|
||||||
//Nehon 08/18/2010 : Added an offset to the extend to avoid banding artifacts when the frustum are aligned
|
//Nehon 08/18/2010 : Added an offset to the extend to avoid banding artifacts when the frustum are aligned
|
||||||
return new BoundingBox(center, extent.x + 2.0f, extent.y + 2.0f, extent.z +2.5f);
|
return new BoundingBox(center, extent.x + 2.0f, extent.y + 2.0f, extent.z + 2.5f);
|
||||||
//return new BoundingBox(center, extent.x, extent.y, extent.z);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -248,7 +274,7 @@ public class ShadowUtil {
|
|||||||
* @param lightCam
|
* @param lightCam
|
||||||
* @param points
|
* @param points
|
||||||
*/
|
*/
|
||||||
public static void updateShadowCamera(Camera shadowCam, Vector3f[] points){
|
public static void updateShadowCamera(Camera shadowCam, Vector3f[] points) {
|
||||||
boolean ortho = shadowCam.isParallelProjection();
|
boolean ortho = shadowCam.isParallelProjection();
|
||||||
shadowCam.setProjectionMatrix(null);
|
shadowCam.setProjectionMatrix(null);
|
||||||
|
|
||||||
@ -304,7 +330,7 @@ public class ShadowUtil {
|
|||||||
public static void updateShadowCamera(GeometryList occluders,
|
public static void updateShadowCamera(GeometryList occluders,
|
||||||
GeometryList receivers,
|
GeometryList receivers,
|
||||||
Camera shadowCam,
|
Camera shadowCam,
|
||||||
Vector3f[] points){
|
Vector3f[] points) {
|
||||||
updateShadowCamera(occluders, receivers, shadowCam, points, null);
|
updateShadowCamera(occluders, receivers, shadowCam, points, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -321,48 +347,45 @@ public class ShadowUtil {
|
|||||||
GeometryList receivers,
|
GeometryList receivers,
|
||||||
Camera shadowCam,
|
Camera shadowCam,
|
||||||
Vector3f[] points,
|
Vector3f[] points,
|
||||||
GeometryList splitOccluders){
|
GeometryList splitOccluders) {
|
||||||
|
|
||||||
boolean ortho = shadowCam.isParallelProjection();
|
boolean ortho = shadowCam.isParallelProjection();
|
||||||
|
|
||||||
shadowCam.setProjectionMatrix(null);
|
shadowCam.setProjectionMatrix(null);
|
||||||
|
|
||||||
if (ortho){
|
if (ortho) {
|
||||||
shadowCam.setFrustum(-1, 1, -1, 1, 1, -1);
|
shadowCam.setFrustum(-1, 1, -1, 1, 1, -1);
|
||||||
}else{
|
} else {
|
||||||
shadowCam.setFrustumPerspective(45, 1, 1, 150);
|
shadowCam.setFrustumPerspective(45, 1, 1, 150);
|
||||||
}
|
}
|
||||||
|
|
||||||
// create transform to rotate points to viewspace
|
// create transform to rotate points to viewspace
|
||||||
//Transform t = new Transform(shadowCam.getRotation());
|
|
||||||
Matrix4f viewProjMatrix = shadowCam.getViewProjectionMatrix();
|
Matrix4f viewProjMatrix = shadowCam.getViewProjectionMatrix();
|
||||||
|
|
||||||
// BoundingBox casterBB = computeUnionBound(occluders, viewProjMatrix);
|
|
||||||
// BoundingBox receiverBB = computeUnionBound(receivers, viewProjMatrix);
|
|
||||||
BoundingBox splitBB = computeBoundForPoints(points, viewProjMatrix);
|
BoundingBox splitBB = computeBoundForPoints(points, viewProjMatrix);
|
||||||
|
|
||||||
ArrayList<BoundingVolume> visRecvList = new ArrayList<BoundingVolume>();
|
ArrayList<BoundingVolume> visRecvList = new ArrayList<BoundingVolume>();
|
||||||
for (int i = 0; i < receivers.size(); i++){
|
for (int i = 0; i < receivers.size(); i++) {
|
||||||
// convert bounding box to light's viewproj space
|
// convert bounding box to light's viewproj space
|
||||||
Geometry receiver = receivers.get(i);
|
Geometry receiver = receivers.get(i);
|
||||||
BoundingVolume bv = receiver.getWorldBound();
|
BoundingVolume bv = receiver.getWorldBound();
|
||||||
BoundingVolume recvBox = bv.transform(viewProjMatrix, null);
|
BoundingVolume recvBox = bv.transform(viewProjMatrix, null);
|
||||||
|
|
||||||
if (splitBB.intersects(recvBox)){
|
if (splitBB.intersects(recvBox)) {
|
||||||
visRecvList.add(recvBox);
|
visRecvList.add(recvBox);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayList<BoundingVolume> visOccList = new ArrayList<BoundingVolume>();
|
ArrayList<BoundingVolume> visOccList = new ArrayList<BoundingVolume>();
|
||||||
for (int i = 0; i < occluders.size(); i++){
|
for (int i = 0; i < occluders.size(); i++) {
|
||||||
// convert bounding box to light's viewproj space
|
// convert bounding box to light's viewproj space
|
||||||
Geometry occluder = occluders.get(i);
|
Geometry occluder = occluders.get(i);
|
||||||
BoundingVolume bv = occluder.getWorldBound();
|
BoundingVolume bv = occluder.getWorldBound();
|
||||||
BoundingVolume occBox = bv.transform(viewProjMatrix, null);
|
BoundingVolume occBox = bv.transform(viewProjMatrix, null);
|
||||||
|
|
||||||
boolean intersects = splitBB.intersects(occBox);
|
boolean intersects = splitBB.intersects(occBox);
|
||||||
if (!intersects && occBox instanceof BoundingBox){
|
if (!intersects && occBox instanceof BoundingBox) {
|
||||||
BoundingBox occBB = (BoundingBox)occBox;
|
BoundingBox occBB = (BoundingBox) occBox;
|
||||||
//Kirill 01/10/2011
|
//Kirill 01/10/2011
|
||||||
// Extend the occluder further into the frustum
|
// Extend the occluder further into the frustum
|
||||||
// This fixes shadow dissapearing issues when
|
// This fixes shadow dissapearing issues when
|
||||||
@ -371,20 +394,20 @@ public class ShadowUtil {
|
|||||||
// The number is in world units
|
// The number is in world units
|
||||||
occBB.setZExtent(occBB.getZExtent() + 50);
|
occBB.setZExtent(occBB.getZExtent() + 50);
|
||||||
occBB.setCenter(occBB.getCenter().addLocal(0, 0, 25));
|
occBB.setCenter(occBB.getCenter().addLocal(0, 0, 25));
|
||||||
if (splitBB.intersects(occBB)){
|
if (splitBB.intersects(occBB)) {
|
||||||
// To prevent extending the depth range too much
|
// To prevent extending the depth range too much
|
||||||
// We return the bound to its former shape
|
// We return the bound to its former shape
|
||||||
// Before adding it
|
// Before adding it
|
||||||
occBB.setZExtent(occBB.getZExtent() - 50);
|
occBB.setZExtent(occBB.getZExtent() - 50);
|
||||||
occBB.setCenter(occBB.getCenter().subtractLocal(0, 0, 25));
|
occBB.setCenter(occBB.getCenter().subtractLocal(0, 0, 25));
|
||||||
visOccList.add(occBox);
|
visOccList.add(occBox);
|
||||||
if(splitOccluders != null){
|
if (splitOccluders != null) {
|
||||||
splitOccluders.add(occluder);
|
splitOccluders.add(occluder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}else if (intersects){
|
} else if (intersects) {
|
||||||
visOccList.add(occBox);
|
visOccList.add(occBox);
|
||||||
if(splitOccluders != null){
|
if (splitOccluders != null) {
|
||||||
splitOccluders.add(occluder);
|
splitOccluders.add(occluder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -409,15 +432,11 @@ public class ShadowUtil {
|
|||||||
Vector3f splitMin = splitBB.getMin(null);
|
Vector3f splitMin = splitBB.getMin(null);
|
||||||
Vector3f splitMax = splitBB.getMax(null);
|
Vector3f splitMax = splitBB.getMax(null);
|
||||||
|
|
||||||
// actualMin.x = FastMath.clamp(actualMin.x, -1, 1);
|
|
||||||
// actualMin.y = FastMath.clamp(actualMin.y, -1, 1);
|
|
||||||
// actualMax.x = FastMath.clamp(actualMax.x, -1, 1);
|
|
||||||
// actualMax.y = FastMath.clamp(actualMax.y, -1, 1);
|
|
||||||
// float far = actualMin.z + actualMax.z * 4 + 1.0f + 1.5f;
|
|
||||||
splitMin.z = 0;
|
splitMin.z = 0;
|
||||||
|
|
||||||
if (!ortho)
|
if (!ortho) {
|
||||||
shadowCam.setFrustumPerspective(45, 1, 1, splitMax.z);
|
shadowCam.setFrustumPerspective(45, 1, 1, splitMax.z);
|
||||||
|
}
|
||||||
|
|
||||||
Matrix4f projMatrix = shadowCam.getProjectionMatrix();
|
Matrix4f projMatrix = shadowCam.getProjectionMatrix();
|
||||||
|
|
||||||
@ -434,11 +453,6 @@ public class ShadowUtil {
|
|||||||
cropMin.z = min(casterMin.z, splitMin.z);
|
cropMin.z = min(casterMin.z, splitMin.z);
|
||||||
cropMax.z = min(receiverMax.z, splitMax.z);
|
cropMax.z = min(receiverMax.z, splitMax.z);
|
||||||
|
|
||||||
// cropMin.set(splitMin);
|
|
||||||
// cropMax.set(splitMax);
|
|
||||||
|
|
||||||
// cropMin.z = Math.min(cropMin.z, cropMax.z - cropMin.z - 1000);
|
|
||||||
// cropMin.z = Math.max(10f, cropMin.z);
|
|
||||||
|
|
||||||
// Create the crop matrix.
|
// Create the crop matrix.
|
||||||
float scaleX, scaleY, scaleZ;
|
float scaleX, scaleY, scaleZ;
|
||||||
@ -453,41 +467,19 @@ public class ShadowUtil {
|
|||||||
scaleZ = 1.0f / (cropMax.z - cropMin.z);
|
scaleZ = 1.0f / (cropMax.z - cropMin.z);
|
||||||
offsetZ = -cropMin.z * scaleZ;
|
offsetZ = -cropMin.z * scaleZ;
|
||||||
|
|
||||||
// scaleZ = 2.0f / (cropMax.z - cropMin.z);
|
|
||||||
// offsetZ = -0.5f * (cropMax.z + cropMin.z) * scaleZ;
|
|
||||||
|
|
||||||
Matrix4f cropMatrix = new Matrix4f(scaleX, 0f, 0f, offsetX,
|
Matrix4f cropMatrix = new Matrix4f(scaleX, 0f, 0f, offsetX,
|
||||||
0f, scaleY, 0f, offsetY,
|
0f, scaleY, 0f, offsetY,
|
||||||
0f, 0f, scaleZ, offsetZ,
|
0f, 0f, scaleZ, offsetZ,
|
||||||
0f, 0f, 0f, 1f);
|
0f, 0f, 0f, 1f);
|
||||||
|
|
||||||
// cropMatrix.transposeLocal();
|
|
||||||
// Matrix4f cropMatrix = new Matrix4f();
|
|
||||||
// cropMatrix.setScale(new Vector3f(scaleX, scaleY, 1f));
|
|
||||||
// cropMatrix.setTranslation(offsetX, offsetY, 0);
|
|
||||||
|
|
||||||
Matrix4f result = new Matrix4f();
|
Matrix4f result = new Matrix4f();
|
||||||
result.set(cropMatrix);
|
result.set(cropMatrix);
|
||||||
result.multLocal(projMatrix);
|
result.multLocal(projMatrix);
|
||||||
// result.set(projMatrix);
|
|
||||||
// result.multLocal(cropMatrix);
|
|
||||||
shadowCam.setProjectionMatrix(result);
|
shadowCam.setProjectionMatrix(result);
|
||||||
|
|
||||||
// shadowCam.setFrustum(cropMin.z, cropMax.z, // near, far
|
|
||||||
// cropMin.x, cropMax.x, // left, right
|
|
||||||
// cropMax.y, cropMin.y); // top, bottom
|
|
||||||
|
|
||||||
// compute size and center of final frustum
|
|
||||||
//float sizeX = (max.x - min.x) / 2f;
|
|
||||||
//float sizeY = (max.y - min.y) / 2f;
|
|
||||||
//float offsetX = (max.x + min.x) / -2f;
|
|
||||||
//float offsetY = (max.y + min.y) / -2f;
|
|
||||||
|
|
||||||
// compute center for frustum
|
|
||||||
//temp.set(offsetX, offsetY, 0);
|
|
||||||
//invRot.mult(temp, temp);
|
|
||||||
|
|
||||||
//shadowCam.setLocation(temp);
|
|
||||||
//shadowCam.setFrustum(min.z, max.z, -sizeX, sizeX, sizeY, -sizeY);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user