Explorar el Código

* Better checking for MRT in renderer (first against max color attachments then against draw buffers)
* Now uses only OpenGL2 draw buffers instead of relying on GL_ARB_draw_buffers existing
* copyFrameBuffer() was non-functional when used against the main framebuffer because the width/height were set to zero erroneously, now it uses the current viewport parameters.
* Added TestRenderToCubemap to demonstrate render to cubemap functionality, it also uses MRT to render to all the cube sides

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9378 75d07b2b-3a1a-0410-a2c5-0572b91ccdca

Sha..rd hace 13 años
padre
commit
cac820803b

+ 44 - 13
engine/src/lwjgl/com/jme3/renderer/lwjgl/LwjglRenderer.java

@@ -355,12 +355,19 @@ public class LwjglRenderer implements Renderer {
                 logger.log(Level.FINER, "Texture Multisample Depth Samples: {0}", maxDepthTexSamples);
             }
 
-            if (ctxCaps.GL_ARB_draw_buffers) {
+            glGetInteger(GL_MAX_DRAW_BUFFERS, intBuf16);
+            maxMRTFBOAttachs = intBuf16.get(0);
+            if (maxMRTFBOAttachs > 1) {
                 caps.add(Caps.FrameBufferMRT);
-                glGetInteger(ARBDrawBuffers.GL_MAX_DRAW_BUFFERS_ARB, intBuf16);
-                maxMRTFBOAttachs = intBuf16.get(0);
                 logger.log(Level.FINER, "FBO Max MRT renderbuffers: {0}", maxMRTFBOAttachs);
             }
+            
+//            if (ctxCaps.GL_ARB_draw_buffers) {
+//                caps.add(Caps.FrameBufferMRT);
+//                glGetInteger(ARBDrawBuffers.GL_MAX_DRAW_BUFFERS_ARB, intBuf16);
+//                maxMRTFBOAttachs = intBuf16.get(0);
+//                logger.log(Level.FINER, "FBO Max MRT renderbuffers: {0}", maxMRTFBOAttachs);
+            //}
         }
 
         if (ctxCaps.GL_ARB_multisample) {
@@ -1175,11 +1182,26 @@ public class LwjglRenderer implements Renderer {
 
     public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst, boolean copyDepth) {
         if (GLContext.getCapabilities().GL_EXT_framebuffer_blit) {
+            int srcX = 0;
+            int srcY = 0;
             int srcW = 0;
             int srcH = 0;
+            
+            int dstX = 0;
+            int dstY = 0;
             int dstW = 0;
             int dstH = 0;
+            
             int prevFBO = context.boundFBO;
+            
+            if (mainFbOverride != null) {
+                if (src == null) {
+                    src = mainFbOverride;
+                }
+                if (dst == null) {
+                    dst = mainFbOverride;
+                }
+            }
 
             if (src != null && src.isUpdateNeeded()) {
                 updateFrameBuffer(src);
@@ -1191,8 +1213,10 @@ public class LwjglRenderer implements Renderer {
 
             if (src == null) {
                 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
-//                srcW = viewWidth;
-//                srcH = viewHeight;
+                srcX = vpX;
+                srcY = vpY;
+                srcW = vpW;
+                srcH = vpH;
             } else {
                 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, src.getId());
                 srcW = src.getWidth();
@@ -1200,20 +1224,22 @@ public class LwjglRenderer implements Renderer {
             }
             if (dst == null) {
                 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
-//                dstW = viewWidth;
-//                dstH = viewHeight;
+                dstX = vpX;
+                dstY = vpY;
+                dstW = vpW - 1;
+                dstH = vpH - 1;
             } else {
                 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, dst.getId());
-                dstW = dst.getWidth();
-                dstH = dst.getHeight();
+                dstW = dst.getWidth() - 1;
+                dstH = dst.getHeight() - 1;
             }
             int mask = GL_COLOR_BUFFER_BIT;
             if (copyDepth) {
                 mask |= GL_DEPTH_BUFFER_BIT;
             }
             glBlitFramebufferEXT(0, 0, srcW, srcH,
-                    0, 0, dstW, dstH, mask,
-                    GL_NEAREST);
+                                 0, 0, dstW, dstH, mask,
+                                 GL_NEAREST);
 
 
             glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, prevFBO);
@@ -1563,11 +1589,16 @@ public class LwjglRenderer implements Renderer {
                     context.boundReadBuf = -2;
                 }
             } else {
+                if (fb.getNumColorBuffers() > maxFBOAttachs) {
+                    throw new RendererException("Framebuffer has more color "
+                            + "attachments than are supported"
+                            + " by the video hardware!");
+                }
                 if (fb.isMultiTarget()) {
                     if (fb.getNumColorBuffers() > maxMRTFBOAttachs) {
                         throw new RendererException("Framebuffer has more"
-                                + " targets than are supported"
-                                + " on the system!");
+                                + " multi targets than are supported"
+                                + " by the video hardware!");
                     }
 
                     if (context.boundDrawBuf != 100 + fb.getNumColorBuffers()) {

+ 132 - 0
engine/src/test/jme3test/post/TestRenderToCubemap.java

@@ -0,0 +1,132 @@
+/*
+ * 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 jme3test.post;
+
+import com.jme3.app.SimpleApplication;
+import com.jme3.material.Material;
+import com.jme3.math.ColorRGBA;
+import com.jme3.math.FastMath;
+import com.jme3.math.Quaternion;
+import com.jme3.math.Vector3f;
+import com.jme3.renderer.Camera;
+import com.jme3.renderer.ViewPort;
+import com.jme3.scene.Geometry;
+import com.jme3.scene.shape.Box;
+import com.jme3.texture.FrameBuffer;
+import com.jme3.texture.Image.Format;
+import com.jme3.texture.Texture;
+import com.jme3.texture.TextureCubeMap;
+import com.jme3.util.SkyFactory;
+
+/**
+ * Renders a rotating box to a cubemap texture, then applies the cubemap
+ * texture as a sky.
+ */
+public class TestRenderToCubemap  extends SimpleApplication {
+ 
+    private Geometry offBox;
+    private float angle = 0;
+    private ViewPort offView;
+ 
+    public static void main(String[] args){
+        TestRenderToCubemap app = new TestRenderToCubemap();
+        app.start();
+    }
+ 
+    public Texture setupOffscreenView(){
+        Camera offCamera = new Camera(512, 512);
+ 
+        offView = renderManager.createPreView("Offscreen View", offCamera);
+        offView.setClearFlags(true, true, true);
+        offView.setBackgroundColor(ColorRGBA.DarkGray);
+ 
+        // create offscreen framebuffer
+        FrameBuffer offBuffer = new FrameBuffer(512, 512, 1);
+ 
+        //setup framebuffer's cam
+        offCamera.setFrustumPerspective(45f, 1f, 1f, 1000f);
+        offCamera.setLocation(new Vector3f(0f, 0f, -5f));
+        offCamera.lookAt(new Vector3f(0f, 0f, 0f), Vector3f.UNIT_Y);
+ 
+        //setup framebuffer's texture
+        TextureCubeMap offTex = new TextureCubeMap(512, 512, Format.RGBA8);
+        offTex.setMinFilter(Texture.MinFilter.Trilinear);
+        offTex.setMagFilter(Texture.MagFilter.Bilinear);
+ 
+        //setup framebuffer to use texture
+        offBuffer.setDepthBuffer(Format.Depth);
+        offBuffer.setMultiTarget(true);
+        offBuffer.addColorTexture(offTex, TextureCubeMap.Face.NegativeX);
+        offBuffer.addColorTexture(offTex, TextureCubeMap.Face.PositiveX);
+        offBuffer.addColorTexture(offTex, TextureCubeMap.Face.NegativeY);
+        offBuffer.addColorTexture(offTex, TextureCubeMap.Face.PositiveY);
+        offBuffer.addColorTexture(offTex, TextureCubeMap.Face.NegativeZ);
+        offBuffer.addColorTexture(offTex, TextureCubeMap.Face.PositiveZ);
+        
+        //set viewport to render to offscreen framebuffer
+        offView.setOutputFrameBuffer(offBuffer);
+ 
+        // setup framebuffer's scene
+        Box boxMesh = new Box(Vector3f.ZERO, 1,1,1);
+        Material material = assetManager.loadMaterial("Interface/Logo/Logo.j3m");
+        offBox = new Geometry("box", boxMesh);
+        offBox.setMaterial(material);
+ 
+        // attach the scene to the viewport to be rendered
+        offView.attachScene(offBox);
+ 
+        return offTex;
+    }
+ 
+    @Override
+    public void simpleInitApp() {
+        cam.setLocation(new Vector3f(3, 3, 3));
+        cam.lookAt(Vector3f.ZERO, Vector3f.UNIT_Y);
+ 
+        Texture offTex = setupOffscreenView();
+        rootNode.attachChild(SkyFactory.createSky(assetManager, offTex, false));
+    }
+ 
+    @Override
+    public void simpleUpdate(float tpf){
+        Quaternion q = new Quaternion();
+ 
+        angle += tpf;
+        angle %= FastMath.TWO_PI;
+        q.fromAngles(angle, 0, angle);
+
+        offBox.setLocalRotation(q);
+        offBox.updateLogicalState(tpf);
+        offBox.updateGeometricState();
+    }
+}