Reworked resource allocation/release in PFramebuffer

This commit is contained in:
codeanticode
2011-07-01 09:04:03 +00:00
parent 7fa3d492ad
commit bce9b9e2d5
4 changed files with 424 additions and 270 deletions

View File

@@ -50,6 +50,13 @@ public class PFramebuffer implements PConstants {
public int glColorBufferMultisampleID;
public int width;
public int height;
protected int depthBits;
protected int stencilBits;
protected boolean combinedDepthStencil;
protected boolean multisample;
protected int nsamples;
protected int numColorBuffers;
protected int[] colorBufferAttchPoints;
@@ -58,41 +65,36 @@ public class PFramebuffer implements PConstants {
protected boolean screenFb;
protected boolean noDepth;
protected boolean fboMode;
protected boolean multisample;
protected int nsamples;
protected boolean fboMode;
protected PTexture backupTexture;
protected IntBuffer pixelBuffer;
PFramebuffer(PApplet parent) {
this(parent, 0, 0, false);
PFramebuffer(PApplet parent, int w, int h) {
this(parent, w, h, 1, 1, 0, 0, false, false);
}
PFramebuffer(PApplet parent, int w, int h) {
this(parent, w, h, false);
}
PFramebuffer(PApplet parent, int w, int h, boolean screen) {
this(parent, w, h, 1, 1, 0, 0, false, screen);
}
PFramebuffer(PApplet parent, int w, int h, int samples, int colorBuffers,
int depthBits, int stencilBits, boolean combinedDepthStencil,
boolean screen) {
this.parent = parent;
ogl = (PGraphicsOpenGL)parent.g;
glFboID = 0;
glDepthBufferID = 0;
glStencilBufferID = 0;
glDepthStencilBufferID = 0;
glDepthStencilBufferID = 0;
glColorBufferMultisampleID = 0;
screenFb = screen;
noDepth = false;
fboMode = PGraphicsOpenGL.fboSupported;
numColorBuffers = 0;
multisample = false;
nsamples = 0;
fboMode = PGraphicsOpenGL.fboSupported;
createFramebuffer(w, h);
allocate(w, h, samples, colorBuffers, depthBits, stencilBits,
combinedDepthStencil, screen);
noDepth = false;
pixelBuffer = null;
@@ -102,11 +104,11 @@ public class PFramebuffer implements PConstants {
// buffer to the texture bound as color buffer to this PFramebuffer object and then drawing
// the backup texture back on the screen.
backupTexture = new PTexture(parent, width, height, new PTexture.Parameters(ARGB, POINT));
}
}
}
public void delete() {
deleteFramebuffer();
release();
}
public void clear() {
@@ -124,181 +126,6 @@ public class PFramebuffer implements PConstants {
GL.GL_COLOR_BUFFER_BIT, GL.GL_NEAREST);
}
public void setColorBuffer(PTexture tex) {
setColorBuffers(new PTexture[] { tex }, 1);
}
public void setColorBuffers(PTexture[] textures) {
setColorBuffers(textures, textures.length);
}
public void setColorBuffers(PTexture[] textures, int n) {
if (screenFb) return;
if (fboMode) {
ogl.pushFramebuffer();
ogl.setFramebuffer(this);
// Making sure nothing is attached.
for (int i = 0; i < numColorBuffers; i++) {
getGl().glFramebufferTexture2D(GL.GL_FRAMEBUFFER, GL.GL_COLOR_ATTACHMENT0 + i,
GL.GL_TEXTURE_2D, 0, 0);
}
numColorBuffers = PApplet.min(n, textures.length);
colorBufferAttchPoints = new int[numColorBuffers];
glColorBufferTargets = new int[numColorBuffers];
glColorBufferIDs = new int[numColorBuffers];
for (int i = 0; i < numColorBuffers; i++) {
colorBufferAttchPoints[i] = GL.GL_COLOR_ATTACHMENT0 + i;
glColorBufferTargets[i] = textures[i].glTarget;
glColorBufferIDs[i] = textures[i].glID;
getGl().glFramebufferTexture2D(GL.GL_FRAMEBUFFER, colorBufferAttchPoints[i],
glColorBufferTargets[i], glColorBufferIDs[i], 0);
}
if (validFbo() && textures != null && 0 < textures.length) {
width = textures[0].glWidth;
height = textures[0].glHeight;
}
ogl.popFramebuffer();
} else {
numColorBuffers = PApplet.min(n, textures.length);
glColorBufferTargets = new int[numColorBuffers];
glColorBufferIDs = new int[numColorBuffers];
for (int i = 0; i < numColorBuffers; i++) {
glColorBufferTargets[i] = textures[i].glTarget;
glColorBufferIDs[i] = textures[i].glID;
}
}
}
public void addColorBufferMultisample(int samples) {
if (screenFb) return;
if (fboMode) {
ogl.pushFramebuffer();
ogl.setFramebuffer(this);
multisample = true;
nsamples = samples;
numColorBuffers = 1;
colorBufferAttchPoints = new int[numColorBuffers];
colorBufferAttchPoints[0] = GL.GL_COLOR_ATTACHMENT0;
glColorBufferMultisampleID = ogl.createGLResource(PGraphicsOpenGL.GL_RENDER_BUFFER);
getGl().glBindRenderbuffer(GL.GL_RENDERBUFFER, glColorBufferMultisampleID);
getGl2().glRenderbufferStorageMultisample(GL.GL_RENDERBUFFER, nsamples,
GL.GL_RGBA8, width, height);
getGl().glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, colorBufferAttchPoints[0],
GL.GL_RENDERBUFFER, glColorBufferMultisampleID);
ogl.popFramebuffer();
}
}
public void addDepthStencilBuffer() {
if (screenFb) return;
if (width == 0 || height == 0) {
throw new RuntimeException("PFramebuffer: size undefined.");
}
if (fboMode) {
ogl.pushFramebuffer();
ogl.setFramebuffer(this);
glDepthStencilBufferID = ogl.createGLResource(PGraphicsOpenGL.GL_RENDER_BUFFER);
getGl().glBindRenderbuffer(GL.GL_RENDERBUFFER, glDepthStencilBufferID);
if (multisample) {
getGl2().glRenderbufferStorageMultisample(GL.GL_RENDERBUFFER, nsamples, GL.GL_DEPTH24_STENCIL8, width, height);
} else {
getGl().glRenderbufferStorage(GL.GL_RENDERBUFFER, GL.GL_DEPTH24_STENCIL8, width, height);
}
getGl().glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT,
GL.GL_RENDERBUFFER, glDepthStencilBufferID);
getGl().glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT,
GL.GL_RENDERBUFFER, glDepthStencilBufferID);
ogl.popFramebuffer();
}
}
public void addDepthBuffer(int bits) {
if (screenFb) return;
if (width == 0 || height == 0) {
throw new RuntimeException("PFramebuffer: size undefined.");
}
if (fboMode) {
ogl.pushFramebuffer();
ogl.setFramebuffer(this);
glDepthBufferID = ogl.createGLResource(PGraphicsOpenGL.GL_RENDER_BUFFER);
getGl().glBindRenderbuffer(GL.GL_RENDERBUFFER, glDepthBufferID);
int glConst = GL.GL_DEPTH_COMPONENT16;
if (bits == 16) {
glConst = GL.GL_DEPTH_COMPONENT16;
} else if (bits == 24) {
glConst = GL.GL_DEPTH_COMPONENT24;
} else if (bits == 32) {
glConst = GL.GL_DEPTH_COMPONENT32;
}
if (multisample) {
getGl2().glRenderbufferStorageMultisample(GL.GL_RENDERBUFFER, nsamples, glConst, width, height);
} else {
getGl().glRenderbufferStorage(GL.GL_RENDERBUFFER, glConst, width, height);
}
getGl().glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT,
GL.GL_RENDERBUFFER, glDepthBufferID);
ogl.popFramebuffer();
}
}
public void addStencilBuffer(int bits) {
if (screenFb) return;
if (width == 0 || height == 0) {
throw new RuntimeException("PFramebuffer: size undefined.");
}
if (fboMode) {
ogl.pushFramebuffer();
ogl.setFramebuffer(this);
glStencilBufferID = ogl.createGLResource(PGraphicsOpenGL.GL_RENDER_BUFFER);
getGl().glBindRenderbuffer(GL.GL_RENDERBUFFER, glStencilBufferID);
int glConst = GL.GL_STENCIL_INDEX1;
if (bits == 1) {
glConst = GL.GL_STENCIL_INDEX1;
} else if (bits == 4) {
glConst = GL.GL_STENCIL_INDEX4;
} else if (bits == 8) {
glConst = GL.GL_STENCIL_INDEX8;
}
if (multisample) {
getGl2().glRenderbufferStorageMultisample(GL.GL_RENDERBUFFER, nsamples, glConst, width, height);
} else {
getGl().glRenderbufferStorage(GL.GL_RENDERBUFFER, glConst, width, height);
}
getGl().glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT,
GL.GL_RENDERBUFFER, glStencilBufferID);
ogl.popFramebuffer();
}
}
public void bind() {
if (screenFb) {
if (PGraphicsOpenGL.fboSupported) {
@@ -354,7 +181,7 @@ public class PFramebuffer implements PConstants {
// Saves content of the screen into the backup texture.
public void backupScreen() {
if (pixelBuffer == null) allocatePixelBuffer();
if (pixelBuffer == null) createPixelBuffer();
getGl().glReadPixels(0, 0, width, height, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, pixelBuffer);
copyToTexture(pixelBuffer, backupTexture.glID, backupTexture.glTarget);
}
@@ -366,7 +193,7 @@ public class PFramebuffer implements PConstants {
// Copies current content of screen to color buffers.
public void copyToColorBuffers() {
if (pixelBuffer == null) allocatePixelBuffer();
if (pixelBuffer == null) createPixelBuffer();
getGl().glReadPixels(0, 0, width, height, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, pixelBuffer);
for (int i = 0; i < numColorBuffers; i++) {
copyToTexture(pixelBuffer, glColorBufferIDs[i], glColorBufferTargets[i]);
@@ -374,7 +201,7 @@ public class PFramebuffer implements PConstants {
}
public void readPixels() {
if (pixelBuffer == null) allocatePixelBuffer();
if (pixelBuffer == null) createPixelBuffer();
getGl().glReadPixels(0, 0, width, height, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, pixelBuffer);
}
@@ -389,26 +216,113 @@ public class PFramebuffer implements PConstants {
return pixelBuffer;
}
// Internal copy to texture method.
protected void copyToTexture(IntBuffer buffer, int glid, int gltarget) {
getGl().glEnable(gltarget);
getGl().glBindTexture(gltarget, glid);
getGl().glTexSubImage2D(gltarget, 0, 0, 0, width, height, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, buffer);
getGl().glBindTexture(gltarget, 0);
getGl().glDisable(gltarget);
public boolean hasDepthBuffer() {
return 0 < depthBits;
}
public boolean hasStencilBuffer() {
return 0 < stencilBits;
}
protected void allocatePixelBuffer() {
pixelBuffer = IntBuffer.allocate(width * height);
pixelBuffer.rewind();
///////////////////////////////////////////////////////////
// Color buffer setters.
public void setColorBuffer(PTexture tex) {
setColorBuffers(new PTexture[] { tex }, 1);
}
public void setColorBuffers(PTexture[] textures) {
setColorBuffers(textures, textures.length);
}
protected void createFramebuffer(int w, int h) {
deleteFramebuffer(); // Just in the case this object is being re-initialized.
public void setColorBuffers(PTexture[] textures, int n) {
if (screenFb) return;
if (numColorBuffers != PApplet.min(n, textures.length)) {
throw new RuntimeException("Wrong number of textures to set the color buffers.");
}
if (fboMode) {
ogl.pushFramebuffer();
ogl.setFramebuffer(this);
// Making sure nothing is attached.
for (int i = 0; i < numColorBuffers; i++) {
getGl().glFramebufferTexture2D(GL.GL_FRAMEBUFFER, GL.GL_COLOR_ATTACHMENT0 + i,
GL.GL_TEXTURE_2D, 0, 0);
}
for (int i = 0; i < numColorBuffers; i++) {
glColorBufferTargets[i] = textures[i].glTarget;
glColorBufferIDs[i] = textures[i].glID;
getGl().glFramebufferTexture2D(GL.GL_FRAMEBUFFER, colorBufferAttchPoints[i],
glColorBufferTargets[i], glColorBufferIDs[i], 0);
}
if (validFbo() && textures != null && 0 < textures.length) {
width = textures[0].glWidth;
height = textures[0].glHeight;
}
ogl.popFramebuffer();
} else {
for (int i = 0; i < numColorBuffers; i++) {
glColorBufferTargets[i] = textures[i].glTarget;
glColorBufferIDs[i] = textures[i].glID;
}
}
}
///////////////////////////////////////////////////////////
// Allocate/release framebuffer.
protected void allocate(int w, int h, int samples, int colorBuffers,
int depthBits, int stencilBits, boolean combinedDepthStencil,
boolean screen) {
release(); // Just in the case this object is being re-initialized.
width = w;
height = h;
if (1 < samples) {
multisample = true;
nsamples = samples;
} else {
multisample = false;
nsamples = 1;
}
numColorBuffers = colorBuffers;
colorBufferAttchPoints = new int[numColorBuffers];
glColorBufferTargets = new int[numColorBuffers];
glColorBufferIDs = new int[numColorBuffers];
for (int i = 0; i < numColorBuffers; i++) {
colorBufferAttchPoints[i] = GL.GL_COLOR_ATTACHMENT0 + i;
}
if (depthBits < 1 && stencilBits < 1) {
this.depthBits = 0;
this.stencilBits = 0;
this.combinedDepthStencil = false;
} else {
if (combinedDepthStencil) {
// When combined depth/stencil format is required, the depth and stencil bits
// are overriden and the 24/8 combination for a 32 bits surface is used.
this.depthBits = 24;
this.stencilBits = 8;
this.combinedDepthStencil = true;
} else {
this.depthBits = depthBits;
this.stencilBits = stencilBits;
this.combinedDepthStencil = false;
}
}
screenFb = screen;
if (screenFb) {
glFboID = 0;
} else if (fboMode) {
@@ -416,37 +330,219 @@ public class PFramebuffer implements PConstants {
} else {
glFboID = 0;
}
// create the rest of the stuff...
if (multisample) {
createColorBufferMultisample();
}
if (combinedDepthStencil) {
createCombinedDepthStencilBuffer();
} else {
if (0 < depthBits) {
createDepthBuffer();
}
if (0 < stencilBits) {
createStencilBuffer();
}
}
}
protected void deleteFramebuffer() {
protected void release() {
deleteFbo();
deleteDepthBuffer();
deleteStencilBuffer();
deleteCombinedDepthStencilBuffer();
deleteColorBufferMultisample();
width = height = 0;
}
protected void deleteFbo() {
if (glFboID != 0) {
ogl.deleteGLResource(glFboID, PGraphicsOpenGL.GL_FRAME_BUFFER);
glFboID = 0;
}
}
}
protected void deleteDepthBuffer() {
if (glDepthBufferID != 0) {
ogl.deleteGLResource(glDepthBufferID, PGraphicsOpenGL.GL_RENDER_BUFFER);
glDepthBufferID = 0;
}
}
protected void deleteStencilBuffer() {
if (glStencilBufferID != 0) {
ogl.deleteGLResource(glStencilBufferID, PGraphicsOpenGL.GL_RENDER_BUFFER);
glStencilBufferID = 0;
}
}
}
protected void deleteColorBufferMultisample() {
if (glColorBufferMultisampleID != 0) {
ogl.deleteGLResource(glColorBufferMultisampleID, PGraphicsOpenGL.GL_RENDER_BUFFER);
glColorBufferMultisampleID = 0;
}
}
}
protected void deleteCombinedDepthStencilBuffer() {
if (glDepthStencilBufferID != 0) {
ogl.deleteGLResource(glDepthStencilBufferID, PGraphicsOpenGL.GL_RENDER_BUFFER);
glDepthStencilBufferID = 0;
}
width = height = 0;
}
protected void createColorBufferMultisample() {
if (screenFb) return;
if (fboMode) {
ogl.pushFramebuffer();
ogl.setFramebuffer(this);
numColorBuffers = 1;
colorBufferAttchPoints = new int[numColorBuffers];
colorBufferAttchPoints[0] = GL.GL_COLOR_ATTACHMENT0;
glColorBufferMultisampleID = ogl.createGLResource(PGraphicsOpenGL.GL_RENDER_BUFFER);
getGl().glBindRenderbuffer(GL.GL_RENDERBUFFER, glColorBufferMultisampleID);
getGl2().glRenderbufferStorageMultisample(GL.GL_RENDERBUFFER, nsamples,
GL.GL_RGBA8, width, height);
getGl().glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, colorBufferAttchPoints[0],
GL.GL_RENDERBUFFER, glColorBufferMultisampleID);
ogl.popFramebuffer();
}
}
protected void createCombinedDepthStencilBuffer() {
if (screenFb) return;
if (width == 0 || height == 0) {
throw new RuntimeException("PFramebuffer: size undefined.");
}
if (fboMode) {
ogl.pushFramebuffer();
ogl.setFramebuffer(this);
glDepthStencilBufferID = ogl.createGLResource(PGraphicsOpenGL.GL_RENDER_BUFFER);
getGl().glBindRenderbuffer(GL.GL_RENDERBUFFER, glDepthStencilBufferID);
if (multisample) {
getGl2().glRenderbufferStorageMultisample(GL.GL_RENDERBUFFER, nsamples, GL.GL_DEPTH24_STENCIL8, width, height);
} else {
getGl().glRenderbufferStorage(GL.GL_RENDERBUFFER, GL.GL_DEPTH24_STENCIL8, width, height);
}
getGl().glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT,
GL.GL_RENDERBUFFER, glDepthStencilBufferID);
getGl().glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT,
GL.GL_RENDERBUFFER, glDepthStencilBufferID);
ogl.popFramebuffer();
}
}
protected void createDepthBuffer() {
if (screenFb) return;
if (width == 0 || height == 0) {
throw new RuntimeException("PFramebuffer: size undefined.");
}
if (fboMode) {
ogl.pushFramebuffer();
ogl.setFramebuffer(this);
glDepthBufferID = ogl.createGLResource(PGraphicsOpenGL.GL_RENDER_BUFFER);
getGl().glBindRenderbuffer(GL.GL_RENDERBUFFER, glDepthBufferID);
int glConst = GL.GL_DEPTH_COMPONENT16;
if (depthBits == 16) {
glConst = GL.GL_DEPTH_COMPONENT16;
} else if (depthBits == 24) {
glConst = GL.GL_DEPTH_COMPONENT24;
} else if (depthBits == 32) {
glConst = GL.GL_DEPTH_COMPONENT32;
}
if (multisample) {
getGl2().glRenderbufferStorageMultisample(GL.GL_RENDERBUFFER, nsamples, glConst, width, height);
} else {
getGl().glRenderbufferStorage(GL.GL_RENDERBUFFER, glConst, width, height);
}
getGl().glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT,
GL.GL_RENDERBUFFER, glDepthBufferID);
ogl.popFramebuffer();
}
}
protected void createStencilBuffer() {
if (screenFb) return;
if (width == 0 || height == 0) {
throw new RuntimeException("PFramebuffer: size undefined.");
}
if (fboMode) {
ogl.pushFramebuffer();
ogl.setFramebuffer(this);
glStencilBufferID = ogl.createGLResource(PGraphicsOpenGL.GL_RENDER_BUFFER);
getGl().glBindRenderbuffer(GL.GL_RENDERBUFFER, glStencilBufferID);
int glConst = GL.GL_STENCIL_INDEX1;
if (stencilBits == 1) {
glConst = GL.GL_STENCIL_INDEX1;
} else if (stencilBits == 4) {
glConst = GL.GL_STENCIL_INDEX4;
} else if (stencilBits == 8) {
glConst = GL.GL_STENCIL_INDEX8;
}
if (multisample) {
getGl2().glRenderbufferStorageMultisample(GL.GL_RENDERBUFFER, nsamples, glConst, width, height);
} else {
getGl().glRenderbufferStorage(GL.GL_RENDERBUFFER, glConst, width, height);
}
getGl().glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT,
GL.GL_RENDERBUFFER, glStencilBufferID);
ogl.popFramebuffer();
}
}
protected void createPixelBuffer() {
pixelBuffer = IntBuffer.allocate(width * height);
pixelBuffer.rewind();
}
///////////////////////////////////////////////////////////
// Utilities.
// Internal copy to texture method.
protected void copyToTexture(IntBuffer buffer, int glid, int gltarget) {
getGl().glEnable(gltarget);
getGl().glBindTexture(gltarget, glid);
getGl().glTexSubImage2D(gltarget, 0, 0, 0, width, height, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, buffer);
getGl().glBindTexture(gltarget, 0);
getGl().glDisable(gltarget);
}
public boolean validFbo() {
int status = getGl().glCheckFramebufferStatus(GL.GL_FRAMEBUFFER);
if (status == GL.GL_FRAMEBUFFER_COMPLETE) {

View File

@@ -715,6 +715,8 @@ public class PGraphicsOpenGL extends PGraphics {
/*
protected int createGLResource(int type, Object obj) {
pTextureObjects.add(obj);
glTextureObjects.add(new Texture(id, obj));
}
@@ -724,7 +726,20 @@ public class PGraphicsOpenGL extends PGraphics {
}
*/
public void recreateGLResources() {
}
protected void registerGLObject(Object obj) {
}
protected void unregisterGLObject(Object obj) {
}
protected int createGLResource(int type) {
int id = 0;
if (type == GL_TEXTURE_OBJECT) {
@@ -732,11 +747,13 @@ public class PGraphicsOpenGL extends PGraphics {
gl.glGenTextures(1, temp, 0);
id = temp[0];
glTextureObjects.add(id);
//pTextureObjects.add((PTexture)obj);
} else if (type == GL_VERTEX_BUFFER) {
int[] temp = new int[1];
gl.glGenBuffers(1, temp, 0);
id = temp[0];
glVertexBuffers.add(id);
//pTextureObjects.add((PTexture)obj);
} else if (type == GL_FRAME_BUFFER) {
int[] temp = new int[1];
gl.glGenFramebuffers(1, temp, 0);
@@ -6990,10 +7007,7 @@ return width * (1 + ox) / 2.0f;
boolean opengl2X = !hints[DISABLE_OPENGL_2X_SMOOTH];
boolean opengl4X = hints[ENABLE_OPENGL_4X_SMOOTH];
offscreenMultisample = false;
offscreenFramebuffer = new PFramebuffer(parent, texture.glWidth, texture.glHeight, false);
// We need the GL2GL3 profile to access the glRenderbufferStorageMultisample
// function used in multisampled (antialiased) offscreen rendering.
if (PGraphicsOpenGL.fboMultisampleSupported && gl2x != null && (opengl2X || opengl4X)) {
@@ -7003,15 +7017,37 @@ return width * (1 + ox) / 2.0f;
} else if (opengl4X) {
nsamples = 4;
}
offscreenFramebufferMultisample = new PFramebuffer(parent, texture.glWidth, texture.glHeight, false);
offscreenFramebufferMultisample = new PFramebuffer(parent, texture.glWidth, texture.glHeight, nsamples, 0,
offscreenDepthBits, offscreenStencilBits,
offscreenDepthBits == 24 && offscreenStencilBits == 8, false);
/*
try {
offscreenFramebufferMultisample.addColorBufferMultisample(nsamples);
offscreenMultisample = true;
} catch (GLException e) {
PGraphics.showWarning("Unable to create antialised offscreen surface.");
}
}
*/
offscreenFramebufferMultisample.clear();
offscreenMultisample = true;
// The offscreen framebuffer where the multisampled image is finally drawn to doesn't
// need depth and stencil buffers since they are part of the multisampled framebuffer.
offscreenFramebuffer = new PFramebuffer(parent, texture.glWidth, texture.glHeight, 1, 1,
0, 0,
false, false);
} else {
offscreenFramebuffer = new PFramebuffer(parent, texture.glWidth, texture.glHeight, 1, 1,
offscreenDepthBits, offscreenStencilBits,
offscreenDepthBits == 24 && offscreenStencilBits == 8, false);
offscreenMultisample = false;
}
offscreenFramebuffer.setColorBuffer(texture);
offscreenFramebuffer.clear();
/*
if (offscreenMultisample) {
// We have multisampling. The fbo with the depth and stencil buffers is the
// multisampled fbo, not the regular one. This is because the actual drawing
@@ -7049,17 +7085,14 @@ return width * (1 + ox) / 2.0f;
}
}
}
*/
offscreenFramebuffer.clear();
}
protected void getGLObjects() {
gl = context.getGL();
//PApplet.println("GL:\n" + gl.getClass());
//PApplet.println("GL3:\n" + gl.getGL4bc());
if (pipeline == PROG_GL4) {
gl4p = gl.getGL4();
gl3p = gl4p;

View File

@@ -224,11 +224,7 @@ public class PShape3D extends PShape {
public void delete() {
if (root != this) return; // Can be done only from the root shape.
deleteVertexBuffer();
deleteColorBuffer();
deleteTexCoordBuffer();
deleteNormalBuffer();
deleteIndexBuffer();
release();
}
////////////////////////////////////////////////////////////
@@ -2103,7 +2099,7 @@ public class PShape3D extends PShape {
////////////////////////////////////////////////////////////
// Data allocation, deletion.
// Init methods.
public void init() {
if (root != this) return; // Can be done only from the root shape.
@@ -2133,7 +2129,7 @@ public class PShape3D extends PShape {
}
setParameters(params);
allocateShape(numVert);
allocate(numVert);
updateElement = -1;
resetBounds();
@@ -2174,15 +2170,22 @@ public class PShape3D extends PShape {
// field, although the actual geometry hasn't been sent to the VBOs yet.
vertexCount = objVertices.size();
}
///////////////////////////////////////////////////////////
// Allocate/release shape.
protected void allocate(int numVert) {
release(); // Just in the case this object is being re-initialized.
protected void allocateShape(int numVert) {
vertexCount = numVert;
numTexBuffers = 1;
firstVertex = 0;
lastVertex = numVert - 1;
initVertexData();
createVertexBuffer();
createVertexBuffer();
initColorData();
createColorBuffer();
initNormalData();
@@ -2193,19 +2196,30 @@ public class PShape3D extends PShape {
initChildrenData();
}
protected void initChildrenData() {
children = null;
vertexChild = new PShape3D[vertexCount];
protected void reallocate() {
allocate(vertexCount);
}
protected void release() {
deleteVertexBuffer();
deleteColorBuffer();
deleteTexCoordBuffer();
deleteNormalBuffer();
deleteIndexBuffer();
}
////////////////////////////////////////////////////////////
// Data creation, deletion.
protected void initVertexData() {
vertices = new float[vertexCount * 3];
}
protected void createVertexBuffer() {
deleteVertexBuffer(); // Just in the case this object is being re-initialized.
glVertexBufferID = ogl.createGLResource(PGraphicsOpenGL.GL_VERTEX_BUFFER);
getGl().glBindBuffer(GL.GL_ARRAY_BUFFER, glVertexBufferID);
final int bufferSize = vertexCount * 3 * PGraphicsOpenGL.SIZEOF_FLOAT;
@@ -2223,8 +2237,6 @@ public class PShape3D extends PShape {
protected void createColorBuffer() {
deleteColorBuffer();
glColorBufferID = ogl.createGLResource(PGraphicsOpenGL.GL_VERTEX_BUFFER);
getGl().glBindBuffer(GL.GL_ARRAY_BUFFER, glColorBufferID);
final int bufferSize = vertexCount * 4 * PGraphicsOpenGL.SIZEOF_FLOAT;
@@ -2239,8 +2251,6 @@ public class PShape3D extends PShape {
protected void createNormalBuffer() {
deleteNormalBuffer();
glNormalBufferID = ogl.createGLResource(PGraphicsOpenGL.GL_VERTEX_BUFFER);
getGl().glBindBuffer(GL.GL_ARRAY_BUFFER, glNormalBufferID);
final int bufferSize = vertexCount * 3 * PGraphicsOpenGL.SIZEOF_FLOAT;
@@ -2261,8 +2271,6 @@ public class PShape3D extends PShape {
if (glTexCoordBufferID == null) {
glTexCoordBufferID = new int[PGraphicsOpenGL.MAX_TEXTURES];
java.util.Arrays.fill(glTexCoordBufferID, 0);
} else {
deleteTexCoordBuffer();
}
glTexCoordBufferID[0] = ogl.createGLResource(PGraphicsOpenGL.GL_VERTEX_BUFFER);
@@ -2302,6 +2310,7 @@ public class PShape3D extends PShape {
updateTexBuffers();
}
protected void updateTexBuffers() {
if (family == GROUP) {
for (int i = 0; i < childCount; i++) {
@@ -2314,6 +2323,7 @@ public class PShape3D extends PShape {
}
}
protected void deleteVertexBuffer() {
if (glVertexBufferID != 0) {
ogl.deleteGLResource(glVertexBufferID, PGraphicsOpenGL.GL_VERTEX_BUFFER);
@@ -2345,6 +2355,7 @@ public class PShape3D extends PShape {
}
}
protected void deleteTexCoordBuffer() {
for (int i = 0; i < numTexBuffers; i++) {
deleteTexCoordBuffer(i);
@@ -2358,8 +2369,14 @@ public class PShape3D extends PShape {
glTexCoordBufferID[idx] = 0;
}
}
protected void initChildrenData() {
children = null;
vertexChild = new PShape3D[vertexCount];
}
///////////////////////////////////////////////////////////
// These methods are not available in PShape3D.
@@ -3045,7 +3062,7 @@ public class PShape3D extends PShape {
}
// Allocate space for the geometry that the triangulator has generated from the OBJ model.
allocateShape(ogl.recordedVertices.size());
allocate(ogl.recordedVertices.size());
updateElement = -1;
width = height = depth = 0;

View File

@@ -96,7 +96,7 @@ public class PTexture implements PConstants {
glID = 0;
setParameters((Parameters)params);
createTexture(width, height);
allocate(width, height);
}
@@ -130,7 +130,7 @@ public class PTexture implements PConstants {
public void delete() {
deleteTexture();
release();
}
////////////////////////////////////////////////////////////
@@ -171,7 +171,7 @@ public class PTexture implements PConstants {
this.width = width;
this.height = height;
setParameters(params);
createTexture(width, height);
allocate(width, height);
}
@@ -256,7 +256,7 @@ public class PTexture implements PConstants {
}
if (glID == 0) {
createTexture(width, height);
allocate(width, height);
}
getGl().glEnable(glTarget);
@@ -682,16 +682,16 @@ public class PTexture implements PConstants {
///////////////////////////////////////////////////////////
// Create/delete texture.
// Allocate/release texture.
/**
* Creates the opengl texture object.
* Allocates the opengl texture object.
* @param w int
* @param h int
*/
protected void createTexture(int w, int h) {
deleteTexture(); // Just in the case this object is being re-initialized.
protected void allocate(int w, int h) {
release(); // Just in the case this object is being re-initialized.
if (PGraphicsOpenGL.npotTexSupported) {
glWidth = w;
@@ -711,15 +711,15 @@ public class PTexture implements PConstants {
usingMipmaps = glMinFilter == GL.GL_LINEAR_MIPMAP_LINEAR;
getGl().glEnable(glTarget);
glID = ogl.createGLResource(PGraphicsOpenGL.GL_TEXTURE_OBJECT);
glID = ogl.createGLResource(PGraphicsOpenGL.GL_TEXTURE_OBJECT);
getGl().glBindTexture(glTarget, glID);
getGl().glTexParameteri(glTarget, GL.GL_TEXTURE_MIN_FILTER, glMinFilter);
getGl().glTexParameteri(glTarget, GL.GL_TEXTURE_MAG_FILTER, glMagFilter);
getGl().glTexParameteri(glTarget, GL.GL_TEXTURE_WRAP_S, glWrapS);
getGl().glTexParameteri(glTarget, GL.GL_TEXTURE_WRAP_T, glWrapT);
//First, we use glTexImage2D to set the full size of the texture (glW/H might be diff from
// w/h in the case that the GPU doesn't support NPOT textures)
// First, we use glTexImage2D to set the full size of the texture (glW/glH might be diff
// from w/h in the case that the GPU doesn't support NPOT textures)
getGl().glTexImage2D(glTarget, 0, glFormat, glWidth, glHeight, 0, GL.GL_RGBA,
GL.GL_UNSIGNED_BYTE, null);
@@ -744,17 +744,25 @@ public class PTexture implements PConstants {
maxTexCoordV = (float)h / glHeight;
}
protected void reallocate() {
allocate(width, height);
}
/**
* Deletes the opengl texture object.
*/
protected void deleteTexture() {
protected void release() {
if (glID != 0) {
ogl.deleteGLResource(glID, PGraphicsOpenGL.GL_TEXTURE_OBJECT);
glID = 0;
}
}
///////////////////////////////////////////////////////////
// Utilities.
// Copies source texture tex into this.
protected void copyTexels(PTexture tex, int x, int y, int w, int h, boolean scale) {
if (tex == null) {
@@ -796,7 +804,7 @@ public class PTexture implements PConstants {
protected void copyObject(PTexture src) {
// The OpenGL texture of this object is replaced with the one from the source object,
// so we delete the former to avoid resource wasting.
deleteTexture();
release();
width = src.width;
height = src.height;