Virtual Screen & Stencil Shadows?

Previous topic - Next topic

Zapp

UPDATE: 29/06/2012 - Reworded question to make it clearer for the community  :|

Hi Guys,

After leaving the problem for a while to think about it and then coming back to look at it again, after some research it seems that the correct terminology for what I wish to accomplish is stencil shadowing.

Wondering if the following is possible to do the following and if so how would I go about it? I've also attached an image from photoshop explaining what I'd like to accomplish, sadly Mentalthink's method will only assist with 1 lightsource, I need a method that is capable of multiple.

1. Create a Virtual Screen for calculating shadows.
2. Draw a Solid Black Rect for the shadow.
3. Draw over this rect with a gradient where light would be cast.
4. overlay this over my topdown 2d world.
5. Is this possible on IOS without massive slowdown? (I'm using polyvectors and need to maintain at least 30fps)
6. Is this possible with standard GLBASIC or will it require inline code?

Kind Regards,

-Zapp




Hi Guys,

I'm usually pretty good with working out inventive ways to solve a problem on my own, but this one has me stumped.

So I have a small action rpg that I'm working on. The Room is top down, I'd like to be able to have some rooms with different levels of darkness to make the game a little harder.
I've managed to get to this stage just fine as a temporary measure I am able to cover the 2d environment with a solid black texture and vary the transparency using ALPHAMODE.

What I really would like to be able to do is somehow allow for lighting on the level, so for instance if the character has a torch, there is an area around him that isn't shadowed, likewise if there is a candle on the wall, then that area would also be without shadow.

Essentially I want to start with a Black fullscreen texture for shadows and then cut out what isn't in shadow by making it transparent. Is this possible and if so how would I go about doing it? Would it severly impact framerate by being too slow a process? Perhaps since my game is 2d Tile based, I may need to calculate shadows properly and use a shadow map, but I'd like to avoid the extra work of calculating all those poly's, if there is an easier solution that can be achieved by only drawing one poly.

Thanks in advance for the assistance.


-Zapp

okee

Android: Samsung Galaxy S2 -  ZTE Blade (Orange San Francisco) - Ainol Novo 7 Aurora 2
IOS: 2 x Ipod Touch (1G)

Zapp

Hi Okee,

Thanks for the suggestion, away from development pc at the moment, will take a look at it in the morning.

Regards,

-Zapp

mentalthink

Hi Zaap I comment this , I think in the post Okee comment, but it´s very easy, only have to do a black great image whit a hole in the center, making whit settrasparency...

The better way it´s in photshop, make the edges in the black hole whit a blur effet this it´s more real else it´s too much cartoon style...


Zapp

Hi Mental,

Thanks for the reply, I think in this case this may not work, I need to be able to have multiple holes in the shadow. I may just have to go with a full screen poly an use co-ords to fill the screen with black transparency or a small gradient.

mentalthink

Hi zaap, well I was do another solution, but a little trouble was the constrast whit the colors...

You can try this, but perhaps don´t looks well...

You have your screen, your graphis and characters moving, ok... now, put over the screen a rectangle drak whit the sizes of the screen, and now you draw 2 circles whit white color...

I don´t rebember the Alphamodes values... for me works, but the colors don´t have too the perfect detail...

Zapp

Hi Again Mental,

Thanks for the suggestion, I've actually tried that thinking it wouldn't work but gave it a go anyway. You are correct it looks too washed out, the colours are messed up.

Zapp

Hi guys,

I've updated my main post with a bit of a clearer description of what I am trying to do. I have a feeling the answer may require inline code with gl commands and may be beyond my current limitations, but I'd appreciate if anyone can answer my questions.

Kind Regards,

-Zapp

Slydog

#8
If you managed to create your middle picture (the one with the 4 white dots and a white arch) then I think it may be possible using alpha transparency.

Change your black / white values to all white, and instead convert that to various alpha values.
The black parts of your original image would be a colour such as (0,0,0,150) and your white would be (0,0,0,0).  And any grey would be interpolated between those.  Adjust the '150' until it looks right with enough dim.

Then just draw your game scene as usual and simply overlay the above picture over your scene.  The white / no-alpha portions will show your scene untouched, and the black / partial alpha will dim the parts it overlays.  And it shouldn't slow down your game much, just use polyvectors (four corner points) and cover the entire screen with the sprite.

[Edit] If you are doing this on the fly, you would need a way to specify the alpha values.  A new / updated colour command would be handy!  RGBA(r, g, b, a)

You may be able to figure that out on your own, I've never tried, but found this snippet to read the alpha value (never tested!):
Code (glbasic) Select
FUNCTION GetAlpha%: colour%
RETURN bAND(colour/0x1000000, 0xff)
ENDFUNCTION
My current project (WIP) :: TwistedMaze <<  [Updated: 2015-11-25]

Slydog

Another cool benefit of overlaying your scene with the generated light sprite, as outlined in my post above, is that your light sprite doesn't need to be the same size (pixel wise) as your scene.  You could scale it by 1/2 or 1/4 and stretch it over your scene.  And this may save processing time while generating it.  The stretched sprite should still look very close and any blurring you get from stretching may help the light effect.  Heck, you could even try a 1/32 scale light sprite.
My current project (WIP) :: TwistedMaze <<  [Updated: 2015-11-25]

Zapp

Hi Slydog,

Thanks so much for the response! I can make sense of what you are saying somewhat, still a little lost on the process.

I was originally planning on just using screen size (480x320) and scaling up as required for the higher resolutions of the other devices. However I think you are right, that 320x160 would work better and scaling it up might smooth the lighting a bit better. I'm a little lost with the conversion from white to transparency that you mention, can you give a little more assistance with this? I am assuming this would require a loop through of each pixel in the image to adjust its data? If so, a smaller sprite always be a benefit.

Forgive my ignorance, but which commands would i be using to adjust pixel data? The help menu suggests that getpixel/setpixel would be slow.

Slydog

I'm in a bit of a rush, I may expand on this later!

What I meant was to NOT create the black / white sprite, but instead create an all black sprite with varying alpha values.  These alpha values will show more or less of the game scene, depending on where your lights are.  Where your lights are is where you put the '0' alpha values (which would just show the game scene at that location 'as is' since the alpha is 0/transparent), and where there is no light is where you put the '150' alpha values to partially darken the scene.

The problem is I don't know exactly how to specify the alpha when creating a pixel.  RGB() only allows setting the red, green, and blue, but no alpha.  I think a simple reverse of the 'bAND(colour/0x1000000, 0xff)' is the key.
My current project (WIP) :: TwistedMaze <<  [Updated: 2015-11-25]

Zapp

Ok thanks! That makes a bit more sense. Would be greatful if you could expand later. In the meantime I'll try to work out the Band method.

Slydog

#13
Try the following (untested)!:
Code (glbasic) Select
FUNCTION RGBA%: r%, g%, b%, a%
    RETURN bOR(RGB(r, g, b), ASL(a, 24))
ENDFUNCTION


I based it from a post by @spacefractal:
http://www.glbasic.com/forum/index.php?topic=7826.msg65579#msg65579

[Edit] To use this for your project, you'd do something like this:
Code (glbasic) Select
cDark = RGBA(0, 0, 0, 150)  // Use this colour returned for your darker areas
cLight = RGBA(0, 0, 0, 0)  // Use this colour returned for your light areas


I think you can use SETPIXEL with these returned values.
And/or try a DRAWRECT first with the cDark colour to fill in the entire light sprite.
Then just draw circles using the cLight colour where your lights are.

I think you need an ALPHAMODE -1 before you plot the light sprite over top of your scene for the DRAWSPRITE / POLYVECTOR command to use your alpha values in your pixels.
My current project (WIP) :: TwistedMaze <<  [Updated: 2015-11-25]

erico

I see no reason why your stencils like the ones on the picture would not work.
For one thing, you could use half resolution for that stencil, and maybe use 2 screens to the light flicks.

Still, working all lights with a single stencil off screen seems to me the best option. Would have to think more about it.