Hi, after understanding that I can't achieve this with existing blending modes I have some questions:
my goal would be a "viewing range" effect.
I thought to take a texture with an alpha/color gradient, add it to (actually maybe it's better to say
subtract it from ) the alpha values of an existing "black" sprite above my scene, and apply the alpha/color values to the black sprite, so that I can show the scene through a nice gradient.
see the attachment, either if it's rough it should give an idea of what I have in mind..
What are my options?
From what I understood shaders could do this, but I am worried that since I need to update this continuously it won't be the best option (am I wrong?) I have a "big" tilemap which can be zoomed in/out and dragged around, and various things that can "create lights".
Assuming that I could succeed in writing an "alpha shader", of which I am not sure, would this be "heavy"?
Looking at Bird Animation 2 example (the one with cos transform) I can see that the output is rendered with renderTarget every now and then, and I fear that it will become too slow in my setup.
Any suggestion? Do I have to forget this?
Thank you
Comments
- Create the mask circle as a bitmap with opaque edges
- Create shapes at runtime to cover top/right/bottom/left sides
- Pop all this in a sprite and make it stick to the character
The trick is to make the shapes as small as possible but big enough to cover the screen. application:getDeviceWidth() and application:getDeviceHeight() would work if the character is moving around a lot, if the character is static you could almost halve it.
Niclas
Likes: pie
:-\"
Likes: vitalitymobile, pie
I'm using TNT particle Engine for that game.
http://www.tntparticlesengine.com/?page_id=58
I used RenderTarget for the dark effect, but i'm using small area of RenderTarget and scaled them big afterward. The scale is quite high (32). That way i won't slow my game.
I think the drawback with all of the techniques decribed here is that it actually involves rendering the scene, then masking it with a black and white or black and transparent mask, thus masked pixels are drawn twice.
If, by any chance, your background happens to be a single sprite with no sub-sprites, then you could use a specific shader to have him been drawn only where it should. I'll try to write one for you to show how this could be done.
(I have a few ideas, but I'd like to know your method)
One of my ideas would be to draw as normal - then have a predrawn overlay that masked out everything apart from where the torch light was.
A second way would be to clear a render target with black, then draw 'transparent' pixels on it, then draw this on the main screen scaled up.
https://deluxepixel.com
The scale is used to reduce CPU usage.
https://deluxepixel.com
@hgy29 any idea?
https://deluxepixel.com
@tkhnoman the "torch like effect" is really cool but I missed one thing: what area do you render with renderTarget and then scale x32?
I actually think that my previous mockup mislead a bit on my game: I put it together quickly to explain the effect I'd like to achieve, but my game is not a platform so I think I can't do as @totebo suggested (I don't have a player fixed in the center of the screen, but it's on a tilemap which can be zoomed in/out and dragged around).
I think I can use this workaround, but since I have "many" lights, I don't know how to handle texture overlapping and drawing a shape that keeps all the textures together in a "black frame".
Here is a "real" mocked up screenshot: please don't mind the graphics which is under development
In image 1 there is a tilemap, which is a sprite composed by different layers/sprites.
Image 2 is a mockup of what I think should be the light casted by objects that have this property (I am guessing on "how": I suppose there will be a gradient texture applied "over" each object with "lighting property")
Image 3 is what I'd like to achieve "mixing" image 1 and image 2: since the player can move, and that he can "turn lights on", I need these to be "movable" and that they could "merge" with each other.
This is why I thought to "cut" alpha from a plain black layer placed above the tilemap: if alpha of a pixel reach 0, then the pixel would be transparent, otherwise it would be a half-transparent black, generating the gradient on the tilemap; while gideros has to blend just between black pixels and their alpha without thinking about pixels with no "light texture" overlapping.
Image 4 is what I have so far: a "tile based lighting", which is a bit "ugly" compared to texture based gradients, and heavy on mobile devices: for each movement I have to set every alpha back to 1, update the alpha of every tile based on its distance from the light source (player is considered a light source), check if at least one tile of each light source is seen by player (so that I know it is in viewing range), and if it is, set the alpha of the adiacent tiles... works well on laptop but android devices get a bit of lag.
@hgy29 if you have some time I'd really like to see a shader managing alpha per pixel, I would also try to use it as a base to "fix" the antialiasing on tiles we talked about here:
http://giderosmobile.com/forum/discussion/comment/42735#Comment_42758
Thank you very much for all your help
@pie I have parts where the lights mix, is that what you mean?
https://deluxepixel.com
Please correct me if I am wrong and fill in the blanks
you have a texture with a "circle" with smooth edges to mimic "light" for each character.
Which colors are you using for your gradient? do you have transparent pixels on that texture?
What are you rendering with renderTarget? I think that this is what I am not getting here: do you have an overlapping black sprite or it's just the not multiplied pixels that remain black? (if you're using multiply)
I didn't try using renderTarget because I didn't understand "where" to use it can you please enlight me?
Thank you very much
1) I create a texture and add it to the stage, the texture is set to it draws using 'multiply'.
2) Every frame I clear the texture solid black, no transparency (test it drawn over your stage, it should be black)
3) Then I draw white orb like sprites on the solid black texture with the middle solid white gradually fading to full alpha on the edges. They can overlap as the edges are full alpha.
Because the rendertexture is a multiply with the screen then any areas that are still black will remain black, but any areas that are full white will show the image underneath. Anything inbetween (the edges of the circles will be a colour mix of black and the image underneath.
https://deluxepixel.com
I am feeling stupid, but I still have a couple of questions:
I made an example with a tilemap (attached): is it expected to have the whole tilemap sprite "multiplied" (pic attached)?
The only reason I found to use renderTarget is to avoid multiplying the tilemap layers between each other (actually using it like a "flatten image" on a sprite). Is there another way to "lock" them? I feel that renderTarget is a bit heavy and if I scale to 1/4 my graphics it will look much different.
Thank you
P.s.
for reference in attachment:
main-basic.lua = main.lua - just multiplying the tilemap
mainRT.lua -this one using renderTarget to "flatten" layers
See my video above.
https://deluxepixel.com
I was trying to multiply the tilemap as in hgy29 suggestion, but I can't get this working as I expect, either if I renderTarget the multiplied light bits as you suggested.
I don't get why my solid white in center gradient looks like in this attachment :-O :
I am losing my mind: I can almost see it, but I think I am still missing something: maybe I don't know how to draw the texture right?
thank you
for reference in attached project:
main.lua - renderTarget on the "fog of war"
main-basic.lua = main.lua - just multiplying the tilemap
mainRT.lua -this one using renderTarget to "flatten" layers
-plus, various gradients textures, each one wrong I suppose
everything to do with the actual game added to stage - eg layers of maps, sprites, etc
a black render target - with white bits 'cut out' of it, set to multiply, added to stage.
the game score panel, etc - anything above the game, added to stage.
https://deluxepixel.com
Normally this would take a while, but I have the black rendertarget set to 1/4 of the screen size and set the scale to 2. I also scale up the white bits with scale(16) and let the hardware do the alias work.
https://deluxepixel.com
do you see something wrong here?
Thank you
https://deluxepixel.com
Likes: SinisterSoft
Plus you had the rt set to the size of the map, huge! It only had to be the size of the screen.
https://deluxepixel.com
https://deluxepixel.com
I still didn't had the time to implement the black render target in my game, I hope I will do it today and see the real impact on its performance
However, I am still wondering if there is a "better way" to achieve the same result without having to rely on renderTarget:
either if we're rendering a small portion of the screen it has to be rendered and scaled every frame or so. It's a good workaround but I don't feel like it's a "best practice"
I believe that multiplying the tilemap as @hgy29 suggested some posts ago would still be the best option; but there is the problem of multiply blending mode passed on to all the Sprite children, as in the project attached here in main-basic.lua. Maybe this would work only on single layered tilemaps with no overlapping objects, it's a pity though
https://deluxepixel.com