* 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
This commit is contained in:
parent
fba447dc60
commit
cac820803b
@ -355,12 +355,19 @@ public class LwjglRenderer implements Renderer {
|
|||||||
logger.log(Level.FINER, "Texture Multisample Depth Samples: {0}", maxDepthTexSamples);
|
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);
|
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);
|
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) {
|
if (ctxCaps.GL_ARB_multisample) {
|
||||||
@ -1175,12 +1182,27 @@ public class LwjglRenderer implements Renderer {
|
|||||||
|
|
||||||
public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst, boolean copyDepth) {
|
public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst, boolean copyDepth) {
|
||||||
if (GLContext.getCapabilities().GL_EXT_framebuffer_blit) {
|
if (GLContext.getCapabilities().GL_EXT_framebuffer_blit) {
|
||||||
|
int srcX = 0;
|
||||||
|
int srcY = 0;
|
||||||
int srcW = 0;
|
int srcW = 0;
|
||||||
int srcH = 0;
|
int srcH = 0;
|
||||||
|
|
||||||
|
int dstX = 0;
|
||||||
|
int dstY = 0;
|
||||||
int dstW = 0;
|
int dstW = 0;
|
||||||
int dstH = 0;
|
int dstH = 0;
|
||||||
|
|
||||||
int prevFBO = context.boundFBO;
|
int prevFBO = context.boundFBO;
|
||||||
|
|
||||||
|
if (mainFbOverride != null) {
|
||||||
|
if (src == null) {
|
||||||
|
src = mainFbOverride;
|
||||||
|
}
|
||||||
|
if (dst == null) {
|
||||||
|
dst = mainFbOverride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (src != null && src.isUpdateNeeded()) {
|
if (src != null && src.isUpdateNeeded()) {
|
||||||
updateFrameBuffer(src);
|
updateFrameBuffer(src);
|
||||||
}
|
}
|
||||||
@ -1191,8 +1213,10 @@ public class LwjglRenderer implements Renderer {
|
|||||||
|
|
||||||
if (src == null) {
|
if (src == null) {
|
||||||
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
|
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
|
||||||
// srcW = viewWidth;
|
srcX = vpX;
|
||||||
// srcH = viewHeight;
|
srcY = vpY;
|
||||||
|
srcW = vpW;
|
||||||
|
srcH = vpH;
|
||||||
} else {
|
} else {
|
||||||
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, src.getId());
|
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, src.getId());
|
||||||
srcW = src.getWidth();
|
srcW = src.getWidth();
|
||||||
@ -1200,20 +1224,22 @@ public class LwjglRenderer implements Renderer {
|
|||||||
}
|
}
|
||||||
if (dst == null) {
|
if (dst == null) {
|
||||||
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
|
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
|
||||||
// dstW = viewWidth;
|
dstX = vpX;
|
||||||
// dstH = viewHeight;
|
dstY = vpY;
|
||||||
|
dstW = vpW - 1;
|
||||||
|
dstH = vpH - 1;
|
||||||
} else {
|
} else {
|
||||||
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, dst.getId());
|
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, dst.getId());
|
||||||
dstW = dst.getWidth();
|
dstW = dst.getWidth() - 1;
|
||||||
dstH = dst.getHeight();
|
dstH = dst.getHeight() - 1;
|
||||||
}
|
}
|
||||||
int mask = GL_COLOR_BUFFER_BIT;
|
int mask = GL_COLOR_BUFFER_BIT;
|
||||||
if (copyDepth) {
|
if (copyDepth) {
|
||||||
mask |= GL_DEPTH_BUFFER_BIT;
|
mask |= GL_DEPTH_BUFFER_BIT;
|
||||||
}
|
}
|
||||||
glBlitFramebufferEXT(0, 0, srcW, srcH,
|
glBlitFramebufferEXT(0, 0, srcW, srcH,
|
||||||
0, 0, dstW, dstH, mask,
|
0, 0, dstW, dstH, mask,
|
||||||
GL_NEAREST);
|
GL_NEAREST);
|
||||||
|
|
||||||
|
|
||||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, prevFBO);
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, prevFBO);
|
||||||
@ -1563,11 +1589,16 @@ public class LwjglRenderer implements Renderer {
|
|||||||
context.boundReadBuf = -2;
|
context.boundReadBuf = -2;
|
||||||
}
|
}
|
||||||
} else {
|
} 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.isMultiTarget()) {
|
||||||
if (fb.getNumColorBuffers() > maxMRTFBOAttachs) {
|
if (fb.getNumColorBuffers() > maxMRTFBOAttachs) {
|
||||||
throw new RendererException("Framebuffer has more"
|
throw new RendererException("Framebuffer has more"
|
||||||
+ " targets than are supported"
|
+ " multi targets than are supported"
|
||||||
+ " on the system!");
|
+ " by the video hardware!");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (context.boundDrawBuf != 100 + fb.getNumColorBuffers()) {
|
if (context.boundDrawBuf != 100 + fb.getNumColorBuffers()) {
|
||||||
|
132
engine/src/test/jme3test/post/TestRenderToCubemap.java
Normal file
132
engine/src/test/jme3test/post/TestRenderToCubemap.java
Normal file
@ -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();
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user