Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Day and Night Cycles

Credits go to André Silva, Edgar Reynaldo, and relpatseht for helping out!
This thread is locked; no one can reply to it. rss feed Print
Day and Night Cycles
Thinkal VB
Member #16,859
May 2018

I have a ALLEGRO_COLOR cameraTint = al_map_rgba_f(1.0f, 1.0f, 1.0f, 1.0f);

Which is applied to every object that is drawn to the screen?
How can I effectively render a day and night cycle -
morning (little yellow and red light and little blue light), noon(white light), evening (little yellow and red light), night(moonlight(dark) + little green(like a night vision effect))?
Thanks in advance.

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Thinkal VB
Member #16,859
May 2018

Hai Edgar Reynaldo,
I do try the blending with reference from the code you posted in the other thread - but the results don't seem very satisfactory - I am not getting a real-life feel like in the other 2D games. So my guess is I am missing something. That's why I asked. ::)
Like is Thier a certain combination of rgba value that works better ... Things like that
Seeking expertise opinions on the matter.

I am truly sorry that I couldn't rise up to your expectation. I was just confused.

relpatseht
Member #5,034
September 2004
avatar

The choice of color is important, but you also probably want to apply a gradient or radial gradient, not just a blanket tint.

André Silva
Member #11,991
May 2010
avatar

How are you applying it to every object? Are you drawing each object with that tint? It's much better, and more controllable, to draw one massive rectangle on the entire screen, after you've drawn the world and objects.

Create a table that maps times of the day to colors, and in-game, draw that covering rectangle with the color and opacity corresponding to the time of day. For instance, from midday to 5 PM, you likely want a fully transparent rectangle, so everything has normal lighting. From 5 PM to 7 PM, you want a bit of an orange tint. From 7 to 8, a darker tint, with maybe a bit of blue in it, etc. You can use interpolation to fade smoothly from one color to another.

Thinkal VB
Member #16,859
May 2018

Thank you relpatseht and André Silva,
https://www.allegro.cc/forums/thread/606569 I got a thread on gradients- I will try that for sure.
How are you applying it to every object?
Well as you guessed, all object's are drawn using the same tint. Someone said that even though we use different versions of al_draw-... all are basically calling the same function al_draw_tinted_scaled_rotated_bitmap - hence I won't be having any additional overheads. So my RenderingEngine class have overloaded functions that use the cameraTint if no other tint is explicitly specified. Interpolation is, however, a new word for me :P Let me dig deep into the mechanisms you briefed - I will try to implement it as well as I can.
Thank you for your expert opinions.
All of my work till today is here at- https://github.com/ThinkalVB/NearEarth
Feel free to make suggestions or changes.

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

I had a really nice lighting demo around here somewhere and now I can't find it. >:(...

SEEK AND YE SHALL FIND

{"name":"611618","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/c\/6\/c6fd320a4c56f234d30cd75a45d6ab40.png","w":1026,"h":801,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/c\/6\/c6fd320a4c56f234d30cd75a45d6ab40"}611618

Found it. >:( Took me a google image search with a screenshot I had taken of it to find the allegro thread where I posted the code I no longer can find.

So, here's a little lighting demo.

Lighting.zip

It should open a full screen window and the light source will follow the mouse showing the background beneath.

The code you need to know is :

#SelectExpand
1 2ALLEGRO_BITMAP* bg = al_load_bitmap("BG.png"); 3ALLEGRO_BITMAP* light = al_create_bitmap(screenw,screenh); 4al_set_target_bitmap(light); 5/// Clear to black 6al_clear_to_color(al_map_rgba(0,0,0,255)); 7al_set_blender(ALLEGRO_ADD , ALLEGRO_ONE , ALLEGRO_ONE); 8/// Draw our lights using additive blending 9al_draw_filled_circle(x1,y1,r1,al_map_rgba(255,0,0,255)); 10al_draw_filled_circle(x2,y2,r2,al_map_rgba(0,255,0,255)); 11al_draw_filled_circle(x3,y3,r3,al_map_rgba(0,0,255,255)); 12/// Reset default blender 13al_set_blender(ALLEGRO_ADD , ALLEGRO_INVERSE_ALPHA , ALLEGRO_ALPHA); 14/// Draw on backbuffer 15al_set_target_backbuffer(d); 16int w = al_get_bitmap_width(bg); 17int h = al_get_bitmap_height(bg); 18al_draw_bitmap(bg , (screenw - w)/2 , (screenh - h)/2 , 0); 19/// Draw lights using multiply blender 20al_set_blender(ALLEGRO_ADD , ALLEGRO_DEST_COLOR , ALLEGRO_ZERO); 21w = al_get_bitmap_width(light); 22h = al_get_bitmap_height(light); 23al_draw_bitmap(light , mousex - w/2 , mousey - h/2 , 0); 24al_flip_display();

If you're just not satisfied with multiply blending, then you'll have to look into additive blending.

Thinkal VB
Member #16,859
May 2018

Thank you Edgar Reynaldo,
Lighting.zip was superb.
So when to use additive and multiplicative blending?

If I am understanding it right - What I got as the basic logic is - Make a bitmap, color it full black. Then draw the lights in it (call it a lightMap). Then draw the lightmap above the background.
And while drawing the lightMap you can use additive or multiplicative blending - so the mixing of colors works fine.
I am right - or am I getting it wrong?

In my project

step 1) clear display backBuffer with black
step 2) clear the lightMap with daylight or cameraTint
step 3) draw the background texture

step 4) draw lights to lightmap
step 4) draw objects to the display back buffer

step 5) When rendering of objects complete
step 6) Draw the lightmap in the display buffer
[This means I no more need to apply the camera tint to every object drawn on the display buffer]
Some results attached - when I used additive and multiplicative blending while drawing the lightMap to the back buffer for RenderingEngine::setCameraTint(al_map_rgba(50,50,50,250)); - It's night :o:P:)

Edit How to fade the light - controlling the luminosity ?

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Yeah, you've pretty much got it.

For altering the luminosity, all you do is vary the white level. The color gets multiplied so it will darken the subject by it's black level. If you mean true luminosity like HSL, you need additive blending because multiply can only decrease the color values.

Thinkal VB
Member #16,859
May 2018

Thank you Edgar Reynaldo,
I think i should stick to additive blending in the lightMap (for all the lights in the scene).
One more question - how to decrease the intensity with the distance - (at the origin - intensity 100% and as we move away it should decrease to 0). One way I figured out is to use a for loop while drawing filled circles. However, it's not working as I intended.

al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ONE);
al_set_target_bitmap(lightMap);
      
for (int radii = 100; radii != 0; radii--)
{
al_draw_filled_circle(600, 500, radii, al_map_rgba(255, 0, 0, 1));
}
switchToDisplayBuffer();

But I think drawing 255 primitives for every light 60 frames per second is very unethical or compute intensive for some reason. Is there a better way to get it done? (faster and clean)??????
Also, I came to know that allegro primitives don't follow the usual transformation. So how to make them follow it?.

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Allegro uses pre-multiplied alpha.

That means you have to multiply by the alpha when you pass it to al_map_rgb*.

Use al_map_rgba_f. Then it's clearer.

al_set_blender(ALLEGRO_ADD , ALLEGRO_ONE , ALLEGRO_ZERO);
float a = 0.5;
for (int i = 100 ; i >= 1 ; --i) {
   float a2 = a/(float)i;
   al_draw_filled_circle(x,y,i,al_map_rgba_f(r*a2 , g*a2 , b*a2 , a2));
}

Thinkal VB
Member #16,859
May 2018

Ah thank you Edgar Reynaldo,

I forgot that one. I corrected the code the result is pretty promising. But don't have any idea why a special region is more illuminated than it's center. Any thoughts?

But I have one simple honest doubt - If it uses pre-multiplied alpha - why we even have to pass the alpha value to the function. Because both seem to produce the same result?

It would be great if you could comment on the transformations in the allegro primitives and any easy or clean way to draw the lights - more efficiently?

One more thing if I have RGB values as 255,144,245 then how can I convert it to float values - to do the pre-multiplied alpha thing? :-X::):P:o:o:o???

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

If you want to use al_map_rgba, then multiply by alpha and divide by 255.

unsigned char r = 255 , g = 0 , b = 0 , a = 127;
al_map_rgba(r*a/255 , g*a/255 , b*a/255 , a);

The key to drawing a gradient is that you need to divide by the radius or something else so that when you draw multiple circles it adds up to the right amount. That's why I suggested you use al_map_rgba_f. See the code in my Lighting.zip file for details. It's the DrawLightA function I think.

If you need to reset the transforms, the manual explains it well in al_use_projection_transform. For the view transform, just reset it to identity. You can use al_get_current_transform and al_get_current_projection_transform to see what is currently set or to reset it when you're done.

Thinkal VB
Member #16,859
May 2018

Thank you Edgar Reynaldo,

My player character is at 1500,1500 but I am drawing the light at 500,600 and both use the same transformation. So essentially the light shouldn't show up on the screen. But you see the result - the light is showing up at the display co-ordinate 500,600. That's the problem. ???

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

You have to draw the light at the coordinates of the player. That means you have to apply the transform you're using for your player to the coordinates of the light you want to draw.

Show code and I can help better.

EDIT
Use al_transform_coordinates to fix the light position.

Thinkal VB
Member #16,859
May 2018

Thank you Edgar Reynaldo,
This is more controllable and better I think.

float alpha = 1.0f;
float gradient = 30.0f;
float radius = 100.0f;

float dGradient = radius / gradient;
float dAlpha = alpha / gradient;

for (auto radii = 1.0f; radii <= radius; radii += dGradient)
{
al_draw_circle(500, 600, radii, al_map_rgb_f(1.0f*alpha, 0.0f*alpha, 0.0f*alpha), dGradient);
alpha -= dAlpha;
}

Full source code is in Git and is up-todate till this minute. [issue: lightMap is not using the transformation]
https://github.com/ThinkalVB/NearEarth

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Full source code is in Git and is up-todate till this minute. [issue: lightMap is not using the transformation]

Oh I see what you're saying now. Of course it's not using the transformation. There are two transforms per bitmap target. If you change the target bitmap, the transforms are reset to the stored version.

You've got to learn about relative coordinates and transforming from one space to another.

Thinkal VB
Member #16,859
May 2018

Thank you Edgar Reynaldo,
I didn't quite get it.
There are two transforms per bitmap target. If you change the target bitmap, the transforms are reset to the stored version.
stored version?

Did you mean there are two transformations related to a bitmap? [like an active and default tranforms] Once you switch to another target bitmap the default transformation's come into effect and once you switch back, the old transformation will be restored????

Isn't there a way to use the same transformation for both the lightMap bitmap and the display's back buffer?:P:-/

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Thinkal VB
Member #16,859
May 2018

Thank you Edgar Reynaldo,
I was very much confused and worried - I thought transforms won't work with primitives.
One more thing :P
I have a bright sun in the scene -

  RenderingEngine::setCameraTint(al_map_rgb(250, 250, 250));

Then I tried to draw a light in the scene - same as the one above. However when using additive blending - it's the same color everywhere (no change - as it is supposed to be). Then I tried multiplicative blending but it was an absolute horror.
So possibly which blending mode should I use in such a bright background light scenario????:)

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Thinkal VB
Member #16,859
May 2018

Thank you Edgar Reynaldo,
I am sorry - I totally forgot to sync it to Git. It's done now. :P
I was doing quite the opposite - For lightmap using additive blending and when drawing the light map over the back buffer I was using multiplicative blending. ::)::):-/
If I use the blending vice verse - the background seems to be fully white.::)

Go to: