mirror of
https://github.com/processing/processing4.git
synced 2026-06-16 04:26:26 +02:00
Improved texture handling in text rendering (closes issue 394). Methods sketchTransparentSurface and sketchColorDepth were renamed to sketchTransparency and sketchColordepth
This commit is contained in:
@@ -736,12 +736,12 @@ public class PApplet extends Activity implements PConstants, Runnable {
|
||||
// We don't need this for the time being since we are using GLES 1.1.
|
||||
// setEGLContextFactory(g3.getContextFactory());
|
||||
|
||||
String depth = sketchColorDepth();
|
||||
String depth = sketchColordepth();
|
||||
if (!depth.equals(DEFAULT_COLOR_DEPTH)) {
|
||||
// Setting user specified color depth. Otherwise, we let the
|
||||
// device to choose the configuration it pleases.
|
||||
|
||||
if (sketchTranslucentSurface()) {
|
||||
if (sketchTranslucency()) {
|
||||
surfaceHolder.setFormat(PixelFormat.TRANSLUCENT);
|
||||
}
|
||||
|
||||
@@ -925,11 +925,11 @@ public class PApplet extends Activity implements PConstants, Runnable {
|
||||
}
|
||||
|
||||
|
||||
public boolean sketchTranslucentSurface() {
|
||||
public boolean sketchTranslucency() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public String sketchColorDepth() {
|
||||
public String sketchColordepth() {
|
||||
return DEFAULT_COLOR_DEPTH;
|
||||
}
|
||||
|
||||
|
||||
@@ -153,13 +153,7 @@ public class PFont implements PConstants {
|
||||
protected PTexture[] textures = null;
|
||||
protected int currentTex;
|
||||
protected int lastTex;
|
||||
|
||||
/*
|
||||
protected int[] texIDList = null;
|
||||
protected int[] texWidthList = null;
|
||||
protected int[] texHeightList = null;
|
||||
*/
|
||||
|
||||
|
||||
|
||||
public PFont() { } // for subclasses
|
||||
|
||||
@@ -688,23 +682,45 @@ public class PFont implements PConstants {
|
||||
lineHeight = 0;
|
||||
}
|
||||
|
||||
public int addTexture() {
|
||||
int w = maxTexWidth;
|
||||
int h = maxTexHeight;
|
||||
|
||||
public boolean addTexture() {
|
||||
int w, h;
|
||||
boolean resize;
|
||||
|
||||
w = maxTexWidth;
|
||||
if (-1 < currentTex && textures[currentTex].glHeight < maxTexHeight) {
|
||||
// The height of the current texture is less than the maximum, this
|
||||
// means we can replace it with a larger texture.
|
||||
h = PApplet.min(2 * textures[currentTex].glHeight, maxTexHeight);
|
||||
resize = true;
|
||||
} else {
|
||||
h = PApplet.max(512, maxTexHeight / 4);
|
||||
resize = false;
|
||||
}
|
||||
|
||||
PTexture tex = new PTexture(parent, w, h, new PTexture.Parameters(ARGB, NEAREST));
|
||||
|
||||
if (textures == null) {
|
||||
textures = new PTexture[1];
|
||||
textures[0] = tex;
|
||||
currentTex = 0;
|
||||
} else if (resize) {
|
||||
// Replacing old smaller texture with larger one.
|
||||
// But first we must copy the contents of the older
|
||||
// texture into the new one.
|
||||
PTexture tex0 = textures[currentTex];
|
||||
tex.put(tex0);
|
||||
textures[currentTex] = tex;
|
||||
} else {
|
||||
// Adding new texture to the list.
|
||||
PTexture[] tmp = textures;
|
||||
textures = new PTexture[textures.length + 1];
|
||||
PApplet.arrayCopy(tmp, textures, tmp.length);
|
||||
textures[tmp.length] = tex;
|
||||
currentTex = textures.length - 1;
|
||||
}
|
||||
currentTex = textures.length - 1;
|
||||
return currentTex;
|
||||
lastTex = currentTex;
|
||||
|
||||
return resize;
|
||||
}
|
||||
|
||||
public void setFirstTexture() {
|
||||
@@ -712,10 +728,9 @@ public class PFont implements PConstants {
|
||||
}
|
||||
|
||||
public void setTexture(int idx) {
|
||||
if (0 <= idx && idx < textures.length) {
|
||||
GL10 gl = ((PGraphicsAndroid3D)parent.g).gl;
|
||||
gl.glBindTexture(textures[idx].glTarget, textures[idx].glID);
|
||||
if (0 <= idx && idx < textures.length) {
|
||||
currentTex = idx;
|
||||
textures[currentTex].bind();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -726,7 +741,17 @@ public class PFont implements PConstants {
|
||||
glyphs[i].addToTexture();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void updateGlyphsTexCoords() {
|
||||
// loop over current glyphs.
|
||||
for (int i = 0; i < glyphCount; i++) {
|
||||
if (glyphs[i].texture != null && glyphs[i].texture.tex == currentTex) {
|
||||
glyphs[i].texture.updateUV();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void recreateResource(PGraphicsAndroid3D renderer) {
|
||||
}
|
||||
|
||||
@@ -898,8 +923,6 @@ public class PFont implements PConstants {
|
||||
// Adds this glyph to the opengl texture in PFont.
|
||||
protected void addToTexture() {
|
||||
// Converting the pixels array from the PImage into a valid RGBA array for OpenGL.
|
||||
GL10 gl = ((PGraphicsAndroid3D)parent.g).gl;
|
||||
|
||||
int[] rgba = new int[width * height];
|
||||
int t = 0;
|
||||
int p = 0;
|
||||
@@ -913,6 +936,7 @@ public class PFont implements PConstants {
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
rgba[t++] = (image.pixels[p++] << 24) | 0x00FFFFFF;
|
||||
//rgba[t++] = 0xFF00FF00;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -925,14 +949,22 @@ public class PFont implements PConstants {
|
||||
lineHeight = 0;
|
||||
}
|
||||
lineHeight = Math.max(lineHeight, height);
|
||||
|
||||
boolean resized = false;
|
||||
if (offsetY + lineHeight > textures[currentTex].glHeight) {
|
||||
// We run out of space in the current texture, we add a new texture:
|
||||
lastTex = addTexture();
|
||||
|
||||
// Reseting texture coordinates and line.
|
||||
offsetX = 0;
|
||||
offsetY = 0;
|
||||
lineHeight = 0;
|
||||
resized = addTexture();
|
||||
if (resized) {
|
||||
// Because the current texture has been resized, we need to
|
||||
// update the UV coordinates of all the glyphs associated to it:
|
||||
updateGlyphsTexCoords();
|
||||
} else {
|
||||
// A new texture has been created. Reseting texture coordinates
|
||||
// and line.
|
||||
offsetX = 0;
|
||||
offsetY = 0;
|
||||
lineHeight = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (lastTex == -1) {
|
||||
@@ -940,12 +972,14 @@ public class PFont implements PConstants {
|
||||
}
|
||||
|
||||
// We assume GL10.GL_TEXTURE_2D is enabled at this point.
|
||||
if (currentTex != lastTex) {
|
||||
// We reset texture when it was resized because even the
|
||||
// texture index didn't change, the texture is a new one
|
||||
// in fact, so we need to rebind.
|
||||
if (currentTex != lastTex || resized) {
|
||||
setTexture(lastTex);
|
||||
}
|
||||
|
||||
gl.glTexSubImage2D(textures[currentTex].glTarget, 0, offsetX, offsetY, width, height,
|
||||
GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, IntBuffer.wrap(rgba));
|
||||
|
||||
textures[currentTex].setTexels(offsetX, offsetY, width, height, rgba);
|
||||
|
||||
texture = new TextureInfo(currentTex, offsetX, offsetY + height, width, -height);
|
||||
offsetX += width;
|
||||
@@ -965,6 +999,13 @@ public class PFont implements PConstants {
|
||||
v1 = (float)cropY / (float)textures[n].glHeight;
|
||||
}
|
||||
|
||||
void updateUV() {
|
||||
u0 = (float)crop[0] / (float)textures[tex].glWidth;
|
||||
u1 = u0 + (float)crop[2] / (float)textures[tex].glWidth;
|
||||
v0 = (float)(crop[1] + crop[3]) / (float)textures[tex].glHeight;
|
||||
v1 = (float)crop[1] / (float)textures[tex].glHeight;
|
||||
}
|
||||
|
||||
public int tex;
|
||||
public int[] crop;
|
||||
public float u0, u1;
|
||||
|
||||
@@ -32,6 +32,8 @@ import javax.microedition.khronos.opengles.GL11ExtensionPack;
|
||||
* When created with onscreen == true, it represents the normal
|
||||
* framebuffer. Needed by the stack mechanism in A3D to return
|
||||
* to onscreen rendering after a sequence of pushFramebuffer calls.
|
||||
* It transparently handles the situations when the FBO extension is
|
||||
* not available.
|
||||
*
|
||||
* By Andres Colubri.
|
||||
*/
|
||||
@@ -88,14 +90,15 @@ public class PFramebuffer implements PConstants {
|
||||
|
||||
initFramebuffer(w, h);
|
||||
|
||||
pixelBuffer = IntBuffer.allocate(width * height);
|
||||
pixelBuffer.rewind();
|
||||
|
||||
if (!screenFb && !FboMode) {
|
||||
// When FBOs are not available, rendering to texture is implemented by saving a portion of
|
||||
// the screen, doing the "offscreen" rendering on this portion, copying the screen color
|
||||
// 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, NEAREST));
|
||||
pixelBuffer = IntBuffer.allocate(width * height);
|
||||
pixelBuffer.rewind();
|
||||
backupTexture = new PTexture(parent, width, height, new PTexture.Parameters(ARGB, NEAREST));
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -297,6 +300,15 @@ public class PFramebuffer implements PConstants {
|
||||
}
|
||||
}
|
||||
|
||||
public void readPixels() {
|
||||
gl.glReadPixels(0, 0, width, height, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, pixelBuffer);
|
||||
}
|
||||
|
||||
public void getPixels(int[] pixels) {
|
||||
pixelBuffer.get(pixels);
|
||||
pixelBuffer.rewind();
|
||||
}
|
||||
|
||||
public IntBuffer getPixelBuffer() {
|
||||
return pixelBuffer;
|
||||
}
|
||||
@@ -307,7 +319,7 @@ public class PFramebuffer implements PConstants {
|
||||
gl.glBindTexture(gltarget, glid);
|
||||
gl.glTexSubImage2D(gltarget, 0, 0, 0, width, height, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, buffer);
|
||||
gl.glDisable(gltarget);
|
||||
}
|
||||
}
|
||||
|
||||
protected void initFramebuffer(int w, int h) {
|
||||
width = w;
|
||||
|
||||
@@ -163,7 +163,7 @@ public class PGraphicsAndroid3D extends PGraphics {
|
||||
/** Used to store empty values to be passed when a light has no
|
||||
ambient, diffuse or specular component **/
|
||||
public float[] zeroLight = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
public float[] baseLight = { 0.2f, 0.2f, 0.2f, 1.0f };
|
||||
public float[] baseLight = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
|
||||
boolean lightsAllocated = false;
|
||||
|
||||
@@ -727,7 +727,7 @@ public class PGraphicsAndroid3D extends PGraphics {
|
||||
// Some things the user might have changed from OpenGL,
|
||||
// but we want to make sure they return to the Processing
|
||||
// defaults (plus these cannot be changed through the API
|
||||
// so they remain constant anyways):
|
||||
// so they should remain constant anyways):
|
||||
gl.glShadeModel(GL10.GL_SMOOTH);
|
||||
gl.glFrontFace(GL10.GL_CW);
|
||||
gl.glDepthFunc(GL10.GL_LEQUAL);
|
||||
@@ -1582,35 +1582,6 @@ public class PGraphicsAndroid3D extends PGraphics {
|
||||
|
||||
// POINTS (override from P3D)
|
||||
|
||||
// Buffers to be passed to gl*Pointer() functions
|
||||
// must be direct, i.e., they must be placed on the
|
||||
// native heap where the garbage collector cannot
|
||||
// move them.
|
||||
//
|
||||
// Buffers with multi-byte datatypes (e.g., short, int, float)
|
||||
// must have their byte order set to native order
|
||||
|
||||
// ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);
|
||||
// vbb.order(ByteOrder.nativeOrder());
|
||||
// mVertexBuffer = vbb.asIntBuffer();
|
||||
// mVertexBuffer.put(vertices);
|
||||
// mVertexBuffer.position(0);
|
||||
//
|
||||
// ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length*4);
|
||||
// cbb.order(ByteOrder.nativeOrder());
|
||||
// mColorBuffer = cbb.asIntBuffer();
|
||||
// mColorBuffer.put(colors);
|
||||
// mColorBuffer.position(0);
|
||||
//
|
||||
// mIndexBuffer = ByteBuffer.allocateDirect(indices.length);
|
||||
// mIndexBuffer.put(indices);
|
||||
// mIndexBuffer.position(0);
|
||||
|
||||
// gl.glFrontFace(gl.GL_CW);
|
||||
// gl.glVertexPointer(3, gl.GL_FIXED, 0, mVertexBuffer);
|
||||
// gl.glColorPointer(4, gl.GL_FIXED, 0, mColorBuffer);
|
||||
// gl.glDrawElements(gl.GL_TRIANGLES, 36, gl.GL_UNSIGNED_BYTE, mIndexBuffer);
|
||||
|
||||
protected void renderPoints(int start, int stop) {
|
||||
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
|
||||
gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
|
||||
@@ -4937,10 +4908,10 @@ public class PGraphicsAndroid3D extends PGraphics {
|
||||
protected void drawTexture(PTexture tex, int[] crop, int x, int y, int w, int h) {
|
||||
gl.glEnable(tex.getGLTarget());
|
||||
gl.glBindTexture(tex.getGLTarget(), tex.getGLID());
|
||||
gl.glDepthMask(false);
|
||||
gl.glDepthMask(false);
|
||||
gl.glDisable(GL10.GL_BLEND);
|
||||
|
||||
// The texels of the texture replace the color of wherever is in the screen.
|
||||
// The texels of the texture replace the color of wherever is on the screen.
|
||||
gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE, GL10.GL_REPLACE);
|
||||
|
||||
// Setting texture crop.
|
||||
|
||||
@@ -59,17 +59,6 @@ public class PImage implements PConstants, Cloneable {
|
||||
|
||||
protected Bitmap bitmap;
|
||||
protected PTexture texture;
|
||||
|
||||
// This boolean variable is used to indicate that there
|
||||
// was a change in the contents of the pixels array and
|
||||
// hasn't been transfered to the texture yet.
|
||||
protected boolean texUpdated = false;
|
||||
|
||||
// This boolean variable is used to indicate that there
|
||||
// was a change in the contents of the texture and
|
||||
// hasn't been transfered to the pixels array yet.
|
||||
protected boolean pixUpdated = true;
|
||||
|
||||
|
||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
|
||||
@@ -204,7 +193,6 @@ public class PImage implements PConstants, Cloneable {
|
||||
public void loadTexture() {
|
||||
if (texture == null) {
|
||||
texture = new PTexture(parent, width, height, new PTexture.Parameters(format));
|
||||
texUpdated = false;
|
||||
}
|
||||
if (pixels == null) {
|
||||
loadPixels(); // loadPixels calls pixelsToTexture().
|
||||
@@ -217,7 +205,6 @@ public class PImage implements PConstants, Cloneable {
|
||||
public void loadTexture(int filter) {
|
||||
if (texture == null) {
|
||||
texture = new PTexture(parent, width, height, new PTexture.Parameters(format, filter));
|
||||
texUpdated = false;
|
||||
}
|
||||
if (pixels == null) {
|
||||
loadPixels(); // loadPixels calls pixelsToTexture().
|
||||
@@ -230,7 +217,6 @@ public class PImage implements PConstants, Cloneable {
|
||||
public void loadTexture(PTexture.Parameters params) {
|
||||
if (texture == null) {
|
||||
texture = new PTexture(parent, width, height, params);
|
||||
texUpdated = false;
|
||||
}
|
||||
if (pixels == null) {
|
||||
loadPixels(); // loadPixels calls pixelsToTexture().
|
||||
@@ -243,7 +229,6 @@ public class PImage implements PConstants, Cloneable {
|
||||
public void setTexture(PTexture tex) {
|
||||
if (tex.width == width && tex.height == height) {
|
||||
texture.set(tex);
|
||||
pixUpdated = false;
|
||||
} else {
|
||||
System.err.println("PImage: cannot set texture with different resolution from PImage object");
|
||||
}
|
||||
@@ -263,20 +248,20 @@ public class PImage implements PConstants, Cloneable {
|
||||
|
||||
|
||||
protected void pixelsToTexture() {
|
||||
if (!texUpdated) {
|
||||
texture.set(pixels);
|
||||
texUpdated = true;
|
||||
}
|
||||
texture.set(pixels);
|
||||
}
|
||||
|
||||
|
||||
protected void textureToPixels() {
|
||||
if (!pixUpdated) {
|
||||
texture.get(pixels);
|
||||
pixUpdated = true;
|
||||
}
|
||||
texture.get(pixels);
|
||||
}
|
||||
|
||||
|
||||
protected void reloadTexture() {
|
||||
if (texture != null) {
|
||||
texture = new PTexture(parent, width, height, texture.getParameters());
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -356,7 +341,6 @@ public class PImage implements PConstants, Cloneable {
|
||||
if (parent.g.is3D()) {
|
||||
if (texture == null) {
|
||||
texture = new PTexture(parent, width, height, new PTexture.Parameters(format));
|
||||
texUpdated = false;
|
||||
}
|
||||
pixelsToTexture();
|
||||
}
|
||||
@@ -423,7 +407,6 @@ public class PImage implements PConstants, Cloneable {
|
||||
// Assuming in good faith that the user only messed up
|
||||
// with the pixels in the specified region. We don't have
|
||||
// any way to know if he or she is lying.
|
||||
texUpdated = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -477,12 +460,16 @@ public class PImage implements PConstants, Cloneable {
|
||||
high = (int) (height * diff);
|
||||
}
|
||||
PImage temp = new PImage(wide, high, this.format);
|
||||
temp.parent = parent;
|
||||
temp.copy(this, 0, 0, width, height, 0, 0, wide, high);
|
||||
this.width = wide;
|
||||
this.height = high;
|
||||
this.pixels = temp.pixels;
|
||||
this.bitmap = null;
|
||||
}
|
||||
if (parent.g.is3D()) {
|
||||
reloadTexture();
|
||||
}
|
||||
}
|
||||
// Mark the pixels array as altered
|
||||
updatePixels();
|
||||
}
|
||||
@@ -2480,6 +2467,10 @@ public class PImage implements PConstants, Cloneable {
|
||||
}
|
||||
|
||||
PImage outgoing = new PImage(width, height, RGB);
|
||||
|
||||
// Not possible because this method is static, so careful when using it.
|
||||
// outgoing.parent = parent;
|
||||
|
||||
int index = 768;
|
||||
count /= 3;
|
||||
for (int i = 0; i < count; i++) {
|
||||
|
||||
@@ -65,6 +65,9 @@ public class PTexture implements PConstants {
|
||||
protected boolean flippedX;
|
||||
protected boolean flippedY;
|
||||
|
||||
protected int[] tmpPixels = null;
|
||||
protected PFramebuffer tmpFbo = null;
|
||||
|
||||
protected int recreateResourceIdx;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
@@ -198,12 +201,17 @@ public class PTexture implements PConstants {
|
||||
tex.set(this);
|
||||
|
||||
// Now, overwriting "this" with tex.
|
||||
copy(tex);
|
||||
copyObject(tex);
|
||||
|
||||
// Zeroing the texture id of tex, so the texture is not
|
||||
// deleted by OpenGL when the object is finalized by the GC.
|
||||
// "This" texture now wraps the one created in tex.
|
||||
tex.glID = 0;
|
||||
|
||||
// Nullifying some utility objects so they are recreated with the appropriate
|
||||
// size when needed.
|
||||
tmpPixels = null;
|
||||
tmpFbo = null;
|
||||
}
|
||||
|
||||
|
||||
@@ -250,29 +258,13 @@ public class PTexture implements PConstants {
|
||||
|
||||
|
||||
public void set(PTexture tex) {
|
||||
set(tex, 0, 0, tex.width, tex.height);
|
||||
copyTexels(tex, 0, 0, tex.width, tex.height, true);
|
||||
}
|
||||
|
||||
|
||||
// Copies source texture to this.
|
||||
public void set(PTexture tex, int x, int y, int w, int h) {
|
||||
if (tex == null) {
|
||||
throw new RuntimeException("PTexture: source texture is null");
|
||||
}
|
||||
|
||||
PFramebuffer fbo = new PFramebuffer(parent, glWidth, glHeight);
|
||||
// This texture is the color (destination) buffer of the FBO.
|
||||
fbo.setColorBuffer(this);
|
||||
fbo.disableDepthTest();
|
||||
|
||||
// FBO copy:
|
||||
a3d.pushFramebuffer();
|
||||
a3d.setFramebuffer(fbo);
|
||||
// Rendering tex into "this", and scaling the source rectangle
|
||||
// to cover the entire destination region.
|
||||
a3d.drawTexture(tex, x, y, w, h, 0, 0, width, height);
|
||||
a3d.popFramebuffer();
|
||||
}
|
||||
copyTexels(tex, x, y, w, h, true);
|
||||
}
|
||||
|
||||
|
||||
public void set(int[] pixels) {
|
||||
@@ -326,7 +318,7 @@ public class PTexture implements PConstants {
|
||||
int[] rgbaPixels = new int[glWidth * glHeight];
|
||||
convertToRGBA(pixels, rgbaPixels, format, 0, 0, width, height);
|
||||
gl.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_GENERATE_MIPMAP, GL11.GL_TRUE);
|
||||
gl.glTexSubImage2D(glTarget, 0, x, y, w, h, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, IntBuffer.wrap(rgbaPixels));
|
||||
setTexels(x, y, w, h, rgbaPixels);
|
||||
} else {
|
||||
/*
|
||||
// Code by Mike Miller obtained from here:
|
||||
@@ -398,47 +390,54 @@ public class PTexture implements PConstants {
|
||||
}
|
||||
|
||||
int size = glWidth * glHeight;
|
||||
|
||||
// TODO: This operation could be optimized somehow by declaring these two variables global
|
||||
// and allocating them only once.
|
||||
int[] tmp = new int[size];
|
||||
IntBuffer buffer;
|
||||
PFramebuffer fbo;
|
||||
|
||||
if (tmpFbo == null) {
|
||||
tmpFbo = new PFramebuffer(parent, glWidth, glHeight);
|
||||
}
|
||||
|
||||
if (PGraphicsAndroid3D.fboSupported) {
|
||||
// Attaching the texture to the color buffer of a FBO, binding the FBO and reading the pixels
|
||||
// from the current draw buffer (which is the color buffer of the FBO).
|
||||
|
||||
buffer = IntBuffer.allocate(size);
|
||||
buffer.rewind();
|
||||
|
||||
fbo = new PFramebuffer(parent, glWidth, glHeight);
|
||||
fbo.setColorBuffer(this);
|
||||
|
||||
tmpFbo.setColorBuffer(this);
|
||||
a3d.pushFramebuffer();
|
||||
a3d.setFramebuffer(fbo);
|
||||
gl.glReadPixels(0, 0, glWidth, glHeight, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, buffer);
|
||||
a3d.setFramebuffer(tmpFbo);
|
||||
tmpFbo.readPixels();
|
||||
a3d.popFramebuffer();
|
||||
} else {
|
||||
// Here we don't have FBOs, so the method above is of no use. What we do instead is
|
||||
// to draw the texture to the framebuffer, and then grab the pixels from the screen.
|
||||
|
||||
fbo = new PFramebuffer(parent, glWidth, glHeight);
|
||||
// to draw the texture to the screen framebuffer, and then grab the pixels from there.
|
||||
a3d.pushFramebuffer();
|
||||
a3d.setFramebuffer(fbo);
|
||||
a3d.setFramebuffer(tmpFbo);
|
||||
a3d.drawTexture(this, 0, 0, glWidth, glHeight, 0, 0, glWidth, glHeight);
|
||||
buffer = fbo.getPixelBuffer();
|
||||
tmpFbo.readPixels();
|
||||
a3d.popFramebuffer();
|
||||
}
|
||||
|
||||
buffer.get(tmp);
|
||||
buffer.rewind();
|
||||
if (tmpPixels == null) {
|
||||
tmpPixels = new int[size];
|
||||
}
|
||||
tmpFbo.getPixels(tmpPixels);
|
||||
|
||||
convertToARGB(tmp, pixels);
|
||||
convertToARGB(tmpPixels, pixels);
|
||||
if (flippedX) flipArrayOnX(pixels, 1);
|
||||
if (flippedY) flipArrayOnY(pixels, 1);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
// Put methods
|
||||
|
||||
|
||||
public void put(PTexture tex) {
|
||||
copyTexels(tex, 0, 0, tex.width, tex.height, false);
|
||||
}
|
||||
|
||||
|
||||
public void put(PTexture tex, int x, int y, int w, int h) {
|
||||
copyTexels(tex, x, y, w, h, false);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -880,7 +879,44 @@ public class PTexture implements PConstants {
|
||||
}
|
||||
|
||||
|
||||
protected void copy(PTexture src) {
|
||||
// Copies source texture to this.
|
||||
protected void copyTexels(PTexture tex, int x, int y, int w, int h, boolean scale) {
|
||||
if (tex == null) {
|
||||
throw new RuntimeException("PTexture: source texture is null");
|
||||
}
|
||||
|
||||
if (tmpFbo == null) {
|
||||
tmpFbo = new PFramebuffer(parent, glWidth, glHeight);
|
||||
}
|
||||
// This texture is the color (destination) buffer of the FBO.
|
||||
tmpFbo.setColorBuffer(this);
|
||||
tmpFbo.disableDepthTest();
|
||||
|
||||
// FBO copy:
|
||||
a3d.pushFramebuffer();
|
||||
a3d.setFramebuffer(tmpFbo);
|
||||
if (scale) {
|
||||
// Rendering tex into "this", and scaling the source rectangle
|
||||
// to cover the entire destination region.
|
||||
a3d.drawTexture(tex, x, y, w, h, 0, 0, width, height);
|
||||
} else {
|
||||
// Rendering tex into "this" but without scaling so the contents
|
||||
// of the source texture fall in the corresponding texels of the
|
||||
// destination.
|
||||
a3d.drawTexture(tex, x, y, w, h, x, y, w, h);
|
||||
}
|
||||
a3d.popFramebuffer();
|
||||
}
|
||||
|
||||
protected void setTexels(int x, int y, int w, int h, int[] pix) {
|
||||
gl.glTexSubImage2D(glTarget, 0, x, y, w, h, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, IntBuffer.wrap(pix));
|
||||
}
|
||||
|
||||
protected void bind() {
|
||||
gl.glBindTexture(glTarget, glID);
|
||||
}
|
||||
|
||||
protected void copyObject(PTexture src) {
|
||||
a3d.removeRecreateResourceMethod(recreateResourceIdx);
|
||||
deleteTexture();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user