mirror of
https://github.com/processing/processing4.git
synced 2026-01-30 03:41:15 +01:00
Reworked resource allocation/release in PFramebuffer
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user