|
24 | 24 | import processing.core.PApplet; |
25 | 25 | import processing.core.PConstants; |
26 | 26 | import processing.core.PGraphics; |
| 27 | + |
27 | 28 | import java.lang.reflect.Method; |
28 | 29 | import java.nio.ByteBuffer; |
29 | 30 | import java.nio.IntBuffer; |
| 31 | +import java.util.Arrays; |
30 | 32 | import java.util.LinkedList; |
31 | 33 | import java.util.NoSuchElementException; |
32 | 34 |
|
@@ -100,6 +102,10 @@ public class Texture implements PConstants { |
100 | 102 |
|
101 | 103 | protected int[] rgbaPixels = null; |
102 | 104 | protected IntBuffer pixelBuffer = null; |
| 105 | + |
| 106 | + protected int[] edgePixels = null; |
| 107 | + protected IntBuffer edgeBuffer = null; |
| 108 | + |
103 | 109 | protected FrameBuffer tempFbo = null; |
104 | 110 | protected int pixBufUpdateCount = 0; |
105 | 111 | protected int rgbaPixUpdateCount = 0; |
@@ -340,82 +346,20 @@ public void set(int[] pixels, int x, int y, int w, int h, int format) { |
340 | 346 | } |
341 | 347 | pgl.bindTexture(glTarget, glName); |
342 | 348 |
|
| 349 | + loadPixels(w * h); |
| 350 | + convertToRGBA(pixels, format, w, h); |
| 351 | + updatePixelBuffer(rgbaPixels); |
| 352 | + pgl.texSubImage2D(glTarget, 0, x, y, w, h, PGL.RGBA, PGL.UNSIGNED_BYTE, |
| 353 | + pixelBuffer); |
| 354 | + fillEdges(x, y, w, h); |
| 355 | + |
343 | 356 | if (usingMipmaps) { |
344 | 357 | if (PGraphicsOpenGL.autoMipmapGenSupported) { |
345 | | - // Automatic mipmap generation. |
346 | | - loadPixels(w * h); |
347 | | - convertToRGBA(pixels, format, w, h); |
348 | | - updatePixelBuffer(rgbaPixels); |
349 | | - pgl.texSubImage2D(glTarget, 0, x, y, w, h, PGL.RGBA, PGL.UNSIGNED_BYTE, |
350 | | - pixelBuffer); |
351 | 358 | pgl.generateMipmap(glTarget); |
352 | 359 | } else { |
353 | | - // TODO: finish manual mipmap generation, replacing Bitmap with AWT's BufferedImage, |
354 | | - // making it work in npot textures (embed npot tex into larger pot tex?), subregions, |
355 | | - // and moving GLUtils.texImage2D (originally from Android SDK) into PGL. |
356 | | - // Actually, this whole code should go into PGL, so the Android implementation can |
357 | | - // use Bitmap, and desktop use BufferedImage. |
358 | | - |
359 | | - /* |
360 | | - if (w != width || h != height) { |
361 | | - System.err.println("Sorry but I don't know how to generate mipmaps for a subregion."); |
362 | | - return; |
363 | | - } |
364 | | -
|
365 | | - // Code by Mike Miller obtained from here: |
366 | | - // http://insanitydesign.com/wp/2009/08/01/android-opengl-es-mipmaps/ |
367 | | - int w0 = glWidth; |
368 | | - int h0 = glHeight; |
369 | | - int[] argbPixels = new int[w0 * h0]; |
370 | | - convertToARGB(pixels, argbPixels, format); |
371 | | - int level = 0; |
372 | | - int denom = 1; |
373 | | -
|
374 | | - // We create a Bitmap because then we use its built-in filtered downsampling |
375 | | - // functionality. |
376 | | - Bitmap bitmap = Bitmap.createBitmap(w0, h0, Config.ARGB_8888); |
377 | | - bitmap.setPixels(argbPixels, 0, w0, 0, 0, w0, h0); |
378 | | -
|
379 | | - while (w0 >= 1 || h0 >= 1) { |
380 | | - //First of all, generate the texture from our bitmap and set it to the according level |
381 | | - GLUtils.texImage2D(glTarget, level, bitmap, 0); |
382 | | -
|
383 | | - // We are done. |
384 | | - if (w0 == 1 && h0 == 1) { |
385 | | - break; |
386 | | - } |
387 | | -
|
388 | | - // Increase the mipmap level |
389 | | - level++; |
390 | | - denom *= 2; |
391 | | -
|
392 | | - // Downsampling bitmap. We must eventually arrive to the 1x1 level, |
393 | | - // and if the width and height are different, there will be a few 1D |
394 | | - // texture levels just before. |
395 | | - // This update formula also allows for NPOT resolutions. |
396 | | - w0 = PApplet.max(1, PApplet.floor((float)glWidth / denom)); |
397 | | - h0 = PApplet.max(1, PApplet.floor((float)glHeight / denom)); |
398 | | - // (see getScaledInstance in AWT Image) |
399 | | - Bitmap bitmap2 = Bitmap.createScaledBitmap(bitmap, w0, h0, true); |
400 | | -
|
401 | | - // Clean up |
402 | | - bitmap.recycle(); |
403 | | - bitmap = bitmap2; |
404 | | - } |
405 | | - */ |
406 | | - |
407 | | - loadPixels(w * h); |
408 | | - convertToRGBA(pixels, format, w, h); |
409 | | - updatePixelBuffer(rgbaPixels); |
410 | | - pgl.texSubImage2D(glTarget, 0, x, y, w, h, PGL.RGBA, PGL.UNSIGNED_BYTE, |
411 | | - pixelBuffer); |
| 360 | + // TODO: finish manual mipmap generation, |
| 361 | + // https://github.com/processing/processing/issues/3335 |
412 | 362 | } |
413 | | - } else { |
414 | | - loadPixels(w * h); |
415 | | - convertToRGBA(pixels, format, w, h); |
416 | | - updatePixelBuffer(rgbaPixels); |
417 | | - pgl.texSubImage2D(glTarget, 0, x, y, w, h, PGL.RGBA, PGL.UNSIGNED_BYTE, |
418 | | - pixelBuffer); |
419 | 363 | } |
420 | 364 |
|
421 | 365 | pgl.bindTexture(glTarget, 0); |
@@ -472,20 +416,18 @@ public void setNative(IntBuffer pixBuf, int x, int y, int w, int h) { |
472 | 416 | } |
473 | 417 | pgl.bindTexture(glTarget, glName); |
474 | 418 |
|
| 419 | + pgl.texSubImage2D(glTarget, 0, x, y, w, h, PGL.RGBA, PGL.UNSIGNED_BYTE, |
| 420 | + pixBuf); |
| 421 | + fillEdges(x, y, w, h); |
| 422 | + |
475 | 423 | if (usingMipmaps) { |
476 | 424 | if (PGraphicsOpenGL.autoMipmapGenSupported) { |
477 | | - pgl.texSubImage2D(glTarget, 0, x, y, w, h, PGL.RGBA, PGL.UNSIGNED_BYTE, |
478 | | - pixBuf); |
479 | 425 | pgl.generateMipmap(glTarget); |
480 | 426 | } else { |
481 | | - pgl.texSubImage2D(glTarget, 0, x, y, w, h, PGL.RGBA, PGL.UNSIGNED_BYTE, |
482 | | - pixBuf); |
| 427 | + // TODO: finish manual mipmap generation, |
| 428 | + // https://github.com/processing/processing/issues/3335 |
483 | 429 | } |
484 | | - } else { |
485 | | - pgl.texSubImage2D(glTarget, 0, x, y, w, h, PGL.RGBA, PGL.UNSIGNED_BYTE, |
486 | | - pixBuf); |
487 | 430 | } |
488 | | - |
489 | 431 | pgl.bindTexture(glTarget, 0); |
490 | 432 | if (enabledTex) { |
491 | 433 | pgl.disableTexturing(glTarget); |
@@ -1504,6 +1446,44 @@ protected void setParameters(Parameters params) { |
1504 | 1446 | } |
1505 | 1447 |
|
1506 | 1448 |
|
| 1449 | + protected void fillEdges(int x, int y, int w, int h) { |
| 1450 | + if ((width < glWidth || height < glHeight) && (x + w == width || y + h == height)) { |
| 1451 | + if (x + w == width) { |
| 1452 | + int ew = glWidth - width; |
| 1453 | + edgePixels = new int[h * ew]; |
| 1454 | + for (int i = 0; i < h; i++) { |
| 1455 | + int c = rgbaPixels[i * w + (w - 1)]; |
| 1456 | + Arrays.fill(edgePixels, i * ew, (i + 1) * ew, c); |
| 1457 | + } |
| 1458 | + edgeBuffer = PGL.updateIntBuffer(edgeBuffer, edgePixels, true); |
| 1459 | + pgl.texSubImage2D(glTarget, 0, width, y, ew, h, PGL.RGBA, |
| 1460 | + PGL.UNSIGNED_BYTE, edgeBuffer); |
| 1461 | + } |
| 1462 | + |
| 1463 | + if (y + h == height) { |
| 1464 | + int eh = glHeight - height; |
| 1465 | + edgePixels = new int[eh * w]; |
| 1466 | + for (int i = 0; i < eh; i++) { |
| 1467 | + System.arraycopy(rgbaPixels, (h - 1) * w, edgePixels, i * w, w); |
| 1468 | + } |
| 1469 | + edgeBuffer = PGL.updateIntBuffer(edgeBuffer, edgePixels, true); |
| 1470 | + pgl.texSubImage2D(glTarget, 0, x, height, w, eh, PGL.RGBA, |
| 1471 | + PGL.UNSIGNED_BYTE, edgeBuffer); |
| 1472 | + } |
| 1473 | + |
| 1474 | + if (x + w == width && y + h == height) { |
| 1475 | + int ew = glWidth - width; |
| 1476 | + int eh = glHeight - height; |
| 1477 | + int c = rgbaPixels[w * h - 1]; |
| 1478 | + edgePixels = new int[eh * ew]; |
| 1479 | + Arrays.fill(edgePixels, 0, eh * ew, c); |
| 1480 | + edgeBuffer = PGL.updateIntBuffer(edgeBuffer, edgePixels, true); |
| 1481 | + pgl.texSubImage2D(glTarget, 0, width, height, ew, eh, PGL.RGBA, |
| 1482 | + PGL.UNSIGNED_BYTE, edgeBuffer); |
| 1483 | + } |
| 1484 | + } |
| 1485 | + } |
| 1486 | + |
1507 | 1487 | /////////////////////////////////////////////////////////////////////////// |
1508 | 1488 |
|
1509 | 1489 | // Parameters object |
|
0 commit comments