Hi,
I think I've found a bug in Pixel Bender that's so far been missed.
If you want to upsample a buffer using a ShaderJob and ByteArray/Vector.<Number> it doesn't work with sampleLinear, only sampleNearest. Using sampleLinear it returns a buffer with mostly black pixels but with every 2nd pixel (for upsampling to a double sized buffer) written to. So basically it looks like it's upsampling but only writing to some of the target pixels...
Btw, I'm talking about in Flash here. And I need to use ByteArray/Vector.<Number> instead of BitmapData as I need to process 32-bit data.
Strangely it works in the PB toolkit in all of the modes (GPU, CPU, Flash).
Am I doing something wrong or is this a known issue?
Here's my sample code:
package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Shader;
import flash.display.ShaderJob;
import flash.display.ShaderPrecision;
import flash.display.Sprite;
import flash.display.StageQuality;
import flash.geom.Vector3D;
import flash.utils.ByteArray;
import flash.utils.Endian;
import flash.utils.Timer;
public class Test_Upscale extends Sprite
{
[Embed ( source = "../data/embed/pixelbender/bilinearresample.pbj", mimeType = "application/octet-stream" ) ]
private var BilinearScalingKernel:Class;
public function Test_Upscale()
{
const srcWidth:int = 256;
const srcHeight:int = 256;
const dstWidth:int = 256;
const dstHeight:int = 256;
this.stage.quality = StageQuality.BEST;
// Create noise input buffer
var input:ByteArray = new ByteArray();
input.endian = Endian.LITTLE_ENDIAN;
input.length = srcWidth * srcHeight * 4 * 4;
for (var i:int = 0; i < srcWidth*srcHeight; i++)
{
var val:int = Math.random() * 255.0;
input.writeFloat(val);
input.writeFloat(val);
input.writeFloat(val);
input.writeFloat(255.0);
}
input.position = 0;
// Create output buffer
var output:ByteArray = new ByteArray();
output.endian = Endian.LITTLE_ENDIAN;
output.length = dstWidth * dstHeight * 4 * 4;
// Resample
Resample(input, srcWidth, srcHeight, dstWidth, dstHeight, output);
// Display as a bitmap
this.addChild(new Bitmap(ToBitmap(dstWidth, dstHeight, output) ));
}
private static function ToBitmap(width:int, height:int, data:ByteArray):BitmapData
{
data.position = 0;
var bmp:BitmapData = new BitmapData(width, height, false);
var idx:int = 0;
for (var j:int = 0; j < height; j++)
{
for (var i:int = 0; i < width; i++)
{
var r:int = data.readFloat() as int;
var g:int = data.readFloat() as int;
var b:int = data.readFloat() as int;
data.readFloat();
var c:int = r + (g << 8) + (b << 16);
bmp.setPixel(i, j, c);
idx++;
}
}
return bmp;
}
public function Resample(src:ByteArray, srcWidth:int, srcHeight:int, dstWidth:int, dstHeight:int, dst:ByteArray):void
{
// create and configure a Shader object
var shader:Shader = new Shader();
shader.precisionHint =ShaderPrecision.FULL;
shader.byteCode = new BilinearScalingKernel();
shader.data.src.input = src;
shader.data.src.width = srcWidth;
shader.data.src.height = srcHeight;
shader.data.scaley.value = [0.5];
var job:ShaderJob = new ShaderJob(shader, dst, dstWidth, dstHeight);
job.start(true); // true flag runs the job synchronously.
}
}
}
<languageVersion : 1.0;>
kernel BilinearResample
< namespace : "com.test.pixelbender";
vendor : "me";
version : 1;
description : "bilinear";
>
{
input image4 src;
output pixel4 dst;
parameter float scaley;
void
evaluatePixel()
{
dst = sampleLinear(src, outCoord() * float2(scaley, scaley)); // bilinear scaling
}
}
North America
Europe, Middle East and Africa
Asia Pacific