Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Good programmig practice light effects

This thread is locked; no one can reply to it. rss feed Print
Good programmig practice light effects
Travis Peterson
Member #16,756
October 2017

Been fiddling around with multiplying and al_set_blender and getting lights to work finally got 1 central light to follow the player around on screen with a black semitransparent tint following the camera.. this is almost the desired output, but woth this code each time a new light point is pushed back into a vector containing light positions it interferes with other points within proximity and overlaps its back night mask with the region thats supposed to be illuminatied.

Was wondering a good architecture for lighting, was thinking of having a black mask follow the camera and whenever a light position is within camera range it affects that bitmap, is this a good method for a sidescrolling game is there a better method?

Also how do you get the lights to not overlap in a negative way appreciate everything

beoran
Member #12,636
March 2011

Probably you only need one "black mask", and a light spot per sprite. So why not keep the sprite and it's light spot together?
Could you post some code or put it up on something like github so we can see what you have programmed?

Mark Oates
Member #1,146
March 2001
avatar

I actually read the last thread a while back but missed replying, sorry about that.

A lot of people make the mistake of thinking of this as a "light mask" when in actuality it's better to think of it as a shadow mask. AllegroFlare has a very easy to understand and use ShadowMask class. :) Here are the files:

shadow_mask.h.
shadow_mask.cpp.

Also if you're interested:

Note that for the example program, you'll need to compile AllegroFlare, but the ShadowMask class is stand-alone.

Edgar Reynaldo
Member #8,592
May 2007
avatar

Oates, could you explain some of this? I don't understand allegro's blenders very well. I've read the manual and I still don't get it.

I don't understand what your line with the blender here does :

al_set_blender(ALLEGRO_ADD, ALLEGRO_DST_COLOR, ALLEGRO_ZERO);

How does that let you draw the shadow mask?

And how do you combine lights with this?

al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ONE);

EDIT

I tried to do my own lights and I'm having problems :

My code [ https://pastebin.com/c2srVteB ] and the results [ https://imgur.com/a/NRPQ1 ]

EDIT2

{"name":"611131","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/0\/0\/00e9941907378dcb44cbd19d86049cf7.png","w":802,"h":633,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/0\/0\/00e9941907378dcb44cbd19d86049cf7"}611131

Chris Katko
Member #1,881
January 2002
avatar

That doesn't look like add... that looks like replace... maybe it's the alpha and not the luminescence of the light messing with it?

[edit] Wait, and the circle doesn't make sense. If it's a square bitmap/texture, how is it drawing a circle / drawing stuff under it? Check the alpha for sure...

-----sig:
“Programs should be written for people to read, and only incidentally for machines to execute.” - Structure and Interpretation of Computer Programs

Travis Peterson
Member #16,756
October 2017

The light effects and merging of lights works 100% visually now thanks to all your help only problem is it cuts fps by 1000%
Anyone have ideas to remedy this

Chris Katko
Member #1,881
January 2002
avatar

How many draws are we talking about per frame? (Lightmap) lighting effects are almost free on any GPU made after the 90's and maybe even before. So there's most likely something else going on.

Do you know how to use a profiler?

-----sig:
“Programs should be written for people to read, and only incidentally for machines to execute.” - Structure and Interpretation of Computer Programs

Travis Peterson
Member #16,756
October 2017

Dont know how to use profilers in the context you describe and theres only 1 draw of the lightmap per frame, surface its drawn to is 1280x720 and theres 3 light points currently. Perhaps its somehow running on cpu rather than gpu?

Also noticed it runs near 100% speed when laptop is plugged in and 10% speed when not plugged in

Edgar Reynaldo
Member #8,592
May 2007
avatar

Okay, I discussed this on IRC with Mr-Hide and we have working lighting now.

https://imgur.com/a/AAXVT

Here's the code :

https://pastebin.com/PB1qWz56

I finally understand the blending better. I was wasting my time with a pure black bitmap with varying alpha and an alpha blender when it is as simple as drawing in plain color and using a multiply blender. The color value becomes the light value.

In regards to your slowdown, don't profile yet, sit down and think about what you're doing. Look at your code and examine what it is doing. Post code so we can help.

Travis Peterson
Member #16,756
October 2017

//light.cpp
include "light.h"

light::light()
{
torch = al_load_bitmap("images/torchlight.png");
draw = false;
}

void light::UpdateXYLight()
{
x1 = positionX;
x2 = positionX + 450;
y1 = positionY;
y2 = positionY + 450;
}

//////blend.cpp
#include "blend.h"

void blend::update_surface(std::vector<light*> &lightVector, std::vector<light*>::const_iterator &iter44, std::vector<player*> &playerVector, float cameraPosition[2])
{
ALLEGRO_STATE previous_state;
al_store_state(&previous_state, ALLEGRO_STATE_TARGET_BITMAP | ALLEGRO_STATE_BLENDER);
al_set_target_bitmap(surface);
al_clear_to_color(al_map_rgb(0, 0, 0));
al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ONE);

int counter_ = 0;
for (iter44 = lightVector.begin(); iter44 != lightVector.end(); iter44++)
{
int tempposx = lightVector[counter_]->positionX - cameraPosition[0];
int tempposy = lightVector[counter_]->positionY - cameraPosition[1];
if (lightVector[counter_]->draw)
al_draw_bitmap(lightVector[counter_]->torch, tempposx, tempposy, NULL);
counter_++;
}

al_draw_bitmap(playerVector[0]->torch, playerVector[0]->positionX - cameraPosition[0] - 180, playerVector[0]->positionY - cameraPosition[1] - 200, NULL);

al_restore_state(&previous_state);
}

void blend::draw(std::vector<light*> &lightVector, std::vector<light*>::const_iterator &iter44, std::vector<player*> &playerVector, float cameraPosition[2])
{
update_surface(lightVector, iter44, playerVector, cameraPosition);

ALLEGRO_STATE previous_state;
al_store_state(&previous_state, ALLEGRO_STATE_BLENDER);
al_set_blender(ALLEGRO_ADD, ALLEGRO_DST_COLOR, ALLEGRO_ZERO);///

al_draw_bitmap(surface, cameraPosition[0], cameraPosition[1], 0);

al_restore_state(&previous_state);
}

void blend::UpdateLight(std::vector<player*> &playerVector, float cameraPosition[2])
{
//points[0].x = playerVector[0]->positionX - 300;
//points[0].y = playerVector[0]->positionY - 850;
//points[#include "blend.h"

void blend::update_surface(std::vector<light*> &lightVector, std::vector<light*>::const_iterator &iter44, std::vector<player*> &playerVector, float cameraPosition[2])
{
ALLEGRO_STATE previous_state;
al_store_state(&previous_state, ALLEGRO_STATE_TARGET_BITMAP | ALLEGRO_STATE_BLENDER);
al_set_target_bitmap(surface);
al_clear_to_color(al_map_rgb(0, 0, 0));
al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ONE);

int counter_ = 0;
for (iter44 = lightVector.begin(); iter44 != lightVector.end(); iter44++)
{
int tempposx = lightVector[counter_]->positionX - cameraPosition[0];
int tempposy = lightVector[counter_]->positionY - cameraPosition[1];
if (lightVector[counter_]->draw)
al_draw_bitmap(lightVector[counter_]->torch, tempposx, tempposy, NULL);
counter_++;
}

al_draw_bitmap(playerVector[0]->torch, playerVector[0]->positionX - cameraPosition[0] - 180, playerVector[0]->positionY - cameraPosition[1] - 200, NULL);

al_restore_state(&previous_state);
}

void blend::draw(std::vector<light*> &lightVector, std::vector<light*>::const_iterator &iter44, std::vector<player*> &playerVector, float cameraPosition[2])
{
update_surface(lightVector, iter44, playerVector, cameraPosition);

ALLEGRO_STATE previous_state;
al_store_state(&previous_state, ALLEGRO_STATE_BLENDER);
al_set_blender(ALLEGRO_ADD, ALLEGRO_DST_COLOR, ALLEGRO_ZERO);///

al_draw_bitmap(surface, cameraPosition[0], cameraPosition[1], 0);

al_restore_state(&previous_state);
}

void blend::UpdateLight(std::vector<player*> &playerVector, float cameraPosition[2])
{
//
}

void blend::UpdateXYScreen()
{
x1 = positionX;
x2 = positionX + 1280;
y1 = positionY;
y2 = positionY + 720;
}

void blend::UpdateXYScreen()
{
x1 = positionX;
x2 = positionX + 1280;
y1 = positionY;
y2 = positionY + 720;
}

Chris Katko
Member #1,881
January 2002
avatar

added code tag

#SelectExpand
1//light.cpp 2include "light.h" 3 4light::light() 5{ 6torch = al_load_bitmap("images/torchlight.png"); 7draw = false; 8} 9 10void light::UpdateXYLight() 11{ 12x1 = positionX; 13x2 = positionX + 450; 14y1 = positionY; 15y2 = positionY + 450; 16} 17 18//////blend.cpp 19#include "blend.h" 20 21void blend::update_surface(std::vector<light*> &lightVector, std::vector<light*>::const_iterator &iter44, std::vector<player*> &playerVector, float cameraPosition[2]) 22{ 23ALLEGRO_STATE previous_state; 24al_store_state(&previous_state, ALLEGRO_STATE_TARGET_BITMAP | ALLEGRO_STATE_BLENDER); 25al_set_target_bitmap(surface); 26al_clear_to_color(al_map_rgb(0, 0, 0)); 27al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ONE); 28 29int counter_ = 0; 30for (iter44 = lightVector.begin(); iter44 != lightVector.end(); iter44++) 31{ 32int tempposx = lightVector[counter_]->positionX - cameraPosition[0]; 33int tempposy = lightVector[counter_]->positionY - cameraPosition[1]; 34if (lightVector[counter_]->draw) 35al_draw_bitmap(lightVector[counter_]->torch, tempposx, tempposy, NULL); 36counter_++; 37} 38 39al_draw_bitmap(playerVector[0]->torch, playerVector[0]->positionX - cameraPosition[0] - 180, playerVector[0]->positionY - cameraPosition[1] - 200, NULL); 40 41al_restore_state(&previous_state); 42} 43 44void blend::draw(std::vector<light*> &lightVector, std::vector<light*>::const_iterator &iter44, std::vector<player*> &playerVector, float cameraPosition[2]) 45{ 46update_surface(lightVector, iter44, playerVector, cameraPosition); 47 48ALLEGRO_STATE previous_state; 49al_store_state(&previous_state, ALLEGRO_STATE_BLENDER); 50al_set_blender(ALLEGRO_ADD, ALLEGRO_DST_COLOR, ALLEGRO_ZERO);/// 51 52al_draw_bitmap(surface, cameraPosition[0], cameraPosition[1], 0); 53 54al_restore_state(&previous_state); 55} 56 57void blend::UpdateLight(std::vector<player*> &playerVector, float cameraPosition[2]) 58{ 59//points[0].x = playerVector[0]->positionX - 300; 60//points[0].y = playerVector[0]->positionY - 850; 61//points[#include "blend.h" 62 63void blend::update_surface(std::vector<light*> &lightVector, std::vector<light*>::const_iterator &iter44, std::vector<player*> &playerVector, float cameraPosition[2]) 64{ 65ALLEGRO_STATE previous_state; 66al_store_state(&previous_state, ALLEGRO_STATE_TARGET_BITMAP | ALLEGRO_STATE_BLENDER); 67al_set_target_bitmap(surface); 68al_clear_to_color(al_map_rgb(0, 0, 0)); 69al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ONE); 70 71int counter_ = 0; 72for (iter44 = lightVector.begin(); iter44 != lightVector.end(); iter44++) 73{ 74int tempposx = lightVector[counter_]->positionX - cameraPosition[0]; 75int tempposy = lightVector[counter_]->positionY - cameraPosition[1]; 76if (lightVector[counter_]->draw) 77al_draw_bitmap(lightVector[counter_]->torch, tempposx, tempposy, NULL); 78counter_++; 79} 80 81al_draw_bitmap(playerVector[0]->torch, playerVector[0]->positionX - cameraPosition[0] - 180, playerVector[0]->positionY - cameraPosition[1] - 200, NULL); 82 83al_restore_state(&previous_state); 84} 85 86void blend::draw(std::vector<light*> &lightVector, std::vector<light*>::const_iterator &iter44, std::vector<player*> &playerVector, float cameraPosition[2]) 87{ 88update_surface(lightVector, iter44, playerVector, cameraPosition); 89 90ALLEGRO_STATE previous_state; 91al_store_state(&previous_state, ALLEGRO_STATE_BLENDER); 92al_set_blender(ALLEGRO_ADD, ALLEGRO_DST_COLOR, ALLEGRO_ZERO);/// 93 94al_draw_bitmap(surface, cameraPosition[0], cameraPosition[1], 0); 95 96al_restore_state(&previous_state); 97} 98 99void blend::UpdateLight(std::vector<player*> &playerVector, float cameraPosition[2]) 100{ 101// 102} 103 104void blend::UpdateXYScreen() 105{ 106x1 = positionX; 107x2 = positionX + 1280; 108y1 = positionY; 109y2 = positionY + 720; 110} 111 112void blend::UpdateXYScreen() 113{ 114x1 = positionX; 115x2 = positionX + 1280; 116y1 = positionY; 117y2 = positionY + 720; 118}

Also noticed it runs near 100% speed when laptop is plugged in and 10% speed when not plugged in

That sounds like your power settings are set to keep the GPU usage to a minimum. What are your hardware specs? Are other 3D programs affected?

Quote:

Dont know how to use profilers in the context you describe and theres only 1 draw of the lightmap per frame, surface its drawn to is 1280x720 and theres 3 light points currently. Perhaps its somehow running on cpu rather than gpu?

Run a profile. See what's taking all of the time. It could be a clue, like you have a memory bitmap by accident.

-----sig:
“Programs should be written for people to read, and only incidentally for machines to execute.” - Structure and Interpretation of Computer Programs

Edgar Reynaldo
Member #8,592
May 2007
avatar

Go to: