We are about to switch to a new forum software. Until then we have removed the registration on this forum.
Is something like this possible?
testImg = loadImage("someImage.jpg");
testImg.filter(shader);
The reason I ask is cause getting the color of an image directly is insane fast
int c = img.get(mouseX, mouseY);
Like 500 frames a second. But if I draw to the main canvas first (g) then it's really slow. Like:
int c =get(mouseX, mouseY);
Answers
Not sure if there is better solution, but you could draw the source image, apply a filter and then copy the result to a new PImage.
I'm looking for something faster. The code above will create a new PImage every time which is slow. I'm hoping for something that doesn't leave GPU.
Well, get(int, int) just returns the color value saved in the pixels array. For PImage.get() this is pretty fast, because pixels is always uptodate. For PGraphics.get() (actually only the OpenGL based PGraphics) this is reeaally slow, because every time get() is called, PGraphics will attempt to flush (render every buffered vertex) and copy the whole image from the VRAM texture object to the backing pixels array in your RAM.
I'm looking for something faster. The code above will create a new PImage every time which is slow. I'm hoping for something that doesn't leave GPU.
It has to leave the GPU or you won't be able to interact with it in Processing anymore. So that's not possible, but if you only need to get the color value for one or a handful of pixels you could try to request the data directly from your graphics card:
Anyways, applying a PShader to an PImage directly isn't possible - in Processing. While it is possible in OpenGL, it's more complicated than you might think: You'd have to have two texture objects, one as input (sampler2D) and one as output (Frame Buffer Object) and use ping pong rendering (from A to B, the next frame B to A, etc.) to be efficient. Plus, using a texture as render target can be more slowly than using a default render buffer (depending on the hardware).
Thanks that might help. I need to jump a lot. Like jump 63 pixels forward, and again and again... So it might help. After that I will dive into CUDA.
No problem. :)
Is there a way to get the integers like blendMode(REPLACE) was used. I'm getting different values at the moment. Which is most likely due the alpha channel adjusting the RGB values again.
Blend mode works like it should, but Processing returns the color value in BGRA instead of the chosen RGBA... :/
The following code should fix the problem:
Once again thanks :)
I looked into it. It's really slow! Even for 1 pixel my frameRate goes from around 400 to 100. If i check like 60 pixels my frameRate is around 20. Damn...
Do you know any other way apart from CUDA?
Yeah because calling the graphics card directly is always slow... I'm currently at work, but it should be possible to update your canvas' pixels array just once per frame and then get the color values from the CPU sided pixels array instead of requesting it from the GPU again and again.
The following code will update the pixels array only once a frame - only one graphics card call, this is as fast as it gets (with Processing):
I modified Processing's loadPixels() and updatePixels() as they seem to be broken (in 3.0 at least). I also modified get() to use the pixels array and removed all unnecessary overhead (like calling loadPixels() again and again and needless bounding checks).
Btw.: I know this is still slow, updatePixels() lowers my framerate from 1000 (can't set a higher rate) to around 330, but the following get() calls are basically for free.
Nice! This is really cool! I tested and this is faster. Now I have a framerate of 60 again. And there is a loot of room for optimization in my shaders, but I will do that as last.
I think this is bugged:
Let's say I have an image of 800*800. That will be an array of 640.000 pixels.
If I get the coordinate at 0,0:
Then it prints 639200, so where 800 short!
Edit #3 This seems to be ok:
In a shader, if I want to check one pixel higher do I use:
or
?
Correction:
I think this is correct:
Nope, it's correct. If width & height equal 800, get(799, 799) will return the color from the index 799. get(799, 0) will return the color from the index 0. That strange behavior is caused by the flipped Y axis of the OpenGL texture.
Just use the following image to test the code. In the top-right corner is a green pixel, in the bottom-right a red one and in the bottom-left corner a blue pixel. You wouldn't even be able to "hit" them with the mouse if the index calculation would be off by 1 pixel or more:
And if you don't believe your mouse:
get(599, 0)
will return greenget(599, 599)
will return redget(0, 599)
will return blueMaking a test like that was the first thing I wanted to do this morning :)
Just to be sure, this is correct right?
(If it's not I have a bug somewhere else :) )
Jup, but you don't really need to subtract tx from index, dividing it by width will floor the value anyways (in this case (index - tx) / width == index / width). Oh, and try to avoid using modulo, it's a pretty slow operator. This should be a little faster:
Your tx calculation makes no sense but I can't figure out why apart from that it's pretty late :) .
Yeah, I guess it was pretty late for me too! :D
My code just worked for the extreme values (0,0 / 599,599 / etc.) your tx calculation is right. This should do the trick:
Cool. For now I got rid of getting the pixels with pgl. What i'm doing is already complex and with the reversed array it made thing so much more complex. And reversing the array results in a nasty crash.