mirror of
https://github.com/processing/processing4.git
synced 2026-05-31 12:37:14 +02:00
Faster pixel get/set in P3D
This commit is contained in:
@@ -250,7 +250,7 @@ class PFontTexture implements PConstants {
|
||||
int[] rgba = new int[w * h];
|
||||
int t = 0;
|
||||
int p = 0;
|
||||
if (PGraphicsOpenGL.BIG_ENDIAN) {
|
||||
if (PGL.BIG_ENDIAN) {
|
||||
java.util.Arrays.fill(rgba, 0, w, 0xFFFFFF00); // Set the first row to blank pixels.
|
||||
t = w;
|
||||
for (int y = 0; y < glyph.height; y++) {
|
||||
|
||||
@@ -103,6 +103,34 @@ public class PGL {
|
||||
/** Maximum dimension of a texture used to hold font data. **/
|
||||
public static final int MAX_FONT_TEX_SIZE = 256;
|
||||
|
||||
/** Minimum array size to use arrayCopy method(). **/
|
||||
static protected final int MIN_ARRAYCOPY_SIZE = 2;
|
||||
|
||||
/** Machine Epsilon for float precision. **/
|
||||
static public float FLOAT_EPS = Float.MIN_VALUE;
|
||||
// Calculation of the Machine Epsilon for float precision. From:
|
||||
// http://en.wikipedia.org/wiki/Machine_epsilon#Approximation_using_Java
|
||||
static {
|
||||
float eps = 1.0f;
|
||||
|
||||
do {
|
||||
eps /= 2.0f;
|
||||
} while ((float)(1.0 + (eps / 2.0)) != 1.0);
|
||||
|
||||
FLOAT_EPS = eps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true if the host system is big endian (PowerPC, MIPS, SPARC), false
|
||||
* if little endian (x86 Intel for Mac or PC).
|
||||
*/
|
||||
static public boolean BIG_ENDIAN = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN;
|
||||
|
||||
protected static final String SHADER_PREPROCESSOR_DIRECTIVE = "#ifdef GL_ES\n" +
|
||||
"precision mediump float;\n" +
|
||||
"precision mediump int;\n" +
|
||||
"#endif;\n";
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// OpenGL constants
|
||||
@@ -151,10 +179,12 @@ public class PGL {
|
||||
public static final int GL_RGBA8 = GL.GL_RGBA8;
|
||||
public static final int GL_DEPTH24_STENCIL8 = GL.GL_DEPTH24_STENCIL8;
|
||||
|
||||
public static final int GL_DEPTH_COMPONENT = GL2.GL_DEPTH_COMPONENT;
|
||||
public static final int GL_DEPTH_COMPONENT16 = GL.GL_DEPTH_COMPONENT16;
|
||||
public static final int GL_DEPTH_COMPONENT24 = GL.GL_DEPTH_COMPONENT24;
|
||||
public static final int GL_DEPTH_COMPONENT32 = GL.GL_DEPTH_COMPONENT32;
|
||||
|
||||
public static final int GL_STENCIL_INDEX = GL2.GL_STENCIL_INDEX;
|
||||
public static final int GL_STENCIL_INDEX1 = GL.GL_STENCIL_INDEX1;
|
||||
public static final int GL_STENCIL_INDEX4 = GL.GL_STENCIL_INDEX4;
|
||||
public static final int GL_STENCIL_INDEX8 = GL.GL_STENCIL_INDEX8;
|
||||
@@ -325,7 +355,8 @@ public class PGL {
|
||||
" vertTexcoord = inTexcoord;" +
|
||||
"}";
|
||||
|
||||
protected String texFragShaderSource = "uniform sampler2D textureSampler;" +
|
||||
protected String texFragShaderSource = SHADER_PREPROCESSOR_DIRECTIVE +
|
||||
"uniform sampler2D textureSampler;" +
|
||||
"varying vec2 vertTexcoord;" +
|
||||
"void main() {" +
|
||||
" gl_FragColor = texture2D(textureSampler, vertTexcoord.st);" +
|
||||
@@ -357,11 +388,21 @@ public class PGL {
|
||||
" gl_Position = vec4(inVertex, 0, 1);" +
|
||||
"}";
|
||||
|
||||
protected String rectFragShaderSource = "uniform vec4 rectColor;" +
|
||||
protected String rectFragShaderSource = SHADER_PREPROCESSOR_DIRECTIVE +
|
||||
"uniform vec4 rectColor;" +
|
||||
"void main() {" +
|
||||
" gl_FragColor = rectColor;" +
|
||||
"}";
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// 1-pixel color, depth, stencil buffers
|
||||
|
||||
protected IntBuffer colorBuffer;
|
||||
protected FloatBuffer depthBuffer;
|
||||
protected ByteBuffer stencilBuffer;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Intialization, finalization
|
||||
@@ -1186,21 +1227,30 @@ public class PGL {
|
||||
|
||||
|
||||
public void enableTexturing(int target) {
|
||||
gl.glEnable(target);
|
||||
glEnable(target);
|
||||
}
|
||||
|
||||
|
||||
public void disableTexturing(int target) {
|
||||
gl.glDisable(target);
|
||||
glDisable(target);
|
||||
}
|
||||
|
||||
|
||||
public void initTexture(int target, int width, int height, int format, int type) {
|
||||
public void initTexture(int target, int format, int width, int height) {
|
||||
int[] texels = new int[width * height];
|
||||
gl.glTexSubImage2D(target, 0, 0, 0, width, height, format, type, IntBuffer.wrap(texels));
|
||||
glTexSubImage2D(target, 0, 0, 0, width, height, format, GL_UNSIGNED_BYTE, IntBuffer.wrap(texels));
|
||||
}
|
||||
|
||||
|
||||
public void copyToTexture(int target, int format, int id, int x, int y, int w, int h, IntBuffer buffer) {
|
||||
enableTexturing(target);
|
||||
glBindTexture(target, id);
|
||||
glTexSubImage2D(target, 0, x, y, w, h, format, GL_UNSIGNED_BYTE, buffer);
|
||||
glBindTexture(target, 0);
|
||||
disableTexturing(target);
|
||||
}
|
||||
|
||||
|
||||
public void drawTexture(int target, int id, int width, int height,
|
||||
int texX0, int texY0, int texX1, int texY1,
|
||||
int scrX0, int scrY0, int scrX1, int scrY1) {
|
||||
@@ -1352,7 +1402,36 @@ public class PGL {
|
||||
glDepthMask(writeMask);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public int getColorValue(int scrX, int scrY) {
|
||||
if (colorBuffer == null) {
|
||||
colorBuffer = IntBuffer.allocate(1);
|
||||
}
|
||||
colorBuffer.rewind();
|
||||
glReadPixels(scrX, pg.height - scrY - 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, colorBuffer);
|
||||
return colorBuffer.get();
|
||||
}
|
||||
|
||||
|
||||
public float getDepthValue(int scrX, int scrY) {
|
||||
if (depthBuffer == null) {
|
||||
depthBuffer = FloatBuffer.allocate(1);
|
||||
}
|
||||
depthBuffer.rewind();
|
||||
glReadPixels(scrX, pg.height - scrY - 1, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, depthBuffer);
|
||||
return depthBuffer.get(0);
|
||||
}
|
||||
|
||||
|
||||
public byte getStencilValue(int scrX, int scrY) {
|
||||
if (stencilBuffer == null) {
|
||||
stencilBuffer = ByteBuffer.allocate(1);
|
||||
}
|
||||
glReadPixels(scrX, pg.height - scrY - 1, 1, 1, GL_STENCIL_INDEX, GL.GL_UNSIGNED_BYTE, stencilBuffer);
|
||||
return stencilBuffer.get(0);
|
||||
}
|
||||
|
||||
|
||||
// bit shifting this might be more efficient
|
||||
static public int nextPowerOfTwo(int val) {
|
||||
@@ -1363,6 +1442,238 @@ public class PGL {
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert native OpenGL format into palatable ARGB format. This function
|
||||
* leaves alone (ignores) the alpha component. Also flips the image
|
||||
* vertically, since images are upside-down in GL.
|
||||
*/
|
||||
static public void nativeToJavaRGB(int[] pixels, int width, int height) {
|
||||
int index = 0;
|
||||
int yindex = (height - 1) * width;
|
||||
for (int y = 0; y < height / 2; y++) {
|
||||
if (BIG_ENDIAN) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
int temp = pixels[index];
|
||||
// ignores alpha component, just sets it opaque
|
||||
pixels[index] = 0xff000000 | ((pixels[yindex] >> 8) & 0x00ffffff);
|
||||
pixels[yindex] = 0xff000000 | ((temp >> 8) & 0x00ffffff);
|
||||
index++;
|
||||
yindex++;
|
||||
}
|
||||
} else { // LITTLE_ENDIAN, convert ABGR to ARGB
|
||||
for (int x = 0; x < width; x++) {
|
||||
int temp = pixels[index];
|
||||
// identical to endPixels because only two
|
||||
// components are being swapped
|
||||
pixels[index] = 0xff000000 | ((pixels[yindex] << 16) & 0xff0000) |
|
||||
(pixels[yindex] & 0xff00) |
|
||||
((pixels[yindex] >> 16) & 0xff);
|
||||
pixels[yindex] = 0xff000000 | ((temp << 16) & 0xff0000) |
|
||||
(temp & 0xff00) |
|
||||
((temp >> 16) & 0xff);
|
||||
index++;
|
||||
yindex++;
|
||||
}
|
||||
}
|
||||
yindex -= width * 2;
|
||||
}
|
||||
|
||||
// When height is an odd number, the middle line needs to be
|
||||
// endian swapped, but not y-swapped.
|
||||
// http://dev.processing.org/bugs/show_bug.cgi?id=944
|
||||
if ((height % 2) == 1) {
|
||||
index = (height / 2) * width;
|
||||
if (BIG_ENDIAN) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
pixels[index] = 0xff000000 | ((pixels[index] >> 8) & 0x00ffffff);
|
||||
index++;
|
||||
}
|
||||
} else {
|
||||
for (int x = 0; x < width; x++) {
|
||||
pixels[index] = 0xff000000 | ((pixels[index] << 16) & 0xff0000) |
|
||||
(pixels[index] & 0xff00) |
|
||||
((pixels[index] >> 16) & 0xff);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert native OpenGL format into palatable ARGB format. This function
|
||||
* leaves alone (ignores) the alpha component. Also flips the image
|
||||
* vertically, since images are upside-down in GL.
|
||||
*/
|
||||
static public void nativeToJavaARGB(int[] pixels, int width, int height) {
|
||||
int index = 0;
|
||||
int yindex = (height - 1) * width;
|
||||
for (int y = 0; y < height / 2; y++) {
|
||||
if (BIG_ENDIAN) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
int temp = pixels[index];
|
||||
// ignores alpha component, just sets it opaque
|
||||
pixels[index] = (pixels[yindex] & 0xff000000) |
|
||||
((pixels[yindex] >> 8) & 0x00ffffff);
|
||||
pixels[yindex] = (temp & 0xff000000) |
|
||||
((temp >> 8) & 0x00ffffff);
|
||||
index++;
|
||||
yindex++;
|
||||
}
|
||||
} else { // LITTLE_ENDIAN, convert ABGR to ARGB
|
||||
for (int x = 0; x < width; x++) {
|
||||
int temp = pixels[index];
|
||||
pixels[index] = (pixels[yindex] & 0xff000000) |
|
||||
((pixels[yindex] << 16) & 0xff0000) |
|
||||
(pixels[yindex] & 0xff00) |
|
||||
((pixels[yindex] >> 16) & 0xff);
|
||||
pixels[yindex] = (temp & 0xff000000) |
|
||||
((temp << 16) & 0xff0000) |
|
||||
(temp & 0xff00) |
|
||||
((temp >> 16) & 0xff);
|
||||
index++;
|
||||
yindex++;
|
||||
}
|
||||
}
|
||||
yindex -= width * 2;
|
||||
}
|
||||
|
||||
if ((height % 2) == 1) {
|
||||
index = (height / 2) * width;
|
||||
if (BIG_ENDIAN) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
pixels[index] = (pixels[index] & 0xff000000) |
|
||||
((pixels[index] >> 8) & 0x00ffffff);
|
||||
index++;
|
||||
}
|
||||
} else {
|
||||
for (int x = 0; x < width; x++) {
|
||||
pixels[index] = (pixels[index] & 0xff000000) |
|
||||
((pixels[index] << 16) & 0xff0000) |
|
||||
(pixels[index] & 0xff00) |
|
||||
((pixels[index] >> 16) & 0xff);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert ARGB (Java/Processing) data to native OpenGL format. This function
|
||||
* leaves alone (ignores) the alpha component. Also flips the image
|
||||
* vertically, since images are upside-down in GL.
|
||||
*/
|
||||
static public void javaToNativeRGB(int[] pixels, int width, int height) {
|
||||
int index = 0;
|
||||
int yindex = (height - 1) * width;
|
||||
for (int y = 0; y < height / 2; y++) {
|
||||
if (BIG_ENDIAN) {
|
||||
// and convert ARGB back to opengl RGBA components (big endian)
|
||||
for (int x = 0; x < width; x++) {
|
||||
int temp = pixels[index];
|
||||
pixels[index] = ((pixels[yindex] << 8) & 0xffffff00) | 0xff;
|
||||
pixels[yindex] = ((temp << 8) & 0xffffff00) | 0xff;
|
||||
index++;
|
||||
yindex++;
|
||||
}
|
||||
|
||||
} else {
|
||||
// convert ARGB back to native little endian ABGR
|
||||
for (int x = 0; x < width; x++) {
|
||||
int temp = pixels[index];
|
||||
pixels[index] = 0xff000000 | ((pixels[yindex] << 16) & 0xff0000) |
|
||||
(pixels[yindex] & 0xff00) |
|
||||
((pixels[yindex] >> 16) & 0xff);
|
||||
pixels[yindex] = 0xff000000 | ((temp << 16) & 0xff0000) |
|
||||
(temp & 0xff00) |
|
||||
((temp >> 16) & 0xff);
|
||||
index++;
|
||||
yindex++;
|
||||
}
|
||||
}
|
||||
yindex -= width * 2;
|
||||
}
|
||||
|
||||
if ((height % 2) == 1) {
|
||||
index = (height / 2) * width;
|
||||
if (BIG_ENDIAN) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
pixels[index] = ((pixels[index] << 8) & 0xffffff00) | 0xff;
|
||||
index++;
|
||||
}
|
||||
} else {
|
||||
for (int x = 0; x < width; x++) {
|
||||
pixels[index] = 0xff000000 | ((pixels[index] << 16) & 0xff0000) |
|
||||
(pixels[index] & 0xff00) |
|
||||
((pixels[index] >> 16) & 0xff);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert Java ARGB to native OpenGL format. Also flips the image vertically,
|
||||
* since images are upside-down in GL.
|
||||
*/
|
||||
static public void javaToNativeARGB(int[] pixels, int width, int height) {
|
||||
int index = 0;
|
||||
int yindex = (height - 1) * width;
|
||||
for (int y = 0; y < height / 2; y++) {
|
||||
if (BIG_ENDIAN) {
|
||||
// and convert ARGB back to opengl RGBA components (big endian)
|
||||
for (int x = 0; x < width; x++) {
|
||||
int temp = pixels[index];
|
||||
pixels[index] = ((pixels[yindex] >> 24) & 0xff) |
|
||||
((pixels[yindex] << 8) & 0xffffff00);
|
||||
pixels[yindex] = ((temp >> 24) & 0xff) |
|
||||
((temp << 8) & 0xffffff00);
|
||||
index++;
|
||||
yindex++;
|
||||
}
|
||||
|
||||
} else {
|
||||
// convert ARGB back to native little endian ABGR
|
||||
for (int x = 0; x < width; x++) {
|
||||
int temp = pixels[index];
|
||||
pixels[index] = (pixels[yindex] & 0xff000000) |
|
||||
((pixels[yindex] << 16) & 0xff0000) |
|
||||
(pixels[yindex] & 0xff00) |
|
||||
((pixels[yindex] >> 16) & 0xff);
|
||||
pixels[yindex] = (pixels[yindex] & 0xff000000) |
|
||||
((temp << 16) & 0xff0000) |
|
||||
(temp & 0xff00) |
|
||||
((temp >> 16) & 0xff);
|
||||
index++;
|
||||
yindex++;
|
||||
}
|
||||
}
|
||||
yindex -= width * 2;
|
||||
}
|
||||
|
||||
if ((height % 2) == 1) {
|
||||
index = (height / 2) * width;
|
||||
if (BIG_ENDIAN) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
pixels[index] = ((pixels[index] >> 24) & 0xff) |
|
||||
((pixels[index] << 8) & 0xffffff00);
|
||||
index++;
|
||||
}
|
||||
} else {
|
||||
for (int x = 0; x < width; x++) {
|
||||
pixels[index] = (pixels[index] & 0xff000000) |
|
||||
((pixels[index] << 16) & 0xff0000) |
|
||||
(pixels[index] & 0xff00) |
|
||||
((pixels[index] >> 16) & 0xff);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public int createShader(int shaderType, String source) {
|
||||
int shader = glCreateShader(shaderType);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -3952,7 +3952,7 @@ public class PShape3D extends PShape {
|
||||
expand(newSize);
|
||||
}
|
||||
|
||||
if (dataSize <= PGraphicsOpenGL.MIN_ARRAYCOPY_SIZE) {
|
||||
if (dataSize <= PGL.MIN_ARRAYCOPY_SIZE) {
|
||||
// Copying elements one by one instead of using arrayCopy is more efficient for
|
||||
// few vertices...
|
||||
for (int i = 0; i < dataSize; i++) {
|
||||
@@ -3995,7 +3995,7 @@ public class PShape3D extends PShape {
|
||||
expand(newSize);
|
||||
}
|
||||
|
||||
if (dataSize <= PGraphicsOpenGL.MIN_ARRAYCOPY_SIZE) {
|
||||
if (dataSize <= PGL.MIN_ARRAYCOPY_SIZE) {
|
||||
// Copying elements one by one instead of using arrayCopy is more efficient for
|
||||
// few vertices...
|
||||
for (int i = 0; i < dataSize; i++) {
|
||||
|
||||
@@ -542,7 +542,7 @@ public class PTexture implements PConstants {
|
||||
* @param h int
|
||||
*/
|
||||
protected void convertToRGBA(int[] intArray, int[] tIntArray, int arrayFormat, int w, int h) {
|
||||
if (PGraphicsOpenGL.BIG_ENDIAN) {
|
||||
if (PGL.BIG_ENDIAN) {
|
||||
switch (arrayFormat) {
|
||||
case ALPHA:
|
||||
|
||||
@@ -682,7 +682,7 @@ public class PTexture implements PConstants {
|
||||
protected void convertToARGB(int[] intArray, int[] tIntArray) {
|
||||
int t = 0;
|
||||
int p = 0;
|
||||
if (PGraphicsOpenGL.BIG_ENDIAN) {
|
||||
if (PGL.BIG_ENDIAN) {
|
||||
|
||||
// RGBA to ARGB conversion: shifting RGB 8 bits to the right,
|
||||
// and placing A 24 bits to the left.
|
||||
@@ -768,7 +768,7 @@ public class PTexture implements PConstants {
|
||||
pgl.glTexImage2D(glTarget, 0, glFormat, glWidth, glHeight, 0, PGL.GL_RGBA, PGL.GL_UNSIGNED_BYTE, null);
|
||||
|
||||
// Makes sure that the texture buffer in video memory doesn't contain any garbage.
|
||||
pgl.initTexture(glTarget, width, height, PGL.GL_RGBA, PGL.GL_UNSIGNED_BYTE);
|
||||
pgl.initTexture(glTarget, PGL.GL_RGBA, width, height);
|
||||
|
||||
pgl.glBindTexture(glTarget, 0);
|
||||
pgl.disableTexturing(glTarget);
|
||||
@@ -819,12 +819,15 @@ public class PTexture implements PConstants {
|
||||
if (scale) {
|
||||
// Rendering tex into "this", and scaling the source rectangle
|
||||
// to cover the entire destination region.
|
||||
pg.drawTexture(tex, x, y, w, h, 0, 0, width, height);
|
||||
pgl.drawTexture(tex.glTarget, tex.glID, tex.glWidth, tex.glHeight,
|
||||
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.
|
||||
pg.drawTexture(tex, x, y, w, h, x, y, w, h);
|
||||
pgl.drawTexture(tex.glTarget, tex.glID, tex.glWidth, tex.glHeight,
|
||||
x, y, w, h, x, y, w, h);
|
||||
}
|
||||
pg.popFramebuffer();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user