darwin.renderer.opengl.FrameBuffer.FrameBufferObject Maven / Gradle / Ivy
The newest version!
/*
* Copyright (C) 2012 daniel
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package darwin.renderer.opengl.FrameBuffer;
import darwin.renderer.GraphicContext;
import darwin.renderer.opengl.GLClientConstants;
import darwin.util.misc.SaveClosable;
import com.jogamp.opengl.util.texture.Texture;
import javax.inject.Inject;
import javax.media.opengl.*;
/**
*
* @author Daniel Heinrich
*/
public class FrameBufferObject {
private class FboCloser implements SaveClosable {
private final int[] viewport;
private final int prevDraw, prevRead;
public FboCloser(int[] viewport, int prevDraw, int prevRead) {
this.viewport = viewport;
this.prevDraw = prevDraw;
this.prevRead = prevRead;
}
@Override
public void close() {
popViewPort();
popBoundFBO();
}
/**
* load back the last viewport
*/
public void popViewPort() {
gc.getGL().glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
}
/**
* re-binds the last FBO
*/
public void popBoundFBO() {
bindDrawBuffer(prevDraw);
bindReadBuffer(prevRead);
}
}
/**
* Current bound Draw/Read Buffer
*/
private static int currdraw = 0;
private static int currread = 0;
private final int id;
private int width, height;
private final Object[] color_attachment;
private Object depth_attachment, stencil_attachment;
protected final GraphicContext gc;
/**
* erstellt ein neues FrameBufferObjekt.
*
* @param gl der GL Context in dem das FBO erstellt werden soll.
*/
@Inject
public FrameBufferObject(GraphicContext gc, GLClientConstants constants) {
this.gc = gc;
color_attachment = new Object[constants.getMaxColorAttachments()];
int[] ids = new int[1];
gc.getGL().glGenFramebuffers(1, ids, 0);
id = ids[0];
}
FrameBufferObject(GraphicContext gc, int a) {
this.gc = gc;
color_attachment = null;
id = a;
if (id != 0) {
throw new UnsupportedOperationException("Other framebuffer then the Default(id=0) arn't supported yet!");
//TODO höhe breite usw abfragen(attachments)
}
}
//
/**
* Binded ein Renderbuffer auf ein bestimmtes Color Attachment des FBO.
*
* @param nummber
Nummer des Color Attachments(0 bis
* GL_MAX_COLOR_ATTACHMENTS_EXT-1).
* @param rb
Der Renderbuffer der gebunden werden soll.
*/
public void setColor_Attachment(int nummber, RenderBuffer rb) {
assert (nummber < GL2GL3.GL_MAX_COLOR_ATTACHMENTS);
bindRenderBuffer(rb, GL.GL_COLOR_ATTACHMENT0 + nummber);
color_attachment[nummber] = rb;
}
/**
* Binded eine Textur auf ein bestimmtes Color Attachment des FBO.
*
* @param nummber
Nummer des Color Attachments(0 bis
* GL_MAX_COLOR_ATTACHMENTS_EXT-1).
* @param tex
Die Textur die gebunden werden soll.
*/
public void setColor_Attachment(int nummber, Texture tex) {
assert (nummber < GL2GL3.GL_MAX_COLOR_ATTACHMENTS);
bindTexture(tex, GL.GL_COLOR_ATTACHMENT0 + nummber);
color_attachment[nummber] = tex;
}
/**
* Gibt die Textur zur�ck die an ein bestimmtes Color Attechment gebunden
* ist.
*
* @param nummber
Nummer des Color Attachments(0 bis
* GL_MAX_COLOR_ATTACHMENTS_EXT-1).
*
* @return Gibt die an das Color Attachtment gebundene Textur zur�ck. NULL
* wenn anstatt einer Textur ein Renderbuffer gebunden ist oder das
* Attachment noch frei ist.
*/
public Texture getColorAttachmentTexture(int nummber) {
assert (id != 0);
assert (nummber < GL2GL3.GL_MAX_COLOR_ATTACHMENTS);
return (Texture) color_attachment[nummber];
}
/**
* Gibt den Renderbuffer zur�ck der an ein bestimmtes Color Attechment
* gebunden ist.
*
* @param nummber
Nummer des Color Attachments(0 bis
* GL_MAX_COLOR_ATTACHMENTS_EXT-1).
*
* @return Gibt den an das Color Attachtment gebundenen Renderbuffer zur�ck.
* NULL wenn anstatt eines Renderbuffers eine Textur gebunden ist oder das
* Attachment noch frei ist.
*/
public RenderBuffer getColorAttachmentBuffer(int nummber) {
assert (id != 0);
assert (nummber < GL2GL3.GL_MAX_COLOR_ATTACHMENTS);
return (RenderBuffer) color_attachment[nummber];
}
public Class extends Object> getColorAttachmentType(int nummber) {
assert (id != 0);
assert (nummber < GL2GL3.GL_MAX_COLOR_ATTACHMENTS);
return color_attachment[nummber].getClass();
}
//
//
/**
* Binded ein Renderbuffer als Depth Attachment des FBOs.
*
* @param rb
Der Renderbuffer der gebunden werden soll.
*/
public void setDepth_Attachment(RenderBuffer rb) {
bindRenderBuffer(rb, GL.GL_DEPTH_ATTACHMENT);
depth_attachment = rb;
}
/**
* Binded eine Textur als Depth Attachment des FBOs.
*
* @param tex
Die Textur die gebunden werden soll.
*/
public void setDepth_Attachment(Texture tex) {
bindTexture(tex, GL.GL_DEPTH_ATTACHMENT);
depth_attachment = tex;
}
/**
* Gibt die Textur zur�ck die als Depth Attachment gebunden ist.
*
* @return Gibt die als Depth Attachment gebundene Textur zur�ck. NULL wenn
* anstatt einer Textur ein Renderbuffer gebunden ist oder das Attachment
* noch frei ist.
*/
public Texture getDepth_AttachmentTexture() {
assert (id != 0);
return getDepth_Attachment(Texture.class);
}
/**
* Gibt den RenderBuffer zur�ck der als Depth Attachment gebunden ist.
*
* @return Gibt den als Depth Attachment gebundenen RenderBuffer zur�ck.
* NULL wenn anstatt einer Textur ein Renderbuffer gebunden ist oder das
* Attachment noch frei ist.
*/
public RenderBuffer getDepth_AttachmentBuffer() {
assert (id != 0);
return getDepth_Attachment(RenderBuffer.class);
}
@SuppressWarnings("unchecked")
private T getDepth_Attachment(Class cl) {
assert (id != 0);
if (cl.isInstance(depth_attachment)) {
return (T) depth_attachment;
}
return null;
}//
//
/**
* Binded ein Renderbuffer als Stencil Attachment des FBOs.
*
* @param rb
Der Renderbuffer der gebunden werden soll.
*/
public void setStencil_Attachment(RenderBuffer rb) {
bindRenderBuffer(rb, GL.GL_STENCIL_ATTACHMENT);
stencil_attachment = rb;
}
/**
* Binded eine Textur als Stencil Attachment des FBOs.
*
* @param tex
Die Textur die gebunden werden soll.
*/
public void setStencil_Attachment(Texture tex) {
bindTexture(tex, GL.GL_STENCIL_ATTACHMENT);
stencil_attachment = tex;
}
/**
* Gibt die Textur zur�ck die als Stencil Attachment gebunden ist.
*
* @return Gibt die als Depth Attachment gebundene Textur zur�ck. NULL wenn
* anstatt einer Textur ein Renderbuffer gebunden ist oder das Attachment
* noch frei ist.
*/
public Texture getStencil_AttachmentTexture() {
assert (id != 0);
return getStencil_Attachment(Texture.class);
}
/**
* Gibt den RenderBuffer zur�ck der als Stencil Attachment gebunden ist.
*
*
* @return Gibt den als Depth Attachment gebundenen RenderBuffer zur�ck.
* NULL wenn anstatt einer Textur ein Renderbuffer gebunden ist oder das
* Attachment noch frei ist.
*/
public RenderBuffer getStencil_AttachmentBuffer() {
assert (id != 0);
return getStencil_Attachment(RenderBuffer.class);
}
/**
*
* @param target on of: GL_COLOR_ATTACHMENT<0 - GL_MAX_COLOR_ATTACHMENTS>
* GL_DEPTH_ATTACHMENT GL_STENCIL_ATTACHMENT
*/
public void detach(int target) {
assert (id != 0);
gc.getGL().glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, target,
GL.GL_RENDERBUFFER, 0);
}
@SuppressWarnings("unchecked")
private T getStencil_Attachment(Class cl) {
assert (id != 0);
if (cl.isInstance(stencil_attachment)) {
return (T) stencil_attachment;
}
return null;
}
private void bindTexture(Texture tex, int glType) {
assert (tex != null);
assert (currdraw == id);
boolean size = checkSize(tex.getWidth(), tex.getHeight());
assert (size);
assert ((tex.getTarget() == GL.GL_TEXTURE_2D || tex.getTarget() == GL2GL3.GL_TEXTURE_RECTANGLE));
assert (id != 0);
gc.getGL().glFramebufferTexture2D(GL.GL_FRAMEBUFFER,
glType,
GL.GL_TEXTURE_2D, tex.getTextureObject(null),
0);
}
private void bindRenderBuffer(RenderBuffer rb, int glType) {
assert (rb != null);
assert (currdraw == id);
assert (checkSize(rb.getWidth(), rb.getHeight()));
assert (id != 0);
gc.getGL().glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER,
glType,
GL.GL_RENDERBUFFER,
rb.getRenderBufferID());
}
//
/**
* bindet das FBO an den GL Context.
*/
public void bind() {
gc.getGL().glBindFramebuffer(GL.GL_FRAMEBUFFER, id);
currdraw = id;
currread = id;
}
/**
* Saves the current FBO OpenGL state so that the state can be
* restored after this FBO was used
*
* @return
* Returns a Closable which when closed resets the OpenGL FBO state to before
* this method was called.
* Can be used with the new JRE 7 try block, like:
*
*
* try(SaveClosable c = fbo.use())
* {
* _____draw something_____
* }
*
*/
public SaveClosable use() {
//save state
int[] viewport = new int[4];
gc.getGL().glGetIntegerv(GL.GL_VIEWPORT, viewport, 0);
FboCloser closer = new FboCloser(viewport, currdraw, currread);
//binding
gc.getGL().glViewport(0, 0, getWidth(), getHeight());
bind();
return closer;
}
public void bindAsDrawBuffer() {
bindDrawBuffer(id);
}
private void bindDrawBuffer(int id) {
gc.getGL().glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, id);
currdraw = id;
}
public void bindAsReadBuffer() {
bindReadBuffer(id);
}
private void bindReadBuffer(int id) {
gc.getGL().glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, id);
currread = id;
}
public void copyColorTo(FrameBufferObject dst) {
bindAsReadBuffer();
dst.bindAsDrawBuffer();
gc.getGL().getGL2GL3().glBlitFramebuffer(0, 0, width, height,
0, 0, dst.getWidth(), dst.getHeight(),
GL.GL_COLOR_BUFFER_BIT, GL.GL_LINEAR);
}
/**
* Falls das Color_Attachment0 eine Textur nutzt wird diese an den GL
* Context gebunden.
*/
public void bindColorAtt0Texture() {
assert (id != 0);
Texture tex = getColorAttachmentTexture(0);
if (tex != null) {
tex.bind(gc.getGL());
}
}
/**
* Loescht das FBO aus dem Grafikspeicher.
*/
public void delete() {
assert (id != 0);
gc.getGL().glDeleteFramebuffers(1, new int[]{id}, 0);
}
/**
* @return gibt die H�he des FBO in pixel zur�ck
*/
public int getHeight() {
return height;
}
/**
* @return gibt die Breite des FBO in pixel zur�ck
*/
public int getWidth() {
return width;
}
public int getStatus() {
assert (currdraw == id);
return gc.getGL().glCheckFramebufferStatus(GL.GL_FRAMEBUFFER);
}
public boolean isComplete() {
return getStatus() == GL.GL_FRAMEBUFFER_COMPLETE;
}
public String getStatusString() {
switch (getStatus()) {
case GL.GL_FRAMEBUFFER_COMPLETE:
return "GL_FRAMEBUFFER_COMPLETE";
case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
return "INCOMPLETE_ATTACHMENT";
case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
return "INCOMPLETE_DIMENSIONS";
case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
return "INCOMPLETE_DRAW_BUFFER";
case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_FORMATS:
return "INCOMPLETE_FORMATS";
case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_ARB:
return "INCOMPLETE_LAYER_COUNT";
case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_ARB:
return "INCOMPLETE_LAYER_TARGETS";
case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
return "INCOMPLETE_MISSING_ATTACHMENT";
case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
return "INCOMPLETE_MULTISAMPLE";
case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
return "INCOMPLETE_READ_BUFFER";
case GL2GL3.GL_FRAMEBUFFER_UNSUPPORTED:
return "INCOMPLETE_UNSUPPORTED";
default:
return "ERROR: UNKNOWN STATUS";
}
}
public int getId() {
return id;
}
private boolean checkSize(int width, int height) {
if (this.width == 0) {
this.width = width;
}
if (this.height == 0) {
this.height = height;
}
return this.width == width || this.height == height;
}
public void resetSize() {
assert (id != 0);
width = 0;
height = 0;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy