Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

AppGameKit Classic Chat / Shader Scratch Off (Make Transparent the Portion of 2D Texture Touched by Pointer)

Author
Message
JosephB
15
Years of Service
User Offline
Joined: 12th Sep 2006
Location:
Posted: 6th Apr 2022 22:32 Edited at: 7th Apr 2022 15:20
I have been researching if it is possible to use a shader to "scratch off' a portion of a sprite's texture that the pointer touches (basically make that part of the sprite's texture to be transparent and reveal whatever that sprite is covering). It seems that it might be possible with a shader, but I have not located anything specific to how this might be done in OpenGL 2.0. I am guessing that the shader would use the area of the pointer sprite, which is set into position using the pointer. The shader possibly would use those coordinates to determine what UV coordinates on the texture should become transparent. Currently I use several sprites to cover another sprite and using the covering sprites' Hit Group to delete any of those sprites touched by the pointer's coordinates. This works fine but is a bit laborious to setup and probably uses more resources than is necessary. I appreciate any help in creating the shader code to do this if it is possible.

Edit: I added some commented code below to show how I do this using many "scratch off" sprites and show performance by moving all the sprites each frame:

Arch-Ok
Developer
3
Years of Service
User Offline
Joined: 11th Jul 2019
Location:
Posted: 7th Apr 2022 21:42 Edited at: 7th Apr 2022 21:57
I made it with shaders but it was so slow.

Using memblocks would be nice;

bon apetit;




Attachments

Login to view attachments
Arch-Ok
Developer
3
Years of Service
User Offline
Joined: 11th Jul 2019
Location:
Posted: 7th Apr 2022 22:15
And here is a literally image scratcher;

JosephB
15
Years of Service
User Offline
Joined: 12th Sep 2006
Location:
Posted: 8th Apr 2022 00:06
Arch-OK,

Thank you very much. I had not thought of using memblocls images. It works very nicely, but still has performance issues, but better than using many sprites. You mentioned using a shader and that it was slow. Would you mind providing the shader, so that I can learn from it? Again, thanks for your help.
Virtual Nomad
Moderator
16
Years of Service
User Offline
Joined: 14th Dec 2005
Location: SF Bay Area, USA
Posted: 8th Apr 2022 04:05
you could probably modify janbo's burn shader to suit your needs.

ie, get rid of the auto-burn and concentrate the 0 alpha on the "scratch me" sprite around wherever the mouse is?

meanwhile, using your initial method, you're basically keeping track of what's being removed with the sprite count. i'm not sure how to go about that with the shader. keep track of a grid (boolean-ish array) with much fewer than ~2400 areas if you DO need to track it. otherwise, simply apply the burn shader nearly "as is"?

otherwise, i know very little about shaders but hope this helps you along.

JosephB
15
Years of Service
User Offline
Joined: 12th Sep 2006
Location:
Posted: 8th Apr 2022 17:59
Virtual Nomad

Thank you. Like you, I have very little experience with shaders. I agree that this will likely require some array in the shader, but based on the size of the image and the radius of the scratching area, this will probably require an array index of several thousand, which would end up being a performance hit. When I changed the burn.ps file a bit, I was able to get the shader to only burn the area around the match, but as soon as I moved the match the new area would burn, but the previous area would return, so the shader was forgetting what had already been burned. That is why an array is likely needed to use with a for/next loop in the shader. Much to learn yet; however, when I did place a simple for/next loop in the shader (just counts up from 0 to 200,000, I did not see a performance issue in the app. Will try to learn how to send an array of floor x and y positions based on radius of scratching sprite to the shader and then have the shader search through increased index number to ensure that only new indexes (arrays of different x and y values) are only inserted into the shader array of positions. Then it must go through the entire length of the array to burn off positions already scratched. Thanks for any help others could provide in coding this into the shader.
Arch-Ok
Developer
3
Years of Service
User Offline
Joined: 11th Jul 2019
Location:
Posted: 8th Apr 2022 21:20
Here is my code to create a surface and draw there just by touching.
It creates a surface with sprites size of 16x16 pixels.
When pointer touches, the code finds which sprite is at the pointers position then the program finds which pixel of that sprite is at the pointer's position and sets the color for that pixel.
Why subdivide?
because, arrays in shaders have limits of 16384 bytes (guessing) -> uniform vec4 pixeldata[1024]; -> 16 x 1024...

as I remember the code runs good but it was slow for big areas.

a small area example;



anyways, I hope you can modify it to your liking...

surface.vs



surface.ps



agk code
JosephB
15
Years of Service
User Offline
Joined: 12th Sep 2006
Location:
Posted: 9th Apr 2022 04:34
Arch-Ok,

Again, thanks. Interesting take with much to study. Like you noticed it does seem to have a slight performance hit, even when not scratching. I think if I can somehow use your segment/offset idea with Janbo's burn shader, it might work very well, something like just increasing the dot size you use. Hopefully I'll be able to work it out, but I think it will take a while as I truly do not understand shaders very well and what they can and cannot do. I think the scratch idea would work well to reveal the hidden areas of a map in the HUD as a player searches through a dungeon and other similar uses.
Arch-Ok
Developer
3
Years of Service
User Offline
Joined: 11th Jul 2019
Location:
Posted: 9th Apr 2022 15:05 Edited at: 9th Apr 2022 15:26
You are welcome joseph. I am also not into the shaders that much but the code with the memblocks runs much faster than the code with shaders on my pc. (the codes I shared on this topic only. The shaders are always faster for common/general/known purposes!)
Using mask sprite as (W/2)x(H/2) sizes on an other sprite (sprite to be revealed) with sizes of WxH would be faster with resizing the sprite to WxH.

Anyways, I'm on a project may be after a month it will be released and it opens areas on an sprite and I am using memblocks.
Creating a dll for faster memblock usage is possible, I mean without checking if a memblock exists, and if the offset limit exceeds the memblock size e.t.c.
I hope you find a way and share with us, good luck bud
JosephB
15
Years of Service
User Offline
Joined: 12th Sep 2006
Location:
Posted: 9th Apr 2022 23:55 Edited at: 10th Apr 2022 00:29
Have not had much success yet. However, I at least am able to change the color of the individual segments of a segmented sprite (21 by 13). Code and shaders below (quickly put together, but mainly works. Two things I am desperately trying to understand are the following:

1. The arrayIndex part of the SetShaderConstantArrayByName (arrayIndex - The index of the element within the array to modify) command. It seems that the command sends the specific index number to the shader, but I am at a loss as to how to use that number in the shader.
2. I am having great difficulty in getting the shader to change the alpha of the sprites texture for each segment. I can get the color to change based on the x(red) and y(green) values sent to the shader, but have not determined how to get the alpha vale to change to zero.

The current code and shaders do not (in present form) take a performance hit, so it seems to be in the right direction. If anyone is able to provide guidance and information to the two problems, please help.

AGK Code: (no media needed)


Shader VS code:


Shade PS Code:
Arch-Ok
Developer
3
Years of Service
User Offline
Joined: 11th Jul 2019
Location:
Posted: 10th Apr 2022 01:17 Edited at: 10th Apr 2022 09:52
Yes, shaders are much more faster. The shader code is really small and easy. The init of the agk code is a little bit complex. Loading media makes some functions obsolote



scratch.vs


scratch.ps



agk code;
Arch-Ok
Developer
3
Years of Service
User Offline
Joined: 11th Jul 2019
Location:
Posted: 10th Apr 2022 11:06 Edited at: 10th Apr 2022 11:07
The code with media is much more simple.



Attachments

Login to view attachments
Arch-Ok
Developer
3
Years of Service
User Offline
Joined: 11th Jul 2019
Location:
Posted: 10th Apr 2022 21:55 Edited at: 10th Apr 2022 21:58
I ajusted the pixel shader a little bit;

scratch.ps;




Memblock version is faster, on my PC.
JosephB
15
Years of Service
User Offline
Joined: 12th Sep 2006
Location:
Posted: 11th Apr 2022 00:16
Arch-OK,

Thank you, the codes are wonderful. All works well. I do notice that sometimes when I use the 1024 array index in the shader ps code, it will not run because the error message states that the vs and ps shader codes failed to link because it is calculating that there will be more than 1024 indexes. It seems that 1024 is the limit. I do not know if anyone else has experienced this.

Do you know how the arrayIndex part of the SetShaderConstantArrayByName (arrayIndex - The index of the element within the array to modify) works. It seems that the command sends the specific index number to the shader, but is there a way to use that submitted index number and not have to calculate the index in the shader ps code?

I am carefully studying your code and will see if I can segment just one sprite into 1024 segments which the shader will then change just that segment of the image for the one sprite. I do not see much difference in the performance (FPS) between either the provided image or memory block codes. Both show about 300 FPS when scratching and 900 FPS when not pressing the mouse button.

Thank you very much for your help. This has been most helpful and a great learning experience.
Arch-Ok
Developer
3
Years of Service
User Offline
Joined: 11th Jul 2019
Location:
Posted: 11th Apr 2022 06:56
You are welcome

The last index is 1023 not 1024 (0 - 1023) but I can not say that the limit is this or that as I mentioned before I am not into the shaders and even agk itself that much.

The command "SetShaderConstantArrayByName" sends 1 or 2 or 3 or max 4 float values to the shader. In the scratch code it sends 1 float because our array is 1024 floats, not vec2, vec3 or vec4. Also the size of the float variable could be 11 bits, 16 bits, 32 and 64 bits, I always assumed it is 32 bits.

I tried it with "UINT" variable at the shader but 0xFFFFFFFF was a Nan/QNan or something like that so the alpha channel did not work as using float array. I was Imagining to fit 4 pixel's alpha value in to 1 integer (4 x 8 = 32 bits) so less usage of sprites and more work for shader(extracting corresponding byte from that integer). It just failed to set the alpha value because agk sends only floats???

Instead of "SetShaderConstantArrayByName" there is "SetShaderConstantByName" command.

I'd go with memblocks anyway because I must have the control to the last bit of my code, even I'll create a dll for faster memblock usage but not now, I'm on an another project.

Final notes, yes my codes are unique but usually what happens is this, I do hard code a program, it works and gives the expected results and then I learn/realise a command of AppGameKit that I did not know before, and laugh at my code because there was a simple and a fast way with the command I've newly learned.

All I mean is, this scratch code is and never be the best solution, so I hope you find a faster and reliable way and share with us.


tboy
9
Years of Service
User Offline
Joined: 1st Jan 2013
Location: UK
Posted: 11th Apr 2022 21:00
It's not shader code but I did this some time ago for a small project, hope it's of some use.

Attachments

Login to view attachments
Arch-Ok
Developer
3
Years of Service
User Offline
Joined: 11th Jul 2019
Location:
Posted: 12th Apr 2022 06:45
very nice @tboy

As I mentinoed before, "then I learn/realise a command of AppGameKit that I did not know before, and laugh at my code because there was a simple and a fast way with the command I've newly learned."
-SetRenderToImage
-SetRenderToScreen
-CloneSprite
I learned these commands now, thanks for your example.


JosephB
15
Years of Service
User Offline
Joined: 12th Sep 2006
Location:
Posted: 12th Apr 2022 15:39
Thank you, that's great option @ tboy. Works slightly quicker (more FPS) than the subdivided image with sprites and shaders. I am just struggling with the shader code trying to get just one image and one sprite to change alpha--always just turns black, but not transparent.

This might possibly work but I would have to change the HUD location of the scratch off map as this seems to be limited to a x, y position of 0, 0 because of where the image rendered to is placed. Also have to add a color layer to the scratch off image that will match the SetImageTransparentColor. I do not know how to do that just using AppGameKit code, so it requires loading an image.

I was able to reduce the code that you provided a bit as follows:

Attachments

Login to view attachments
janbo
Tower Defence Competition 2nd Place
13
Years of Service
User Offline
Joined: 10th Nov 2008
Location: Germany
Posted: 12th Apr 2022 21:49 Edited at: 12th Apr 2022 22:05
shaders cant remember, and giving them a huge array doesnt seem to be a good solution either.
So dont try using shaders for that besides the obvious transparency.
I'd suggest you render the brush onto a black and white mask texture, white for transparency for example and just set the alpha value inside the shader to that value of the mask texture.
That way you can erase your drawings by overwriting the mask with black again.
I think thats how i did it here:
JosephB
15
Years of Service
User Offline
Joined: 12th Sep 2006
Location:
Posted: 12th Apr 2022 22:59
Thank you @janbo. Would your suggestion be any quicker than using something similar to the image overlay that uses setrendertoimage and a transparent color to render a sprite (the suggestion provided by tboy? )
janbo
Tower Defence Competition 2nd Place
13
Years of Service
User Offline
Joined: 10th Nov 2008
Location: Germany
Posted: 13th Apr 2022 15:30
Well if you dont want to use a specific transparency color for your image like you had in the past like pink seen in the old days cause it's not used in the resulting image, then nope this would be the way to go, but instead of using draw circle you would use a sprite as a brush
But if you want to be slightly more flexible you'd still use setrendertoimage but you'd render to a mask cause drawing a fully transparent sprite or circle will do nothing as rendering to something only knows about the RGB Chanels.
Performance wise the first method would probably be a tiny bit faster as you dont need to pass a second image to the shader that renders your final image to the screen.
JosephB
15
Years of Service
User Offline
Joined: 12th Sep 2006
Location:
Posted: 13th Apr 2022 17:07 Edited at: 14th Apr 2022 19:39
Thanks very much to all who have helped. I was able to improve the performance of the no shader approach a bit by eliminating the sprite cloning and sprite creation and deletion, by just setting the sprite image to the new render image. I have also determined how to set the sprites to another position other than the render image position, code as follows (needed image is below the code):

Attachments

Login to view attachments
JosephB
15
Years of Service
User Offline
Joined: 12th Sep 2006
Location:
Posted: 14th Apr 2022 18:52 Edited at: 14th Apr 2022 21:39
Although shaders do not remember what has been done to an image, in an indirect way I have been able to use a shader to obtain the changes to an image done by a shader to the sprite's image by using AGK's GetImage command. While advised not to use this command each frame, it has a better performance than the other options in this thread. I have included a sample code as well as the burn vs and ps shader created by janbo. Just mouse over the image to scratch off the gray sprite's image and reveal the blue sprite underneath.



vs code:


ps code:


I have also attached the original noise.png file used in janbo's example for the burn shader.

Attachments

Login to view attachments
Lorenzo
6
Years of Service
User Offline
Joined: 19th Dec 2015
Location:
Posted: 14th Apr 2022 19:44
insert DeleteImage (IMAGEID) before ImageID = GetImage(50, 50, 410, 256)
JosephB
15
Years of Service
User Offline
Joined: 12th Sep 2006
Location:
Posted: 14th Apr 2022 21:40
Thanks. Change made to code.

Login to post a reply

Server time is: 2022-08-18 11:42:21
Your offset time is: 2022-08-18 11:42:21