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){
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){
if (GLContext.getCapabilities().GL_EXT_framebuffer_blit){

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

@ -80,12 +80,12 @@ public abstract class Filter implements Savable {
Collection<Caps> caps = renderer.getCaps();
if (numSamples > 1 && caps.contains(Caps.FrameBufferMultisample) && caps.contains(Caps.OpenGL31)) {
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);
} else {
renderFrameBuffer = new FrameBuffer(width, height, 1);
renderedTexture = new Texture2D(width, height, textureFormat);
// depthTexture = new Texture2D(width, height, depthBufferFormat);
// depthTexture = new Texture2D(width, height, depthBufferFormat);
}
renderFrameBuffer.setColorTexture(renderedTexture);
@ -200,7 +200,7 @@ public abstract class Filter implements Savable {
* @param renderManager
* @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) {
}
/**
* 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
* This method should always begin by super.write(ex);
@ -267,6 +275,14 @@ public abstract class Filter implements Savable {
public boolean isRequiresDepthTexture() {
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() {
return postRenderPasses;

@ -40,6 +40,7 @@ import com.jme3.export.InputCapsule;
import com.jme3.export.OutputCapsule;
import com.jme3.export.Savable;
import com.jme3.material.Material;
import com.jme3.post.filters.TranslucentBucketFilter;
import com.jme3.renderer.Camera;
import com.jme3.renderer.Caps;
import com.jme3.renderer.RenderManager;
@ -80,6 +81,10 @@ public class FilterPostProcessor implements SceneProcessor, Savable {
private int originalHeight;
private int lastFilterIndex = -1;
private boolean cameraInit = false;
// private boolean handleTranslucentBucket = false;
// private FrameBuffer transFrameBuffer;
// private Material transMaterial;
// private boolean isTransparencyRendered=false;
/**
* Create a FilterProcessor constructor
@ -159,8 +164,9 @@ public class FilterPostProcessor implements SceneProcessor, Savable {
filterCam.resize(buff.getWidth(), buff.getHeight(), true);
fsQuad.setPosition(0, 0);
}
if (mat.getAdditionalRenderState().isDepthWrite()) {
mat.getAdditionalRenderState().setDepthWrite(false);
}
fsQuad.setMaterial(mat);
fsQuad.updateGeometricState();
@ -179,14 +185,16 @@ public class FilterPostProcessor implements SceneProcessor, Savable {
for (Iterator<Filter> it = filters.iterator(); it.hasNext();) {
Filter filter = it.next();
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;
FrameBuffer buff = null;
boolean msDepth = depthTexture != null && depthTexture.getImage().getMultiSamples() > 1;
for (int i = 0; i < filters.size(); 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();
if (msDepth && filter.isRequiresDepthTexture()) {
mat.setInt("NumSamplesDepth", depthTexture.getImage().getMultiSamples());
}
mat.setTexture("Texture", tex);
if (tex.getImage().getMultiSamples() > 1) {
mat.setInt("NumSamples", tex.getImage().getMultiSamples());
} else {
mat.clearParam("NumSamples");
if (filter.isRequiresSceneTexture()) {
mat.setTexture("Texture", tex);
if (tex.getImage().getMultiSamples() > 1) {
mat.setInt("NumSamples", tex.getImage().getMultiSamples());
} else {
mat.clearParam("NumSamples");
}
}
FrameBuffer buff = outputBuffer;
buff = outputBuffer;
if (i != lastFilterIndex) {
buff = filter.getRenderFrameBuffer();
tex = filter.getRenderedTexture();
}
renderProcessing(r, buff, mat);
}
@ -240,11 +253,13 @@ public class FilterPostProcessor implements SceneProcessor, Savable {
public void postFrame(FrameBuffer out) {
FrameBuffer sceneBuffer = renderFrameBuffer;
if (renderFrameBufferMS != null && !renderer.getCaps().contains(Caps.OpenGL31)) {
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);
filterTexture = msColor;
depthTexture = msDepth;
// samplePositions = ((LwjglRenderer) renderer).getFrameBufferSamplePositions(renderFrameBufferMS);
} else {
renderFrameBufferMS.setDepthBuffer(Format.Depth);
renderFrameBufferMS.setColorBuffer(Format.RGBA8);
@ -420,4 +434,12 @@ public class FilterPostProcessor implements SceneProcessor, Savable {
numSamples = ic.readInt("numSamples", 0);
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();
//temp technique
private String tmpTech;
private boolean handleTranlucentBucket = true;
/**
* Create a high-level rendering interface over the
@ -518,7 +519,7 @@ public class RenderManager {
//restoring cam state before proceeding children recusively
vp.getCamera().setPlaneState(camState);
renderScene(children.get(i), vp);
}
} 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) {
// this will make sure to update viewport only if needed
if (cam != prevCam || cam.isViewportChanged()) {
@ -729,7 +737,8 @@ public class RenderManager {
proc.postFrame(vp.getOutputFrameBuffer());
}
}
//renders the translucent objects queue after processors have been rendered
renderTranslucentQueue(vp);
// clear any remaining spatials that were not rendered.
clearQueue(vp);
}
@ -768,4 +777,12 @@ public class RenderManager {
public void setAlphaToCoverage(boolean 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
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.jme3.renderer;
import com.jme3.light.LightList;
@ -138,6 +137,12 @@ public interface Renderer {
*/
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.
*/
@ -212,5 +217,4 @@ public interface Renderer {
* @param value
*/
public void setAlphaToCoverage(boolean value);
}

@ -29,7 +29,6 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.jme3.renderer.queue;
import com.jme3.renderer.Camera;
@ -42,28 +41,33 @@ public class RenderQueue {
private GeometryList opaqueList;
private GeometryList guiList;
private GeometryList transparentList;
private GeometryList translucentList;
private GeometryList skyList;
private GeometryList shadowRecv;
private GeometryList shadowCast;
public RenderQueue(){
this.opaqueList = new GeometryList(new OpaqueComparator());
public RenderQueue() {
this.opaqueList = new GeometryList(new OpaqueComparator());
this.guiList = new GeometryList(new GuiComparator());
this.transparentList = new GeometryList(new TransparentComparator());
this.translucentList = new GeometryList(new TransparentComparator());
this.skyList = new GeometryList(new NullComparator());
this.shadowRecv = new GeometryList(new OpaqueComparator());
this.shadowCast = new GeometryList(new OpaqueComparator());
}
public enum Bucket {
Gui,
Opaque,
Sky,
Transparent,
Translucent,
Inherit,
}
public enum ShadowMode {
Off,
Cast,
Receive,
@ -89,6 +93,8 @@ public class RenderQueue {
* by material first and front to back within the same material.
* <li>Bucket.Transparent: {@link com.jme3.renderer.queue.TransparentComparator} which
* 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
* at all.
* <li>Bucket.Gui: {@link com.jme3.renderer.queue.GuiComparator} sorts geometries back to
@ -108,15 +114,20 @@ public class RenderQueue {
case Transparent:
transparentList = new GeometryList(c);
break;
case Translucent:
translucentList = new GeometryList(c);
break;
default:
throw new UnsupportedOperationException("Unknown bucket type: "+bucket);
throw new UnsupportedOperationException("Unknown bucket type: " + bucket);
}
}
public void addToShadowQueue(Geometry g, ShadowMode shadBucket){
switch (shadBucket){
case Inherit: break;
case Off: break;
public void addToShadowQueue(Geometry g, ShadowMode shadBucket) {
switch (shadBucket) {
case Inherit:
break;
case Off:
break;
case Cast:
shadowCast.add(g);
break;
@ -128,7 +139,7 @@ public class RenderQueue {
shadowRecv.add(g);
break;
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:
transparentList.add(g);
break;
case Translucent:
translucentList.add(g);
break;
default:
throw new UnsupportedOperationException("Unknown bucket type: "+bucket);
throw new UnsupportedOperationException("Unknown bucket type: " + bucket);
}
}
public GeometryList getShadowQueueContent(ShadowMode shadBucket){
switch (shadBucket){
public GeometryList getShadowQueueContent(ShadowMode shadBucket) {
switch (shadBucket) {
case Cast:
return shadowCast;
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.sort();
for (int i = 0; i < list.size(); i++){
for (int i = 0; i < list.size(); i++) {
Spatial obj = list.get(i);
assert obj != null;
if (obj instanceof Geometry){
Geometry g = (Geometry) obj;
rm.renderGeometry(g);
// make sure to reset queue distance
}
if (obj != null)
if (obj instanceof Geometry) {
Geometry g = (Geometry) obj;
rm.renderGeometry(g);
// make sure to reset queue distance
}
if (obj != null) {
obj.queueDistance = Float.NEGATIVE_INFINITY;
}
}
if (clear)
if (clear) {
list.clear();
}
}
public void renderShadowQueue(GeometryList list, RenderManager rm, Camera cam, boolean clear){
renderGeometryList(list, rm, cam, clear);
public void renderShadowQueue(GeometryList list, RenderManager rm, Camera cam, boolean clear) {
renderGeometryList(list, rm, cam, clear);
}
public void renderShadowQueue(ShadowMode shadBucket, RenderManager rm, Camera cam, boolean clear){
switch (shadBucket){
public void renderShadowQueue(ShadowMode shadBucket, RenderManager rm, Camera cam, boolean clear) {
switch (shadBucket) {
case Cast:
renderGeometryList(shadowCast, rm, cam, clear);
break;
@ -197,8 +213,8 @@ public class RenderQueue {
}
}
public boolean isQueueEmpty(Bucket bucket){
switch (bucket){
public boolean isQueueEmpty(Bucket bucket) {
switch (bucket) {
case Gui:
return guiList.size() == 0;
case Opaque:
@ -207,17 +223,19 @@ public class RenderQueue {
return skyList.size() == 0;
case Transparent:
return transparentList.size() == 0;
case Translucent:
return translucentList.size() == 0;
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);
}
public void renderQueue(Bucket bucket, RenderManager rm, Camera cam, boolean clear){
switch (bucket){
public void renderQueue(Bucket bucket, RenderManager rm, Camera cam, boolean clear) {
switch (bucket) {
case Gui:
renderGeometryList(guiList, rm, cam, clear);
break;
@ -230,18 +248,22 @@ public class RenderQueue {
case Transparent:
renderGeometryList(transparentList, rm, cam, clear);
break;
case Translucent:
renderGeometryList(translucentList, rm, cam, clear);
break;
default:
throw new UnsupportedOperationException("Unsupported bucket type: "+bucket);
throw new UnsupportedOperationException("Unsupported bucket type: " + bucket);
}
}
public void clear(){
public void clear() {
opaqueList.clear();
guiList.clear();
transparentList.clear();
translucentList.clear();
skyList.clear();
shadowCast.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, boolean copyDepth) {
}
public void setFrameBuffer(FrameBuffer fb) {
}

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

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

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

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

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

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

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

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

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

@ -74,9 +74,6 @@ public class RadialBlurFilter extends Filter {
return material;
}
@Override
public void preRender(RenderManager renderManager, ViewPort viewPort) {
}
public float getSampleDist() {
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 Material downSampleMat;
private Pass downSamplePass;
private int downSampleFactor = 1;
private float downSampleFactor = 1f;
/**
* Create a Screen Space Ambiant Occlusion Filter
@ -101,7 +101,7 @@ public class SSAOFilter extends Filter {
}
@Override
public void preRender(RenderManager renderManager, ViewPort viewPort) {
public void postQueue(RenderManager renderManager, ViewPort viewPort) {
Renderer r = renderManager.getRenderer();
r.setFrameBuffer(normalPass.getRenderFrameBuffer());
renderManager.getRenderer().clearBuffers(true, true, true);
@ -123,7 +123,7 @@ public class SSAOFilter extends Filter {
postRenderPasses = new ArrayList<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();
@ -149,11 +149,11 @@ public class SSAOFilter extends Filter {
@Override
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().setMagFilter(Texture.MagFilter.Bilinear);
postRenderPasses.add(ssaoPass);
@ -174,7 +174,7 @@ public class SSAOFilter extends Filter {
float xScale = 1.0f / w;
float yScale = 1.0f / h;
float blurScale = 2.0f;
float blurScale = 2f;
material.setFloat("XScale", blurScale * xScale);
material.setFloat("YScale", blurScale * yScale);

@ -138,7 +138,7 @@ public class WaterFilter extends Filter {
}
@Override
public void preRender(RenderManager renderManager, ViewPort viewPort) {
public void postQueue(RenderManager renderManager, ViewPort viewPort) {
Camera sceneCam = viewPort.getCamera();
biasMatrix.mult(sceneCam.getViewProjectionMatrix(), textureProjMatrix);
material.setMatrix4("TextureProjMatrix", textureProjMatrix);
@ -171,7 +171,15 @@ public class WaterFilter extends Filter {
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);
if (!rtb) {
renderManager.setHandleTranslucentBucket(false);
}
renderManager.getRenderer().setFrameBuffer(viewPort.getOutputFrameBuffer());
renderManager.setCamera(sceneCam, false);
}

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

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

@ -33,6 +33,8 @@
package jme3test.light;
import com.jme3.app.SimpleApplication;
import com.jme3.effect.ParticleEmitter;
import com.jme3.effect.ParticleMesh;
import com.jme3.light.AmbientLight;
import com.jme3.light.DirectionalLight;
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));
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);
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.filters.BloomFilter;
import com.jme3.post.filters.CartoonEdgeFilter;
import com.jme3.post.filters.CrossHatchFilter;
import com.jme3.post.filters.FogFilter;
import com.jme3.post.filters.RadialBlurFilter;
import com.jme3.post.ssao.SSAOFilter;
@ -62,6 +63,7 @@ public class TestMultiViewsFilters extends SimpleApplication {
// create the geometry and attach it
Geometry teaGeom = (Geometry) assetManager.loadModel("Models/Teapot/Teapot.obj");
teaGeom.scale(3);
teaGeom.getMaterial().setColor("GlowColor", ColorRGBA.Green);
DirectionalLight dl = new DirectionalLight();
dl.setColor(ColorRGBA.White);
@ -109,18 +111,38 @@ public class TestMultiViewsFilters extends SimpleApplication {
view4.setClearFlags(true, true, true);
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));
final FilterPostProcessor fpp = new FilterPostProcessor(assetManager);
final FilterPostProcessor fpp2 = new FilterPostProcessor(assetManager);
final FilterPostProcessor fpp3 = 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)));
fpp3.addFilter(new CartoonEdgeFilter());
fpp2.addFilter(new BloomFilter());
fpp2.addFilter(new CrossHatchFilter());
final FogFilter ff = new FogFilter(ColorRGBA.Yellow, 0.7f, 2);
fpp.addFilter(ff);
@ -132,11 +154,14 @@ public class TestMultiViewsFilters extends SimpleApplication {
SSAOFilter f = new SSAOFilter(1.8899765f, 20.490374f, 0.4699998f, 0.1f);;
fpp4.addFilter(f);
SSAOUI ui = new SSAOUI(inputManager, f);
fpp5.addFilter(new BloomFilter(BloomFilter.GlowMode.Objects));
viewPort.addProcessor(fpp);
view2.addProcessor(fpp2);
view3.addProcessor(fpp3);
view4.addProcessor(fpp4);
view5.addProcessor(fpp5);
@ -149,11 +174,13 @@ public class TestMultiViewsFilters extends SimpleApplication {
view2.removeProcessor(fpp2);
view3.removeProcessor(fpp3);
view4.removeProcessor(fpp4);
view5.removeProcessor(fpp5);
} else {
viewPort.addProcessor(fpp);
view2.addProcessor(fpp2);
view3.addProcessor(fpp3);
view4.addProcessor(fpp4);
view5.addProcessor(fpp5);
}
filterEnabled = !filterEnabled;
}

@ -3,20 +3,29 @@ package jme3test.water;
import com.jme3.app.SimpleApplication;
import com.jme3.audio.AudioNode;
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.KeyTrigger;
import com.jme3.light.DirectionalLight;
import com.jme3.material.Material;
import com.jme3.material.RenderState.BlendMode;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
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.queue.RenderQueue.Bucket;
import com.jme3.renderer.queue.RenderQueue.ShadowMode;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.shape.Box;
import com.jme3.terrain.geomipmap.TerrainQuad;
import com.jme3.terrain.heightmap.AbstractHeightMap;
import com.jme3.terrain.heightmap.ImageBasedHeightMap;
@ -35,7 +44,6 @@ import jme3tools.converters.ImageToAwt;
*/
public class TestPostWater extends SimpleApplication {
private FilterPostProcessor fpp;
private Vector3f lightDir = new Vector3f(-4.9236743f, -1.27054665f, 5.896916f);
private WaterFilter water;
TerrainQuad terrain;
@ -65,10 +73,10 @@ public class TestPostWater extends SimpleApplication {
l.setColor(ColorRGBA.White.clone().multLocal(0.3f));
mainScene.addLight(l);
flyCam.setMoveSpeed(50);
flyCam.setMoveSpeed(100);
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);
@ -80,44 +88,112 @@ public class TestPostWater extends SimpleApplication {
waves.setLooping(true);
audioRenderer.playSource(waves);
//private FilterPostProcessor fpp;
fpp = new FilterPostProcessor(assetManager);
// fpp.setNumSamples(4);
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.setMaxAmplitude(2f);
water.setFoamExistence(new Vector3f(1f, 4, 0.5f));
water.setFoamTexture((Texture2D) assetManager.loadTexture("Common/MatDefs/Water/Textures/foam2.jpg"));
//water.setNormalScale(0.5f);
//water.setRefractionConstant(0.25f);
water.setRefractionStrength(0.2f);
water.setRefractionStrength(0.2f);
//water.setFoamHardness(0.6f);
water.setWaterHeight(initialWaterHeight);
fpp.addFilter(water);
//
viewPort.addProcessor(fpp);
inputManager.addListener(new ActionListener() {
public void onAction(String name, boolean isPressed, float tpf) {
if(isPressed){
if(name.equals("foam1")){
water.setFoamTexture((Texture2D) assetManager.loadTexture("Common/MatDefs/Water/Textures/foam.jpg"));
if (isPressed) {
if (name.equals("foam1")) {
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"));
}
if(name.equals("foam3")){
if (name.equals("foam3")) {
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("foam2", new KeyTrigger(keyInput.KEY_2));
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) {
@ -138,7 +214,7 @@ public class TestPostWater extends SimpleApplication {
rock.setWrap(WrapMode.Repeat);
matRock.setTexture("DiffuseMap_2", rock);
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);
Texture normalMap1 = assetManager.loadTexture("Textures/Terrain/splat/dirt_normal.png");
normalMap1.setWrap(WrapMode.Repeat);
@ -161,8 +237,8 @@ public class TestPostWater extends SimpleApplication {
List<Camera> cameras = new ArrayList<Camera>();
cameras.add(getCamera());
terrain.setMaterial(matRock);
terrain.setLocalScale(new Vector3f(5,5,5));
terrain.setLocalTranslation(new Vector3f(0,-30,0));
terrain.setLocalScale(new Vector3f(5, 5, 5));
terrain.setLocalTranslation(new Vector3f(0, -30, 0));
terrain.setModelBound(new BoundingBox());
terrain.updateModelBound();
terrain.setLocked(false); // unlock it so we can edit the height
@ -171,7 +247,6 @@ public class TestPostWater extends SimpleApplication {
rootNode.attachChild(terrain);
}
//This part is to emulate tides, slightly varrying the height of the water plane
private float time = 0.0f;
private float waterHeight = 0.0f;
@ -180,6 +255,7 @@ public class TestPostWater extends SimpleApplication {
@Override
public void simpleUpdate(float tpf) {
super.simpleUpdate(tpf);
// box.updateGeometricState();
time += tpf;
waterHeight = (float) Math.cos(((time * 0.6f) % FastMath.TWO_PI)) * 1.5f;
water.setWaterHeight(initialWaterHeight + waterHeight);

Loading…
Cancel
Save