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
33package jme3test.post;
34
35import com.jme3.app.SimpleApplication;
36import com.jme3.light.PointLight;
37import com.jme3.material.Material;
38import com.jme3.math.*;
39import com.jme3.post.SceneProcessor;
40import com.jme3.renderer.RenderManager;
41import com.jme3.renderer.ViewPort;
42import com.jme3.renderer.queue.RenderQueue;
43import com.jme3.scene.Geometry;
44import com.jme3.scene.Node;
45import com.jme3.texture.FrameBuffer;
46import com.jme3.texture.Image.Format;
47import com.jme3.texture.Texture2D;
48import com.jme3.ui.Picture;
49
50public 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             Don’t 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