Bläddra i källkod

* Added new uniform binding WorldMatrixInverseTranspose (thanks kwando)

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9197 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
Sha..rd 13 år sedan
förälder
incheckning
ea0617fa81
2 ändrade filer med 1345 tillägg och 1332 borttagningar
  1. 1175 1170
      engine/src/core/com/jme3/renderer/RenderManager.java
  2. 170 162
      engine/src/core/com/jme3/shader/UniformBinding.java

+ 1175 - 1170
engine/src/core/com/jme3/renderer/RenderManager.java

@@ -1,1170 +1,1175 @@
-/*
- * Copyright (c) 2009-2012 jMonkeyEngine
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
- *   may be used to endorse or promote products derived from this software
- *   without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * 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.material.Material;
-import com.jme3.material.MaterialDef;
-import com.jme3.material.RenderState;
-import com.jme3.material.Technique;
-import com.jme3.math.*;
-import com.jme3.post.SceneProcessor;
-import com.jme3.renderer.queue.GeometryList;
-import com.jme3.renderer.queue.RenderQueue;
-import com.jme3.renderer.queue.RenderQueue.Bucket;
-import com.jme3.renderer.queue.RenderQueue.ShadowMode;
-import com.jme3.scene.*;
-import com.jme3.shader.Uniform;
-import com.jme3.shader.UniformBinding;
-import com.jme3.shader.VarType;
-import com.jme3.system.NullRenderer;
-import com.jme3.system.Timer;
-import com.jme3.util.IntMap.Entry;
-import com.jme3.util.TempVars;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.logging.Logger;
-
-/**
- * <code>RenderManager</code> is a high-level rendering interface that is
- * above the Renderer implementation. RenderManager takes care
- * of rendering the scene graphs attached to each viewport and
- * handling SceneProcessors.
- *
- * @see SceneProcessor
- * @see ViewPort
- * @see Spatial
- */
-public class RenderManager {
-
-    private static final Logger logger = Logger.getLogger(RenderManager.class.getName());
-    
-    private Renderer renderer;
-    private Timer timer;
-    private ArrayList<ViewPort> preViewPorts = new ArrayList<ViewPort>();
-    private ArrayList<ViewPort> viewPorts = new ArrayList<ViewPort>();
-    private ArrayList<ViewPort> postViewPorts = new ArrayList<ViewPort>();
-    private Camera prevCam = null;
-    private Material forcedMaterial = null;
-    private String forcedTechnique = null;
-    private RenderState forcedRenderState = null;
-    private boolean shader;
-    private int viewX, viewY, viewWidth, viewHeight;
-    private float near, far;
-    private Matrix4f orthoMatrix = new Matrix4f();
-    private Matrix4f viewMatrix = new Matrix4f();
-    private Matrix4f projMatrix = new Matrix4f();
-    private Matrix4f viewProjMatrix = new Matrix4f();
-    private Matrix4f worldMatrix = new Matrix4f();
-    private Vector3f camUp = new Vector3f(),
-            camLeft = new Vector3f(),
-            camDir = new Vector3f(),
-            camLoc = new Vector3f();
-    //temp technique
-    private String tmpTech;
-    private boolean handleTranlucentBucket = true;
-
-    /**
-     * Create a high-level rendering interface over the
-     * low-level rendering interface.
-     * @param renderer
-     */
-    public RenderManager(Renderer renderer) {
-        this.renderer = renderer;
-        //this.shader = renderer.getCaps().contains(Caps.GLSL100);
-    }
-
-    /**
-     * Returns the pre ViewPort with the given name.
-     * 
-     * @param viewName The name of the pre ViewPort to look up
-     * @return The ViewPort, or null if not found.
-     * 
-     * @see #createPreView(java.lang.String, com.jme3.renderer.Camera) 
-     */
-    public ViewPort getPreView(String viewName) {
-        for (int i = 0; i < preViewPorts.size(); i++) {
-            if (preViewPorts.get(i).getName().equals(viewName)) {
-                return preViewPorts.get(i);
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Removes the specified pre ViewPort.
-     * 
-     * @param view The pre ViewPort to remove
-     * @return True if the ViewPort was removed successfully.
-     * 
-     * @see #createPreView(java.lang.String, com.jme3.renderer.Camera) 
-     */
-    public boolean removePreView(ViewPort view) {
-        return preViewPorts.remove(view);
-    }
-
-    /**
-     * Returns the main ViewPort with the given name.
-     * 
-     * @param viewName The name of the main ViewPort to look up
-     * @return The ViewPort, or null if not found.
-     * 
-     * @see #createMainView(java.lang.String, com.jme3.renderer.Camera) 
-     */
-    public ViewPort getMainView(String viewName) {
-        for (int i = 0; i < viewPorts.size(); i++) {
-            if (viewPorts.get(i).getName().equals(viewName)) {
-                return viewPorts.get(i);
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Removes the main ViewPort with the specified name.
-     * 
-     * @param viewName The main ViewPort name to remove
-     * @return True if the ViewPort was removed successfully.
-     * 
-     * @see #createMainView(java.lang.String, com.jme3.renderer.Camera) 
-     */
-    public boolean removeMainView(String viewName) {
-        for (int i = 0; i < viewPorts.size(); i++) {
-            if (viewPorts.get(i).getName().equals(viewName)) {
-                viewPorts.remove(i);
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Removes the specified main ViewPort.
-     * 
-     * @param view The main ViewPort to remove
-     * @return True if the ViewPort was removed successfully.
-     * 
-     * @see #createMainView(java.lang.String, com.jme3.renderer.Camera) 
-     */
-    public boolean removeMainView(ViewPort view) {
-        return viewPorts.remove(view);
-    }
-
-    /**
-     * Returns the post ViewPort with the given name.
-     * 
-     * @param viewName The name of the post ViewPort to look up
-     * @return The ViewPort, or null if not found.
-     * 
-     * @see #createPostView(java.lang.String, com.jme3.renderer.Camera) 
-     */
-    public ViewPort getPostView(String viewName) {
-        for (int i = 0; i < postViewPorts.size(); i++) {
-            if (postViewPorts.get(i).getName().equals(viewName)) {
-                return postViewPorts.get(i);
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Removes the post ViewPort with the specified name.
-     * 
-     * @param viewName The post ViewPort name to remove
-     * @return True if the ViewPort was removed successfully.
-     * 
-     * @see #createPostView(java.lang.String, com.jme3.renderer.Camera) 
-     */
-    public boolean removePostView(String viewName) {
-        for (int i = 0; i < postViewPorts.size(); i++) {
-            if (postViewPorts.get(i).getName().equals(viewName)) {
-                postViewPorts.remove(i);
-
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Removes the specified post ViewPort.
-     * 
-     * @param view The post ViewPort to remove
-     * @return True if the ViewPort was removed successfully.
-     * 
-     * @see #createPostView(java.lang.String, com.jme3.renderer.Camera) 
-     */
-    public boolean removePostView(ViewPort view) {
-        return postViewPorts.remove(view);
-    }
-
-    /**
-     * Returns a read-only list of all pre ViewPorts
-     * @return a read-only list of all pre ViewPorts
-     * @see #createPreView(java.lang.String, com.jme3.renderer.Camera) 
-     */
-    public List<ViewPort> getPreViews() {
-        return Collections.unmodifiableList(preViewPorts);
-    }
-
-    /**
-     * Returns a read-only list of all main ViewPorts
-     * @return a read-only list of all main ViewPorts
-     * @see #createMainView(java.lang.String, com.jme3.renderer.Camera) 
-     */
-    public List<ViewPort> getMainViews() {
-        return Collections.unmodifiableList(viewPorts);
-    }
-
-    /**
-     * Returns a read-only list of all post ViewPorts
-     * @return a read-only list of all post ViewPorts
-     * @see #createPostView(java.lang.String, com.jme3.renderer.Camera) 
-     */
-    public List<ViewPort> getPostViews() {
-        return Collections.unmodifiableList(postViewPorts);
-    }
-
-    /**
-     * Creates a new pre ViewPort, to display the given camera's content.
-     * <p>
-     * The view will be processed before the main and post viewports.
-     */
-    public ViewPort createPreView(String viewName, Camera cam) {
-        ViewPort vp = new ViewPort(viewName, cam);
-        preViewPorts.add(vp);
-        return vp;
-    }
-
-    /**
-     * Creates a new main ViewPort, to display the given camera's content.
-     * <p>
-     * The view will be processed before the post viewports but after
-     * the pre viewports.
-     */
-    public ViewPort createMainView(String viewName, Camera cam) {
-        ViewPort vp = new ViewPort(viewName, cam);
-        viewPorts.add(vp);
-        return vp;
-    }
-
-    /**
-     * Creates a new post ViewPort, to display the given camera's content.
-     * <p>
-     * The view will be processed after the pre and main viewports.
-     */
-    public ViewPort createPostView(String viewName, Camera cam) {
-        ViewPort vp = new ViewPort(viewName, cam);
-        postViewPorts.add(vp);
-        return vp;
-    }
-
-    private void notifyReshape(ViewPort vp, int w, int h) {
-        List<SceneProcessor> processors = vp.getProcessors();
-        for (SceneProcessor proc : processors) {
-            if (!proc.isInitialized()) {
-                proc.initialize(this, vp);
-            } else {
-                proc.reshape(vp, w, h);
-            }
-        }
-    }
-
-    /**
-     * Internal use only.
-     * Updates the resolution of all on-screen cameras to match
-     * the given width and height.
-     */
-    public void notifyReshape(int w, int h) {
-        for (ViewPort vp : preViewPorts) {
-            if (vp.getOutputFrameBuffer() == null) {
-                Camera cam = vp.getCamera();
-                cam.resize(w, h, true);
-            }
-            notifyReshape(vp, w, h);
-        }
-        for (ViewPort vp : viewPorts) {
-            if (vp.getOutputFrameBuffer() == null) {
-                Camera cam = vp.getCamera();
-                cam.resize(w, h, true);
-            }
-            notifyReshape(vp, w, h);
-        }
-        for (ViewPort vp : postViewPorts) {
-            if (vp.getOutputFrameBuffer() == null) {
-                Camera cam = vp.getCamera();
-                cam.resize(w, h, true);
-            }
-            notifyReshape(vp, w, h);
-        }
-    }
-
-    /**
-     * Internal use only.
-     * Updates the given list of uniforms with {@link UniformBinding uniform bindings}
-     * based on the current world state.
-     */
-    public void updateUniformBindings(List<Uniform> params) {
-        // assums worldMatrix is properly set.
-        TempVars vars = TempVars.get();
-
-        Matrix4f tempMat4 = vars.tempMat4;
-        Matrix3f tempMat3 = vars.tempMat3;
-        Vector2f tempVec2 = vars.vect2d;
-        Quaternion tempVec4 = vars.quat1;
-
-        for (int i = 0; i < params.size(); i++) {
-            Uniform u = params.get(i);
-            switch (u.getBinding()) {
-                case WorldMatrix:
-                    u.setValue(VarType.Matrix4, worldMatrix);
-                    break;
-                case ViewMatrix:
-                    u.setValue(VarType.Matrix4, viewMatrix);
-                    break;
-                case ProjectionMatrix:
-                    u.setValue(VarType.Matrix4, projMatrix);
-                    break;
-                case ViewProjectionMatrix:
-                    u.setValue(VarType.Matrix4, viewProjMatrix);
-                    break;
-                case WorldViewMatrix:
-                    tempMat4.set(viewMatrix);
-                    tempMat4.multLocal(worldMatrix);
-                    u.setValue(VarType.Matrix4, tempMat4);
-                    break;
-                case NormalMatrix:
-                    tempMat4.set(viewMatrix);
-                    tempMat4.multLocal(worldMatrix);
-                    tempMat4.toRotationMatrix(tempMat3);
-                    tempMat3.invertLocal();
-                    tempMat3.transposeLocal();
-                    u.setValue(VarType.Matrix3, tempMat3);
-                    break;
-                case WorldViewProjectionMatrix:
-                    tempMat4.set(viewProjMatrix);
-                    tempMat4.multLocal(worldMatrix);
-                    u.setValue(VarType.Matrix4, tempMat4);
-                    break;
-                case WorldMatrixInverse:
-                    tempMat4.multLocal(worldMatrix);
-                    tempMat4.invertLocal();
-                    u.setValue(VarType.Matrix4, tempMat4);
-                    break;
-                case ViewMatrixInverse:
-                    tempMat4.set(viewMatrix);
-                    tempMat4.invertLocal();
-                    u.setValue(VarType.Matrix4, tempMat4);
-                    break;
-                case ProjectionMatrixInverse:
-                    tempMat4.set(projMatrix);
-                    tempMat4.invertLocal();
-                    u.setValue(VarType.Matrix4, tempMat4);
-                    break;
-                case ViewProjectionMatrixInverse:
-                    tempMat4.set(viewProjMatrix);
-                    tempMat4.invertLocal();
-                    u.setValue(VarType.Matrix4, tempMat4);
-                    break;
-                case WorldViewMatrixInverse:
-                    tempMat4.set(viewMatrix);
-                    tempMat4.multLocal(worldMatrix);
-                    tempMat4.invertLocal();
-                    u.setValue(VarType.Matrix4, tempMat4);
-                    break;
-                case NormalMatrixInverse:
-                    tempMat4.set(viewMatrix);
-                    tempMat4.multLocal(worldMatrix);
-                    tempMat4.toRotationMatrix(tempMat3);
-                    tempMat3.invertLocal();
-                    tempMat3.transposeLocal();
-                    tempMat3.invertLocal();
-                    u.setValue(VarType.Matrix3, tempMat3);
-                    break;
-                case WorldViewProjectionMatrixInverse:
-                    tempMat4.set(viewProjMatrix);
-                    tempMat4.multLocal(worldMatrix);
-                    tempMat4.invertLocal();
-                    u.setValue(VarType.Matrix4, tempMat4);
-                    break;
-                case ViewPort:
-                    tempVec4.set(viewX, viewY, viewWidth, viewHeight);
-                    u.setValue(VarType.Vector4, tempVec4);
-                    break;
-                case Resolution:
-                    tempVec2.set(viewWidth, viewHeight);
-                    u.setValue(VarType.Vector2, tempVec2);
-                    break;
-                case Aspect:
-                    float aspect = ((float) viewWidth) / viewHeight;
-                    u.setValue(VarType.Float, aspect);
-                    break;
-                case FrustumNearFar:
-                    tempVec2.set(near, far);
-                    u.setValue(VarType.Vector2, tempVec2);
-                    break;
-                case CameraPosition:
-                    u.setValue(VarType.Vector3, camLoc);
-                    break;
-                case CameraDirection:
-                    u.setValue(VarType.Vector3, camDir);
-                    break;
-                case CameraLeft:
-                    u.setValue(VarType.Vector3, camLeft);
-                    break;
-                case CameraUp:
-                    u.setValue(VarType.Vector3, camUp);
-                    break;
-                case Time:
-                    u.setValue(VarType.Float, timer.getTimeInSeconds());
-                    break;
-                case Tpf:
-                    u.setValue(VarType.Float, timer.getTimePerFrame());
-                    break;
-                case FrameRate:
-                    u.setValue(VarType.Float, timer.getFrameRate());
-                    break;
-            }
-        }
-
-        vars.release();
-    }
-
-    /**
-     * Set the material to use to render all future objects.
-     * This overrides the material set on the geometry and renders
-     * with the provided material instead.
-     * Use null to clear the material and return renderer to normal
-     * functionality.
-     * @param mat The forced material to set, or null to return to normal
-     */
-    public void setForcedMaterial(Material mat) {
-        forcedMaterial = mat;
-    }
-
-    /**
-     * Returns the forced render state previously set with 
-     * {@link #setForcedRenderState(com.jme3.material.RenderState) }.
-     * @return the forced render state
-     */
-    public RenderState getForcedRenderState() {
-        return forcedRenderState;
-    }
-
-    /**
-     * Set the render state to use for all future objects.
-     * This overrides the render state set on the material and instead
-     * forces this render state to be applied for all future materials
-     * rendered. Set to null to return to normal functionality.
-     * 
-     * @param forcedRenderState The forced render state to set, or null
-     * to return to normal
-     */
-    public void setForcedRenderState(RenderState forcedRenderState) {
-        this.forcedRenderState = forcedRenderState;
-    }
-
-    /**
-     * Set the timer that should be used to query the time based
-     * {@link UniformBinding}s for material world parameters.
-     * 
-     * @param timer The timer to query time world parameters
-     */
-    public void setTimer(Timer timer) {
-        this.timer = timer;
-    }
-
-    /**
-     * Returns the forced technique name set.
-     * 
-     * @return the forced technique name set.
-     * 
-     * @see #setForcedTechnique(java.lang.String) 
-     */
-    public String getForcedTechnique() {
-        return forcedTechnique;
-    }
-
-    /**
-     * Sets the forced technique to use when rendering geometries.
-     * <p>
-     * If the specified technique name is available on the geometry's
-     * material, then it is used, otherwise, the 
-     * {@link #setForcedMaterial(com.jme3.material.Material) forced material} is used.
-     * If a forced material is not set and the forced technique name cannot
-     * be found on the material, the geometry will <em>not</em> be rendered.
-     * 
-     * @param forcedTechnique The forced technique name to use, set to null
-     * to return to normal functionality.
-     * 
-     * @see #renderGeometry(com.jme3.scene.Geometry) 
-     */
-    public void setForcedTechnique(String forcedTechnique) {
-        this.forcedTechnique = forcedTechnique;
-    }
-
-    /**
-     * Enable or disable alpha-to-coverage. 
-     * <p>
-     * When alpha to coverage is enabled and the renderer implementation
-     * supports it, then alpha blending will be replaced with alpha dissolve
-     * if multi-sampling is also set on the renderer.
-     * This feature allows avoiding of alpha blending artifacts due to
-     * lack of triangle-level back-to-front sorting.
-     * 
-     * @param value True to enable alpha-to-coverage, false otherwise.
-     */
-    public void setAlphaToCoverage(boolean value) {
-        renderer.setAlphaToCoverage(value);
-    }
-
-    /**
-     * True if the translucent bucket should automatically be rendered
-     * by the RenderManager.
-     * 
-     * @return Whether or not the translucent bucket is rendered.
-     * 
-     * @see #setHandleTranslucentBucket(boolean) 
-     */
-    public boolean isHandleTranslucentBucket() {
-        return handleTranlucentBucket;
-    }
-
-    /**
-     * Enable or disable rendering of the 
-     * {@link Bucket#Translucent translucent bucket}
-     * by the RenderManager. The default is enabled.
-     * 
-     * @param handleTranslucentBucket Whether or not the translucent bucket should
-     * be rendered.
-     */
-    public void setHandleTranslucentBucket(boolean handleTranslucentBucket) {
-        this.handleTranlucentBucket = handleTranslucentBucket;
-    }
-
-    /**
-     * Internal use only. Sets the world matrix to use for future
-     * rendering. This has no effect unless objects are rendered manually
-     * using {@link Material#render(com.jme3.scene.Geometry, com.jme3.renderer.RenderManager) }.
-     * Using {@link #renderGeometry(com.jme3.scene.Geometry) } will 
-     * override this value.
-     * 
-     * @param mat The world matrix to set
-     */
-    public void setWorldMatrix(Matrix4f mat) {
-        if (shader) {
-            worldMatrix.set(mat);
-        } else {
-            renderer.setWorldMatrix(mat);
-        }
-    }
-
-    /**
-     * Renders the given geometry.
-     * <p>
-     * First the proper world matrix is set, if 
-     * the geometry's {@link Geometry#setIgnoreTransform(boolean) ignore transform}
-     * feature is enabled, the identity world matrix is used, otherwise, the 
-     * geometry's {@link Geometry#getWorldMatrix() world transform matrix} is used. 
-     * <p>
-     * Once the world matrix is applied, the proper material is chosen for rendering.
-     * If a {@link #setForcedMaterial(com.jme3.material.Material) forced material} is
-     * set on this RenderManager, then it is used for rendering the geometry,
-     * otherwise, the {@link Geometry#getMaterial() geometry's material} is used.
-     * <p>
-     * If a {@link #setForcedTechnique(java.lang.String) forced technique} is
-     * set on this RenderManager, then it is selected automatically
-     * on the geometry's material and is used for rendering. Otherwise, one
-     * of the {@link MaterialDef#getDefaultTechniques() default techniques} is
-     * used.
-     * <p>
-     * If a {@link #setForcedRenderState(com.jme3.material.RenderState) forced
-     * render state} is set on this RenderManager, then it is used
-     * for rendering the material, and the material's own render state is ignored.
-     * Otherwise, the material's render state is used as intended.
-     * 
-     * @param g The geometry to render
-     * 
-     * @see Technique
-     * @see RenderState
-     * @see Material#selectTechnique(java.lang.String, com.jme3.renderer.RenderManager) 
-     * @see Material#render(com.jme3.scene.Geometry, com.jme3.renderer.RenderManager) 
-     */
-    public void renderGeometry(Geometry g) {
-        if (g.isIgnoreTransform()) {
-            setWorldMatrix(Matrix4f.IDENTITY);
-        } else {
-            setWorldMatrix(g.getWorldMatrix());
-        }
-
-        //if forcedTechnique we try to force it for render,
-        //if it does not exists in the mat def, we check for forcedMaterial and render the geom if not null
-        //else the geom is not rendered
-        if (forcedTechnique != null) {
-            if (g.getMaterial().getMaterialDef().getTechniqueDef(forcedTechnique) != null) {
-                tmpTech = g.getMaterial().getActiveTechnique() != null ? g.getMaterial().getActiveTechnique().getDef().getName() : "Default";
-                g.getMaterial().selectTechnique(forcedTechnique, this);
-                // use geometry's material
-                g.getMaterial().render(g, this);
-                g.getMaterial().selectTechnique(tmpTech, this);
-                //Reverted this part from revision 6197
-                //If forcedTechnique does not exists, and frocedMaterial is not set, the geom MUST NOT be rendered
-            } else if (forcedMaterial != null) {
-                // use forced material
-                forcedMaterial.render(g, this);
-            }
-        } else if (forcedMaterial != null) {
-            // use forced material
-            forcedMaterial.render(g, this);
-        } else {
-            g.getMaterial().render(g, this);
-        }
-    }
-
-    /**
-     * Renders the given GeometryList.
-     * <p>
-     * For every geometry in the list, the 
-     * {@link #renderGeometry(com.jme3.scene.Geometry) } method is called.
-     * 
-     * @param gl The geometry list to render.
-     * 
-     * @see GeometryList
-     * @see #renderGeometry(com.jme3.scene.Geometry) 
-     */
-    public void renderGeometryList(GeometryList gl) {
-        for (int i = 0; i < gl.size(); i++) {
-            renderGeometry(gl.get(i));
-        }
-    }
-
-    /**
-     * If a spatial is not inside the eye frustum, it
-     * is still rendered in the shadow frustum (shadow casting queue)
-     * through this recursive method.
-     */
-    private void renderShadow(Spatial s, RenderQueue rq) {
-        if (s instanceof Node) {
-            Node n = (Node) s;
-            List<Spatial> children = n.getChildren();
-            for (int i = 0; i < children.size(); i++) {
-                renderShadow(children.get(i), rq);
-            }
-        } else if (s instanceof Geometry) {
-            Geometry gm = (Geometry) s;
-
-            RenderQueue.ShadowMode shadowMode = s.getShadowMode();
-            if (shadowMode != RenderQueue.ShadowMode.Off && shadowMode != RenderQueue.ShadowMode.Receive) {
-                //forcing adding to shadow cast mode, culled objects doesn't have to be in the receiver queue
-                rq.addToShadowQueue(gm, RenderQueue.ShadowMode.Cast);
-            }
-        }
-    }
-
-    /**
-     * Preloads a scene for rendering.
-     * <p>
-     * After invocation of this method, the underlying
-     * renderer would have uploaded any textures, shaders and meshes
-     * used by the given scene to the video driver. 
-     * Using this method is useful when wishing to avoid the initial pause
-     * when rendering a scene for the first time. Note that it is not 
-     * guaranteed that the underlying renderer will actually choose to upload
-     * the data to the GPU so some pause is still to be expected.
-     * 
-     * @param scene The scene to preload
-     */
-    public void preloadScene(Spatial scene) {
-        if (scene instanceof Node) {
-            // recurse for all children
-            Node n = (Node) scene;
-            List<Spatial> children = n.getChildren();
-            for (int i = 0; i < children.size(); i++) {
-                preloadScene(children.get(i));
-            }
-        } else if (scene instanceof Geometry) {
-            // add to the render queue
-            Geometry gm = (Geometry) scene;
-            if (gm.getMaterial() == null) {
-                throw new IllegalStateException("No material is set for Geometry: " + gm.getName());
-            }
-
-            gm.getMaterial().preload(this);
-            Mesh mesh = gm.getMesh();
-            if (mesh != null) {
-                for (Entry<VertexBuffer> entry : mesh.getBuffers()) {
-                    VertexBuffer buf = entry.getValue();
-                    if (buf.getData() != null) {
-                        renderer.updateBufferData(buf);
-                    }
-                }
-            }
-        }
-    }
-
-    /**
-     * Flattens the given scene graph into the ViewPort's RenderQueue,
-     * checking for culling as the call goes down the graph recursively.
-     * <p>
-     * First, the scene is checked for culling based on the <code>Spatial</code>s
-     * {@link Spatial#setCullHint(com.jme3.scene.Spatial.CullHint) cull hint},
-     * if the camera frustum contains the scene, then this method is recursively
-     * called on its children.
-     * <p>
-     * When the scene's leaves or {@link Geometry geometries} are reached,
-     * they are each enqueued into the 
-     * {@link ViewPort#getQueue() ViewPort's render queue}.
-     * <p>
-     * In addition to enqueuing the visible geometries, this method
-     * also scenes which cast or receive shadows, by putting them into the
-     * RenderQueue's 
-     * {@link RenderQueue#addToShadowQueue(com.jme3.scene.Geometry, com.jme3.renderer.queue.RenderQueue.ShadowMode) 
-     * shadow queue}. Each Spatial which has its 
-     * {@link Spatial#setShadowMode(com.jme3.renderer.queue.RenderQueue.ShadowMode) shadow mode}
-     * set to not off, will be put into the appropriate shadow queue, note that
-     * this process does not check for frustum culling on any 
-     * {@link ShadowMode#Cast shadow casters}, as they don't have to be
-     * in the eye camera frustum to cast shadows on objects that are inside it.
-     * 
-     * @param scene The scene to flatten into the queue
-     * @param vp The ViewPort provides the {@link ViewPort#getCamera() camera}
-     * used for culling and the {@link ViewPort#getQueue() queue} used to 
-     * contain the flattened scene graph.
-     */
-    public void renderScene(Spatial scene, ViewPort vp) {
-        if (scene.getParent() == null) {
-            vp.getCamera().setPlaneState(0);
-        }
-        // check culling first.
-        if (!scene.checkCulling(vp.getCamera())) {
-            // move on to shadow-only render
-            if ((scene.getShadowMode() != RenderQueue.ShadowMode.Off || scene instanceof Node) && scene.getCullHint()!=Spatial.CullHint.Always) {
-                renderShadow(scene, vp.getQueue());
-            }
-            return;
-        }
-
-        scene.runControlRender(this, vp);
-        if (scene instanceof Node) {
-            // recurse for all children
-            Node n = (Node) scene;
-            List<Spatial> children = n.getChildren();
-            //saving cam state for culling
-            int camState = vp.getCamera().getPlaneState();
-            for (int i = 0; i < children.size(); i++) {
-                //restoring cam state before proceeding children recusively
-                vp.getCamera().setPlaneState(camState);
-                renderScene(children.get(i), vp);
-
-            }
-        } else if (scene instanceof Geometry) {
-
-            // add to the render queue
-            Geometry gm = (Geometry) scene;
-            if (gm.getMaterial() == null) {
-                throw new IllegalStateException("No material is set for Geometry: " + gm.getName());
-            }
-
-            vp.getQueue().addToQueue(gm, scene.getQueueBucket());
-
-            // add to shadow queue if needed
-            RenderQueue.ShadowMode shadowMode = scene.getShadowMode();
-            if (shadowMode != RenderQueue.ShadowMode.Off) {
-                vp.getQueue().addToShadowQueue(gm, shadowMode);
-            }
-        }
-    }
-
-    /**
-     * Returns the camera currently used for rendering.
-     * <p>
-     * The camera can be set with {@link #setCamera(com.jme3.renderer.Camera, boolean) }.
-     * 
-     * @return the camera currently used for rendering.
-     */
-    public Camera getCurrentCamera() {
-        return prevCam;
-    }
-
-    /**
-     * The renderer implementation used for rendering operations.
-     * 
-     * @return The renderer implementation
-     * 
-     * @see #RenderManager(com.jme3.renderer.Renderer) 
-     * @see Renderer
-     */
-    public Renderer getRenderer() {
-        return renderer;
-    }
-
-    /**
-     * Flushes the ViewPort's {@link ViewPort#getQueue() render queue}
-     * by rendering each of its visible buckets.
-     * By default the queues will automatically be cleared after rendering,
-     * so there's no need to clear them manually.
-     * 
-     * @param vp The ViewPort of which the queue will be flushed
-     * 
-     * @see RenderQueue#renderQueue(com.jme3.renderer.queue.RenderQueue.Bucket, com.jme3.renderer.RenderManager, com.jme3.renderer.Camera) 
-     * @see #renderGeometryList(com.jme3.renderer.queue.GeometryList) 
-     */
-    public void flushQueue(ViewPort vp) {
-        renderViewPortQueues(vp, true);
-    }
-
-    /**
-     * Clears the queue of the given ViewPort.
-     * Simply calls {@link RenderQueue#clear() } on the ViewPort's 
-     * {@link ViewPort#getQueue() render queue}.
-     * 
-     * @param vp The ViewPort of which the queue will be cleared.
-     * 
-     * @see RenderQueue#clear()
-     * @see ViewPort#getQueue()
-     */
-    public void clearQueue(ViewPort vp) {
-        vp.getQueue().clear();
-    }
-
-    /**
-     * Render the given viewport queues.
-     * <p>
-     * Changes the {@link Renderer#setDepthRange(float, float) depth range}
-     * appropriately as expected by each queue and then calls 
-     * {@link RenderQueue#renderQueue(com.jme3.renderer.queue.RenderQueue.Bucket, com.jme3.renderer.RenderManager, com.jme3.renderer.Camera, boolean) }
-     * on the queue. Makes sure to restore the depth range to [0, 1] 
-     * at the end of the call.
-     * Note that the {@link Bucket#Translucent translucent bucket} is NOT
-     * rendered by this method. Instead the user should call 
-     * {@link #renderTranslucentQueue(com.jme3.renderer.ViewPort) }
-     * after this call.
-     * 
-     * @param vp the viewport of which queue should be rendered
-     * @param flush If true, the queues will be cleared after
-     * rendering.
-     * 
-     * @see RenderQueue
-     * @see #renderTranslucentQueue(com.jme3.renderer.ViewPort) 
-     */
-    public void renderViewPortQueues(ViewPort vp, boolean flush) {
-        RenderQueue rq = vp.getQueue();
-        Camera cam = vp.getCamera();
-        boolean depthRangeChanged = false;
-
-        // render opaque objects with default depth range
-        // opaque objects are sorted front-to-back, reducing overdraw
-        rq.renderQueue(Bucket.Opaque, this, cam, flush);
-
-        // render the sky, with depth range set to the farthest
-        if (!rq.isQueueEmpty(Bucket.Sky)) {
-            renderer.setDepthRange(1, 1);
-            rq.renderQueue(Bucket.Sky, this, cam, flush);
-            depthRangeChanged = true;
-        }
-
-
-        // transparent objects are last because they require blending with the
-        // rest of the scene's objects. Consequently, they are sorted
-        // back-to-front.
-        if (!rq.isQueueEmpty(Bucket.Transparent)) {
-            if (depthRangeChanged) {
-                renderer.setDepthRange(0, 1);
-                depthRangeChanged = false;
-            }
-
-            rq.renderQueue(Bucket.Transparent, this, cam, flush);
-        }
-
-        if (!rq.isQueueEmpty(Bucket.Gui)) {
-            renderer.setDepthRange(0, 0);
-            setCamera(cam, true);
-            rq.renderQueue(Bucket.Gui, this, cam, flush);
-            setCamera(cam, false);
-            depthRangeChanged = true;
-        }
-
-        // restore range to default
-        if (depthRangeChanged) {
-            renderer.setDepthRange(0, 1);
-        }
-    }
-
-    /**
-     * Renders the {@link Bucket#Translucent translucent queue} on the viewPort.
-     * <p>
-     * This call does nothing unless {@link #setHandleTranslucentBucket(boolean) }
-     * is set to true. This method clears the translucent queue after rendering
-     * it.
-     * 
-     * @param vp The viewport of which the translucent queue should be rendered.
-     * 
-     * @see #renderViewPortQueues(com.jme3.renderer.ViewPort, boolean) 
-     * @see #setHandleTranslucentBucket(boolean) 
-     */
-    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()) {
-            viewX = (int) (cam.getViewPortLeft() * cam.getWidth());
-            viewY = (int) (cam.getViewPortBottom() * cam.getHeight());
-            viewWidth = (int) ((cam.getViewPortRight() - cam.getViewPortLeft()) * cam.getWidth());
-            viewHeight = (int) ((cam.getViewPortTop() - cam.getViewPortBottom()) * cam.getHeight());
-            renderer.setViewPort(viewX, viewY, viewWidth, viewHeight);
-            renderer.setClipRect(viewX, viewY, viewWidth, viewHeight);
-            cam.clearViewportChanged();
-            prevCam = cam;
-
-//            float translateX = viewWidth == viewX ? 0 : -(viewWidth + viewX) / (viewWidth - viewX);
-//            float translateY = viewHeight == viewY ? 0 : -(viewHeight + viewY) / (viewHeight - viewY);
-//            float scaleX = viewWidth == viewX ? 1f : 2f / (viewWidth - viewX);
-//            float scaleY = viewHeight == viewY ? 1f : 2f / (viewHeight - viewY);
-//            
-//            orthoMatrix.loadIdentity();
-//            orthoMatrix.setTranslation(translateX, translateY, 0);
-//            orthoMatrix.setScale(scaleX, scaleY, 0); 
-
-            orthoMatrix.loadIdentity();
-            orthoMatrix.setTranslation(-1f, -1f, 0f);
-            orthoMatrix.setScale(2f / cam.getWidth(), 2f / cam.getHeight(), 0f);
-        }
-    }
-
-    private void setViewProjection(Camera cam, boolean ortho) {
-        if (shader) {
-            if (ortho) {
-                viewMatrix.set(Matrix4f.IDENTITY);
-                projMatrix.set(orthoMatrix);
-                viewProjMatrix.set(orthoMatrix);
-            } else {
-                viewMatrix.set(cam.getViewMatrix());
-                projMatrix.set(cam.getProjectionMatrix());
-                viewProjMatrix.set(cam.getViewProjectionMatrix());
-            }
-
-            camLoc.set(cam.getLocation());
-            cam.getLeft(camLeft);
-            cam.getUp(camUp);
-            cam.getDirection(camDir);
-
-            near = cam.getFrustumNear();
-            far = cam.getFrustumFar();
-        } else {
-            if (ortho) {
-                renderer.setViewProjectionMatrices(Matrix4f.IDENTITY, orthoMatrix);
-            } else {
-                renderer.setViewProjectionMatrices(cam.getViewMatrix(),
-                        cam.getProjectionMatrix());
-            }
-
-        }
-    }
-
-    /**
-     * Set the camera to use for rendering.
-     * <p>
-     * First, the camera's 
-     * {@link Camera#setViewPort(float, float, float, float) view port parameters}
-     * are applied. Then, the camera's {@link Camera#getViewMatrix() view} and 
-     * {@link Camera#getProjectionMatrix() projection} matrices are set
-     * on the renderer. If <code>ortho</code> is <code>true</code>, then
-     * instead of using the camera's view and projection matrices, an ortho
-     * matrix is computed and used instead of the view projection matrix. 
-     * The ortho matrix converts from the range (0 ~ Width, 0 ~ Height, -1 ~ +1)
-     * to the clip range (-1 ~ +1, -1 ~ +1, -1 ~ +1).
-     * 
-     * @param cam The camera to set
-     * @param ortho True if to use orthographic projection (for GUI rendering),
-     * false if to use the camera's view and projection matrices.
-     */
-    public void setCamera(Camera cam, boolean ortho) {
-        setViewPort(cam);
-        setViewProjection(cam, ortho);
-    }
-
-    /**
-     * Draws the viewport but without notifying {@link SceneProcessor scene
-     * processors} of any rendering events.
-     * 
-     * @param vp The ViewPort to render
-     * 
-     * @see #renderViewPort(com.jme3.renderer.ViewPort, float) 
-     */
-    public void renderViewPortRaw(ViewPort vp) {
-        setCamera(vp.getCamera(), false);
-        List<Spatial> scenes = vp.getScenes();
-        for (int i = scenes.size() - 1; i >= 0; i--) {
-            renderScene(scenes.get(i), vp);
-        }
-        flushQueue(vp);
-    }
-
-    /**
-     * Renders the {@link ViewPort}.
-     * <p>
-     * If the ViewPort is {@link ViewPort#isEnabled() disabled}, this method
-     * returns immediately. Otherwise, the ViewPort is rendered by 
-     * the following process:<br>
-     * <ul>
-     * <li>All {@link SceneProcessor scene processors} that are attached
-     * to the ViewPort are {@link SceneProcessor#initialize(com.jme3.renderer.RenderManager, com.jme3.renderer.ViewPort) initialized}.
-     * </li>
-     * <li>The SceneProcessors' {@link SceneProcessor#preFrame(float) } method 
-     * is called.</li>
-     * <li>The ViewPort's {@link ViewPort#getOutputFrameBuffer() output framebuffer}
-     * is set on the Renderer</li>
-     * <li>The camera is set on the renderer, including its view port parameters.
-     * (see {@link #setCamera(com.jme3.renderer.Camera, boolean) })</li>
-     * <li>Any buffers that the ViewPort requests to be cleared are cleared
-     * and the {@link ViewPort#getBackgroundColor() background color} is set</li>
-     * <li>Every scene that is attached to the ViewPort is flattened into 
-     * the ViewPort's render queue 
-     * (see {@link #renderViewPortQueues(com.jme3.renderer.ViewPort, boolean) })
-     * </li>
-     * <li>The SceneProcessors' {@link SceneProcessor#postQueue(com.jme3.renderer.queue.RenderQueue) }
-     * method is called.</li>
-     * <li>The render queue is sorted and then flushed, sending
-     * rendering commands to the underlying Renderer implementation. 
-     * (see {@link #flushQueue(com.jme3.renderer.ViewPort) })</li>
-     * <li>The SceneProcessors' {@link SceneProcessor#postFrame(com.jme3.texture.FrameBuffer) }
-     * method is called.</li>
-     * <li>The translucent queue of the ViewPort is sorted and then flushed
-     * (see {@link #renderTranslucentQueue(com.jme3.renderer.ViewPort) })</li>
-     * <li>If any objects remained in the render queue, they are removed
-     * from the queue. This is generally objects added to the 
-     * {@link RenderQueue#renderShadowQueue(com.jme3.renderer.queue.RenderQueue.ShadowMode, com.jme3.renderer.RenderManager, com.jme3.renderer.Camera, boolean) 
-     * shadow queue}
-     * which were not rendered because of a missing shadow renderer.</li>
-     * </ul>
-     * 
-     * @param vp
-     * @param tpf 
-     */
-    public void renderViewPort(ViewPort vp, float tpf) {
-        if (!vp.isEnabled()) {
-            return;
-        }
-        List<SceneProcessor> processors = vp.getProcessors();
-        if (processors.isEmpty()) {
-            processors = null;
-        }
-
-        if (processors != null) {
-            for (SceneProcessor proc : processors) {
-                if (!proc.isInitialized()) {
-                    proc.initialize(this, vp);
-                }
-                proc.preFrame(tpf);
-            }
-        }
-
-        renderer.setFrameBuffer(vp.getOutputFrameBuffer());
-        setCamera(vp.getCamera(), false);
-        if (vp.isClearDepth() || vp.isClearColor() || vp.isClearStencil()) {
-            if (vp.isClearColor()) {
-                renderer.setBackgroundColor(vp.getBackgroundColor());
-            }
-            renderer.clearBuffers(vp.isClearColor(),
-                    vp.isClearDepth(),
-                    vp.isClearStencil());
-        }
-
-        List<Spatial> scenes = vp.getScenes();
-        for (int i = scenes.size() - 1; i >= 0; i--) {
-            renderScene(scenes.get(i), vp);
-        }
-
-        if (processors != null) {
-            for (SceneProcessor proc : processors) {
-                proc.postQueue(vp.getQueue());
-            }
-        }
-
-        flushQueue(vp);
-
-        if (processors != null) {
-            for (SceneProcessor proc : processors) {
-                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);
-    }
-
-    /**
-     * Called by the application to render any ViewPorts
-     * added to this RenderManager.
-     * <p>
-     * Renders any viewports that were added using the following methods:
-     * <ul>
-     * <li>{@link #createPreView(java.lang.String, com.jme3.renderer.Camera) }</li>
-     * <li>{@link #createMainView(java.lang.String, com.jme3.renderer.Camera) }</li>
-     * <li>{@link #createPostView(java.lang.String, com.jme3.renderer.Camera) }</li>
-     * </ul>
-     * 
-     * @param tpf Time per frame value
-     */
-    public void render(float tpf, boolean mainFrameBufferActive) {
-        if (renderer instanceof NullRenderer) {
-            return;
-        }
-
-        this.shader = renderer.getCaps().contains(Caps.GLSL100);
-
-        for (int i = 0; i < preViewPorts.size(); i++) {
-            ViewPort vp = preViewPorts.get(i);
-            if (vp.getOutputFrameBuffer() != null || mainFrameBufferActive){
-                renderViewPort(vp, tpf);
-            }
-        }
-        for (int i = 0; i < viewPorts.size(); i++) {
-            ViewPort vp = viewPorts.get(i);
-            if (vp.getOutputFrameBuffer() != null || mainFrameBufferActive){
-                renderViewPort(vp, tpf);
-            }
-        }
-        for (int i = 0; i < postViewPorts.size(); i++) {
-            ViewPort vp = postViewPorts.get(i);
-            if (vp.getOutputFrameBuffer() != null || mainFrameBufferActive){
-                renderViewPort(vp, tpf);
-            }
-        }
-    }
-}
+/*
+ * Copyright (c) 2009-2012 jMonkeyEngine
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ *   may be used to endorse or promote products derived from this software
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * 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.material.Material;
+import com.jme3.material.MaterialDef;
+import com.jme3.material.RenderState;
+import com.jme3.material.Technique;
+import com.jme3.math.*;
+import com.jme3.post.SceneProcessor;
+import com.jme3.renderer.queue.GeometryList;
+import com.jme3.renderer.queue.RenderQueue;
+import com.jme3.renderer.queue.RenderQueue.Bucket;
+import com.jme3.renderer.queue.RenderQueue.ShadowMode;
+import com.jme3.scene.*;
+import com.jme3.shader.Uniform;
+import com.jme3.shader.UniformBinding;
+import com.jme3.shader.VarType;
+import com.jme3.system.NullRenderer;
+import com.jme3.system.Timer;
+import com.jme3.util.IntMap.Entry;
+import com.jme3.util.TempVars;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.logging.Logger;
+
+/**
+ * <code>RenderManager</code> is a high-level rendering interface that is
+ * above the Renderer implementation. RenderManager takes care
+ * of rendering the scene graphs attached to each viewport and
+ * handling SceneProcessors.
+ *
+ * @see SceneProcessor
+ * @see ViewPort
+ * @see Spatial
+ */
+public class RenderManager {
+
+    private static final Logger logger = Logger.getLogger(RenderManager.class.getName());
+    
+    private Renderer renderer;
+    private Timer timer;
+    private ArrayList<ViewPort> preViewPorts = new ArrayList<ViewPort>();
+    private ArrayList<ViewPort> viewPorts = new ArrayList<ViewPort>();
+    private ArrayList<ViewPort> postViewPorts = new ArrayList<ViewPort>();
+    private Camera prevCam = null;
+    private Material forcedMaterial = null;
+    private String forcedTechnique = null;
+    private RenderState forcedRenderState = null;
+    private boolean shader;
+    private int viewX, viewY, viewWidth, viewHeight;
+    private float near, far;
+    private Matrix4f orthoMatrix = new Matrix4f();
+    private Matrix4f viewMatrix = new Matrix4f();
+    private Matrix4f projMatrix = new Matrix4f();
+    private Matrix4f viewProjMatrix = new Matrix4f();
+    private Matrix4f worldMatrix = new Matrix4f();
+    private Vector3f camUp = new Vector3f(),
+            camLeft = new Vector3f(),
+            camDir = new Vector3f(),
+            camLoc = new Vector3f();
+    //temp technique
+    private String tmpTech;
+    private boolean handleTranlucentBucket = true;
+
+    /**
+     * Create a high-level rendering interface over the
+     * low-level rendering interface.
+     * @param renderer
+     */
+    public RenderManager(Renderer renderer) {
+        this.renderer = renderer;
+        //this.shader = renderer.getCaps().contains(Caps.GLSL100);
+    }
+
+    /**
+     * Returns the pre ViewPort with the given name.
+     * 
+     * @param viewName The name of the pre ViewPort to look up
+     * @return The ViewPort, or null if not found.
+     * 
+     * @see #createPreView(java.lang.String, com.jme3.renderer.Camera) 
+     */
+    public ViewPort getPreView(String viewName) {
+        for (int i = 0; i < preViewPorts.size(); i++) {
+            if (preViewPorts.get(i).getName().equals(viewName)) {
+                return preViewPorts.get(i);
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Removes the specified pre ViewPort.
+     * 
+     * @param view The pre ViewPort to remove
+     * @return True if the ViewPort was removed successfully.
+     * 
+     * @see #createPreView(java.lang.String, com.jme3.renderer.Camera) 
+     */
+    public boolean removePreView(ViewPort view) {
+        return preViewPorts.remove(view);
+    }
+
+    /**
+     * Returns the main ViewPort with the given name.
+     * 
+     * @param viewName The name of the main ViewPort to look up
+     * @return The ViewPort, or null if not found.
+     * 
+     * @see #createMainView(java.lang.String, com.jme3.renderer.Camera) 
+     */
+    public ViewPort getMainView(String viewName) {
+        for (int i = 0; i < viewPorts.size(); i++) {
+            if (viewPorts.get(i).getName().equals(viewName)) {
+                return viewPorts.get(i);
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Removes the main ViewPort with the specified name.
+     * 
+     * @param viewName The main ViewPort name to remove
+     * @return True if the ViewPort was removed successfully.
+     * 
+     * @see #createMainView(java.lang.String, com.jme3.renderer.Camera) 
+     */
+    public boolean removeMainView(String viewName) {
+        for (int i = 0; i < viewPorts.size(); i++) {
+            if (viewPorts.get(i).getName().equals(viewName)) {
+                viewPorts.remove(i);
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Removes the specified main ViewPort.
+     * 
+     * @param view The main ViewPort to remove
+     * @return True if the ViewPort was removed successfully.
+     * 
+     * @see #createMainView(java.lang.String, com.jme3.renderer.Camera) 
+     */
+    public boolean removeMainView(ViewPort view) {
+        return viewPorts.remove(view);
+    }
+
+    /**
+     * Returns the post ViewPort with the given name.
+     * 
+     * @param viewName The name of the post ViewPort to look up
+     * @return The ViewPort, or null if not found.
+     * 
+     * @see #createPostView(java.lang.String, com.jme3.renderer.Camera) 
+     */
+    public ViewPort getPostView(String viewName) {
+        for (int i = 0; i < postViewPorts.size(); i++) {
+            if (postViewPorts.get(i).getName().equals(viewName)) {
+                return postViewPorts.get(i);
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Removes the post ViewPort with the specified name.
+     * 
+     * @param viewName The post ViewPort name to remove
+     * @return True if the ViewPort was removed successfully.
+     * 
+     * @see #createPostView(java.lang.String, com.jme3.renderer.Camera) 
+     */
+    public boolean removePostView(String viewName) {
+        for (int i = 0; i < postViewPorts.size(); i++) {
+            if (postViewPorts.get(i).getName().equals(viewName)) {
+                postViewPorts.remove(i);
+
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Removes the specified post ViewPort.
+     * 
+     * @param view The post ViewPort to remove
+     * @return True if the ViewPort was removed successfully.
+     * 
+     * @see #createPostView(java.lang.String, com.jme3.renderer.Camera) 
+     */
+    public boolean removePostView(ViewPort view) {
+        return postViewPorts.remove(view);
+    }
+
+    /**
+     * Returns a read-only list of all pre ViewPorts
+     * @return a read-only list of all pre ViewPorts
+     * @see #createPreView(java.lang.String, com.jme3.renderer.Camera) 
+     */
+    public List<ViewPort> getPreViews() {
+        return Collections.unmodifiableList(preViewPorts);
+    }
+
+    /**
+     * Returns a read-only list of all main ViewPorts
+     * @return a read-only list of all main ViewPorts
+     * @see #createMainView(java.lang.String, com.jme3.renderer.Camera) 
+     */
+    public List<ViewPort> getMainViews() {
+        return Collections.unmodifiableList(viewPorts);
+    }
+
+    /**
+     * Returns a read-only list of all post ViewPorts
+     * @return a read-only list of all post ViewPorts
+     * @see #createPostView(java.lang.String, com.jme3.renderer.Camera) 
+     */
+    public List<ViewPort> getPostViews() {
+        return Collections.unmodifiableList(postViewPorts);
+    }
+
+    /**
+     * Creates a new pre ViewPort, to display the given camera's content.
+     * <p>
+     * The view will be processed before the main and post viewports.
+     */
+    public ViewPort createPreView(String viewName, Camera cam) {
+        ViewPort vp = new ViewPort(viewName, cam);
+        preViewPorts.add(vp);
+        return vp;
+    }
+
+    /**
+     * Creates a new main ViewPort, to display the given camera's content.
+     * <p>
+     * The view will be processed before the post viewports but after
+     * the pre viewports.
+     */
+    public ViewPort createMainView(String viewName, Camera cam) {
+        ViewPort vp = new ViewPort(viewName, cam);
+        viewPorts.add(vp);
+        return vp;
+    }
+
+    /**
+     * Creates a new post ViewPort, to display the given camera's content.
+     * <p>
+     * The view will be processed after the pre and main viewports.
+     */
+    public ViewPort createPostView(String viewName, Camera cam) {
+        ViewPort vp = new ViewPort(viewName, cam);
+        postViewPorts.add(vp);
+        return vp;
+    }
+
+    private void notifyReshape(ViewPort vp, int w, int h) {
+        List<SceneProcessor> processors = vp.getProcessors();
+        for (SceneProcessor proc : processors) {
+            if (!proc.isInitialized()) {
+                proc.initialize(this, vp);
+            } else {
+                proc.reshape(vp, w, h);
+            }
+        }
+    }
+
+    /**
+     * Internal use only.
+     * Updates the resolution of all on-screen cameras to match
+     * the given width and height.
+     */
+    public void notifyReshape(int w, int h) {
+        for (ViewPort vp : preViewPorts) {
+            if (vp.getOutputFrameBuffer() == null) {
+                Camera cam = vp.getCamera();
+                cam.resize(w, h, true);
+            }
+            notifyReshape(vp, w, h);
+        }
+        for (ViewPort vp : viewPorts) {
+            if (vp.getOutputFrameBuffer() == null) {
+                Camera cam = vp.getCamera();
+                cam.resize(w, h, true);
+            }
+            notifyReshape(vp, w, h);
+        }
+        for (ViewPort vp : postViewPorts) {
+            if (vp.getOutputFrameBuffer() == null) {
+                Camera cam = vp.getCamera();
+                cam.resize(w, h, true);
+            }
+            notifyReshape(vp, w, h);
+        }
+    }
+
+    /**
+     * Internal use only.
+     * Updates the given list of uniforms with {@link UniformBinding uniform bindings}
+     * based on the current world state.
+     */
+    public void updateUniformBindings(List<Uniform> params) {
+        // assums worldMatrix is properly set.
+        TempVars vars = TempVars.get();
+
+        Matrix4f tempMat4 = vars.tempMat4;
+        Matrix3f tempMat3 = vars.tempMat3;
+        Vector2f tempVec2 = vars.vect2d;
+        Quaternion tempVec4 = vars.quat1;
+
+        for (int i = 0; i < params.size(); i++) {
+            Uniform u = params.get(i);
+            switch (u.getBinding()) {
+                case WorldMatrix:
+                    u.setValue(VarType.Matrix4, worldMatrix);
+                    break;
+                case ViewMatrix:
+                    u.setValue(VarType.Matrix4, viewMatrix);
+                    break;
+                case ProjectionMatrix:
+                    u.setValue(VarType.Matrix4, projMatrix);
+                    break;
+                case ViewProjectionMatrix:
+                    u.setValue(VarType.Matrix4, viewProjMatrix);
+                    break;
+                case WorldViewMatrix:
+                    tempMat4.set(viewMatrix);
+                    tempMat4.multLocal(worldMatrix);
+                    u.setValue(VarType.Matrix4, tempMat4);
+                    break;
+                case NormalMatrix:
+                    tempMat4.set(viewMatrix);
+                    tempMat4.multLocal(worldMatrix);
+                    tempMat4.toRotationMatrix(tempMat3);
+                    tempMat3.invertLocal();
+                    tempMat3.transposeLocal();
+                    u.setValue(VarType.Matrix3, tempMat3);
+                    break;
+                case WorldViewProjectionMatrix:
+                    tempMat4.set(viewProjMatrix);
+                    tempMat4.multLocal(worldMatrix);
+                    u.setValue(VarType.Matrix4, tempMat4);
+                    break;
+                case WorldMatrixInverse:
+                    tempMat4.multLocal(worldMatrix);
+                    tempMat4.invertLocal();
+                    u.setValue(VarType.Matrix4, tempMat4);
+                    break;
+                case WorldMatrixInverseTranspose:
+                    worldMatrix.toRotationMatrix(tempMat3);
+                    tempMat3.invertLocal().transposeLocal();
+                    u.setValue(VarType.Matrix3, tempMat3);
+                    break;
+                case ViewMatrixInverse:
+                    tempMat4.set(viewMatrix);
+                    tempMat4.invertLocal();
+                    u.setValue(VarType.Matrix4, tempMat4);
+                    break;
+                case ProjectionMatrixInverse:
+                    tempMat4.set(projMatrix);
+                    tempMat4.invertLocal();
+                    u.setValue(VarType.Matrix4, tempMat4);
+                    break;
+                case ViewProjectionMatrixInverse:
+                    tempMat4.set(viewProjMatrix);
+                    tempMat4.invertLocal();
+                    u.setValue(VarType.Matrix4, tempMat4);
+                    break;
+                case WorldViewMatrixInverse:
+                    tempMat4.set(viewMatrix);
+                    tempMat4.multLocal(worldMatrix);
+                    tempMat4.invertLocal();
+                    u.setValue(VarType.Matrix4, tempMat4);
+                    break;
+                case NormalMatrixInverse:
+                    tempMat4.set(viewMatrix);
+                    tempMat4.multLocal(worldMatrix);
+                    tempMat4.toRotationMatrix(tempMat3);
+                    tempMat3.invertLocal();
+                    tempMat3.transposeLocal();
+                    tempMat3.invertLocal();
+                    u.setValue(VarType.Matrix3, tempMat3);
+                    break;
+                case WorldViewProjectionMatrixInverse:
+                    tempMat4.set(viewProjMatrix);
+                    tempMat4.multLocal(worldMatrix);
+                    tempMat4.invertLocal();
+                    u.setValue(VarType.Matrix4, tempMat4);
+                    break;
+                case ViewPort:
+                    tempVec4.set(viewX, viewY, viewWidth, viewHeight);
+                    u.setValue(VarType.Vector4, tempVec4);
+                    break;
+                case Resolution:
+                    tempVec2.set(viewWidth, viewHeight);
+                    u.setValue(VarType.Vector2, tempVec2);
+                    break;
+                case Aspect:
+                    float aspect = ((float) viewWidth) / viewHeight;
+                    u.setValue(VarType.Float, aspect);
+                    break;
+                case FrustumNearFar:
+                    tempVec2.set(near, far);
+                    u.setValue(VarType.Vector2, tempVec2);
+                    break;
+                case CameraPosition:
+                    u.setValue(VarType.Vector3, camLoc);
+                    break;
+                case CameraDirection:
+                    u.setValue(VarType.Vector3, camDir);
+                    break;
+                case CameraLeft:
+                    u.setValue(VarType.Vector3, camLeft);
+                    break;
+                case CameraUp:
+                    u.setValue(VarType.Vector3, camUp);
+                    break;
+                case Time:
+                    u.setValue(VarType.Float, timer.getTimeInSeconds());
+                    break;
+                case Tpf:
+                    u.setValue(VarType.Float, timer.getTimePerFrame());
+                    break;
+                case FrameRate:
+                    u.setValue(VarType.Float, timer.getFrameRate());
+                    break;
+            }
+        }
+
+        vars.release();
+    }
+
+    /**
+     * Set the material to use to render all future objects.
+     * This overrides the material set on the geometry and renders
+     * with the provided material instead.
+     * Use null to clear the material and return renderer to normal
+     * functionality.
+     * @param mat The forced material to set, or null to return to normal
+     */
+    public void setForcedMaterial(Material mat) {
+        forcedMaterial = mat;
+    }
+
+    /**
+     * Returns the forced render state previously set with 
+     * {@link #setForcedRenderState(com.jme3.material.RenderState) }.
+     * @return the forced render state
+     */
+    public RenderState getForcedRenderState() {
+        return forcedRenderState;
+    }
+
+    /**
+     * Set the render state to use for all future objects.
+     * This overrides the render state set on the material and instead
+     * forces this render state to be applied for all future materials
+     * rendered. Set to null to return to normal functionality.
+     * 
+     * @param forcedRenderState The forced render state to set, or null
+     * to return to normal
+     */
+    public void setForcedRenderState(RenderState forcedRenderState) {
+        this.forcedRenderState = forcedRenderState;
+    }
+
+    /**
+     * Set the timer that should be used to query the time based
+     * {@link UniformBinding}s for material world parameters.
+     * 
+     * @param timer The timer to query time world parameters
+     */
+    public void setTimer(Timer timer) {
+        this.timer = timer;
+    }
+
+    /**
+     * Returns the forced technique name set.
+     * 
+     * @return the forced technique name set.
+     * 
+     * @see #setForcedTechnique(java.lang.String) 
+     */
+    public String getForcedTechnique() {
+        return forcedTechnique;
+    }
+
+    /**
+     * Sets the forced technique to use when rendering geometries.
+     * <p>
+     * If the specified technique name is available on the geometry's
+     * material, then it is used, otherwise, the 
+     * {@link #setForcedMaterial(com.jme3.material.Material) forced material} is used.
+     * If a forced material is not set and the forced technique name cannot
+     * be found on the material, the geometry will <em>not</em> be rendered.
+     * 
+     * @param forcedTechnique The forced technique name to use, set to null
+     * to return to normal functionality.
+     * 
+     * @see #renderGeometry(com.jme3.scene.Geometry) 
+     */
+    public void setForcedTechnique(String forcedTechnique) {
+        this.forcedTechnique = forcedTechnique;
+    }
+
+    /**
+     * Enable or disable alpha-to-coverage. 
+     * <p>
+     * When alpha to coverage is enabled and the renderer implementation
+     * supports it, then alpha blending will be replaced with alpha dissolve
+     * if multi-sampling is also set on the renderer.
+     * This feature allows avoiding of alpha blending artifacts due to
+     * lack of triangle-level back-to-front sorting.
+     * 
+     * @param value True to enable alpha-to-coverage, false otherwise.
+     */
+    public void setAlphaToCoverage(boolean value) {
+        renderer.setAlphaToCoverage(value);
+    }
+
+    /**
+     * True if the translucent bucket should automatically be rendered
+     * by the RenderManager.
+     * 
+     * @return Whether or not the translucent bucket is rendered.
+     * 
+     * @see #setHandleTranslucentBucket(boolean) 
+     */
+    public boolean isHandleTranslucentBucket() {
+        return handleTranlucentBucket;
+    }
+
+    /**
+     * Enable or disable rendering of the 
+     * {@link Bucket#Translucent translucent bucket}
+     * by the RenderManager. The default is enabled.
+     * 
+     * @param handleTranslucentBucket Whether or not the translucent bucket should
+     * be rendered.
+     */
+    public void setHandleTranslucentBucket(boolean handleTranslucentBucket) {
+        this.handleTranlucentBucket = handleTranslucentBucket;
+    }
+
+    /**
+     * Internal use only. Sets the world matrix to use for future
+     * rendering. This has no effect unless objects are rendered manually
+     * using {@link Material#render(com.jme3.scene.Geometry, com.jme3.renderer.RenderManager) }.
+     * Using {@link #renderGeometry(com.jme3.scene.Geometry) } will 
+     * override this value.
+     * 
+     * @param mat The world matrix to set
+     */
+    public void setWorldMatrix(Matrix4f mat) {
+        if (shader) {
+            worldMatrix.set(mat);
+        } else {
+            renderer.setWorldMatrix(mat);
+        }
+    }
+
+    /**
+     * Renders the given geometry.
+     * <p>
+     * First the proper world matrix is set, if 
+     * the geometry's {@link Geometry#setIgnoreTransform(boolean) ignore transform}
+     * feature is enabled, the identity world matrix is used, otherwise, the 
+     * geometry's {@link Geometry#getWorldMatrix() world transform matrix} is used. 
+     * <p>
+     * Once the world matrix is applied, the proper material is chosen for rendering.
+     * If a {@link #setForcedMaterial(com.jme3.material.Material) forced material} is
+     * set on this RenderManager, then it is used for rendering the geometry,
+     * otherwise, the {@link Geometry#getMaterial() geometry's material} is used.
+     * <p>
+     * If a {@link #setForcedTechnique(java.lang.String) forced technique} is
+     * set on this RenderManager, then it is selected automatically
+     * on the geometry's material and is used for rendering. Otherwise, one
+     * of the {@link MaterialDef#getDefaultTechniques() default techniques} is
+     * used.
+     * <p>
+     * If a {@link #setForcedRenderState(com.jme3.material.RenderState) forced
+     * render state} is set on this RenderManager, then it is used
+     * for rendering the material, and the material's own render state is ignored.
+     * Otherwise, the material's render state is used as intended.
+     * 
+     * @param g The geometry to render
+     * 
+     * @see Technique
+     * @see RenderState
+     * @see Material#selectTechnique(java.lang.String, com.jme3.renderer.RenderManager) 
+     * @see Material#render(com.jme3.scene.Geometry, com.jme3.renderer.RenderManager) 
+     */
+    public void renderGeometry(Geometry g) {
+        if (g.isIgnoreTransform()) {
+            setWorldMatrix(Matrix4f.IDENTITY);
+        } else {
+            setWorldMatrix(g.getWorldMatrix());
+        }
+
+        //if forcedTechnique we try to force it for render,
+        //if it does not exists in the mat def, we check for forcedMaterial and render the geom if not null
+        //else the geom is not rendered
+        if (forcedTechnique != null) {
+            if (g.getMaterial().getMaterialDef().getTechniqueDef(forcedTechnique) != null) {
+                tmpTech = g.getMaterial().getActiveTechnique() != null ? g.getMaterial().getActiveTechnique().getDef().getName() : "Default";
+                g.getMaterial().selectTechnique(forcedTechnique, this);
+                // use geometry's material
+                g.getMaterial().render(g, this);
+                g.getMaterial().selectTechnique(tmpTech, this);
+                //Reverted this part from revision 6197
+                //If forcedTechnique does not exists, and frocedMaterial is not set, the geom MUST NOT be rendered
+            } else if (forcedMaterial != null) {
+                // use forced material
+                forcedMaterial.render(g, this);
+            }
+        } else if (forcedMaterial != null) {
+            // use forced material
+            forcedMaterial.render(g, this);
+        } else {
+            g.getMaterial().render(g, this);
+        }
+    }
+
+    /**
+     * Renders the given GeometryList.
+     * <p>
+     * For every geometry in the list, the 
+     * {@link #renderGeometry(com.jme3.scene.Geometry) } method is called.
+     * 
+     * @param gl The geometry list to render.
+     * 
+     * @see GeometryList
+     * @see #renderGeometry(com.jme3.scene.Geometry) 
+     */
+    public void renderGeometryList(GeometryList gl) {
+        for (int i = 0; i < gl.size(); i++) {
+            renderGeometry(gl.get(i));
+        }
+    }
+
+    /**
+     * If a spatial is not inside the eye frustum, it
+     * is still rendered in the shadow frustum (shadow casting queue)
+     * through this recursive method.
+     */
+    private void renderShadow(Spatial s, RenderQueue rq) {
+        if (s instanceof Node) {
+            Node n = (Node) s;
+            List<Spatial> children = n.getChildren();
+            for (int i = 0; i < children.size(); i++) {
+                renderShadow(children.get(i), rq);
+            }
+        } else if (s instanceof Geometry) {
+            Geometry gm = (Geometry) s;
+
+            RenderQueue.ShadowMode shadowMode = s.getShadowMode();
+            if (shadowMode != RenderQueue.ShadowMode.Off && shadowMode != RenderQueue.ShadowMode.Receive) {
+                //forcing adding to shadow cast mode, culled objects doesn't have to be in the receiver queue
+                rq.addToShadowQueue(gm, RenderQueue.ShadowMode.Cast);
+            }
+        }
+    }
+
+    /**
+     * Preloads a scene for rendering.
+     * <p>
+     * After invocation of this method, the underlying
+     * renderer would have uploaded any textures, shaders and meshes
+     * used by the given scene to the video driver. 
+     * Using this method is useful when wishing to avoid the initial pause
+     * when rendering a scene for the first time. Note that it is not 
+     * guaranteed that the underlying renderer will actually choose to upload
+     * the data to the GPU so some pause is still to be expected.
+     * 
+     * @param scene The scene to preload
+     */
+    public void preloadScene(Spatial scene) {
+        if (scene instanceof Node) {
+            // recurse for all children
+            Node n = (Node) scene;
+            List<Spatial> children = n.getChildren();
+            for (int i = 0; i < children.size(); i++) {
+                preloadScene(children.get(i));
+            }
+        } else if (scene instanceof Geometry) {
+            // add to the render queue
+            Geometry gm = (Geometry) scene;
+            if (gm.getMaterial() == null) {
+                throw new IllegalStateException("No material is set for Geometry: " + gm.getName());
+            }
+
+            gm.getMaterial().preload(this);
+            Mesh mesh = gm.getMesh();
+            if (mesh != null) {
+                for (Entry<VertexBuffer> entry : mesh.getBuffers()) {
+                    VertexBuffer buf = entry.getValue();
+                    if (buf.getData() != null) {
+                        renderer.updateBufferData(buf);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Flattens the given scene graph into the ViewPort's RenderQueue,
+     * checking for culling as the call goes down the graph recursively.
+     * <p>
+     * First, the scene is checked for culling based on the <code>Spatial</code>s
+     * {@link Spatial#setCullHint(com.jme3.scene.Spatial.CullHint) cull hint},
+     * if the camera frustum contains the scene, then this method is recursively
+     * called on its children.
+     * <p>
+     * When the scene's leaves or {@link Geometry geometries} are reached,
+     * they are each enqueued into the 
+     * {@link ViewPort#getQueue() ViewPort's render queue}.
+     * <p>
+     * In addition to enqueuing the visible geometries, this method
+     * also scenes which cast or receive shadows, by putting them into the
+     * RenderQueue's 
+     * {@link RenderQueue#addToShadowQueue(com.jme3.scene.Geometry, com.jme3.renderer.queue.RenderQueue.ShadowMode) 
+     * shadow queue}. Each Spatial which has its 
+     * {@link Spatial#setShadowMode(com.jme3.renderer.queue.RenderQueue.ShadowMode) shadow mode}
+     * set to not off, will be put into the appropriate shadow queue, note that
+     * this process does not check for frustum culling on any 
+     * {@link ShadowMode#Cast shadow casters}, as they don't have to be
+     * in the eye camera frustum to cast shadows on objects that are inside it.
+     * 
+     * @param scene The scene to flatten into the queue
+     * @param vp The ViewPort provides the {@link ViewPort#getCamera() camera}
+     * used for culling and the {@link ViewPort#getQueue() queue} used to 
+     * contain the flattened scene graph.
+     */
+    public void renderScene(Spatial scene, ViewPort vp) {
+        if (scene.getParent() == null) {
+            vp.getCamera().setPlaneState(0);
+        }
+        // check culling first.
+        if (!scene.checkCulling(vp.getCamera())) {
+            // move on to shadow-only render
+            if ((scene.getShadowMode() != RenderQueue.ShadowMode.Off || scene instanceof Node) && scene.getCullHint()!=Spatial.CullHint.Always) {
+                renderShadow(scene, vp.getQueue());
+            }
+            return;
+        }
+
+        scene.runControlRender(this, vp);
+        if (scene instanceof Node) {
+            // recurse for all children
+            Node n = (Node) scene;
+            List<Spatial> children = n.getChildren();
+            //saving cam state for culling
+            int camState = vp.getCamera().getPlaneState();
+            for (int i = 0; i < children.size(); i++) {
+                //restoring cam state before proceeding children recusively
+                vp.getCamera().setPlaneState(camState);
+                renderScene(children.get(i), vp);
+
+            }
+        } else if (scene instanceof Geometry) {
+
+            // add to the render queue
+            Geometry gm = (Geometry) scene;
+            if (gm.getMaterial() == null) {
+                throw new IllegalStateException("No material is set for Geometry: " + gm.getName());
+            }
+
+            vp.getQueue().addToQueue(gm, scene.getQueueBucket());
+
+            // add to shadow queue if needed
+            RenderQueue.ShadowMode shadowMode = scene.getShadowMode();
+            if (shadowMode != RenderQueue.ShadowMode.Off) {
+                vp.getQueue().addToShadowQueue(gm, shadowMode);
+            }
+        }
+    }
+
+    /**
+     * Returns the camera currently used for rendering.
+     * <p>
+     * The camera can be set with {@link #setCamera(com.jme3.renderer.Camera, boolean) }.
+     * 
+     * @return the camera currently used for rendering.
+     */
+    public Camera getCurrentCamera() {
+        return prevCam;
+    }
+
+    /**
+     * The renderer implementation used for rendering operations.
+     * 
+     * @return The renderer implementation
+     * 
+     * @see #RenderManager(com.jme3.renderer.Renderer) 
+     * @see Renderer
+     */
+    public Renderer getRenderer() {
+        return renderer;
+    }
+
+    /**
+     * Flushes the ViewPort's {@link ViewPort#getQueue() render queue}
+     * by rendering each of its visible buckets.
+     * By default the queues will automatically be cleared after rendering,
+     * so there's no need to clear them manually.
+     * 
+     * @param vp The ViewPort of which the queue will be flushed
+     * 
+     * @see RenderQueue#renderQueue(com.jme3.renderer.queue.RenderQueue.Bucket, com.jme3.renderer.RenderManager, com.jme3.renderer.Camera) 
+     * @see #renderGeometryList(com.jme3.renderer.queue.GeometryList) 
+     */
+    public void flushQueue(ViewPort vp) {
+        renderViewPortQueues(vp, true);
+    }
+
+    /**
+     * Clears the queue of the given ViewPort.
+     * Simply calls {@link RenderQueue#clear() } on the ViewPort's 
+     * {@link ViewPort#getQueue() render queue}.
+     * 
+     * @param vp The ViewPort of which the queue will be cleared.
+     * 
+     * @see RenderQueue#clear()
+     * @see ViewPort#getQueue()
+     */
+    public void clearQueue(ViewPort vp) {
+        vp.getQueue().clear();
+    }
+
+    /**
+     * Render the given viewport queues.
+     * <p>
+     * Changes the {@link Renderer#setDepthRange(float, float) depth range}
+     * appropriately as expected by each queue and then calls 
+     * {@link RenderQueue#renderQueue(com.jme3.renderer.queue.RenderQueue.Bucket, com.jme3.renderer.RenderManager, com.jme3.renderer.Camera, boolean) }
+     * on the queue. Makes sure to restore the depth range to [0, 1] 
+     * at the end of the call.
+     * Note that the {@link Bucket#Translucent translucent bucket} is NOT
+     * rendered by this method. Instead the user should call 
+     * {@link #renderTranslucentQueue(com.jme3.renderer.ViewPort) }
+     * after this call.
+     * 
+     * @param vp the viewport of which queue should be rendered
+     * @param flush If true, the queues will be cleared after
+     * rendering.
+     * 
+     * @see RenderQueue
+     * @see #renderTranslucentQueue(com.jme3.renderer.ViewPort) 
+     */
+    public void renderViewPortQueues(ViewPort vp, boolean flush) {
+        RenderQueue rq = vp.getQueue();
+        Camera cam = vp.getCamera();
+        boolean depthRangeChanged = false;
+
+        // render opaque objects with default depth range
+        // opaque objects are sorted front-to-back, reducing overdraw
+        rq.renderQueue(Bucket.Opaque, this, cam, flush);
+
+        // render the sky, with depth range set to the farthest
+        if (!rq.isQueueEmpty(Bucket.Sky)) {
+            renderer.setDepthRange(1, 1);
+            rq.renderQueue(Bucket.Sky, this, cam, flush);
+            depthRangeChanged = true;
+        }
+
+
+        // transparent objects are last because they require blending with the
+        // rest of the scene's objects. Consequently, they are sorted
+        // back-to-front.
+        if (!rq.isQueueEmpty(Bucket.Transparent)) {
+            if (depthRangeChanged) {
+                renderer.setDepthRange(0, 1);
+                depthRangeChanged = false;
+            }
+
+            rq.renderQueue(Bucket.Transparent, this, cam, flush);
+        }
+
+        if (!rq.isQueueEmpty(Bucket.Gui)) {
+            renderer.setDepthRange(0, 0);
+            setCamera(cam, true);
+            rq.renderQueue(Bucket.Gui, this, cam, flush);
+            setCamera(cam, false);
+            depthRangeChanged = true;
+        }
+
+        // restore range to default
+        if (depthRangeChanged) {
+            renderer.setDepthRange(0, 1);
+        }
+    }
+
+    /**
+     * Renders the {@link Bucket#Translucent translucent queue} on the viewPort.
+     * <p>
+     * This call does nothing unless {@link #setHandleTranslucentBucket(boolean) }
+     * is set to true. This method clears the translucent queue after rendering
+     * it.
+     * 
+     * @param vp The viewport of which the translucent queue should be rendered.
+     * 
+     * @see #renderViewPortQueues(com.jme3.renderer.ViewPort, boolean) 
+     * @see #setHandleTranslucentBucket(boolean) 
+     */
+    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()) {
+            viewX = (int) (cam.getViewPortLeft() * cam.getWidth());
+            viewY = (int) (cam.getViewPortBottom() * cam.getHeight());
+            viewWidth = (int) ((cam.getViewPortRight() - cam.getViewPortLeft()) * cam.getWidth());
+            viewHeight = (int) ((cam.getViewPortTop() - cam.getViewPortBottom()) * cam.getHeight());
+            renderer.setViewPort(viewX, viewY, viewWidth, viewHeight);
+            renderer.setClipRect(viewX, viewY, viewWidth, viewHeight);
+            cam.clearViewportChanged();
+            prevCam = cam;
+
+//            float translateX = viewWidth == viewX ? 0 : -(viewWidth + viewX) / (viewWidth - viewX);
+//            float translateY = viewHeight == viewY ? 0 : -(viewHeight + viewY) / (viewHeight - viewY);
+//            float scaleX = viewWidth == viewX ? 1f : 2f / (viewWidth - viewX);
+//            float scaleY = viewHeight == viewY ? 1f : 2f / (viewHeight - viewY);
+//            
+//            orthoMatrix.loadIdentity();
+//            orthoMatrix.setTranslation(translateX, translateY, 0);
+//            orthoMatrix.setScale(scaleX, scaleY, 0); 
+
+            orthoMatrix.loadIdentity();
+            orthoMatrix.setTranslation(-1f, -1f, 0f);
+            orthoMatrix.setScale(2f / cam.getWidth(), 2f / cam.getHeight(), 0f);
+        }
+    }
+
+    private void setViewProjection(Camera cam, boolean ortho) {
+        if (shader) {
+            if (ortho) {
+                viewMatrix.set(Matrix4f.IDENTITY);
+                projMatrix.set(orthoMatrix);
+                viewProjMatrix.set(orthoMatrix);
+            } else {
+                viewMatrix.set(cam.getViewMatrix());
+                projMatrix.set(cam.getProjectionMatrix());
+                viewProjMatrix.set(cam.getViewProjectionMatrix());
+            }
+
+            camLoc.set(cam.getLocation());
+            cam.getLeft(camLeft);
+            cam.getUp(camUp);
+            cam.getDirection(camDir);
+
+            near = cam.getFrustumNear();
+            far = cam.getFrustumFar();
+        } else {
+            if (ortho) {
+                renderer.setViewProjectionMatrices(Matrix4f.IDENTITY, orthoMatrix);
+            } else {
+                renderer.setViewProjectionMatrices(cam.getViewMatrix(),
+                        cam.getProjectionMatrix());
+            }
+
+        }
+    }
+
+    /**
+     * Set the camera to use for rendering.
+     * <p>
+     * First, the camera's 
+     * {@link Camera#setViewPort(float, float, float, float) view port parameters}
+     * are applied. Then, the camera's {@link Camera#getViewMatrix() view} and 
+     * {@link Camera#getProjectionMatrix() projection} matrices are set
+     * on the renderer. If <code>ortho</code> is <code>true</code>, then
+     * instead of using the camera's view and projection matrices, an ortho
+     * matrix is computed and used instead of the view projection matrix. 
+     * The ortho matrix converts from the range (0 ~ Width, 0 ~ Height, -1 ~ +1)
+     * to the clip range (-1 ~ +1, -1 ~ +1, -1 ~ +1).
+     * 
+     * @param cam The camera to set
+     * @param ortho True if to use orthographic projection (for GUI rendering),
+     * false if to use the camera's view and projection matrices.
+     */
+    public void setCamera(Camera cam, boolean ortho) {
+        setViewPort(cam);
+        setViewProjection(cam, ortho);
+    }
+
+    /**
+     * Draws the viewport but without notifying {@link SceneProcessor scene
+     * processors} of any rendering events.
+     * 
+     * @param vp The ViewPort to render
+     * 
+     * @see #renderViewPort(com.jme3.renderer.ViewPort, float) 
+     */
+    public void renderViewPortRaw(ViewPort vp) {
+        setCamera(vp.getCamera(), false);
+        List<Spatial> scenes = vp.getScenes();
+        for (int i = scenes.size() - 1; i >= 0; i--) {
+            renderScene(scenes.get(i), vp);
+        }
+        flushQueue(vp);
+    }
+
+    /**
+     * Renders the {@link ViewPort}.
+     * <p>
+     * If the ViewPort is {@link ViewPort#isEnabled() disabled}, this method
+     * returns immediately. Otherwise, the ViewPort is rendered by 
+     * the following process:<br>
+     * <ul>
+     * <li>All {@link SceneProcessor scene processors} that are attached
+     * to the ViewPort are {@link SceneProcessor#initialize(com.jme3.renderer.RenderManager, com.jme3.renderer.ViewPort) initialized}.
+     * </li>
+     * <li>The SceneProcessors' {@link SceneProcessor#preFrame(float) } method 
+     * is called.</li>
+     * <li>The ViewPort's {@link ViewPort#getOutputFrameBuffer() output framebuffer}
+     * is set on the Renderer</li>
+     * <li>The camera is set on the renderer, including its view port parameters.
+     * (see {@link #setCamera(com.jme3.renderer.Camera, boolean) })</li>
+     * <li>Any buffers that the ViewPort requests to be cleared are cleared
+     * and the {@link ViewPort#getBackgroundColor() background color} is set</li>
+     * <li>Every scene that is attached to the ViewPort is flattened into 
+     * the ViewPort's render queue 
+     * (see {@link #renderViewPortQueues(com.jme3.renderer.ViewPort, boolean) })
+     * </li>
+     * <li>The SceneProcessors' {@link SceneProcessor#postQueue(com.jme3.renderer.queue.RenderQueue) }
+     * method is called.</li>
+     * <li>The render queue is sorted and then flushed, sending
+     * rendering commands to the underlying Renderer implementation. 
+     * (see {@link #flushQueue(com.jme3.renderer.ViewPort) })</li>
+     * <li>The SceneProcessors' {@link SceneProcessor#postFrame(com.jme3.texture.FrameBuffer) }
+     * method is called.</li>
+     * <li>The translucent queue of the ViewPort is sorted and then flushed
+     * (see {@link #renderTranslucentQueue(com.jme3.renderer.ViewPort) })</li>
+     * <li>If any objects remained in the render queue, they are removed
+     * from the queue. This is generally objects added to the 
+     * {@link RenderQueue#renderShadowQueue(com.jme3.renderer.queue.RenderQueue.ShadowMode, com.jme3.renderer.RenderManager, com.jme3.renderer.Camera, boolean) 
+     * shadow queue}
+     * which were not rendered because of a missing shadow renderer.</li>
+     * </ul>
+     * 
+     * @param vp
+     * @param tpf 
+     */
+    public void renderViewPort(ViewPort vp, float tpf) {
+        if (!vp.isEnabled()) {
+            return;
+        }
+        List<SceneProcessor> processors = vp.getProcessors();
+        if (processors.isEmpty()) {
+            processors = null;
+        }
+
+        if (processors != null) {
+            for (SceneProcessor proc : processors) {
+                if (!proc.isInitialized()) {
+                    proc.initialize(this, vp);
+                }
+                proc.preFrame(tpf);
+            }
+        }
+
+        renderer.setFrameBuffer(vp.getOutputFrameBuffer());
+        setCamera(vp.getCamera(), false);
+        if (vp.isClearDepth() || vp.isClearColor() || vp.isClearStencil()) {
+            if (vp.isClearColor()) {
+                renderer.setBackgroundColor(vp.getBackgroundColor());
+            }
+            renderer.clearBuffers(vp.isClearColor(),
+                    vp.isClearDepth(),
+                    vp.isClearStencil());
+        }
+
+        List<Spatial> scenes = vp.getScenes();
+        for (int i = scenes.size() - 1; i >= 0; i--) {
+            renderScene(scenes.get(i), vp);
+        }
+
+        if (processors != null) {
+            for (SceneProcessor proc : processors) {
+                proc.postQueue(vp.getQueue());
+            }
+        }
+
+        flushQueue(vp);
+
+        if (processors != null) {
+            for (SceneProcessor proc : processors) {
+                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);
+    }
+
+    /**
+     * Called by the application to render any ViewPorts
+     * added to this RenderManager.
+     * <p>
+     * Renders any viewports that were added using the following methods:
+     * <ul>
+     * <li>{@link #createPreView(java.lang.String, com.jme3.renderer.Camera) }</li>
+     * <li>{@link #createMainView(java.lang.String, com.jme3.renderer.Camera) }</li>
+     * <li>{@link #createPostView(java.lang.String, com.jme3.renderer.Camera) }</li>
+     * </ul>
+     * 
+     * @param tpf Time per frame value
+     */
+    public void render(float tpf, boolean mainFrameBufferActive) {
+        if (renderer instanceof NullRenderer) {
+            return;
+        }
+
+        this.shader = renderer.getCaps().contains(Caps.GLSL100);
+
+        for (int i = 0; i < preViewPorts.size(); i++) {
+            ViewPort vp = preViewPorts.get(i);
+            if (vp.getOutputFrameBuffer() != null || mainFrameBufferActive){
+                renderViewPort(vp, tpf);
+            }
+        }
+        for (int i = 0; i < viewPorts.size(); i++) {
+            ViewPort vp = viewPorts.get(i);
+            if (vp.getOutputFrameBuffer() != null || mainFrameBufferActive){
+                renderViewPort(vp, tpf);
+            }
+        }
+        for (int i = 0; i < postViewPorts.size(); i++) {
+            ViewPort vp = postViewPorts.get(i);
+            if (vp.getOutputFrameBuffer() != null || mainFrameBufferActive){
+                renderViewPort(vp, tpf);
+            }
+        }
+    }
+}

+ 170 - 162
engine/src/core/com/jme3/shader/UniformBinding.java

@@ -1,162 +1,170 @@
-/*
- * Copyright (c) 2009-2010 jMonkeyEngine
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
- *   may be used to endorse or promote products derived from this software
- *   without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * 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.shader;
-
-public enum UniformBinding {
-
-    /**
-     * The world matrix. Converts Model space to World space.
-     * Type: mat4
-     */
-    WorldMatrix,
-
-    /**
-     * The view matrix. Converts World space to View space.
-     * Type: mat4
-     */
-    ViewMatrix,
-
-    /**
-     * The projection matrix. Converts View space to Clip/Projection space.
-     * Type: mat4
-     */
-    ProjectionMatrix,
-
-    /**
-     * The world view matrix. Converts Model space to View space.
-     * Type: mat4
-     */
-    WorldViewMatrix,
-
-    /**
-     * The normal matrix. The inverse transpose of the worldview matrix.
-     * Converts normals from model space to view space.
-     * Type: mat3
-     */
-    NormalMatrix,
-
-    /**
-     * The world view projection matrix. Converts Model space to Clip/Projection
-     * space.
-     * Type: mat4
-     */
-    WorldViewProjectionMatrix,
-
-    /**
-     * The view projection matrix. Converts Model space to Clip/Projection
-     * space.
-     * Type: mat4
-     */
-    ViewProjectionMatrix,
-
-
-    WorldMatrixInverse,
-    ViewMatrixInverse,
-    ProjectionMatrixInverse,
-    ViewProjectionMatrixInverse,
-    WorldViewMatrixInverse,
-    NormalMatrixInverse,
-    WorldViewProjectionMatrixInverse,
-
-    /**
-     * Contains the four viewport parameters in this order:
-     * X = Left,
-     * Y = Top,
-     * Z = Right,
-     * W = Bottom.
-     * Type: vec4
-     */
-    ViewPort,
-
-    /**
-     * The near and far values for the camera frustum.
-     * X = Near
-     * Y = Far.
-     * Type: vec2
-     */
-    FrustumNearFar,
-    
-    /**
-     * The width and height of the camera.
-     * Type: vec2
-     */
-    Resolution,
-
-    /**
-     * Aspect ratio of the resolution currently set. Width/Height.
-     * Type: float
-     */
-    Aspect,
-
-    /**
-     * Camera position in world space.
-     * Type: vec3
-     */
-    CameraPosition,
-
-    /**
-     * Direction of the camera.
-     * Type: vec3
-     */
-    CameraDirection,
-
-    /**
-     * Left vector of the camera.
-     * Type: vec3
-     */
-    CameraLeft,
-
-    /**
-     * Up vector of the camera.
-     * Type: vec3
-     */
-    CameraUp,
-
-    /**
-     * Time in seconds since the application was started.
-     * Type: float
-     */
-    Time,
-
-    /**
-     * Time in seconds that the last frame took.
-     * Type: float
-     */
-    Tpf,
-
-    /**
-     * Frames per second.
-     * Type: float
-     */
-    FrameRate,
-}
+/*
+ * Copyright (c) 2009-2010 jMonkeyEngine
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ *   may be used to endorse or promote products derived from this software
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * 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.shader;
+
+public enum UniformBinding {
+
+    /**
+     * The world matrix. Converts Model space to World space.
+     * Type: mat4
+     */
+    WorldMatrix,
+
+    /**
+     * The view matrix. Converts World space to View space.
+     * Type: mat4
+     */
+    ViewMatrix,
+
+    /**
+     * The projection matrix. Converts View space to Clip/Projection space.
+     * Type: mat4
+     */
+    ProjectionMatrix,
+
+    /**
+     * The world view matrix. Converts Model space to View space.
+     * Type: mat4
+     */
+    WorldViewMatrix,
+
+    /**
+     * The normal matrix. The inverse transpose of the worldview matrix.
+     * Converts normals from model space to view space.
+     * Type: mat3
+     */
+    NormalMatrix,
+
+    /**
+     * The world view projection matrix. Converts Model space to Clip/Projection
+     * space.
+     * Type: mat4
+     */
+    WorldViewProjectionMatrix,
+
+    /**
+     * The view projection matrix. Converts Model space to Clip/Projection
+     * space.
+     * Type: mat4
+     */
+    ViewProjectionMatrix,
+
+    /**
+     * The world matrix inverse transpose. Converts a normals from Model space
+     * to world space.
+     * Type: mat3
+     */
+    WorldMatrixInverseTranspose,      
+
+
+
+    WorldMatrixInverse,
+    ViewMatrixInverse,
+    ProjectionMatrixInverse,
+    ViewProjectionMatrixInverse,
+    WorldViewMatrixInverse,
+    NormalMatrixInverse,
+    WorldViewProjectionMatrixInverse,
+
+    /**
+     * Contains the four viewport parameters in this order:
+     * X = Left,
+     * Y = Top,
+     * Z = Right,
+     * W = Bottom.
+     * Type: vec4
+     */
+    ViewPort,
+
+    /**
+     * The near and far values for the camera frustum.
+     * X = Near
+     * Y = Far.
+     * Type: vec2
+     */
+    FrustumNearFar,
+    
+    /**
+     * The width and height of the camera.
+     * Type: vec2
+     */
+    Resolution,
+
+    /**
+     * Aspect ratio of the resolution currently set. Width/Height.
+     * Type: float
+     */
+    Aspect,
+
+    /**
+     * Camera position in world space.
+     * Type: vec3
+     */
+    CameraPosition,
+
+    /**
+     * Direction of the camera.
+     * Type: vec3
+     */
+    CameraDirection,
+
+    /**
+     * Left vector of the camera.
+     * Type: vec3
+     */
+    CameraLeft,
+
+    /**
+     * Up vector of the camera.
+     * Type: vec3
+     */
+    CameraUp,
+
+    /**
+     * Time in seconds since the application was started.
+     * Type: float
+     */
+    Time,
+
+    /**
+     * Time in seconds that the last frame took.
+     * Type: float
+     */
+    Tpf,
+
+    /**
+     * Frames per second.
+     * Type: float
+     */
+    FrameRate,
+}