Skip to content

Commit

Permalink
Add GLFramebuffer, refactor FrameBuffer and FrameBufferCubempa to ext…
Browse files Browse the repository at this point in the history
…end it
  • Loading branch information
realitix committed Apr 3, 2015
1 parent ae96dc5 commit 9036b80
Show file tree
Hide file tree
Showing 4 changed files with 329 additions and 268 deletions.
8 changes: 4 additions & 4 deletions gdx/src/com/badlogic/gdx/graphics/Cubemap.java
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,13 @@ public int getGLEnum () {
}

/** @return The up vector of the side. */
public Vector3 getUp () {
return up;
public Vector3 getUp (Vector3 out) {
return out.set(up);
}

/** @return The direction vector of the side. */
public Vector3 getDirection () {
return direction;
public Vector3 getDirection (Vector3 out) {
return out.set(direction);
}
}

Expand Down
255 changes: 5 additions & 250 deletions gdx/src/com/badlogic/gdx/graphics/glutils/FrameBuffer.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,10 @@

package com.badlogic.gdx.graphics.glutils;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;
import java.util.HashMap;
import java.util.Map;

import com.badlogic.gdx.Application;
import com.badlogic.gdx.Application.ApplicationType;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.GLTexture;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.Texture.TextureFilter;
import com.badlogic.gdx.graphics.Texture.TextureWrap;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.BufferUtils;
import com.badlogic.gdx.utils.Disposable;

/** <p>
* Encapsulates OpenGL ES 2.0 frame buffer objects. This is a simple helper class which should cover most FBO uses. It will
Expand All @@ -50,43 +36,8 @@
* A FrameBuffer must be disposed if it is no longer needed
* </p>
*
* @author mzechner */
public class FrameBuffer implements Disposable {
/** the frame buffers **/
private final static Map<Application, Array<FrameBuffer>> buffers = new HashMap<Application, Array<FrameBuffer>>();

/** the color buffer texture **/
protected GLTexture colorTexture;

/** the default framebuffer handle, a.k.a screen. */
private static int defaultFramebufferHandle;
/** true if we have polled for the default handle already. */
private static boolean defaultFramebufferHandleInitialized = false;

/** the framebuffer handle **/
private int framebufferHandle;

/** the depthbuffer render object handle **/
private int depthbufferHandle;

/** the stencilbuffer render object handle **/
private int stencilbufferHandle;

/** width **/
protected final int width;

/** height **/
protected final int height;

/** depth **/
protected final boolean hasDepth;

/** stencil **/
protected final boolean hasStencil;

/** format **/
protected final Pixmap.Format format;

* @author mzechner, realitix */
public class FrameBuffer extends GLFrameBuffer<Texture> {

/** Creates a new FrameBuffer having the given dimensions and potentially a depth buffer attached.
*
Expand All @@ -109,215 +60,19 @@ public FrameBuffer (Pixmap.Format format, int width, int height, boolean hasDept
* @param hasDepth whether to attach a depth buffer
* @throws com.badlogic.gdx.utils.GdxRuntimeException in case the FrameBuffer could not be created */
public FrameBuffer (Pixmap.Format format, int width, int height, boolean hasDepth, boolean hasStencil) {
this.width = width;
this.height = height;
this.format = format;
this.hasDepth = hasDepth;
this.hasStencil = hasStencil;
build();

addManagedFrameBuffer(Gdx.app, this);
super(format, width, height, hasDepth, hasStencil);
}

/** Override this method in a derived class to set up the backing texture as you like. */
@Override
protected void setupTexture () {
colorTexture = new Texture(width, height, format);
colorTexture.setFilter(TextureFilter.Linear, TextureFilter.Linear);
colorTexture.setWrap(TextureWrap.ClampToEdge, TextureWrap.ClampToEdge);
}

private void build () {
GL20 gl = Gdx.gl20;

// iOS uses a different framebuffer handle! (not necessarily 0)
if (!defaultFramebufferHandleInitialized) {
defaultFramebufferHandleInitialized = true;
if (Gdx.app.getType() == ApplicationType.iOS) {
IntBuffer intbuf = ByteBuffer.allocateDirect(16 * Integer.SIZE / 8).order(ByteOrder.nativeOrder()).asIntBuffer();
gl.glGetIntegerv(GL20.GL_FRAMEBUFFER_BINDING, intbuf);
defaultFramebufferHandle = intbuf.get(0);
} else {
defaultFramebufferHandle = 0;
}
}

setupTexture();


framebufferHandle = gl.glGenFramebuffer();

if (hasDepth) {
depthbufferHandle = gl.glGenRenderbuffer();
}

if (hasStencil) {
stencilbufferHandle = gl.glGenRenderbuffer();
}

gl.glBindTexture(GL20.GL_TEXTURE_2D, colorTexture.getTextureObjectHandle());

if (hasDepth) {
gl.glBindRenderbuffer(GL20.GL_RENDERBUFFER, depthbufferHandle);
gl.glRenderbufferStorage(GL20.GL_RENDERBUFFER, GL20.GL_DEPTH_COMPONENT16, colorTexture.getWidth(),
colorTexture.getHeight());
}

if (hasStencil) {
gl.glBindRenderbuffer(GL20.GL_RENDERBUFFER, stencilbufferHandle);
gl.glRenderbufferStorage(GL20.GL_RENDERBUFFER, GL20.GL_STENCIL_INDEX8, colorTexture.getWidth(), colorTexture.getHeight());
}

gl.glBindFramebuffer(GL20.GL_FRAMEBUFFER, framebufferHandle);
gl.glFramebufferTexture2D(GL20.GL_FRAMEBUFFER, GL20.GL_COLOR_ATTACHMENT0, GL20.GL_TEXTURE_2D,
colorTexture.getTextureObjectHandle(), 0);
if (hasDepth) {
gl.glFramebufferRenderbuffer(GL20.GL_FRAMEBUFFER, GL20.GL_DEPTH_ATTACHMENT, GL20.GL_RENDERBUFFER, depthbufferHandle);
}

if (hasStencil) {
gl.glFramebufferRenderbuffer(GL20.GL_FRAMEBUFFER, GL20.GL_STENCIL_ATTACHMENT, GL20.GL_RENDERBUFFER, stencilbufferHandle);
}

int result = gl.glCheckFramebufferStatus(GL20.GL_FRAMEBUFFER);

gl.glBindRenderbuffer(GL20.GL_RENDERBUFFER, 0);
gl.glBindTexture(GL20.GL_TEXTURE_2D, 0);
gl.glBindFramebuffer(GL20.GL_FRAMEBUFFER, defaultFramebufferHandle);

if (result != GL20.GL_FRAMEBUFFER_COMPLETE) {
colorTexture.dispose();

if (hasDepth)
gl.glDeleteRenderbuffer(depthbufferHandle);

if (hasStencil)
gl.glDeleteRenderbuffer(stencilbufferHandle);

gl.glDeleteFramebuffer(framebufferHandle);

if (result == GL20.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)
throw new IllegalStateException("frame buffer couldn't be constructed: incomplete attachment");
if (result == GL20.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS)
throw new IllegalStateException("frame buffer couldn't be constructed: incomplete dimensions");
if (result == GL20.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)
throw new IllegalStateException("frame buffer couldn't be constructed: missing attachment");
if (result == GL20.GL_FRAMEBUFFER_UNSUPPORTED)
throw new IllegalStateException("frame buffer couldn't be constructed: unsupported combination of formats");
throw new IllegalStateException("frame buffer couldn't be constructed: unknown error " + result);
}
}

/** Releases all resources associated with the FrameBuffer. */
@Override
public void dispose () {
GL20 gl = Gdx.gl20;

IntBuffer handle = BufferUtils.newIntBuffer(1);

colorTexture.dispose();
if (hasDepth)
gl.glDeleteRenderbuffer(depthbufferHandle);

if (hasStencil)
gl.glDeleteRenderbuffer(stencilbufferHandle);

gl.glDeleteFramebuffer(framebufferHandle);

if (buffers.get(Gdx.app) != null) buffers.get(Gdx.app).removeValue(this, true);
}

/** Makes the frame buffer current so everything gets drawn to it. */
public void bind () {
Gdx.gl20.glBindFramebuffer(GL20.GL_FRAMEBUFFER, framebufferHandle);
}

/** Unbinds the framebuffer, all drawing will be performed to the normal framebuffer from here on. */
public static void unbind () {
Gdx.gl20.glBindFramebuffer(GL20.GL_FRAMEBUFFER, defaultFramebufferHandle);
}

/** Binds the frame buffer and sets the viewport accordingly, so everything gets drawn to it. */
public void begin () {
bind();
setFrameBufferViewport();
}

/** Sets viewport to the dimensions of framebuffer. Called by {@link #begin()}. */
protected void setFrameBufferViewport () {
Gdx.gl20.glViewport(0, 0, colorTexture.getWidth(), colorTexture.getHeight());
}

/** Unbinds the framebuffer, all drawing will be performed to the normal framebuffer from here on. */
public void end () {
unbind();
setDefaultFrameBufferViewport();
}

/** Sets viewport to the dimensions of default framebuffer (window). Called by {@link #end()}. */
protected void setDefaultFrameBufferViewport () {
Gdx.gl20.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
}

/** Unbinds the framebuffer and sets viewport sizes, all drawing will be performed to the normal framebuffer from here on.
*
* @param x the x-axis position of the viewport in pixels
* @param y the y-asis position of the viewport in pixels
* @param width the width of the viewport in pixels
* @param height the height of the viewport in pixels */
public void end (int x, int y, int width, int height) {
unbind();
Gdx.gl20.glViewport(x, y, width, height);
}

/** @return the color buffer texture */
public Texture getColorBufferTexture () {
return (Texture)colorTexture;
}

/** @return the height of the framebuffer in pixels */
public int getHeight () {
return colorTexture.getHeight();
}

/** @return the width of the framebuffer in pixels */
public int getWidth () {
return colorTexture.getWidth();
}

private static void addManagedFrameBuffer (Application app, FrameBuffer frameBuffer) {
Array<FrameBuffer> managedResources = buffers.get(app);
if (managedResources == null) managedResources = new Array<FrameBuffer>();
managedResources.add(frameBuffer);
buffers.put(app, managedResources);
}

/** Invalidates all frame buffers. This can be used when the OpenGL context is lost to rebuild all managed frame buffers. This
* assumes that the texture attached to this buffer has already been rebuild! Use with care. */
public static void invalidateAllFrameBuffers (Application app) {
if (Gdx.gl20 == null) return;

Array<FrameBuffer> bufferArray = buffers.get(app);
if (bufferArray == null) return;
for (int i = 0; i < bufferArray.size; i++) {
bufferArray.get(i).build();
}
}

public static void clearAllFrameBuffers (Application app) {
buffers.remove(app);
}

public static StringBuilder getManagedStatus (final StringBuilder builder) {
builder.append("Managed buffers/app: { ");
for (Application app : buffers.keySet()) {
builder.append(buffers.get(app).size);
builder.append(" ");
}
builder.append("}");
return builder;
}

public static String getManagedStatus () {
return getManagedStatus(new StringBuilder()).toString();
return colorTexture;
}
}
22 changes: 8 additions & 14 deletions gdx/src/com/badlogic/gdx/graphics/glutils/FrameBufferCubemap.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@

/** <p>
* Encapsulates OpenGL ES 2.0 frame buffer objects. This is a simple helper class which should cover most FBO uses. It will
* automatically create a texture for the color attachment and a renderbuffer for the depth buffer. You can get a hold of the
* texture by {@link FrameBufferCubemap#getColorBufferTexture()}. This class will only work with OpenGL ES 2.0.
* automatically create a cubemap for the color attachment and a renderbuffer for the depth buffer. You can get a hold of the
* cubemap by {@link FrameBufferCubemap#getColorBufferCubemap()}. This class will only work with OpenGL ES 2.0.
* </p>
*
* <p>
Expand All @@ -41,11 +41,11 @@
*
* <p>
* Typical use: <br />
* FrameBufferCubemap frameBuffer = new FrameBufferCubemap(Format.RGBA8888, fSize, fSize, fSize, true); <br />
* FrameBufferCubemap frameBuffer = new FrameBufferCubemap(Format.RGBA8888, fSize, fSize, true); <br />
* frameBuffer.begin(); <br />
* while( frameBuffer.nextSide() ) { <br />
* camera.up.set(frameBuffer.getSide().getUp()); <br />
* camera.direction.set(frameBuffer.getSide().getDirection()); <br />
* frameBuffer.getSide().getUp(camera.up); <br />
* frameBuffer.getSide().getDirection(camera.direction);<br />
* camera.update(); <br />
*
* Gdx.gl.glClearColor(0, 0, 0, 1); <br />
Expand All @@ -59,7 +59,8 @@
* </p>
*
* @author realitix */
public class FrameBufferCubemap extends FrameBuffer {
public class FrameBufferCubemap extends GLFrameBuffer<Cubemap> {

/** the index of last side rendered **/
protected int nbSides;

Expand Down Expand Up @@ -135,13 +136,6 @@ public Cubemap.CubemapSide getSide() {
return Cubemap.CubemapSide.values()[nbSides];
}

/** Unbinds the framebuffer, all drawing will be performed to the normal framebuffer from here on. */
@Override
public void end() {
end(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
}


/** Unbinds the framebuffer and sets viewport sizes, all drawing will be performed to the normal framebuffer from here on.
*
* @param x the x-axis position of the viewport in pixels
Expand All @@ -156,6 +150,6 @@ public void end (int x, int y, int width, int height) {

/** @return the color buffer cubemap */
public Cubemap getColorBufferCubemap () {
return (Cubemap) colorTexture;
return colorTexture;
}
}

0 comments on commit 9036b80

Please sign in to comment.