TranslucentBucket :

- Added a translucent bucket that is rendered after the processors (usefull for shadows)
- For filters, rendering this bucket is a bit particular, so you can use the TranslucentBucketFilter to render the translucent bucket in the middle of the fillter stack (doc is comming up in the wiki)
- renamed Filter's preRender method to postQueue for consistancy with processors
- added translucent objects in TestPostWater, added a fire (particles) in test transparent shadows

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7540 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
rem..om 14 years ago
parent 29a4e7e01c
commit 2d4896942d
  1. 3
      engine/src/android/com/jme3/renderer/android/OGLESShaderRenderer.java
  2. 5
      engine/src/core-data/Common/MatDefs/Post/Post.vert
  3. 22
      engine/src/core/com/jme3/post/Filter.java
  4. 48
      engine/src/core/com/jme3/post/FilterPostProcessor.java
  5. 21
      engine/src/core/com/jme3/renderer/RenderManager.java
  6. 8
      engine/src/core/com/jme3/renderer/Renderer.java
  7. 90
      engine/src/core/com/jme3/renderer/queue/RenderQueue.java
  8. 3
      engine/src/core/com/jme3/system/NullRenderer.java
  9. 2
      engine/src/desktop-fx/com/jme3/post/filters/BloomFilter.java
  10. 2
      engine/src/desktop-fx/com/jme3/post/filters/CartoonEdgeFilter.java
  11. 4
      engine/src/desktop-fx/com/jme3/post/filters/ColorOverlayFilter.java
  12. 4
      engine/src/desktop-fx/com/jme3/post/filters/CrossHatchFilter.java
  13. 4
      engine/src/desktop-fx/com/jme3/post/filters/DepthOfFieldFilter.java
  14. 3
      engine/src/desktop-fx/com/jme3/post/filters/FadeFilter.java
  15. 3
      engine/src/desktop-fx/com/jme3/post/filters/FogFilter.java
  16. 2
      engine/src/desktop-fx/com/jme3/post/filters/LightScatteringFilter.java
  17. 3
      engine/src/desktop-fx/com/jme3/post/filters/PosterizationFilter.java
  18. 3
      engine/src/desktop-fx/com/jme3/post/filters/RadialBlurFilter.java
  19. 76
      engine/src/desktop-fx/com/jme3/post/filters/TranslucentBucketFilter.java
  20. 12
      engine/src/desktop-fx/com/jme3/post/ssao/SSAOFilter.java
  21. 10
      engine/src/desktop-fx/com/jme3/water/WaterFilter.java
  22. 176
      engine/src/lwjgl-ogl/com/jme3/renderer/lwjgl/LwjglGL1Renderer.java
  23. 195
      engine/src/lwjgl-ogl/com/jme3/renderer/lwjgl/LwjglRenderer.java
  24. 27
      engine/src/test/jme3test/light/TestTransparentShadow.java
  25. 29
      engine/src/test/jme3test/post/TestMultiViewsFilters.java
  26. 112
      engine/src/test/jme3test/water/TestPostWater.java

@ -1259,6 +1259,9 @@ public class OGLESShaderRenderer implements Renderer {
public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst){ public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst){
logger.warning("copyFrameBuffer is not supported."); logger.warning("copyFrameBuffer is not supported.");
} }
public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst, boolean copyDepth){
logger.warning("copyFrameBuffer is not supported.");
}
/* /*
public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst){ public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst){
if (GLContext.getCapabilities().GL_EXT_framebuffer_blit){ if (GLContext.getCapabilities().GL_EXT_framebuffer_blit){

@ -4,8 +4,7 @@ attribute vec4 inPosition;
attribute vec2 inTexCoord; attribute vec2 inTexCoord;
varying vec2 texCoord; varying vec2 texCoord;
void main() { void main() {
vec2 pos = (g_WorldViewProjectionMatrix * inPosition).xy; gl_Position = inPosition * 2.0 - 1.0; //vec4(pos, 0.0, 1.0);
gl_Position = vec4(pos, 0.0, 1.0);
texCoord = inTexCoord; texCoord = inTexCoord;
} }

@ -80,12 +80,12 @@ public abstract class Filter implements Savable {
Collection<Caps> caps = renderer.getCaps(); Collection<Caps> caps = renderer.getCaps();
if (numSamples > 1 && caps.contains(Caps.FrameBufferMultisample) && caps.contains(Caps.OpenGL31)) { if (numSamples > 1 && caps.contains(Caps.FrameBufferMultisample) && caps.contains(Caps.OpenGL31)) {
renderFrameBuffer = new FrameBuffer(width, height, numSamples); renderFrameBuffer = new FrameBuffer(width, height, numSamples);
renderedTexture = new Texture2D(width, height, numSamples, textureFormat); renderedTexture = new Texture2D(width, height, numSamples, textureFormat);
// depthTexture = new Texture2D(width, height, numSamples, depthBufferFormat); // depthTexture = new Texture2D(width, height, numSamples, depthBufferFormat);
} else { } else {
renderFrameBuffer = new FrameBuffer(width, height, 1); renderFrameBuffer = new FrameBuffer(width, height, 1);
renderedTexture = new Texture2D(width, height, textureFormat); renderedTexture = new Texture2D(width, height, textureFormat);
// depthTexture = new Texture2D(width, height, depthBufferFormat); // depthTexture = new Texture2D(width, height, depthBufferFormat);
} }
renderFrameBuffer.setColorTexture(renderedTexture); renderFrameBuffer.setColorTexture(renderedTexture);
@ -200,7 +200,7 @@ public abstract class Filter implements Savable {
* @param renderManager * @param renderManager
* @param viewPort * @param viewPort
*/ */
public void preRender(RenderManager renderManager, ViewPort viewPort) { public void postQueue(RenderManager renderManager, ViewPort viewPort) {
} }
/** /**
@ -211,6 +211,14 @@ public abstract class Filter implements Savable {
public void preFrame(float tpf) { public void preFrame(float tpf) {
} }
/**
* Override this method if you want to make a pass just after the frame has been rendered and just before the filter rendering
* @param renderManager
* @param viewPort
*/
public void postFrame(RenderManager renderManager, ViewPort viewPort, FrameBuffer prevFilterBuffer, FrameBuffer sceneBuffer) {
}
/** /**
* Override this method if you want to save extra properties when the filter is saved else only basic properties of the filter will be saved * Override this method if you want to save extra properties when the filter is saved else only basic properties of the filter will be saved
* This method should always begin by super.write(ex); * This method should always begin by super.write(ex);
@ -267,6 +275,14 @@ public abstract class Filter implements Savable {
public boolean isRequiresDepthTexture() { public boolean isRequiresDepthTexture() {
return false; return false;
} }
/**
* Override this method and return false if your Filter does not need the scene texture
* @return
*/
public boolean isRequiresSceneTexture() {
return true;
}
public List<Pass> getPostRenderPasses() { public List<Pass> getPostRenderPasses() {
return postRenderPasses; return postRenderPasses;

@ -40,6 +40,7 @@ import com.jme3.export.InputCapsule;
import com.jme3.export.OutputCapsule; import com.jme3.export.OutputCapsule;
import com.jme3.export.Savable; import com.jme3.export.Savable;
import com.jme3.material.Material; import com.jme3.material.Material;
import com.jme3.post.filters.TranslucentBucketFilter;
import com.jme3.renderer.Camera; import com.jme3.renderer.Camera;
import com.jme3.renderer.Caps; import com.jme3.renderer.Caps;
import com.jme3.renderer.RenderManager; import com.jme3.renderer.RenderManager;
@ -80,6 +81,10 @@ public class FilterPostProcessor implements SceneProcessor, Savable {
private int originalHeight; private int originalHeight;
private int lastFilterIndex = -1; private int lastFilterIndex = -1;
private boolean cameraInit = false; private boolean cameraInit = false;
// private boolean handleTranslucentBucket = false;
// private FrameBuffer transFrameBuffer;
// private Material transMaterial;
// private boolean isTransparencyRendered=false;
/** /**
* Create a FilterProcessor constructor * Create a FilterProcessor constructor
@ -159,8 +164,9 @@ public class FilterPostProcessor implements SceneProcessor, Savable {
filterCam.resize(buff.getWidth(), buff.getHeight(), true); filterCam.resize(buff.getWidth(), buff.getHeight(), true);
fsQuad.setPosition(0, 0); fsQuad.setPosition(0, 0);
} }
if (mat.getAdditionalRenderState().isDepthWrite()) {
mat.getAdditionalRenderState().setDepthWrite(false);
}
fsQuad.setMaterial(mat); fsQuad.setMaterial(mat);
fsQuad.updateGeometricState(); fsQuad.updateGeometricState();
@ -179,14 +185,16 @@ public class FilterPostProcessor implements SceneProcessor, Savable {
for (Iterator<Filter> it = filters.iterator(); it.hasNext();) { for (Iterator<Filter> it = filters.iterator(); it.hasNext();) {
Filter filter = it.next(); Filter filter = it.next();
if (filter.isEnabled()) { if (filter.isEnabled()) {
filter.preRender(renderManager, viewPort); filter.postQueue(renderManager, viewPort);
} }
} }
} }
Picture pic = new Picture("debug");
public void renderFilterChain(Renderer r) { public void renderFilterChain(Renderer r, FrameBuffer sceneFb) {
Texture2D tex = filterTexture; Texture2D tex = filterTexture;
FrameBuffer buff = null;
boolean msDepth = depthTexture != null && depthTexture.getImage().getMultiSamples() > 1; boolean msDepth = depthTexture != null && depthTexture.getImage().getMultiSamples() > 1;
for (int i = 0; i < filters.size(); i++) { for (int i = 0; i < filters.size(); i++) {
Filter filter = filters.get(i); Filter filter = filters.get(i);
@ -216,22 +224,27 @@ public class FilterPostProcessor implements SceneProcessor, Savable {
} }
} }
filter.postFrame(renderManager, viewPort, buff, sceneFb);
Material mat = filter.getMaterial(); Material mat = filter.getMaterial();
if (msDepth && filter.isRequiresDepthTexture()) { if (msDepth && filter.isRequiresDepthTexture()) {
mat.setInt("NumSamplesDepth", depthTexture.getImage().getMultiSamples()); mat.setInt("NumSamplesDepth", depthTexture.getImage().getMultiSamples());
} }
mat.setTexture("Texture", tex); if (filter.isRequiresSceneTexture()) {
if (tex.getImage().getMultiSamples() > 1) { mat.setTexture("Texture", tex);
mat.setInt("NumSamples", tex.getImage().getMultiSamples()); if (tex.getImage().getMultiSamples() > 1) {
} else { mat.setInt("NumSamples", tex.getImage().getMultiSamples());
mat.clearParam("NumSamples"); } else {
mat.clearParam("NumSamples");
}
} }
FrameBuffer buff = outputBuffer; buff = outputBuffer;
if (i != lastFilterIndex) { if (i != lastFilterIndex) {
buff = filter.getRenderFrameBuffer(); buff = filter.getRenderFrameBuffer();
tex = filter.getRenderedTexture(); tex = filter.getRenderedTexture();
} }
renderProcessing(r, buff, mat); renderProcessing(r, buff, mat);
} }
@ -240,11 +253,13 @@ public class FilterPostProcessor implements SceneProcessor, Savable {
public void postFrame(FrameBuffer out) { public void postFrame(FrameBuffer out) {
FrameBuffer sceneBuffer = renderFrameBuffer;
if (renderFrameBufferMS != null && !renderer.getCaps().contains(Caps.OpenGL31)) { if (renderFrameBufferMS != null && !renderer.getCaps().contains(Caps.OpenGL31)) {
renderer.copyFrameBuffer(renderFrameBufferMS, renderFrameBuffer); renderer.copyFrameBuffer(renderFrameBufferMS, renderFrameBuffer);
} else if (renderFrameBufferMS != null) {
sceneBuffer = renderFrameBufferMS;
} }
renderFilterChain(renderer); renderFilterChain(renderer, sceneBuffer);
} }
@ -336,7 +351,6 @@ public class FilterPostProcessor implements SceneProcessor, Savable {
renderFrameBufferMS.setColorTexture(msColor); renderFrameBufferMS.setColorTexture(msColor);
filterTexture = msColor; filterTexture = msColor;
depthTexture = msDepth; depthTexture = msDepth;
// samplePositions = ((LwjglRenderer) renderer).getFrameBufferSamplePositions(renderFrameBufferMS);
} else { } else {
renderFrameBufferMS.setDepthBuffer(Format.Depth); renderFrameBufferMS.setDepthBuffer(Format.Depth);
renderFrameBufferMS.setColorBuffer(Format.RGBA8); renderFrameBufferMS.setColorBuffer(Format.RGBA8);
@ -420,4 +434,12 @@ public class FilterPostProcessor implements SceneProcessor, Savable {
numSamples = ic.readInt("numSamples", 0); numSamples = ic.readInt("numSamples", 0);
filters = ic.readSavableArrayList("filters", null); filters = ic.readSavableArrayList("filters", null);
} }
public Texture2D getDepthTexture() {
return depthTexture;
}
public Texture2D getFilterTexture() {
return filterTexture;
}
} }

@ -94,6 +94,7 @@ public class RenderManager {
camLoc = new Vector3f(); camLoc = new Vector3f();
//temp technique //temp technique
private String tmpTech; private String tmpTech;
private boolean handleTranlucentBucket = true;
/** /**
* Create a high-level rendering interface over the * Create a high-level rendering interface over the
@ -518,7 +519,7 @@ public class RenderManager {
//restoring cam state before proceeding children recusively //restoring cam state before proceeding children recusively
vp.getCamera().setPlaneState(camState); vp.getCamera().setPlaneState(camState);
renderScene(children.get(i), vp); renderScene(children.get(i), vp);
} }
} else if (scene instanceof Geometry) { } else if (scene instanceof Geometry) {
@ -607,6 +608,13 @@ public class RenderManager {
} }
} }
public void renderTranslucentQueue(ViewPort vp) {
RenderQueue rq = vp.getQueue();
if (!rq.isQueueEmpty(Bucket.Translucent) && handleTranlucentBucket) {
rq.renderQueue(Bucket.Translucent, this, vp.getCamera(), true);
}
}
private void setViewPort(Camera cam) { private void setViewPort(Camera cam) {
// this will make sure to update viewport only if needed // this will make sure to update viewport only if needed
if (cam != prevCam || cam.isViewportChanged()) { if (cam != prevCam || cam.isViewportChanged()) {
@ -729,7 +737,8 @@ public class RenderManager {
proc.postFrame(vp.getOutputFrameBuffer()); proc.postFrame(vp.getOutputFrameBuffer());
} }
} }
//renders the translucent objects queue after processors have been rendered
renderTranslucentQueue(vp);
// clear any remaining spatials that were not rendered. // clear any remaining spatials that were not rendered.
clearQueue(vp); clearQueue(vp);
} }
@ -768,4 +777,12 @@ public class RenderManager {
public void setAlphaToCoverage(boolean value) { public void setAlphaToCoverage(boolean value) {
renderer.setAlphaToCoverage(value); renderer.setAlphaToCoverage(value);
} }
public boolean isHandleTranslucentBucket() {
return handleTranlucentBucket;
}
public void setHandleTranslucentBucket(boolean handleTranslucentBucket) {
this.handleTranlucentBucket = handleTranslucentBucket;
}
} }

@ -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.renderer; package com.jme3.renderer;
import com.jme3.light.LightList; import com.jme3.light.LightList;
@ -138,6 +137,12 @@ public interface Renderer {
*/ */
public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst); public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst);
/**
* Copies contents from src to dst, scaling if neccessary.
* set copyDepth to false ton ly copy the color
*/
public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst, boolean copyDepth);
/** /**
* Sets the framebuffer that will be drawn to. * Sets the framebuffer that will be drawn to.
*/ */
@ -212,5 +217,4 @@ public interface Renderer {
* @param value * @param value
*/ */
public void setAlphaToCoverage(boolean value); public void setAlphaToCoverage(boolean value);
} }

@ -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.renderer.queue; package com.jme3.renderer.queue;
import com.jme3.renderer.Camera; import com.jme3.renderer.Camera;
@ -42,28 +41,33 @@ public class RenderQueue {
private GeometryList opaqueList; private GeometryList opaqueList;
private GeometryList guiList; private GeometryList guiList;
private GeometryList transparentList; private GeometryList transparentList;
private GeometryList translucentList;
private GeometryList skyList; private GeometryList skyList;
private GeometryList shadowRecv; private GeometryList shadowRecv;
private GeometryList shadowCast; private GeometryList shadowCast;
public RenderQueue(){ public RenderQueue() {
this.opaqueList = new GeometryList(new OpaqueComparator()); this.opaqueList = new GeometryList(new OpaqueComparator());
this.guiList = new GeometryList(new GuiComparator()); this.guiList = new GeometryList(new GuiComparator());
this.transparentList = new GeometryList(new TransparentComparator()); this.transparentList = new GeometryList(new TransparentComparator());
this.translucentList = new GeometryList(new TransparentComparator());
this.skyList = new GeometryList(new NullComparator()); this.skyList = new GeometryList(new NullComparator());
this.shadowRecv = new GeometryList(new OpaqueComparator()); this.shadowRecv = new GeometryList(new OpaqueComparator());
this.shadowCast = new GeometryList(new OpaqueComparator()); this.shadowCast = new GeometryList(new OpaqueComparator());
} }
public enum Bucket { public enum Bucket {
Gui, Gui,
Opaque, Opaque,
Sky, Sky,
Transparent, Transparent,
Translucent,
Inherit, Inherit,
} }
public enum ShadowMode { public enum ShadowMode {
Off, Off,
Cast, Cast,
Receive, Receive,
@ -89,6 +93,8 @@ public class RenderQueue {
* by material first and front to back within the same material. * by material first and front to back within the same material.
* <li>Bucket.Transparent: {@link com.jme3.renderer.queue.TransparentComparator} which * <li>Bucket.Transparent: {@link com.jme3.renderer.queue.TransparentComparator} which
* sorts purely back to front by leading bounding edge with no material sort. * sorts purely back to front by leading bounding edge with no material sort.
* <li>Bucket.Translucent: {@link com.jme3.renderer.queue.TransparentComparator} which
* sorts purely back to front by leading bounding edge with no material sort. this bucket is rendered after post processors.
* <li>Bucket.Sky: {@link com.jme3.renderer.queue.NullComparator} which does no sorting * <li>Bucket.Sky: {@link com.jme3.renderer.queue.NullComparator} which does no sorting
* at all. * at all.
* <li>Bucket.Gui: {@link com.jme3.renderer.queue.GuiComparator} sorts geometries back to * <li>Bucket.Gui: {@link com.jme3.renderer.queue.GuiComparator} sorts geometries back to
@ -108,15 +114,20 @@ public class RenderQueue {
case Transparent: case Transparent:
transparentList = new GeometryList(c); transparentList = new GeometryList(c);
break; break;
case Translucent:
translucentList = new GeometryList(c);
break;
default: default:
throw new UnsupportedOperationException("Unknown bucket type: "+bucket); throw new UnsupportedOperationException("Unknown bucket type: " + bucket);
} }
} }
public void addToShadowQueue(Geometry g, ShadowMode shadBucket){ public void addToShadowQueue(Geometry g, ShadowMode shadBucket) {
switch (shadBucket){ switch (shadBucket) {
case Inherit: break; case Inherit:
case Off: break; break;
case Off:
break;
case Cast: case Cast:
shadowCast.add(g); shadowCast.add(g);
break; break;
@ -128,7 +139,7 @@ public class RenderQueue {
shadowRecv.add(g); shadowRecv.add(g);
break; break;
default: default:
throw new UnsupportedOperationException("Unrecognized shadow bucket type: "+shadBucket); throw new UnsupportedOperationException("Unrecognized shadow bucket type: " + shadBucket);
} }
} }
@ -146,13 +157,16 @@ public class RenderQueue {
case Transparent: case Transparent:
transparentList.add(g); transparentList.add(g);
break; break;
case Translucent:
translucentList.add(g);
break;
default: default:
throw new UnsupportedOperationException("Unknown bucket type: "+bucket); throw new UnsupportedOperationException("Unknown bucket type: " + bucket);
} }
} }
public GeometryList getShadowQueueContent(ShadowMode shadBucket){ public GeometryList getShadowQueueContent(ShadowMode shadBucket) {
switch (shadBucket){ switch (shadBucket) {
case Cast: case Cast:
return shadowCast; return shadowCast;
case Receive: case Receive:
@ -162,30 +176,32 @@ public class RenderQueue {
} }
} }
private void renderGeometryList(GeometryList list, RenderManager rm, Camera cam, boolean clear){ private void renderGeometryList(GeometryList list, RenderManager rm, Camera cam, boolean clear) {
list.setCamera(cam); // select camera for sorting list.setCamera(cam); // select camera for sorting
list.sort(); list.sort();
for (int i = 0; i < list.size(); i++){ for (int i = 0; i < list.size(); i++) {
Spatial obj = list.get(i); Spatial obj = list.get(i);
assert obj != null; assert obj != null;
if (obj instanceof Geometry){ if (obj instanceof Geometry) {
Geometry g = (Geometry) obj; Geometry g = (Geometry) obj;
rm.renderGeometry(g); rm.renderGeometry(g);
// make sure to reset queue distance // make sure to reset queue distance
} }
if (obj != null) if (obj != null) {
obj.queueDistance = Float.NEGATIVE_INFINITY; obj.queueDistance = Float.NEGATIVE_INFINITY;
}
} }
if (clear) if (clear) {
list.clear(); list.clear();
}
} }
public void renderShadowQueue(GeometryList list, RenderManager rm, Camera cam, boolean clear){ public void renderShadowQueue(GeometryList list, RenderManager rm, Camera cam, boolean clear) {
renderGeometryList(list, rm, cam, clear); renderGeometryList(list, rm, cam, clear);
} }
public void renderShadowQueue(ShadowMode shadBucket, RenderManager rm, Camera cam, boolean clear){ public void renderShadowQueue(ShadowMode shadBucket, RenderManager rm, Camera cam, boolean clear) {
switch (shadBucket){ switch (shadBucket) {
case Cast: case Cast:
renderGeometryList(shadowCast, rm, cam, clear); renderGeometryList(shadowCast, rm, cam, clear);
break; break;
@ -197,8 +213,8 @@ public class RenderQueue {
} }
} }
public boolean isQueueEmpty(Bucket bucket){ public boolean isQueueEmpty(Bucket bucket) {
switch (bucket){ switch (bucket) {
case Gui: case Gui:
return guiList.size() == 0; return guiList.size() == 0;
case Opaque: case Opaque:
@ -207,17 +223,19 @@ public class RenderQueue {
return skyList.size() == 0; return skyList.size() == 0;
case Transparent: case Transparent:
return transparentList.size() == 0; return transparentList.size() == 0;
case Translucent:
return translucentList.size() == 0;
default: default:
throw new UnsupportedOperationException("Unsupported bucket type: "+bucket); throw new UnsupportedOperationException("Unsupported bucket type: " + bucket);
} }
} }
public void renderQueue(Bucket bucket, RenderManager rm, Camera cam){ public void renderQueue(Bucket bucket, RenderManager rm, Camera cam) {
renderQueue(bucket, rm, cam, true); renderQueue(bucket, rm, cam, true);
} }
public void renderQueue(Bucket bucket, RenderManager rm, Camera cam, boolean clear){ public void renderQueue(Bucket bucket, RenderManager rm, Camera cam, boolean clear) {
switch (bucket){ switch (bucket) {
case Gui: case Gui:
renderGeometryList(guiList, rm, cam, clear); renderGeometryList(guiList, rm, cam, clear);
break; break;
@ -230,18 +248,22 @@ public class RenderQueue {
case Transparent: case Transparent:
renderGeometryList(transparentList, rm, cam, clear); renderGeometryList(transparentList, rm, cam, clear);
break; break;
case Translucent:
renderGeometryList(translucentList, rm, cam, clear);
break;
default: default:
throw new UnsupportedOperationException("Unsupported bucket type: "+bucket); throw new UnsupportedOperationException("Unsupported bucket type: " + bucket);
} }
} }
public void clear(){ public void clear() {
opaqueList.clear(); opaqueList.clear();
guiList.clear(); guiList.clear();
transparentList.clear(); transparentList.clear();
translucentList.clear();
skyList.clear(); skyList.clear();
shadowCast.clear(); shadowCast.clear();
shadowRecv.clear(); shadowRecv.clear();
} }
} }

@ -110,6 +110,9 @@ public class NullRenderer implements Renderer {
public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst) { public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst) {
} }
public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst, boolean copyDepth) {
}
public void setFrameBuffer(FrameBuffer fb) { public void setFrameBuffer(FrameBuffer fb) {
} }

@ -202,7 +202,7 @@ public class BloomFilter extends Filter {
} }
@Override @Override
public void preRender(RenderManager renderManager, ViewPort viewPort) { public void postQueue(RenderManager renderManager, ViewPort viewPort) {
if (glowMode != GlowMode.Scene) { if (glowMode != GlowMode.Scene) {
backupColor = viewPort.getBackgroundColor(); backupColor = viewPort.getBackgroundColor();
viewPort.setBackgroundColor(ColorRGBA.Black); viewPort.setBackgroundColor(ColorRGBA.Black);

@ -67,7 +67,7 @@ public class CartoonEdgeFilter extends Filter {
} }
@Override @Override
public void preRender(RenderManager renderManager, ViewPort viewPort) { public void postQueue(RenderManager renderManager, ViewPort viewPort) {
Renderer r = renderManager.getRenderer(); Renderer r = renderManager.getRenderer();
r.setFrameBuffer(normalPass.getRenderFrameBuffer()); r.setFrameBuffer(normalPass.getRenderFrameBuffer());
renderManager.getRenderer().clearBuffers(true, true, true); renderManager.getRenderer().clearBuffers(true, true, true);

@ -76,10 +76,6 @@ public class ColorOverlayFilter extends Filter {
this.color = color; this.color = color;
} }
@Override
public void preRender(RenderManager renderManager, ViewPort viewPort) {
}
@Override @Override
public void initFilter(AssetManager manager, RenderManager renderManager, ViewPort vp, int w, int h) { public void initFilter(AssetManager manager, RenderManager renderManager, ViewPort vp, int w, int h) {
material = new Material(manager, "Common/MatDefs/Post/Overlay.j3md"); material = new Material(manager, "Common/MatDefs/Post/Overlay.j3md");

@ -105,10 +105,6 @@ public class CrossHatchFilter extends Filter {
return material; return material;
} }
@Override
public void preRender(RenderManager renderManager, ViewPort viewPort) {
}
@Override @Override
public void cleanUpFilter(Renderer r) { public void cleanUpFilter(Renderer r) {
} }

@ -70,10 +70,6 @@ public class DepthOfFieldFilter extends Filter {
return material; return material;
} }
@Override
public void preRender(RenderManager renderManager, ViewPort viewPort) {
}
@Override @Override
public void initFilter(AssetManager assets, RenderManager renderManager, public void initFilter(AssetManager assets, RenderManager renderManager,
ViewPort vp, int w, int h) { ViewPort vp, int w, int h) {

@ -71,9 +71,6 @@ public class FadeFilter extends Filter {
return material; return material;
} }
@Override
public void preRender(RenderManager renderManager, ViewPort viewPort) {
}
@Override @Override
public void initFilter(AssetManager manager, RenderManager renderManager, ViewPort vp, int w, int h) { public void initFilter(AssetManager manager, RenderManager renderManager, ViewPort vp, int w, int h) {

@ -84,9 +84,6 @@ public class FogFilter extends Filter {
return material; return material;
} }
@Override
public void preRender(RenderManager renderManager, ViewPort viewPort) {
}
/** /**
* returns the fog color * returns the fog color

@ -88,7 +88,7 @@ public class LightScatteringFilter extends Filter {
} }
@Override @Override
public void preRender(RenderManager renderManager, ViewPort viewPort) { public void postQueue(RenderManager renderManager, ViewPort viewPort) {
getClipCoordinates(lightPosition, screenLightPos, viewPort.getCamera()); getClipCoordinates(lightPosition, screenLightPos, viewPort.getCamera());
// screenLightPos.x = screenLightPos.x / viewPort.getCamera().getWidth(); // screenLightPos.x = screenLightPos.x / viewPort.getCamera().getWidth();
// screenLightPos.y = screenLightPos.y / viewPort.getCamera().getHeight(); // screenLightPos.y = screenLightPos.y / viewPort.getCamera().getHeight();

@ -88,9 +88,6 @@ public class PosterizationFilter extends Filter {
return material; return material;
} }
@Override
public void preRender(RenderManager renderManager, ViewPort viewPort) {
}
@Override @Override
public void cleanUpFilter(Renderer r) { public void cleanUpFilter(Renderer r) {

@ -74,9 +74,6 @@ public class RadialBlurFilter extends Filter {
return material; return material;
} }
@Override
public void preRender(RenderManager renderManager, ViewPort viewPort) {
}
public float getSampleDist() { public float getSampleDist() {
return sampleDist; return sampleDist;

@ -0,0 +1,76 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.jme3.post.filters;
import com.jme3.asset.AssetManager;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.post.Filter;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.Renderer;
import com.jme3.renderer.ViewPort;
import com.jme3.renderer.queue.RenderQueue;
import com.jme3.texture.FrameBuffer;
import com.jme3.texture.Texture2D;
/**
*
* @author Nehon
*/
public final class TranslucentBucketFilter extends Filter {
private RenderManager renderManager;
@Override
public void initFilter(AssetManager manager, RenderManager rm, ViewPort vp, int w, int h) {
this.renderManager = rm;
material = new Material(manager, "Common/MatDefs/Post/Overlay.j3md");
material.setColor("Color", ColorRGBA.White);
Texture2D tex = processor.getFilterTexture();
material.setTexture("Texture", tex);
if (tex.getImage().getMultiSamples() > 1) {
material.setInt("NumSamples", tex.getImage().getMultiSamples());
} else {
material.clearParam("NumSamples");
}
renderManager.setHandleTranslucentBucket(false);
}
/**
* Override this method and return false if your Filter does not need the scene texture
* @return
*/
public boolean isRequiresSceneTexture() {
return false;
}
@Override
public void postFrame(RenderManager renderManager, ViewPort viewPort, FrameBuffer prevFilterBuffer, FrameBuffer sceneBuffer) {
renderManager.setCamera(viewPort.getCamera(), false);
renderManager.getRenderer().copyFrameBuffer(prevFilterBuffer, sceneBuffer, false);
renderManager.getRenderer().setFrameBuffer(sceneBuffer);
viewPort.getQueue().renderQueue(RenderQueue.Bucket.Translucent, renderManager, viewPort.getCamera());
}
@Override
public void cleanUpFilter(Renderer r) {
if (renderManager != null) {
renderManager.setHandleTranslucentBucket(true);
}
}
@Override
public Material getMaterial() {
return material;
}
@Override
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
if (renderManager != null) {
renderManager.setHandleTranslucentBucket(!enabled);
}
}
}

@ -70,7 +70,7 @@ public class SSAOFilter extends Filter {
private Pass ssaoPass; private Pass ssaoPass;
private Material downSampleMat; private Material downSampleMat;
private Pass downSamplePass; private Pass downSamplePass;
private int downSampleFactor = 1; private float downSampleFactor = 1f;
/** /**
* Create a Screen Space Ambiant Occlusion Filter * Create a Screen Space Ambiant Occlusion Filter
@ -101,7 +101,7 @@ public class SSAOFilter extends Filter {
} }
@Override @Override
public void preRender(RenderManager renderManager, ViewPort viewPort) { public void postQueue(RenderManager renderManager, ViewPort viewPort) {
Renderer r = renderManager.getRenderer(); Renderer r = renderManager.getRenderer();
r.setFrameBuffer(normalPass.getRenderFrameBuffer()); r.setFrameBuffer(normalPass.getRenderFrameBuffer());
renderManager.getRenderer().clearBuffers(true, true, true); renderManager.getRenderer().clearBuffers(true, true, true);
@ -123,7 +123,7 @@ public class SSAOFilter extends Filter {
postRenderPasses = new ArrayList<Pass>(); postRenderPasses = new ArrayList<Pass>();
normalPass = new Pass(); normalPass = new Pass();
normalPass.init(renderManager.getRenderer(), screenWidth / downSampleFactor, screenHeight / downSampleFactor, Format.RGBA8, Format.Depth); normalPass.init(renderManager.getRenderer(), (int)(screenWidth / downSampleFactor), (int)(screenHeight / downSampleFactor), Format.RGBA8, Format.Depth);
frustumNearFar = new Vector2f(); frustumNearFar = new Vector2f();
@ -149,11 +149,11 @@ public class SSAOFilter extends Filter {
@Override @Override
public boolean requiresDepthAsTexture() { public boolean requiresDepthAsTexture() {
return downSampleFactor == 1; return true;
} }
}; };
ssaoPass.init(renderManager.getRenderer(), screenWidth / downSampleFactor, screenHeight / downSampleFactor, Format.RGBA8, Format.Depth, 1, ssaoMat); ssaoPass.init(renderManager.getRenderer(), (int)(screenWidth / downSampleFactor), (int)(screenHeight / downSampleFactor), Format.RGBA8, Format.Depth, 1, ssaoMat);
ssaoPass.getRenderedTexture().setMinFilter(Texture.MinFilter.Trilinear); ssaoPass.getRenderedTexture().setMinFilter(Texture.MinFilter.Trilinear);
ssaoPass.getRenderedTexture().setMagFilter(Texture.MagFilter.Bilinear); ssaoPass.getRenderedTexture().setMagFilter(Texture.MagFilter.Bilinear);
postRenderPasses.add(ssaoPass); postRenderPasses.add(ssaoPass);
@ -174,7 +174,7 @@ public class SSAOFilter extends Filter {
float xScale = 1.0f / w; float xScale = 1.0f / w;
float yScale = 1.0f / h; float yScale = 1.0f / h;
float blurScale = 2.0f; float blurScale = 2f;
material.setFloat("XScale", blurScale * xScale); material.setFloat("XScale", blurScale * xScale);
material.setFloat("YScale", blurScale * yScale); material.setFloat("YScale", blurScale * yScale);

@ -138,7 +138,7 @@ public class WaterFilter extends Filter {
} }
@Override @Override
public void preRender(RenderManager renderManager, ViewPort viewPort) { public void postQueue(RenderManager renderManager, ViewPort viewPort) {
Camera sceneCam = viewPort.getCamera(); Camera sceneCam = viewPort.getCamera();
biasMatrix.mult(sceneCam.getViewProjectionMatrix(), textureProjMatrix); biasMatrix.mult(sceneCam.getViewProjectionMatrix(), textureProjMatrix);
material.setMatrix4("TextureProjMatrix", textureProjMatrix); material.setMatrix4("TextureProjMatrix", textureProjMatrix);
@ -171,7 +171,15 @@ public class WaterFilter extends Filter {
reflectionCam.setAxes(reflectionCam.getLeft().negateLocal(), reflectionCam.getUp(), reflectionCam.getDirection().negateLocal()); reflectionCam.setAxes(reflectionCam.getLeft().negateLocal(), reflectionCam.getUp(), reflectionCam.getDirection().negateLocal());
} }
boolean rtb = true;
if (!renderManager.isHandleTranslucentBucket()) {
renderManager.setHandleTranslucentBucket(true);
rtb = false;
}
renderManager.renderViewPort(reflectionView, savedTpf); renderManager.renderViewPort(reflectionView, savedTpf);
if (!rtb) {
renderManager.setHandleTranslucentBucket(false);
}
renderManager.getRenderer().setFrameBuffer(viewPort.getOutputFrameBuffer()); renderManager.getRenderer().setFrameBuffer(viewPort.getOutputFrameBuffer());
renderManager.setCamera(sceneCam, false); renderManager.setCamera(sceneCam, false);
} }

@ -42,7 +42,6 @@ import static org.lwjgl.opengl.GL11.*;
public class LwjglGL1Renderer implements GL1Renderer { public class LwjglGL1Renderer implements GL1Renderer {
private static final Logger logger = Logger.getLogger(LwjglRenderer.class.getName()); private static final Logger logger = Logger.getLogger(LwjglRenderer.class.getName());
private final ByteBuffer nameBuf = BufferUtils.createByteBuffer(250); private final ByteBuffer nameBuf = BufferUtils.createByteBuffer(250);
private final StringBuilder stringBuf = new StringBuilder(250); private final StringBuilder stringBuf = new StringBuilder(250);
private final IntBuffer ib1 = BufferUtils.createIntBuffer(1); private final IntBuffer ib1 = BufferUtils.createIntBuffer(1);
@ -51,20 +50,16 @@ public class LwjglGL1Renderer implements GL1Renderer {
private final RenderContext context = new RenderContext(); private final RenderContext context = new RenderContext();
private final GLObjectManager objManager = new GLObjectManager(); private final GLObjectManager objManager = new GLObjectManager();
private final EnumSet<Caps> caps = EnumSet.noneOf(Caps.class); private final EnumSet<Caps> caps = EnumSet.noneOf(Caps.class);
private int maxTexSize; private int maxTexSize;
private int maxCubeTexSize; private int maxCubeTexSize;
private int maxVertCount; private int maxVertCount;
private int maxTriCount; private int maxTriCount;
private final Statistics statistics = new Statistics(); private final Statistics statistics = new Statistics();
private int vpX, vpY, vpW, vpH; private int vpX, vpY, vpW, vpH;
private int clipX, clipY, clipW, clipH; private int clipX, clipY, clipW, clipH;
// private Matrix4f worldMatrix = new Matrix4f(); // private Matrix4f worldMatrix = new Matrix4f();
private Matrix4f viewMatrix = new Matrix4f(); private Matrix4f viewMatrix = new Matrix4f();
// private Matrix4f projMatrix = new Matrix4f(); // private Matrix4f projMatrix = new Matrix4f();
private boolean colorSet = false; private boolean colorSet = false;
private boolean materialSet = false; private boolean materialSet = false;
@ -93,16 +88,16 @@ public class LwjglGL1Renderer implements GL1Renderer {
glShadeModel(GL_SMOOTH); glShadeModel(GL_SMOOTH);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
if (GLContext.getCapabilities().GL_ARB_texture_non_power_of_two){ if (GLContext.getCapabilities().GL_ARB_texture_non_power_of_two) {
caps.add(Caps.NonPowerOfTwoTextures); caps.add(Caps.NonPowerOfTwoTextures);
}else{ } else {
logger.log(Level.WARNING, "Your graphics card does not " logger.log(Level.WARNING, "Your graphics card does not "
+ "support non-power-of-2 textures. " + "support non-power-of-2 textures. "
+ "Some features might not work."); + "Some features might not work.");
} }
} }
public void invalidateState(){ public void invalidateState() {
context.reset(); context.reset();
} }
@ -143,8 +138,8 @@ public class LwjglGL1Renderer implements GL1Renderer {
glClearColor(color.r, color.g, color.b, color.a); glClearColor(color.r, color.g, color.b, color.a);
} }
private void setMaterialColor(int type, ColorRGBA color){ private void setMaterialColor(int type, ColorRGBA color) {
if (!materialSet){ if (!materialSet) {
materialSet = true; materialSet = true;
glEnable(GL_COLOR_MATERIAL); glEnable(GL_COLOR_MATERIAL);
} }
@ -155,8 +150,8 @@ public class LwjglGL1Renderer implements GL1Renderer {
glMaterial(GL_FRONT_AND_BACK, type, fb16); glMaterial(GL_FRONT_AND_BACK, type, fb16);
} }
public void setFixedFuncBinding(FixedFuncBinding ffBinding, Object val){ public void setFixedFuncBinding(FixedFuncBinding ffBinding, Object val) {
switch (ffBinding){ switch (ffBinding) {
case Color: case Color:
ColorRGBA color = (ColorRGBA) val; ColorRGBA color = (ColorRGBA) val;
glColor4f(color.r, color.g, color.b, color.a); glColor4f(color.r, color.g, color.b, color.a);
@ -177,12 +172,12 @@ public class LwjglGL1Renderer implements GL1Renderer {
} }
} }
public void clearSetFixedFuncBindings(){ public void clearSetFixedFuncBindings() {
if (colorSet){ if (colorSet) {
glColor4f(1,1,1,1); glColor4f(1, 1, 1, 1);
colorSet = false; colorSet = false;
} }
if (materialSet){ if (materialSet) {
glDisable(GL_COLOR_MATERIAL); glDisable(GL_COLOR_MATERIAL);
materialSet = false; // TODO: not efficient materialSet = false; // TODO: not efficient
} }
@ -231,7 +226,7 @@ public class LwjglGL1Renderer implements GL1Renderer {
context.colorWriteEnabled = false; context.colorWriteEnabled = false;
} }
if (state.isPointSprite()){ if (state.isPointSprite()) {
logger.log(Level.WARNING, "Point Sprite unsupported!"); logger.log(Level.WARNING, "Point Sprite unsupported!");
} }
@ -325,8 +320,9 @@ public class LwjglGL1Renderer implements GL1Renderer {
context.blendMode = state.getBlendMode(); context.blendMode = state.getBlendMode();
} }
if(state.isStencilTest()) if (state.isStencilTest()) {
throw new UnsupportedOperationException("OpenGL 1.1 doesn't support two sided stencil operations."); throw new UnsupportedOperationException("OpenGL 1.1 doesn't support two sided stencil operations.");
}
} }
@ -519,11 +515,11 @@ public class LwjglGL1Renderer implements GL1Renderer {
} }
// Check sizes if graphics card doesn't support NPOT // Check sizes if graphics card doesn't support NPOT
if (!GLContext.getCapabilities().GL_ARB_texture_non_power_of_two){ if (!GLContext.getCapabilities().GL_ARB_texture_non_power_of_two) {
if (img.getWidth() != 0 && img.getHeight() != 0){ if (img.getWidth() != 0 && img.getHeight() != 0) {
if (!FastMath.isPowerOfTwo(img.getWidth()) if (!FastMath.isPowerOfTwo(img.getWidth())
|| !FastMath.isPowerOfTwo(img.getHeight()) || !FastMath.isPowerOfTwo(img.getHeight())
|| img.getWidth() != img.getHeight()){ || img.getWidth() != img.getHeight()) {
// Resize texture to Power-of-2 size // Resize texture to Power-of-2 size
MipMapGenerator.resizeToPowerOf2(img); MipMapGenerator.resizeToPowerOf2(img);
@ -537,9 +533,9 @@ public class LwjglGL1Renderer implements GL1Renderer {
// generate from base level if required // generate from base level if required
// Check if hardware mips are supported // Check if hardware mips are supported
if (GLContext.getCapabilities().OpenGL14){ if (GLContext.getCapabilities().OpenGL14) {
glTexParameteri(target, GL14.GL_GENERATE_MIPMAP, GL_TRUE); glTexParameteri(target, GL14.GL_GENERATE_MIPMAP, GL_TRUE);
}else{ } else {
MipMapGenerator.generateMipMaps(img); MipMapGenerator.generateMipMaps(img);
} }
} else { } else {
@ -547,33 +543,33 @@ public class LwjglGL1Renderer implements GL1Renderer {
/* /*
if (target == GL_TEXTURE_CUBE_MAP) { if (target == GL_TEXTURE_CUBE_MAP) {
List<ByteBuffer> data = img.getData(); List<ByteBuffer> data = img.getData();
if (data.size() != 6) { if (data.size() != 6) {
logger.log(Level.WARNING, "Invalid texture: {0}\n" logger.log(Level.WARNING, "Invalid texture: {0}\n"
+ "Cubemap textures must contain 6 data units.", img); + "Cubemap textures must contain 6 data units.", img);
return; return;
} }
for (int i = 0; i < 6; i++) { for (int i = 0; i < 6; i++) {
TextureUtil.uploadTexture(img, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, i, 0, tdc); TextureUtil.uploadTexture(img, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, i, 0, tdc);
} }
} else if (target == EXTTextureArray.GL_TEXTURE_2D_ARRAY_EXT) { } else if (target == EXTTextureArray.GL_TEXTURE_2D_ARRAY_EXT) {
List<ByteBuffer> data = img.getData(); List<ByteBuffer> data = img.getData();
// -1 index specifies prepare data for 2D Array // -1 index specifies prepare data for 2D Array
TextureUtil.uploadTexture(img, target, -1, 0, tdc); TextureUtil.uploadTexture(img, target, -1, 0, tdc);
for (int i = 0; i < data.size(); i++) { for (int i = 0; i < data.size(); i++) {
// upload each slice of 2D array in turn // upload each slice of 2D array in turn
// this time with the appropriate index // this time with the appropriate index
TextureUtil.uploadTexture(img, target, i, 0, tdc); TextureUtil.uploadTexture(img, target, i, 0, tdc);
} }
} else {*/ } else {*/
TextureUtil.uploadTexture(img, target, 0, 0, false); TextureUtil.uploadTexture(img, target, 0, 0, false);
//} //}
img.clearUpdateNeeded(); img.clearUpdateNeeded();
} }
public void setTexture(int unit, Texture tex) { public void setTexture(int unit, Texture tex) {
if (unit != 0 || tex.getType() != Texture.Type.TwoDimensional){ if (unit != 0 || tex.getType() != Texture.Type.TwoDimensional) {
//throw new UnsupportedOperationException(); //throw new UnsupportedOperationException();
return; return;
} }
@ -617,7 +613,7 @@ public class LwjglGL1Renderer implements GL1Renderer {
private void checkTexturingUsed() { private void checkTexturingUsed() {
Image[] textures = context.boundTextures; Image[] textures = context.boundTextures;
if (textures[0] != null){ if (textures[0] != null) {
glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_2D);
textures[0] = null; textures[0] = null;
} }
@ -691,8 +687,9 @@ public class LwjglGL1Renderer implements GL1Renderer {
} }
public void drawTriangleArray(Mesh.Mode mode, int count, int vertCount) { public void drawTriangleArray(Mesh.Mode mode, int count, int vertCount) {
if (count > 1) if (count > 1) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
}
glDrawArrays(convertElementMode(mode), 0, vertCount); glDrawArrays(convertElementMode(mode), 0, vertCount);
} }
@ -725,31 +722,34 @@ public class LwjglGL1Renderer implements GL1Renderer {
switch (vb.getBufferType()) { switch (vb.getBufferType()) {
case Position: case Position:
if (!(data instanceof FloatBuffer)) if (!(data instanceof FloatBuffer)) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
}
glVertexPointer(comps, vb.getStride(), (FloatBuffer) data); glVertexPointer(comps, vb.getStride(), (FloatBuffer) data);
break; break;
case Normal: case Normal:
if (!(data instanceof FloatBuffer)) if (!(data instanceof FloatBuffer)) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
}
glNormalPointer(vb.getStride(), (FloatBuffer)data); glNormalPointer(vb.getStride(), (FloatBuffer) data);
break; break;
case Color: case Color:
if (data instanceof FloatBuffer){ if (data instanceof FloatBuffer) {
glColorPointer(comps, vb.getStride(), (FloatBuffer)data); glColorPointer(comps, vb.getStride(), (FloatBuffer) data);
}else if (data instanceof ByteBuffer){ } else if (data instanceof ByteBuffer) {
glColorPointer(comps, true, vb.getStride(), (ByteBuffer)data); glColorPointer(comps, true, vb.getStride(), (ByteBuffer) data);
}else{ } else {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
break; break;
case TexCoord: case TexCoord:
if (!(data instanceof FloatBuffer)) if (!(data instanceof FloatBuffer)) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
}
glTexCoordPointer(comps, vb.getStride(), (FloatBuffer)data); glTexCoordPointer(comps, vb.getStride(), (FloatBuffer) data);
break; break;
default: default:
// Ignore, this is an unsupported attribute for OpenGL1. // Ignore, this is an unsupported attribute for OpenGL1.
@ -761,16 +761,16 @@ public class LwjglGL1Renderer implements GL1Renderer {
setVertexAttrib(vb, null); setVertexAttrib(vb, null);
} }
private void drawElements(int mode, int format, Buffer data){ private void drawElements(int mode, int format, Buffer data) {
switch (format){ switch (format) {
case GL_UNSIGNED_BYTE: case GL_UNSIGNED_BYTE:
glDrawElements(mode, (ByteBuffer)data); glDrawElements(mode, (ByteBuffer) data);
break; break;
case GL_UNSIGNED_SHORT: case GL_UNSIGNED_SHORT:
glDrawElements(mode, (ShortBuffer)data); glDrawElements(mode, (ShortBuffer) data);
break; break;
case GL_UNSIGNED_INT: case GL_UNSIGNED_INT:
glDrawElements(mode, (IntBuffer)data); glDrawElements(mode, (IntBuffer) data);
break; break;
default: default:
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
@ -788,38 +788,36 @@ public class LwjglGL1Renderer implements GL1Renderer {
/* /*
int[] modeStart = mesh.getModeStart(); int[] modeStart = mesh.getModeStart();
int[] elementLengths = mesh.getElementLengths(); int[] elementLengths = mesh.getElementLengths();
int elMode = convertElementMode(Mode.Triangles); int elMode = convertElementMode(Mode.Triangles);
int fmt = convertVertexFormat(indexBuf.getFormat()); int fmt = convertVertexFormat(indexBuf.getFormat());
// int elSize = indexBuf.getFormat().getComponentSize(); // int elSize = indexBuf.getFormat().getComponentSize();
// int listStart = modeStart[0]; // int listStart = modeStart[0];
int stripStart = modeStart[1]; int stripStart = modeStart[1];
int fanStart = modeStart[2]; int fanStart = modeStart[2];
int curOffset = 0; int curOffset = 0;
for (int i = 0; i < elementLengths.length; i++) { for (int i = 0; i < elementLengths.length; i++) {
if (i == stripStart) { if (i == stripStart) {
elMode = convertElementMode(Mode.TriangleStrip); elMode = convertElementMode(Mode.TriangleStrip);
} else if (i == fanStart) { } else if (i == fanStart) {
elMode = convertElementMode(Mode.TriangleStrip); elMode = convertElementMode(Mode.TriangleStrip);
} }
int elementLength = elementLengths[i]; int elementLength = elementLengths[i];
indexData.position(curOffset); indexData.position(curOffset);
drawElements(elMode, drawElements(elMode,
fmt, fmt,
indexData); indexData);
curOffset += elementLength; curOffset += elementLength;
}*/ }*/
} else { } else {
drawElements(convertElementMode(mode), drawElements(convertElementMode(mode),
convertVertexFormat(indexBuf.getFormat()), convertVertexFormat(indexBuf.getFormat()),
indexData); indexData);
} }
} }
public void clearVertexAttribs() { public void clearVertexAttribs() {
for (int i = 0; i < 16; i++) { for (int i = 0; i < 16; i++) {
VertexBuffer vb = context.boundAttribs[i]; VertexBuffer vb = context.boundAttribs[i];
@ -874,8 +872,9 @@ public class LwjglGL1Renderer implements GL1Renderer {
} }
public void renderMesh(Mesh mesh, int lod, int count) { public void renderMesh(Mesh mesh, int lod, int count) {
if (mesh.getVertexCount() == 0) if (mesh.getVertexCount() == 0) {
return; return;
}
if (context.pointSize != mesh.getPointSize()) { if (context.pointSize != mesh.getPointSize()) {
glPointSize(mesh.getPointSize()); glPointSize(mesh.getPointSize());
@ -887,8 +886,9 @@ public class LwjglGL1Renderer implements GL1Renderer {
} }
boolean dynamic = false; boolean dynamic = false;
if (mesh.getBuffer(Type.InterleavedData) != null) if (mesh.getBuffer(Type.InterleavedData) != null) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
}
if (mesh.getNumLodLevels() == 0) { if (mesh.getNumLodLevels() == 0) {
IntMap<VertexBuffer> bufs = mesh.getBuffers(); IntMap<VertexBuffer> bufs = mesh.getBuffers();
@ -905,10 +905,10 @@ public class LwjglGL1Renderer implements GL1Renderer {
statistics.onMeshDrawn(mesh, lod); statistics.onMeshDrawn(mesh, lod);
// if (!dynamic) { // if (!dynamic) {
// dealing with a static object, generate display list // dealing with a static object, generate display list
// renderMeshDisplayList(mesh); // renderMeshDisplayList(mesh);
// } else { // } else {
renderMeshDefault(mesh, lod, count); renderMeshDefault(mesh, lod, count);
// } // }
@ -929,6 +929,9 @@ public class LwjglGL1Renderer implements GL1Renderer {
public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst) { public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst) {
} }
public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst, boolean copyDepth) {
}
public void setFrameBuffer(FrameBuffer fb) { public void setFrameBuffer(FrameBuffer fb) {
} }
@ -943,5 +946,4 @@ public class LwjglGL1Renderer implements GL1Renderer {
public void deleteBuffer(VertexBuffer vb) { public void deleteBuffer(VertexBuffer vb) {
} }
} }

@ -204,7 +204,7 @@ public class LwjglRenderer implements Renderer {
// buffer being used. // buffer being used.
initialDrawBuf = glGetInteger(GL_DRAW_BUFFER); initialDrawBuf = glGetInteger(GL_DRAW_BUFFER);
initialReadBuf = glGetInteger(GL_READ_BUFFER); initialReadBuf = glGetInteger(GL_READ_BUFFER);
// XXX: This has to be GL_BACK for canvas on Mac // XXX: This has to be GL_BACK for canvas on Mac
// Since initialDrawBuf is GL_FRONT for pbuffer, gotta // Since initialDrawBuf is GL_FRONT for pbuffer, gotta
// change this value later on ... // change this value later on ...
@ -326,12 +326,12 @@ public class LwjglRenderer implements Renderer {
caps.add(Caps.VertexBufferArray); caps.add(Caps.VertexBufferArray);
} }
if (ctxCaps.GL_ARB_texture_non_power_of_two){ if (ctxCaps.GL_ARB_texture_non_power_of_two) {
caps.add(Caps.NonPowerOfTwoTextures); caps.add(Caps.NonPowerOfTwoTextures);
}else{ } else {
logger.log(Level.WARNING, "Your graphics card does not " logger.log(Level.WARNING, "Your graphics card does not "
+ "support non-power-of-2 textures. " + "support non-power-of-2 textures. "
+ "Some features might not work."); + "Some features might not work.");
} }
boolean latc = ctxCaps.GL_EXT_texture_compression_latc; boolean latc = ctxCaps.GL_EXT_texture_compression_latc;
@ -414,11 +414,11 @@ public class LwjglRenderer implements Renderer {
logger.log(Level.INFO, "Caps: {0}", caps); logger.log(Level.INFO, "Caps: {0}", caps);
} }
public void invalidateState(){ public void invalidateState() {
context.reset(); context.reset();
boundShader = null; boundShader = null;
lastFb = null; lastFb = null;
initialDrawBuf = glGetInteger(GL_DRAW_BUFFER); initialDrawBuf = glGetInteger(GL_DRAW_BUFFER);
initialReadBuf = glGetInteger(GL_READ_BUFFER); initialReadBuf = glGetInteger(GL_READ_BUFFER);
} }
@ -610,96 +610,91 @@ public class LwjglRenderer implements Renderer {
context.blendMode = state.getBlendMode(); context.blendMode = state.getBlendMode();
} }
if(context.stencilTest!=state.isStencilTest() if (context.stencilTest != state.isStencilTest()
|| context.frontStencilStencilFailOperation!=state.getFrontStencilStencilFailOperation() || context.frontStencilStencilFailOperation != state.getFrontStencilStencilFailOperation()
|| context.frontStencilDepthFailOperation!=state.getFrontStencilDepthFailOperation() || context.frontStencilDepthFailOperation != state.getFrontStencilDepthFailOperation()
|| context.frontStencilDepthPassOperation!=state.getFrontStencilDepthPassOperation() || context.frontStencilDepthPassOperation != state.getFrontStencilDepthPassOperation()
|| context.backStencilStencilFailOperation!=state.getBackStencilStencilFailOperation() || context.backStencilStencilFailOperation != state.getBackStencilStencilFailOperation()
|| context.backStencilDepthFailOperation!=state.getBackStencilDepthFailOperation() || context.backStencilDepthFailOperation != state.getBackStencilDepthFailOperation()
|| context.backStencilDepthPassOperation!=state.getBackStencilDepthPassOperation() || context.backStencilDepthPassOperation != state.getBackStencilDepthPassOperation()
|| context.frontStencilFunction!=state.getFrontStencilFunction() || context.frontStencilFunction != state.getFrontStencilFunction()
|| context.backStencilFunction!=state.getBackStencilFunction() || context.backStencilFunction != state.getBackStencilFunction()) {
){
context.frontStencilStencilFailOperation = state.getFrontStencilStencilFailOperation(); //terrible looking, I know
context.frontStencilStencilFailOperation=state.getFrontStencilStencilFailOperation(); //terrible looking, I know context.frontStencilDepthFailOperation = state.getFrontStencilDepthFailOperation();
context.frontStencilDepthFailOperation=state.getFrontStencilDepthFailOperation(); context.frontStencilDepthPassOperation = state.getFrontStencilDepthPassOperation();
context.frontStencilDepthPassOperation=state.getFrontStencilDepthPassOperation(); context.backStencilStencilFailOperation = state.getBackStencilStencilFailOperation();
context.backStencilStencilFailOperation=state.getBackStencilStencilFailOperation(); context.backStencilDepthFailOperation = state.getBackStencilDepthFailOperation();
context.backStencilDepthFailOperation=state.getBackStencilDepthFailOperation(); context.backStencilDepthPassOperation = state.getBackStencilDepthPassOperation();
context.backStencilDepthPassOperation=state.getBackStencilDepthPassOperation(); context.frontStencilFunction = state.getFrontStencilFunction();
context.frontStencilFunction=state.getFrontStencilFunction(); context.backStencilFunction = state.getBackStencilFunction();
context.backStencilFunction=state.getBackStencilFunction();
if (state.isStencilTest()) {
if(state.isStencilTest()){
glEnable(GL_STENCIL_TEST); glEnable(GL_STENCIL_TEST);
glStencilOpSeparate(GL_FRONT, glStencilOpSeparate(GL_FRONT,
glStencilOpFromStencilOp(state.getFrontStencilStencilFailOperation()), glStencilOpFromStencilOp(state.getFrontStencilStencilFailOperation()),
glStencilOpFromStencilOp(state.getFrontStencilDepthFailOperation()), glStencilOpFromStencilOp(state.getFrontStencilDepthFailOperation()),
glStencilOpFromStencilOp(state.getFrontStencilDepthPassOperation()) glStencilOpFromStencilOp(state.getFrontStencilDepthPassOperation()));
);
glStencilOpSeparate(GL_BACK, glStencilOpSeparate(GL_BACK,
glStencilOpFromStencilOp(state.getBackStencilStencilFailOperation()), glStencilOpFromStencilOp(state.getBackStencilStencilFailOperation()),
glStencilOpFromStencilOp(state.getBackStencilDepthFailOperation()), glStencilOpFromStencilOp(state.getBackStencilDepthFailOperation()),
glStencilOpFromStencilOp(state.getBackStencilDepthPassOperation()) glStencilOpFromStencilOp(state.getBackStencilDepthPassOperation()));
);
glStencilFuncSeparate(GL_FRONT, glStencilFuncSeparate(GL_FRONT,
glStencilFuncFromStencilFunc(state.getFrontStencilFunction()), glStencilFuncFromStencilFunc(state.getFrontStencilFunction()),
0,Integer.MAX_VALUE 0, Integer.MAX_VALUE);
);
glStencilFuncSeparate(GL_BACK, glStencilFuncSeparate(GL_BACK,
glStencilFuncFromStencilFunc(state.getBackStencilFunction()), glStencilFuncFromStencilFunc(state.getBackStencilFunction()),
0,Integer.MAX_VALUE 0, Integer.MAX_VALUE);
); } else {
}else{
glDisable(GL_STENCIL_TEST); glDisable(GL_STENCIL_TEST);
} }
} }
} }
private int glStencilOpFromStencilOp(RenderState.StencilOperation s){ private int glStencilOpFromStencilOp(RenderState.StencilOperation s) {
switch(s){ switch (s) {
case Keep: case Keep:
return GL_KEEP; return GL_KEEP;
case Zero: case Zero:
return GL_ZERO; return GL_ZERO;
case Replace: case Replace:
return GL_REPLACE; return GL_REPLACE;
case Increment: case Increment:
return GL_INCR; return GL_INCR;
case IncrementWrap: case IncrementWrap:
return GL_INCR_WRAP; return GL_INCR_WRAP;
case Decrement: case Decrement:
return GL_DECR; return GL_DECR;
case DecrementWrap: case DecrementWrap:
return GL_DECR_WRAP; return GL_DECR_WRAP;
case Invert: case Invert:
return GL_INVERT; return GL_INVERT;
default: default:
throw new UnsupportedOperationException("Unrecognized front stencil operation: " + s); throw new UnsupportedOperationException("Unrecognized front stencil operation: " + s);
} //end switch } //end switch
} }
private int glStencilFuncFromStencilFunc(RenderState.StencilFunction s){ private int glStencilFuncFromStencilFunc(RenderState.StencilFunction s) {
switch(s){ switch (s) {
case Never: case Never:
return GL_NEVER; return GL_NEVER;
case Less: case Less:
return GL_LESS; return GL_LESS;
case LessEqual: case LessEqual:
return GL_LEQUAL; return GL_LEQUAL;
case Greater: case Greater:
return GL_GREATER; return GL_GREATER;
case GreaterEqual: case GreaterEqual:
return GL_GEQUAL; return GL_GEQUAL;
case Equal: case Equal:
return GL_EQUAL; return GL_EQUAL;
case NotEqual: case NotEqual:
return GL_NOTEQUAL; return GL_NOTEQUAL;
case Always: case Always:
return GL_ALWAYS; return GL_ALWAYS;
default: default:
throw new UnsupportedOperationException("Unrecognized front stencil functin: " + s); throw new UnsupportedOperationException("Unrecognized front stencil functin: " + s);
} //end switch } //end switch
} }
@ -826,7 +821,7 @@ public class LwjglRenderer implements Renderer {
if (val instanceof ColorRGBA) { if (val instanceof ColorRGBA) {
ColorRGBA c = (ColorRGBA) val; ColorRGBA c = (ColorRGBA) val;
glUniform4f(loc, c.r, c.g, c.b, c.a); glUniform4f(loc, c.r, c.g, c.b, c.a);
}else if (val instanceof Vector4f) { } else if (val instanceof Vector4f) {
Vector4f c = (Vector4f) val; Vector4f c = (Vector4f) val;
glUniform4f(loc, c.x, c.y, c.z, c.w); glUniform4f(loc, c.x, c.y, c.z, c.w);
} else { } else {
@ -991,9 +986,9 @@ public class LwjglRenderer implements Renderer {
logger.log(Level.WARNING, "Bad compile of:\n{0}{1}", logger.log(Level.WARNING, "Bad compile of:\n{0}{1}",
new Object[]{source.getDefines(), source.getSource()}); new Object[]{source.getDefines(), source.getSource()});
if (infoLog != null) { if (infoLog != null) {
throw new RendererException( "compile error in:" + source + " error:" + infoLog ); throw new RendererException("compile error in:" + source + " error:" + infoLog);
} else { } else {
throw new RendererException( "compile error in:" + source + " error: <not provided>" ); throw new RendererException("compile error in:" + source + " error: <not provided>");
} }
} }
@ -1072,9 +1067,9 @@ public class LwjglRenderer implements Renderer {
} }
} else { } else {
if (infoLog != null) { if (infoLog != null) {
throw new RendererException("Shader link failure, shader:" + shader + " info:" + infoLog ); throw new RendererException("Shader link failure, shader:" + shader + " info:" + infoLog);
} else { } else {
throw new RendererException("Shader link failure, shader:" + shader + " info: <not provided>" ); throw new RendererException("Shader link failure, shader:" + shader + " info: <not provided>");
} }
} }
@ -1179,6 +1174,10 @@ public class LwjglRenderer implements Renderer {
|* Framebuffers *| |* Framebuffers *|
\*********************************************************************/ \*********************************************************************/
public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst) { public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst) {
copyFrameBuffer(src, dst, true);
}
public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst, boolean copyDepth) {
if (GLContext.getCapabilities().GL_EXT_framebuffer_blit) { if (GLContext.getCapabilities().GL_EXT_framebuffer_blit) {
int srcW = 0; int srcW = 0;
int srcH = 0; int srcH = 0;
@ -1212,11 +1211,15 @@ public class LwjglRenderer implements Renderer {
dstW = dst.getWidth(); dstW = dst.getWidth();
dstH = dst.getHeight(); dstH = dst.getHeight();
} }
int mask = GL_COLOR_BUFFER_BIT;
if (copyDepth) {
mask |= GL_DEPTH_BUFFER_BIT;
}
glBlitFramebufferEXT(0, 0, srcW, srcH, glBlitFramebufferEXT(0, 0, srcW, srcH,
0, 0, dstW, dstH, 0, 0, dstW, dstH, mask,
GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT,
GL_NEAREST); GL_NEAREST);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, prevFBO); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, prevFBO);
try { try {
checkFrameBufferError(); checkFrameBufferError();
@ -1402,7 +1405,7 @@ public class LwjglRenderer implements Renderer {
if (lastFb == fb) { if (lastFb == fb) {
return; return;
} }
// generate mipmaps for last FB if needed // generate mipmaps for last FB if needed
if (lastFb != null) { if (lastFb != null) {
for (int i = 0; i < lastFb.getNumColorBuffers(); i++) { for (int i = 0; i < lastFb.getNumColorBuffers(); i++) {
@ -1643,9 +1646,9 @@ public class LwjglRenderer implements Renderer {
} }
} }
if (context.pointSprite) if (context.pointSprite) {
return; // Attempt to fix glTexParameter crash for some ATI GPUs return; // Attempt to fix glTexParameter crash for some ATI GPUs
}
// repeat modes // repeat modes
switch (tex.getType()) { switch (tex.getType()) {
case ThreeDimensional: case ThreeDimensional:
@ -1722,14 +1725,15 @@ public class LwjglRenderer implements Renderer {
} }
// Yes, some OpenGL2 cards (GeForce 5) still dont support NPOT. // Yes, some OpenGL2 cards (GeForce 5) still dont support NPOT.
if (!GLContext.getCapabilities().GL_ARB_texture_non_power_of_two){ if (!GLContext.getCapabilities().GL_ARB_texture_non_power_of_two) {
if (img.getData(0) == null) if (img.getData(0) == null) {
throw new RendererException("non-power-of-2 framebuffer textures are not supported by the video hardware"); throw new RendererException("non-power-of-2 framebuffer textures are not supported by the video hardware");
}
if (img.getWidth() != 0 && img.getHeight() != 0){
if (img.getWidth() != 0 && img.getHeight() != 0) {
if (!FastMath.isPowerOfTwo(img.getWidth()) if (!FastMath.isPowerOfTwo(img.getWidth())
|| !FastMath.isPowerOfTwo(img.getHeight()) || !FastMath.isPowerOfTwo(img.getHeight())
|| img.getWidth() != img.getHeight()){ || img.getWidth() != img.getHeight()) {
// logger.log(Level.WARNING, "Encountered NPOT texture {0}, " // logger.log(Level.WARNING, "Encountered NPOT texture {0}, "
// + "it might not display correctly.", img); // + "it might not display correctly.", img);
@ -1739,9 +1743,10 @@ public class LwjglRenderer implements Renderer {
} }
// Check if graphics card doesn't support multisample textures // Check if graphics card doesn't support multisample textures
if (!GLContext.getCapabilities().GL_ARB_texture_multisample){ if (!GLContext.getCapabilities().GL_ARB_texture_multisample) {
if (img.getMultiSamples() > 1) if (img.getMultiSamples() > 1) {
throw new RendererException("Multisample textures not supported by graphics hardware"); throw new RendererException("Multisample textures not supported by graphics hardware");
}
} }
if (target == GL_TEXTURE_CUBE_MAP) { if (target == GL_TEXTURE_CUBE_MAP) {

@ -33,6 +33,8 @@
package jme3test.light; package jme3test.light;
import com.jme3.app.SimpleApplication; import com.jme3.app.SimpleApplication;
import com.jme3.effect.ParticleEmitter;
import com.jme3.effect.ParticleMesh;
import com.jme3.light.AmbientLight; import com.jme3.light.AmbientLight;
import com.jme3.light.DirectionalLight; import com.jme3.light.DirectionalLight;
import com.jme3.material.Material; import com.jme3.material.Material;
@ -105,7 +107,30 @@ public class TestTransparentShadow extends SimpleApplication {
dl.setColor(new ColorRGBA(0.965f, 0.949f, 0.772f, 1f).mult(0.7f)); dl.setColor(new ColorRGBA(0.965f, 0.949f, 0.772f, 1f).mult(0.7f));
rootNode.addLight(dl); rootNode.addLight(dl);
rootNode.attachChild(teaGeom); rootNode.attachChild(teaGeom);
/** Uses Texture from jme3-test-data library! */
ParticleEmitter fire = new ParticleEmitter("Emitter", ParticleMesh.Type.Triangle, 30);
Material mat_red = new Material(assetManager, "Common/MatDefs/Misc/Particle.j3md");
mat_red.setTexture("Texture", assetManager.loadTexture("Effects/Explosion/flame.png"));
//mat_red.getAdditionalRenderState().setDepthTest(true);
//mat_red.getAdditionalRenderState().setDepthWrite(true);
fire.setMaterial(mat_red);
fire.setImagesX(2); fire.setImagesY(2); // 2x2 texture animation
fire.setEndColor( new ColorRGBA(1f, 0f, 0f, 1f)); // red
fire.setStartColor(new ColorRGBA(1f, 1f, 0f, 0.5f)); // yellow
fire.setInitialVelocity(new Vector3f(0, 2, 0));
fire.setStartSize(0.6f);
fire.setEndSize(0.1f);
fire.setGravity(0);
fire.setLowLife(0.5f);
fire.setHighLife(1.5f);
fire.setVelocityVariation(0.3f);
fire.setLocalTranslation(1.0f, 0, 1.0f);
fire.setLocalScale(0.3f);
fire.setQueueBucket(Bucket.Translucent);
rootNode.attachChild(fire);
PssmShadowRenderer pssmRenderer = new PssmShadowRenderer(assetManager, 1024, 1); PssmShadowRenderer pssmRenderer = new PssmShadowRenderer(assetManager, 1024, 1);
pssmRenderer.setDirection(new Vector3f(0.01f, -1f, 0.01f).normalizeLocal()); pssmRenderer.setDirection(new Vector3f(0.01f, -1f, 0.01f).normalizeLocal());

@ -42,6 +42,7 @@ import com.jme3.math.Vector3f;
import com.jme3.post.FilterPostProcessor; import com.jme3.post.FilterPostProcessor;
import com.jme3.post.filters.BloomFilter; import com.jme3.post.filters.BloomFilter;
import com.jme3.post.filters.CartoonEdgeFilter; import com.jme3.post.filters.CartoonEdgeFilter;
import com.jme3.post.filters.CrossHatchFilter;
import com.jme3.post.filters.FogFilter; import com.jme3.post.filters.FogFilter;
import com.jme3.post.filters.RadialBlurFilter; import com.jme3.post.filters.RadialBlurFilter;
import com.jme3.post.ssao.SSAOFilter; import com.jme3.post.ssao.SSAOFilter;
@ -62,6 +63,7 @@ public class TestMultiViewsFilters extends SimpleApplication {
// create the geometry and attach it // create the geometry and attach it
Geometry teaGeom = (Geometry) assetManager.loadModel("Models/Teapot/Teapot.obj"); Geometry teaGeom = (Geometry) assetManager.loadModel("Models/Teapot/Teapot.obj");
teaGeom.scale(3); teaGeom.scale(3);
teaGeom.getMaterial().setColor("GlowColor", ColorRGBA.Green);
DirectionalLight dl = new DirectionalLight(); DirectionalLight dl = new DirectionalLight();
dl.setColor(ColorRGBA.White); dl.setColor(ColorRGBA.White);
@ -109,18 +111,38 @@ public class TestMultiViewsFilters extends SimpleApplication {
view4.setClearFlags(true, true, true); view4.setClearFlags(true, true, true);
view4.attachScene(rootNode); view4.attachScene(rootNode);
// Camera cam5 = new Camera(200, 200);
// cam5.setFrustumPerspective(45f, (float)cam.getWidth() / cam.getHeight(), 1f, 1000f);
// cam5.setName("cam5");
// cam5.setViewPort(5.23f, 6.33f, 0.56f, 1.66f);
// this.setViewPortAreas(5.23f, 6.33f, 0.56f, 1.66f);
// this.setViewPortCamSize(200, 200);
// 1046,1266,112,332
Camera cam5 = cam.clone();
cam5.setName("cam5");
cam5.setViewPort(1046f/settings.getWidth(), 1266f/settings.getWidth(), 112f/settings.getHeight(), 332f/settings.getHeight());
cam5.setLocation(new Vector3f(0.2846221f, 6.4271426f, 0.23380789f));
cam5.setRotation(new Quaternion(0.004381671f, 0.72363687f, -0.69015175f, 0.0045953835f));
final ViewPort view5 = renderManager.createMainView("center", cam5);
view5.setClearFlags(true, true, true);
view5.attachScene(rootNode);
rootNode.attachChild(SkyFactory.createSky(assetManager, "Textures/Sky/Bright/BrightSky.dds", false)); rootNode.attachChild(SkyFactory.createSky(assetManager, "Textures/Sky/Bright/BrightSky.dds", false));
final FilterPostProcessor fpp = new FilterPostProcessor(assetManager); final FilterPostProcessor fpp = new FilterPostProcessor(assetManager);
final FilterPostProcessor fpp2 = new FilterPostProcessor(assetManager); final FilterPostProcessor fpp2 = new FilterPostProcessor(assetManager);
final FilterPostProcessor fpp3 = new FilterPostProcessor(assetManager); final FilterPostProcessor fpp3 = new FilterPostProcessor(assetManager);
final FilterPostProcessor fpp4 = new FilterPostProcessor(assetManager); final FilterPostProcessor fpp4 = new FilterPostProcessor(assetManager);
final FilterPostProcessor fpp5 = new FilterPostProcessor(assetManager);
// fpp.addFilter(new WaterFilter(rootNode, Vector3f.UNIT_Y.mult(-1))); // fpp.addFilter(new WaterFilter(rootNode, Vector3f.UNIT_Y.mult(-1)));
fpp3.addFilter(new CartoonEdgeFilter()); fpp3.addFilter(new CartoonEdgeFilter());
fpp2.addFilter(new BloomFilter()); fpp2.addFilter(new CrossHatchFilter());
final FogFilter ff = new FogFilter(ColorRGBA.Yellow, 0.7f, 2); final FogFilter ff = new FogFilter(ColorRGBA.Yellow, 0.7f, 2);
fpp.addFilter(ff); fpp.addFilter(ff);
@ -132,11 +154,14 @@ public class TestMultiViewsFilters extends SimpleApplication {
SSAOFilter f = new SSAOFilter(1.8899765f, 20.490374f, 0.4699998f, 0.1f);; SSAOFilter f = new SSAOFilter(1.8899765f, 20.490374f, 0.4699998f, 0.1f);;
fpp4.addFilter(f); fpp4.addFilter(f);
SSAOUI ui = new SSAOUI(inputManager, f); SSAOUI ui = new SSAOUI(inputManager, f);
fpp5.addFilter(new BloomFilter(BloomFilter.GlowMode.Objects));
viewPort.addProcessor(fpp); viewPort.addProcessor(fpp);
view2.addProcessor(fpp2); view2.addProcessor(fpp2);
view3.addProcessor(fpp3); view3.addProcessor(fpp3);
view4.addProcessor(fpp4); view4.addProcessor(fpp4);
view5.addProcessor(fpp5);
@ -149,11 +174,13 @@ public class TestMultiViewsFilters extends SimpleApplication {
view2.removeProcessor(fpp2); view2.removeProcessor(fpp2);
view3.removeProcessor(fpp3); view3.removeProcessor(fpp3);
view4.removeProcessor(fpp4); view4.removeProcessor(fpp4);
view5.removeProcessor(fpp5);
} else { } else {
viewPort.addProcessor(fpp); viewPort.addProcessor(fpp);
view2.addProcessor(fpp2); view2.addProcessor(fpp2);
view3.addProcessor(fpp3); view3.addProcessor(fpp3);
view4.addProcessor(fpp4); view4.addProcessor(fpp4);
view5.addProcessor(fpp5);
} }
filterEnabled = !filterEnabled; filterEnabled = !filterEnabled;
} }

@ -3,20 +3,29 @@ package jme3test.water;
import com.jme3.app.SimpleApplication; import com.jme3.app.SimpleApplication;
import com.jme3.audio.AudioNode; import com.jme3.audio.AudioNode;
import com.jme3.bounding.BoundingBox; import com.jme3.bounding.BoundingBox;
import com.jme3.effect.ParticleEmitter;
import com.jme3.effect.ParticleMesh;
import com.jme3.input.controls.ActionListener; import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger; import com.jme3.input.controls.KeyTrigger;
import com.jme3.light.DirectionalLight; import com.jme3.light.DirectionalLight;
import com.jme3.material.Material; import com.jme3.material.Material;
import com.jme3.material.RenderState.BlendMode;
import com.jme3.math.ColorRGBA; import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath; import com.jme3.math.FastMath;
import com.jme3.math.Quaternion; import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f; import com.jme3.math.Vector3f;
import com.jme3.post.FilterPostProcessor; import com.jme3.post.FilterPostProcessor;
import com.jme3.post.filters.DepthOfFieldFilter;
import com.jme3.post.filters.LightScatteringFilter;
import com.jme3.post.filters.TranslucentBucketFilter;
import com.jme3.renderer.Camera; import com.jme3.renderer.Camera;
import com.jme3.renderer.queue.RenderQueue.Bucket;
import com.jme3.renderer.queue.RenderQueue.ShadowMode; import com.jme3.renderer.queue.RenderQueue.ShadowMode;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node; import com.jme3.scene.Node;
import com.jme3.scene.Spatial; import com.jme3.scene.Spatial;
import com.jme3.scene.shape.Box;
import com.jme3.terrain.geomipmap.TerrainQuad; import com.jme3.terrain.geomipmap.TerrainQuad;
import com.jme3.terrain.heightmap.AbstractHeightMap; import com.jme3.terrain.heightmap.AbstractHeightMap;
import com.jme3.terrain.heightmap.ImageBasedHeightMap; import com.jme3.terrain.heightmap.ImageBasedHeightMap;
@ -35,7 +44,6 @@ import jme3tools.converters.ImageToAwt;
*/ */
public class TestPostWater extends SimpleApplication { public class TestPostWater extends SimpleApplication {
private FilterPostProcessor fpp;
private Vector3f lightDir = new Vector3f(-4.9236743f, -1.27054665f, 5.896916f); private Vector3f lightDir = new Vector3f(-4.9236743f, -1.27054665f, 5.896916f);
private WaterFilter water; private WaterFilter water;
TerrainQuad terrain; TerrainQuad terrain;
@ -65,10 +73,10 @@ public class TestPostWater extends SimpleApplication {
l.setColor(ColorRGBA.White.clone().multLocal(0.3f)); l.setColor(ColorRGBA.White.clone().multLocal(0.3f));
mainScene.addLight(l); mainScene.addLight(l);
flyCam.setMoveSpeed(50); flyCam.setMoveSpeed(100);
cam.setLocation(new Vector3f(-700, 100, 300)); cam.setLocation(new Vector3f(-700, 100, 300));
cam.setRotation(new Quaternion().fromAngles(new float[]{FastMath.PI*0.06f,FastMath.PI*0.65f,0})); cam.setRotation(new Quaternion().fromAngles(new float[]{FastMath.PI * 0.06f, FastMath.PI * 0.65f, 0}));
Spatial sky = SkyFactory.createSky(assetManager, "Scenes/Beach/FullskiesSunset0068.dds", false); Spatial sky = SkyFactory.createSky(assetManager, "Scenes/Beach/FullskiesSunset0068.dds", false);
@ -80,44 +88,112 @@ public class TestPostWater extends SimpleApplication {
waves.setLooping(true); waves.setLooping(true);
audioRenderer.playSource(waves); audioRenderer.playSource(waves);
//private FilterPostProcessor fpp;
fpp = new FilterPostProcessor(assetManager);
// fpp.setNumSamples(4);
water = new WaterFilter(rootNode, lightDir); water = new WaterFilter(rootNode, lightDir);
FilterPostProcessor fpp = new FilterPostProcessor(assetManager);
fpp.addFilter(water);
DepthOfFieldFilter dof=new DepthOfFieldFilter();
dof.setFocusDistance(0);
dof.setFocusRange(100);
fpp.addFilter(new TranslucentBucketFilter());
fpp.addFilter(dof);
// fpp.setNumSamples(4);
water.setWaveScale(0.003f); water.setWaveScale(0.003f);
water.setMaxAmplitude(2f); water.setMaxAmplitude(2f);
water.setFoamExistence(new Vector3f(1f, 4, 0.5f)); water.setFoamExistence(new Vector3f(1f, 4, 0.5f));
water.setFoamTexture((Texture2D) assetManager.loadTexture("Common/MatDefs/Water/Textures/foam2.jpg")); water.setFoamTexture((Texture2D) assetManager.loadTexture("Common/MatDefs/Water/Textures/foam2.jpg"));
//water.setNormalScale(0.5f); //water.setNormalScale(0.5f);
//water.setRefractionConstant(0.25f); //water.setRefractionConstant(0.25f);
water.setRefractionStrength(0.2f); water.setRefractionStrength(0.2f);
//water.setFoamHardness(0.6f); //water.setFoamHardness(0.6f);
water.setWaterHeight(initialWaterHeight); water.setWaterHeight(initialWaterHeight);
fpp.addFilter(water);
//
viewPort.addProcessor(fpp); viewPort.addProcessor(fpp);
inputManager.addListener(new ActionListener() { inputManager.addListener(new ActionListener() {
public void onAction(String name, boolean isPressed, float tpf) { public void onAction(String name, boolean isPressed, float tpf) {
if(isPressed){ if (isPressed) {
if(name.equals("foam1")){ if (name.equals("foam1")) {
water.setFoamTexture((Texture2D) assetManager.loadTexture("Common/MatDefs/Water/Textures/foam.jpg")); water.setFoamTexture((Texture2D) assetManager.loadTexture("Common/MatDefs/Water/Textures/foam.jpg"));
} }
if(name.equals("foam2")){ if (name.equals("foam2")) {
water.setFoamTexture((Texture2D) assetManager.loadTexture("Common/MatDefs/Water/Textures/foam2.jpg")); water.setFoamTexture((Texture2D) assetManager.loadTexture("Common/MatDefs/Water/Textures/foam2.jpg"));
} }
if(name.equals("foam3")){ if (name.equals("foam3")) {
water.setFoamTexture((Texture2D) assetManager.loadTexture("Common/MatDefs/Water/Textures/foam3.jpg")); water.setFoamTexture((Texture2D) assetManager.loadTexture("Common/MatDefs/Water/Textures/foam3.jpg"));
} }
} }
} }
}, "foam1","foam2","foam3"); }, "foam1", "foam2", "foam3");
inputManager.addMapping("foam1", new KeyTrigger(keyInput.KEY_1)); inputManager.addMapping("foam1", new KeyTrigger(keyInput.KEY_1));
inputManager.addMapping("foam2", new KeyTrigger(keyInput.KEY_2)); inputManager.addMapping("foam2", new KeyTrigger(keyInput.KEY_2));
inputManager.addMapping("foam3", new KeyTrigger(keyInput.KEY_3)); inputManager.addMapping("foam3", new KeyTrigger(keyInput.KEY_3));
createBox();
createFire();
}
Geometry box;
private void createBox() {
//creating a transluscent box
box = new Geometry("box", new Box(new Vector3f(0, 0, 0), 50, 50, 50));
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mat.setColor("Color", new ColorRGBA(1.0f, 0, 0, 0.3f));
mat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
//mat.getAdditionalRenderState().setDepthWrite(false);
//mat.getAdditionalRenderState().setDepthTest(false);
box.setMaterial(mat);
box.setQueueBucket(Bucket.Translucent);
//creating a post view port
// ViewPort post=renderManager.createPostView("transpPost", cam);
// post.setClearFlags(false, true, true);
box.setLocalTranslation(-600, 0, 300);
//attaching the box to the post viewport
//Don't forget to updateGeometricState() the box in the simpleUpdate
// post.attachScene(box);
rootNode.attachChild(box);
}
private void createFire() {
/** Uses Texture from jme3-test-data library! */
ParticleEmitter fire = new ParticleEmitter("Emitter", ParticleMesh.Type.Triangle, 30);
Material mat_red = new Material(assetManager, "Common/MatDefs/Misc/Particle.j3md");
mat_red.setTexture("Texture", assetManager.loadTexture("Effects/Explosion/flame.png"));
fire.setMaterial(mat_red);
fire.setImagesX(2);
fire.setImagesY(2); // 2x2 texture animation
fire.setEndColor(new ColorRGBA(1f, 0f, 0f, 1f)); // red
fire.setStartColor(new ColorRGBA(1f, 1f, 0f, 0.5f)); // yellow
fire.setInitialVelocity(new Vector3f(0, 2, 0));
fire.setStartSize(10f);
fire.setEndSize(1f);
fire.setGravity(0);
fire.setLowLife(0.5f);
fire.setHighLife(1.5f);
fire.setVelocityVariation(0.3f);
fire.setLocalTranslation(-500, 30, 300);
fire.setQueueBucket(Bucket.Translucent);
rootNode.attachChild(fire);
} }
private void createTerrain(Node rootNode) { private void createTerrain(Node rootNode) {
@ -138,7 +214,7 @@ public class TestPostWater extends SimpleApplication {
rock.setWrap(WrapMode.Repeat); rock.setWrap(WrapMode.Repeat);
matRock.setTexture("DiffuseMap_2", rock); matRock.setTexture("DiffuseMap_2", rock);
matRock.setFloat("DiffuseMap_2_scale", 128); matRock.setFloat("DiffuseMap_2_scale", 128);
Texture normalMap0 = assetManager.loadTexture("Textures/Terrain/splat/grass_normal.png"); Texture normalMap0 = assetManager.loadTexture("Textures/Terrain/splat/grass_normal.jpg");
normalMap0.setWrap(WrapMode.Repeat); normalMap0.setWrap(WrapMode.Repeat);
Texture normalMap1 = assetManager.loadTexture("Textures/Terrain/splat/dirt_normal.png"); Texture normalMap1 = assetManager.loadTexture("Textures/Terrain/splat/dirt_normal.png");
normalMap1.setWrap(WrapMode.Repeat); normalMap1.setWrap(WrapMode.Repeat);
@ -161,8 +237,8 @@ public class TestPostWater extends SimpleApplication {
List<Camera> cameras = new ArrayList<Camera>(); List<Camera> cameras = new ArrayList<Camera>();
cameras.add(getCamera()); cameras.add(getCamera());
terrain.setMaterial(matRock); terrain.setMaterial(matRock);
terrain.setLocalScale(new Vector3f(5,5,5)); terrain.setLocalScale(new Vector3f(5, 5, 5));
terrain.setLocalTranslation(new Vector3f(0,-30,0)); terrain.setLocalTranslation(new Vector3f(0, -30, 0));
terrain.setModelBound(new BoundingBox()); terrain.setModelBound(new BoundingBox());
terrain.updateModelBound(); terrain.updateModelBound();
terrain.setLocked(false); // unlock it so we can edit the height terrain.setLocked(false); // unlock it so we can edit the height
@ -171,7 +247,6 @@ public class TestPostWater extends SimpleApplication {
rootNode.attachChild(terrain); rootNode.attachChild(terrain);
} }
//This part is to emulate tides, slightly varrying the height of the water plane //This part is to emulate tides, slightly varrying the height of the water plane
private float time = 0.0f; private float time = 0.0f;
private float waterHeight = 0.0f; private float waterHeight = 0.0f;
@ -180,6 +255,7 @@ public class TestPostWater extends SimpleApplication {
@Override @Override
public void simpleUpdate(float tpf) { public void simpleUpdate(float tpf) {
super.simpleUpdate(tpf); super.simpleUpdate(tpf);
// box.updateGeometricState();
time += tpf; time += tpf;
waterHeight = (float) Math.cos(((time * 0.6f) % FastMath.TWO_PI)) * 1.5f; waterHeight = (float) Math.cos(((time * 0.6f) % FastMath.TWO_PI)) * 1.5f;
water.setWaterHeight(initialWaterHeight + waterHeight); water.setWaterHeight(initialWaterHeight + waterHeight);

Loading…
Cancel
Save