📄 lwjglpbuffertexturerenderer.java
字号:
/*
* Copyright (c) 2003-2009 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.jme.renderer.lwjgl;
import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.AWTGLCanvas;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.Pbuffer;
import org.lwjgl.opengl.PixelFormat;
import org.lwjgl.opengl.RenderTexture;
import com.jme.image.Texture;
import com.jme.image.Texture2D;
import com.jme.math.FastMath;
import com.jme.math.Vector3f;
import com.jme.renderer.Camera;
import com.jme.renderer.ColorRGBA;
import com.jme.renderer.RenderContext;
import com.jme.renderer.TextureRenderer;
import com.jme.scene.Spatial;
import com.jme.scene.state.lwjgl.LWJGLTextureState;
import com.jme.system.JmeException;
import com.jme.system.lwjgl.LWJGLDisplaySystem;
import com.jme.util.TextureManager;
import com.jme.util.geom.BufferUtils;
/**
* This class is used by LWJGL to render textures. Users should <b>not </b>
* create this class directly. Instead, allow DisplaySystem to create it for
* you.
*
* @author Joshua Slack, Mark Powell
* @version $Id: LWJGLPbufferTextureRenderer.java,v 1.9 2007/08/20 20:53:29 nca Exp $
* @see com.jme.system.DisplaySystem#createTextureRenderer
*/
public class LWJGLPbufferTextureRenderer implements TextureRenderer {
private static final Logger logger = Logger.getLogger(LWJGLPbufferTextureRenderer.class.getName());
private LWJGLCamera camera;
private ColorRGBA backgroundColor = new ColorRGBA(1, 1, 1, 1);
private int pBufferWidth = 16;
private int pBufferHeight = 16;
/* Pbuffer instance */
private Pbuffer pbuffer;
private int active, caps;
private boolean useDirectRender = false;
private boolean isSupported = true;
private final LWJGLRenderer parentRenderer;
private RenderTexture texture;
private final LWJGLDisplaySystem display;
private boolean headless = false;
private int bpp, alpha, depth, stencil, samples;
public LWJGLPbufferTextureRenderer(int width, int height,
LWJGLDisplaySystem display, LWJGLRenderer parentRenderer, TextureRenderer.Target target) {
this.display = display;
this.parentRenderer = parentRenderer;
caps = Pbuffer.getCapabilities();
isSupported = (caps & Pbuffer.PBUFFER_SUPPORTED) != 0;
if (!isSupported) {
logger.warning("Pbuffer not supported.");
return;
}
this.bpp = display.getBitDepth();
this.alpha = display.getMinAlphaBits();
this.depth = display.getMinDepthBits();
this.stencil = display.getMinStencilBits();
this.samples = display.getMinSamples();
int pTarget = RenderTexture.RENDER_TEXTURE_2D;
// XXX: It seems this does not work properly on many cards...
boolean nonPow2Support = false; //((Pbuffer.getCapabilities() & Pbuffer.RENDER_TEXTURE_RECTANGLE_SUPPORTED) != 0);
if (!FastMath.isPowerOfTwo(width) || !FastMath.isPowerOfTwo(height)) {
// If we don't support non-pow2 textures in pbuffers, we need to resize them.
if (!nonPow2Support) {
if (!FastMath.isPowerOfTwo(width)) {
int newWidth = 2;
do {
newWidth <<= 1;
} while (newWidth < width);
width = newWidth;
}
if (!FastMath.isPowerOfTwo(height)) {
int newHeight = 2;
do {
newHeight <<= 1;
} while (newHeight < height);
height = newHeight;
}
} else {
pTarget = RenderTexture.RENDER_TEXTURE_RECTANGLE;
}
// sanity check
if (width <= 0)
width = 16;
if (height <= 0)
height = 16;
}
switch (target) {
case Texture1D:
pTarget = RenderTexture.RENDER_TEXTURE_1D;
break;
case TextureCubeMap:
pTarget = RenderTexture.RENDER_TEXTURE_CUBE_MAP;
break;
}
pBufferWidth = width;
pBufferHeight = height;
//boolean useRGB, boolean useRGBA, boolean useDepth, boolean isRectangle, int target, int mipmaps
this.texture = new RenderTexture(false, true, true, pTarget == RenderTexture.RENDER_TEXTURE_RECTANGLE, pTarget, 0);
setMultipleTargets(false);
logger.info("Creating Pbuffer sized: "+pBufferWidth+" x "+pBufferHeight);
initPbuffer();
}
/**
*
* <code>isSupported</code> obtains the capability of the graphics card.
* If the graphics card does not have pbuffer support, false is returned,
* otherwise, true is returned. TextureRenderer will not process any scene
* elements if pbuffer is not supported.
*
* @return if this graphics card supports pbuffers or not.
*/
public boolean isSupported() {
return isSupported;
}
/**
* <code>getCamera</code> retrieves the camera this renderer is using.
*
* @return the camera this renderer is using.
*/
public Camera getCamera() {
return camera;
}
/**
* <code>setCamera</code> sets the camera this renderer should use.
*
* @param camera
* the camera this renderer should use.
*/
public void setCamera(Camera camera) {
this.camera = (LWJGLCamera) camera;
}
/**
* <code>setBackgroundColor</code> sets the OpenGL clear color to the
* color specified.
*
* @see com.jme.renderer.TextureRenderer#setBackgroundColor(com.jme.renderer.ColorRGBA)
* @param c
* the color to set the background color to.
*/
public void setBackgroundColor(ColorRGBA c) {
// if color is null set background to white.
if (c == null) {
backgroundColor.a = 1.0f;
backgroundColor.b = 1.0f;
backgroundColor.g = 1.0f;
backgroundColor.r = 1.0f;
} else {
backgroundColor = c;
}
if (!isSupported) {
return;
}
try {
activate();
GL11.glClearColor(backgroundColor.r, backgroundColor.g,
backgroundColor.b, backgroundColor.a);
}
finally {
deactivate();
}
}
/**
* <code>getBackgroundColor</code> retrieves the clear color of the
* current OpenGL context.
*
* @see com.jme.renderer.Renderer#getBackgroundColor()
* @return the current clear color.
*/
public ColorRGBA getBackgroundColor() {
return backgroundColor;
}
/**
* <code>setupTexture</code> initializes a new Texture object for use with
* TextureRenderer. Generates a valid gl texture id for this texture and
* inits the data type for the texture.
*/
public void setupTexture(Texture2D tex) {
setupTexture(tex, pBufferWidth, pBufferHeight);
}
/**
* <code>setupTexture</code> initializes a new Texture object for use with
* TextureRenderer. Generates a valid gl texture id for this texture and
* inits the data type for the texture.
*/
public void setupTexture(Texture2D tex, int width, int height) {
if (!isSupported) {
return;
}
IntBuffer ibuf = BufferUtils.createIntBuffer(1);
if (tex.getTextureId() != 0) {
ibuf.put(tex.getTextureId());
GL11.glDeleteTextures(ibuf);
ibuf.clear();
}
// Create the texture
GL11.glGenTextures(ibuf);
tex.setTextureId(ibuf.get(0));
TextureManager.registerForCleanup(tex.getTextureKey(), tex.getTextureId());
LWJGLTextureState.doTextureBind(tex.getTextureId(), 0, Texture.Type.TwoDimensional);
int source = GL11.GL_RGBA;
switch (tex.getRTTSource()) {
case RGBA:
case RGBA8:
break;
case RGB:
case RGB8:
source = GL11.GL_RGB;
break;
case Alpha:
case Alpha8:
source = GL11.GL_ALPHA;
break;
case Depth:
source = GL11.GL_DEPTH_COMPONENT;
break;
case Intensity:
case Intensity8:
source = GL11.GL_INTENSITY;
break;
case Luminance:
case Luminance8:
source = GL11.GL_LUMINANCE;
break;
case LuminanceAlpha:
case Luminance8Alpha8:
source = GL11.GL_LUMINANCE_ALPHA;
break;
case Alpha4:
source = GL11.GL_ALPHA;
break;
case Alpha12:
source = GL11.GL_ALPHA;
break;
case Alpha16:
source = GL11.GL_ALPHA;
break;
case Luminance4:
source = GL11.GL_LUMINANCE;
break;
case Luminance12:
source = GL11.GL_LUMINANCE;
break;
case Luminance16:
source = GL11.GL_LUMINANCE;
break;
case Luminance4Alpha4:
source = GL11.GL_LUMINANCE_ALPHA;
break;
case Luminance6Alpha2:
source = GL11.GL_LUMINANCE_ALPHA;
break;
case Luminance12Alpha4:
source = GL11.GL_LUMINANCE_ALPHA;
break;
case Luminance12Alpha12:
source = GL11.GL_LUMINANCE_ALPHA;
break;
case Luminance16Alpha16:
source = GL11.GL_LUMINANCE_ALPHA;
break;
case Intensity4:
source = GL11.GL_INTENSITY;
break;
case Intensity12:
source = GL11.GL_INTENSITY;
break;
case Intensity16:
source = GL11.GL_INTENSITY;
break;
case R3_G3_B2:
source = GL11.GL_RGB;
break;
case RGB4:
source = GL11.GL_RGB;
break;
case RGB5:
source = GL11.GL_RGB;
break;
case RGB10:
source = GL11.GL_RGB;
break;
case RGB12:
source = GL11.GL_RGB;
break;
case RGB16:
source = GL11.GL_RGB;
break;
case RGBA2:
source = GL11.GL_RGBA;
break;
case RGBA4:
source = GL11.GL_RGBA;
break;
case RGB5_A1:
source = GL11.GL_RGBA;
break;
case RGB10_A2:
source = GL11.GL_RGBA;
break;
case RGBA12:
source = GL11.GL_RGBA;
break;
case RGBA16:
source = GL11.GL_RGBA;
break;
case RGBA32F:
source = GL11.GL_RGBA;
break;
case RGB32F:
source = GL11.GL_RGB;
break;
case Alpha32F:
source = GL11.GL_ALPHA;
break;
case Intensity32F:
source = GL11.GL_INTENSITY;
break;
case Luminance32F:
source = GL11.GL_LUMINANCE;
break;
case LuminanceAlpha32F:
source = GL11.GL_LUMINANCE_ALPHA;
break;
case RGBA16F:
source = GL11.GL_RGBA;
break;
case RGB16F:
source = GL11.GL_RGB;
break;
case Alpha16F:
source = GL11.GL_ALPHA;
break;
case Intensity16F:
source = GL11.GL_INTENSITY;
break;
case Luminance16F:
source = GL11.GL_LUMINANCE;
break;
case LuminanceAlpha16F:
source = GL11.GL_LUMINANCE_ALPHA;
break;
}
GL11.glCopyTexImage2D(GL11.GL_TEXTURE_2D, 0, source, 0, 0, width,
height, 0);
logger.info("setup tex" + tex.getTextureId() + ": " + width + ","
+ height);
}
public void render(Spatial spat, Texture tex) {
render(spat, tex, true);
}
/**
* <code>render</code> renders a scene. As it recieves a base class of
* <code>Spatial</code> the renderer hands off management of the scene to
* spatial for it to determine when a <code>Geometry</code> leaf is
* reached. The result of the rendering is then copied into the given
* texture(s). What is copied is based on the Texture object's rttSource
* field.
*
* NOTE: If more than one texture is given, copy-texture is used
* regardless of card capabilities to decrease render time.
*
* @param spat
* the scene to render.
* @param tex
* the Texture(s) to render it to.
*/
public void render(Spatial spat, Texture tex, boolean doClear) {
if (!isSupported) {
return;
}
// clear the current states since we are renderering into a new location
// and can not rely on states still being set.
try {
if (pbuffer.isBufferLost()) {
logger
.warning("PBuffer contents lost - will recreate the buffer");
deactivate();
pbuffer.destroy();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -