1 /* 2 * Copyright (c) 2009-2010 jMonkeyEngine 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * * Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 package jme3test.post; 34 35 import com.jme3.app.SimpleApplication; 36 import com.jme3.light.PointLight; 37 import com.jme3.material.Material; 38 import com.jme3.math.*; 39 import com.jme3.post.SceneProcessor; 40 import com.jme3.renderer.RenderManager; 41 import com.jme3.renderer.ViewPort; 42 import com.jme3.renderer.queue.RenderQueue; 43 import com.jme3.scene.Geometry; 44 import com.jme3.scene.Node; 45 import com.jme3.texture.FrameBuffer; 46 import com.jme3.texture.Image.Format; 47 import com.jme3.texture.Texture2D; 48 import com.jme3.ui.Picture; 49 50 public class TestMultiRenderTarget extends SimpleApplication implements SceneProcessor { 51 52 private FrameBuffer fb; 53 private Texture2D diffuseData, normalData, specularData, depthData; 54 private Geometry sphere; 55 private Picture display1, display2, display3, display4; 56 57 private Picture display; 58 private Material mat; 59 60 public static void main(String[] args){ 61 TestMultiRenderTarget app = new TestMultiRenderTarget(); 62 app.start(); 63 } 64 65 @Override 66 public void simpleInitApp() { 67 viewPort.addProcessor(this); 68 renderManager.setForcedTechnique("GBuf"); 69 70 // flyCam.setEnabled(false); 71 cam.setLocation(new Vector3f(4.8037705f, 4.851632f, 10.789033f)); 72 cam.setRotation(new Quaternion(-0.05143692f, 0.9483723f, -0.21131563f, -0.230846f)); 73 74 Node tank = (Node) assetManager.loadModel("Models/HoverTank/Tank2.mesh.xml"); 75 76 //tankMesh.getMaterial().setColor("Specular", ColorRGBA.Black); 77 rootNode.attachChild(tank); 78 79 display1 = new Picture("Picture"); 80 display1.move(0, 0, -1); // make it appear behind stats view 81 display2 = (Picture) display1.clone(); 82 display3 = (Picture) display1.clone(); 83 display4 = (Picture) display1.clone(); 84 display = (Picture) display1.clone(); 85 86 ColorRGBA[] colors = new ColorRGBA[]{ 87 ColorRGBA.White, 88 ColorRGBA.Blue, 89 ColorRGBA.Cyan, 90 ColorRGBA.DarkGray, 91 ColorRGBA.Green, 92 ColorRGBA.Magenta, 93 ColorRGBA.Orange, 94 ColorRGBA.Pink, 95 ColorRGBA.Red, 96 ColorRGBA.Yellow 97 }; 98 99 for (int i = 0; i < 3; i++){ 100 PointLight pl = new PointLight(); 101 float angle = 0.314159265f * i; 102 pl.setPosition( new Vector3f(FastMath.cos(angle)*2f, 0, 103 FastMath.sin(angle)*2f)); 104 pl.setColor(colors[i]); 105 pl.setRadius(5); 106 rootNode.addLight(pl); 107 display.addLight(pl); 108 } 109 } 110 111 public void initialize(RenderManager rm, ViewPort vp) { 112 reshape(vp, vp.getCamera().getWidth(), vp.getCamera().getHeight()); 113 viewPort.setOutputFrameBuffer(fb); 114 guiViewPort.setClearFlags(true, true, true); 115 guiNode.attachChild(display); 116 // guiNode.attachChild(display1); 117 // guiNode.attachChild(display2); 118 // guiNode.attachChild(display3); 119 // guiNode.attachChild(display4); 120 guiNode.updateGeometricState(); 121 } 122 123 public void reshape(ViewPort vp, int w, int h) { 124 diffuseData = new Texture2D(w, h, Format.RGBA8); 125 normalData = new Texture2D(w, h, Format.RGBA8); 126 specularData = new Texture2D(w, h, Format.RGBA8); 127 depthData = new Texture2D(w, h, Format.Depth); 128 129 mat = new Material(assetManager, "Common/MatDefs/Light/Deferred.j3md"); 130 mat.setTexture("DiffuseData", diffuseData); 131 mat.setTexture("SpecularData", specularData); 132 mat.setTexture("NormalData", normalData); 133 mat.setTexture("DepthData", depthData); 134 135 display.setMaterial(mat); 136 display.setPosition(0, 0); 137 display.setWidth(w); 138 display.setHeight(h); 139 140 display1.setTexture(assetManager, diffuseData, false); 141 display2.setTexture(assetManager, normalData, false); 142 display3.setTexture(assetManager, specularData, false); 143 display4.setTexture(assetManager, depthData, false); 144 145 display1.setPosition(0, 0); 146 display2.setPosition(w/2, 0); 147 display3.setPosition(0, h/2); 148 display4.setPosition(w/2, h/2); 149 150 display1.setWidth(w/2); 151 display1.setHeight(h/2); 152 153 display2.setWidth(w/2); 154 display2.setHeight(h/2); 155 156 display3.setWidth(w/2); 157 display3.setHeight(h/2); 158 159 display4.setWidth(w/2); 160 display4.setHeight(h/2); 161 162 guiNode.updateGeometricState(); 163 164 fb = new FrameBuffer(w, h, 1); 165 fb.setDepthTexture(depthData); 166 fb.addColorTexture(diffuseData); 167 fb.addColorTexture(normalData); 168 fb.addColorTexture(specularData); 169 fb.setMultiTarget(true); 170 171 /* 172 * Marks pixels in front of the far light boundary 173 Render back-faces of light volume 174 Depth test GREATER-EQUAL 175 Write to stencil on depth pass 176 Skipped for very small distant lights 177 */ 178 179 /* 180 * Find amount of lit pixels inside the volume 181 Start pixel query 182 Render front faces of light volume 183 Depth test LESS-EQUAL 184 Dont write anything only EQUAL stencil test 185 */ 186 187 /* 188 * Enable conditional rendering 189 Based on query results from previous stage 190 GPU skips rendering for invisible lights 191 */ 192 193 /* 194 * Render front-faces of light volume 195 Depth test - LESS-EQUAL 196 Stencil test - EQUAL 197 Runs only on marked pixels inside light 198 */ 199 } 200 201 public boolean isInitialized() { 202 return diffuseData != null; 203 } 204 205 public void preFrame(float tpf) { 206 Matrix4f inverseViewProj = cam.getViewProjectionMatrix().invert(); 207 mat.setMatrix4("ViewProjectionMatrixInverse", inverseViewProj); 208 } 209 210 public void postQueue(RenderQueue rq) { 211 } 212 213 public void postFrame(FrameBuffer out) { 214 } 215 216 public void cleanup() { 217 } 218 219 } 220