How to continuously fade a BitmapData to a certain color? - actionscript-3

I'm drawing stuff on a bitmapData and I need to continuously fade every pixel to 0x808080 while still drawing (its for a DisplacementMapFilter)...
I think this illustrates my problem:
http://www.ventdaval.com/lab/grey.swf
The simpler approach I tried was drawing a semi-transparent grey box on it, but it never reaches a single color (i.e. 0x808081 will never be turned to 0x808080)... The same kind of thing happens with a ColorMatrixFilter trying to progressively reduce the saturation and/or contrast. (the example above is applying a filter with -10 contrast every frame).
I'm trying paletteMap now, and I'm sensing this could be the way to go, but I haven't been able to get it... any ideas?

You can try to fade it slightly more than you are fading it now, so color will go to 0x808080, you just need to do some calculations.
Yes, you can do this with paletteMap.
The third way will be to write PixelBender shader for it.
You can also use your normal fading and do paletteMap or PixelBender one once in a few frames, to speed-up all this.

I think the easiest way to do this would be with two successive color filters. That is:
var n:Number = 0.9;
var off:Number = 0x80;
var filter:ColorMatrixFilter = new ColorMatrixFilter( [
1, 0, 0, 0, -off,
0, 1, 0, 0, -off,
0, 0, 1, 0, -off,
0, 0, 0, 1, -off ] );
var filter2:ColorMatrixFilter = new ColorMatrixFilter( [
n, 0, 0, 0, off,
0, n, 0, 0, off,
0, 0, n, 0, off,
0, 0, 0, n, off ] );
function onFrame( e:Event ) {
myBMD.applyFilter( myBMD, myBMD.rect, new Point(), filter );
myBMD.applyFilter( myBMD, myBMD.rect, new Point(), filter2 );
}
The first filter offsets each channel value downwards by 128 - turning your gray-based image into a black-based image. The second filter multiplies each channel value by the modulator (0.9 in my example), and then offsets the values back up by 128.

I wound up solving this by filling the texture with 0xFF808080 every frame, then drawing my dynamic stuff to a second, transparent bitmap, doing a colortransform on it with a lower alpha multiplier (say 0.98), and then copypixeling that bitmap to the main bitmap with mergealpha on. Works a treat:
public function update():void
{
lock();
fillRect(rect, 0xFF808080);
drawTarget.lock();
drawTarget.colorTransform(rect, fadeTransform);
drawTarget.applyFilter(drawTarget, rect, pt, blurFilter);
drawTarget.unlock();
copyPixels(drawTarget, rect, pt, null, null, true);
unlock();
}

Related

lwjgl not drawing vertex buffer

Im try to get a super simple lwjgl app going that draws a simple triangle, but cant find the right order of calls to make anything meaningful appear. im using a simple vertex buffer and no shaders.
for some reason each frame is a white triangle on the lower right side of the frame, regardless of what is in the actual vertex buffer.
public void run() {
GLFWErrorCallback.createThrow().set();
glfwInit();
glfwDefaultWindowHints();
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
long h_window = glfwCreateWindow(640, 480, "test", 0, 0);
glfwShowWindow(h_window);
glfwMakeContextCurrent(h_window);
GL.createCapabilities();
glEnableClientState(GL_VERTEX_ARRAY);
int b_vertex = glGenBuffers();
float[] vertex = {
0,0,0,
0,0,0,
0,0,0
};
glBindBuffer(GL_ARRAY_BUFFER, b_vertex);
glBufferData(GL_ARRAY_BUFFER, vertex, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
while (!glfwWindowShouldClose(h_window)) {
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, b_vertex);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0L);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(0);
glfwSwapBuffers(h_window);
glfwWaitEventsTimeout(1f / 30f);
}
}
im definitely missing something, but have no idea what it is. here is what this shows:
Screenshot of Running app
Found the problem.
glVertexPointer(3, GL_FLOAT, 0, 0L);
is for shaderless buffer descriptions
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0L);
is for buffer descriptions that also bind buffers to shader inputs

Create a pixmap which is the difference of two shapes

I'd like to create an overlay in my libGDX game to be used during onboarding. Basically I'd like to overlay the entire screen with a 40% alpha rectangle (that's easy) but I want a cutout of a circle on top of the area of interest where the user should focus attention. Is there a way to create a texture which is the difference of two shapes or pixmaps?
Pixmap overlay = new Pixmap(screenWidth, screenHeight, Pixmap.Format.RGBA8888);
overlay.setColor(0, 0, 0, 0.4f);
overlay.fillRectangle(0, 0, screenWidth, screenHeight);
Pixmap overlayCutout = new Pixmap(screenWidth, screenHeight, Pixmap.Format.RGBA8888);
overlayCutout.setColor(Color.WHITE);
overlayCutout.fillCircle(focusAreaX, focusAreaY, radius);
Texture t = new Texture(overlay);
//subtract overlayCutout??
overlay.dispose();
overlayCutout.dispose();
batch.draw(t);
I'm not sure I completely got what you want to do, but I think the trick is to use only one Pixmap...
Pixmap overlay = new Pixmap(screenWidth, screenHeight, Pixmap.Format.RGBA8888);
overlay.setColor(0, 0, 0, 0.4f);
overlay.fillRectangle(0, 0, screenWidth, screenHeight);
// the trick is to "redraw" the inner circle with an "invisible" colour alpha=0
overlay.setBlending(Blending.None);
overlay.setColor(1, 1, 1, 0);
overlay.fillCircle(focusAreaX, focusAreaY, radius);
overlay.setBlending(Blending.SourceOver);
Texture t = new Texture(overlay);
overlay.dispose();
batch.draw(t);

Actionscript: ColorMatrixFilter for Photoshop's brightness adjust?

I have a B/W picture and I need to make some adjustments to it - I need to increase it's 'visibility' (it is too gray, I need to make it darker). Does anybody know how to reproduce Photoshop's brightness adjust in AS3? Please note that this is NOT the same as adjusting the brightness in Flash. The difference is:
in PS: brightness adjusts only the pixels that have a color different to white. It does not do anything to white pixels, so white pixels actually stay white
in PS: lightness adjusts all the pixels, so it affects the white pixels as well. Bringing lightness down makes all the image darker; this is unusable for me and this is exactly what Flash does as well (although it is called 'brightness' there)
I could reproduce Flash's brightness with this matrix:
var m:Array = new Array();
m = m.concat([1, 0, 0, 0, value]); // red
m = m.concat([0, 1, 0, 0, value]); // green
m = m.concat([0, 0, 1, 0, value]); // blue
m = m.concat([0, 0, 0, 1, 0]); // alpha
new ColorMatrixFilter(m);
...however this is exactly what doesn't work well as it sets all the image darker, including the white parts.
Any ideas how to reproduce PS's brigthness setting? Or any other matrix that actually keeps white/light pixels light while darkening the darker ones? Thank you!
I doubt this replicates Photoshop's "brightness" exactly (it's more like adjusting the contrast), but you could try scaling the RGB values, then adjusting them so that whites remain white:
var scaling:Number = 4;
var adjustment:Number = 255 * (1 - scaling);
var m:Array = new Array();
m = m.concat([scaling, 0, 0, 0, adjustment]); // red
m = m.concat([0, scaling, 0, 0, adjustment]); // green
m = m.concat([0, 0, scaling, 0, adjustment]); // blue
m = m.concat([0, 0, 0, 1, 0]); // alpha
new ColorMatrixFilter(m);
If you wanted a more traditional contrast, the adjustment would be:
var value:Number = 255 * (1 - scaling) * 0.5;

Html5 Canvas - Shading an outside area

I need to shade an OUTSIDE area, ie the shapes I draw in the shader are drawn normally, and their inverse is then shaded. Its easiest to explain with an example, and noting the bit that is not working:
// canvasBackground is the actual background
// canvasBackgroundContext is its context
// To make it simple, I will fill it with green
canvasBackgroundContext.fillStyle = "#00FF00";
canvasBackgroundContext.clearRect(0, 0, canvasBackground.width, canvasBackground.height);
// I also have a the shader
// canvasShader and canvasShaderContext with same width and height as canvasBackground
canvasShaderContext.fillStyle = "rgba(0, 0, 0, 0.25)"; // Black but slightly transparent
canvasShaderContext.clearRect(0, 0, canvasShader.width, canvasShader.height);
// Everything so far is great - now the problem
// This is wrong, because when I create the area I want to create clear, it does not work
// because when you draw a shape it does not work like clearRect, as it does not set each pixel to a clear pixel
canvasShaderContext.fillStyle = "rgba(0, 0, 0, 0.0)";
// Create the only non shaded bits in the shader, overlapping rects
canvasShaderContext.fillRect(10, 10, 50, 50);
canvasShaderContext.fillRect(40, 40, 50, 50);
// So when I do this, it should shade the entire background except for the two 50x50 overlapping rects at 10,10 and 40,40
canvasBackgroundContext.drawImage(canvasShaderContext, 0, 0);
I don't want to go to a pixel by pixel basis using getImageData, as that is slow. There must be some way of doing this.
I am not sure I fully understand what you try to achieve, but how about adding a composite mode to this:
canvasShaderContext.fillRect(10, 10, 50, 50);
canvasShaderContext.fillRect(40, 40, 50, 50);
which results in:
/// store old mode whatever that is
var oldMode = canvasShaderContext.globalCompositeOperation;
/// this uses any shape that is drawn next to punch a hole
/// in destination (current context).
canvasShaderContext.globalCompositeOperation = 'destination-out';
/// now draw the holes
canvasShaderContext.fillRect(10, 10, 50, 50);
canvasShaderContext.fillRect(40, 40, 50, 50);
/// set back to old mode
canvasShaderContext.globalCompositeOperation = oldMode;
That will also clear the alpha bits.

circular colorTransform

Is there a way to apply a colorTransform to a BitmapData in a circle rather than in a rectangle?
Instead of erasing rectangular parts of an image by reducing the alpha channel as in the code below, I'd like to do it in circles.
_bitmap.colorTransform(new Rectangle(mouseX-d/2, mouseY-d/2, d, d),
new ColorTransform(1, 1, 1, .5, 0, 0, 0, 1));
I do have some code which loops through the pixels, extracts the alpha value and uses setPixel but it seams significantly slower than the colorTransform function.
Try creating a circle using the drawing API (flash.display.Graphics) and then drawing that onto the bitmap data with BlendMode.ERASE. That might solve your problem, if I understand it correctly.
var circle : Shape = new Shape;
circle.graphics.beginFill(0xffcc00, 1);
circle.graphics.drawEllipse(-50, -50, 100, 100);
// Create a transformation matrix for the draw() operation, with
// a translation matching the mouse position.
var mtx : Matrix = new Matrix();
mtx.translate(mouseX, mouseY);
// Draw circle at mouse position with the ERASE blend mode, to
// set affected pixels to alpha=0.
myBitmap.draw(circle, mtx, null, BlendMode.ERASE);
I'm not 100% sure that the ERASE blend mode works satisfyingly with the draw() command, but I can't see why it shouldn't. Please let me know how it works out!