Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: How to simulate night deillumination but have lights like torch  (Read 5888 times)

0 Members and 2 Guests are viewing this topic.

BaneTrapper

  • Full Member
  • ***
  • Posts: 213
  • Do you even see this, i dont need it.
    • View Profile
    • Email
Hello.
I would like to achieve night effect like from this video
https://www.youtube.com/watch?v=QNA9uu4PLMo
It start from 0:40.
How do i achieve such a effect?
One thought is to make a Texture that will be completely black, and for each light draw following image


What are you suggestions?
The game is 2d, top down view
Example of what i attempted to make for night:


As it is clear, the light at day is too bright, but at night its colorless.
I achieve it by drawing a dark background then applying lights over it, and to be honest its not what i want visually.
BaneTrapperDev@hotmail.com Programing, Coding
Projects: Not in development(unfinished/playable):
http://en.sfml-dev.org/forums/index.php?topic=11073.msg76266#msg76266
UP and in Development: The Wanderer - Lost in time
http://en.sfml-dev.org/forums/index.php?topic=14563.0

FRex

  • Hero Member
  • *****
  • Posts: 1846
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re: How to simulate night deillumination but have lights like torch
« Reply #1 on: April 20, 2014, 02:42:33 am »
Maybe it's a custom shader or more elaborate texture at work (or both)?
Effect is almost 100% doable in SFML + GL since it's done with these in the video. ;D
You can try asking Jungletoe yourself: http://en.sfml-dev.org/forums/index.php?topic=11878.0
He seems kind of dormant but maybe will respond to a direct question or PM.
Back to C++ gamedev with SFML in May 2023

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: How to simulate night deillumination but have lights like torch
« Reply #2 on: April 20, 2014, 09:03:12 am »
Clear a RenderTexture with black color. Then draw each light on it, using the kind of texture that you show in your first post. Finally, draw your render-texture on top of your scene with the sf::BlendMultiply blending mode. This way, white areas will show what's under and dark ones will remain black.
Laurent Gomila - SFML developer

BaneTrapper

  • Full Member
  • ***
  • Posts: 213
  • Do you even see this, i dont need it.
    • View Profile
    • Email
Re: How to simulate night deillumination but have lights like torch
« Reply #3 on: April 20, 2014, 12:10:32 pm »
Thank you on help!
Using render texture works flawlessly.
All is left to do another effects that will be actual light showing at day to the player that there is light.
I will post examples and code when i get home, i am going to feast now.
BaneTrapperDev@hotmail.com Programing, Coding
Projects: Not in development(unfinished/playable):
http://en.sfml-dev.org/forums/index.php?topic=11073.msg76266#msg76266
UP and in Development: The Wanderer - Lost in time
http://en.sfml-dev.org/forums/index.php?topic=14563.0

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10846
    • View Profile
    • development blog
    • Email
Re: How to simulate night deillumination but have lights like torch
« Reply #4 on: April 20, 2014, 12:58:54 pm »
You could also play around with different lighting textures. Change the gradient a bit, add more opacity etc.
If you want the same effect as in Dwell, you can always ask the author itself. Also check out his blog to see the advancement in the lighting technique.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

BaneTrapper

  • Full Member
  • ***
  • Posts: 213
  • Do you even see this, i dont need it.
    • View Profile
    • Email
Re: How to simulate night deillumination but have lights like torch
« Reply #5 on: May 27, 2014, 07:34:48 pm »
So i forgot to post, here you got the light system to get image:


So this system works as such.
There are two parts, DayNight which control is it dark on screen or not. And Light which is for color and data.
At DayNight i have RenderTexture that i use to create night effect, "Black screen" Then for each light i draw gradient circle to simulate light there.
At Light, it is just a normal light, A circle textured rectangle on which i control color, give it "Power" intensity via alpha color.
class Light
{
public:
        Light();
        Light(const int Radius, const sf::Color Color, const int PosX, const int PosY, bool IsBinded = 0, int UnitVecID = 0);
        int radius;
        sf::Color color;
        int posX, posY;

        bool isBindedToUnit;
        int unitVecID;
};
class LightHolder
{
public:
        LightHolder();
        void Loop(UnitList & objUnitList);
        void DrawLight(sf::RenderTexture & renTex, sf::RenderWindow & renWin);


        void AddLight(Light & light);
        void RemoveLight(const int VecID);
        void MoveLight(int VecID);

        std::vector<int> lightListEmptyPos;
        std::vector<Light> lightList;
//Light
public:
        sf::VertexArray verArrLight;
        sf::RenderStates renStatLight;
        sf::Texture texLight;
//Reveal
        sf::RenderStates renStatReveal;
        sf::Texture texReveal;
};
class DayNight
{
public:
        DayNight(daynight::TimeType typeOfTime);//0-100%, 0=Dark, 100=Light used to gain color from texture for day night
        void Loop();
        void Draw(sf::RenderWindow & renWin, sf::Vector2f & pos);

        sf::VertexArray verArr;
        sf::Color color;//Vertex color
//Night
        sf::Image imgColorForNight;
        double clockDuration;
        double increment;
        int value;
        int percent;
        daynight::TimeType timeType;
        sf::Color nightColor;
        sf::Sprite sprNight;
//Drawing
        sf::RenderTexture renTex;
        sf::RenderStates renStat;
};


//CPP FILES
DayNight::DayNight(daynight::TimeType typeOfTime)
{
        color = sf::Color(0, 30, 0, 126);
        verArr.setPrimitiveType(sf::PrimitiveType::Quads);
        verArr.append(sf::Vertex(sf::Vector2f(0,0), color, sf::Vector2f(0, 0)));
        verArr.append(sf::Vertex(sf::Vector2f(glob::WINDOW_WIDTH, 0), color, sf::Vector2f(0, 0)));
        verArr.append(sf::Vertex(sf::Vector2f(glob::WINDOW_WIDTH,glob::WINDOW_HEIGHT), color, sf::Vector2f(0, 0)));
        verArr.append(sf::Vertex(sf::Vector2f(0,glob::WINDOW_HEIGHT), color, sf::Vector2f(0, 0)));
        if(imgColorForNight.loadFromFile("./Files/Textures/NightColor.png") == false)
        {
                glob::PrintError("Unable to load image ./Files/Textures/NightColor.png From DayNight::DayNight");
        }

        renTex.create(glob::WINDOW_WIDTH, glob::WINDOW_HEIGHT);
        renStat.blendMode = sf::BlendMultiply;

        clockDuration = daynight::DAY_DURATION;
        increment = 1000/60;
        value = 0;
        percent = 0;

        timeType = typeOfTime;
        if(typeOfTime == daynight::TTDay)
                value = 100;
        else if(typeOfTime == daynight::TTNight)
                value = 0;
        else if(typeOfTime == daynight::TTDawn)
                value = 25;
        else if(typeOfTime == daynight::TTDusk)
                value = 75;
        nightColor = imgColorForNight.getPixel((value * imgColorForNight.getSize().x) / 100, 0);//24 because its max time of day
}

void DayNight::Loop()
{
//DAY
        if(timeType == daynight::TTDay)
        {
                clockDuration -= increment;
                if(clockDuration < 0)
                {//Set dusk
                        clockDuration = daynight::DUSK_DURATION;
                        timeType = daynight::TTDusk;
                        value = 0;
                }
                //nightColor = sf::Color::White;
        }
//DUSK SUN DOWN
        else if(timeType == daynight::TTDusk)
        {
                clockDuration -= increment;

                int percent = static_cast<double>(clockDuration) / daynight::DUSK_DURATION * 100;
                value = (imgColorForNight.getSize().x / 100) * percent;
                if(value < 0)
                        value = 0;
                else if(value > imgColorForNight.getSize().x-1)
                        value = imgColorForNight.getSize().x-1;
                nightColor = imgColorForNight.getPixel(value, 0);

                if(clockDuration < 0)
                {//Set night
                        clockDuration = daynight::NIGHT_DURATION;
                        timeType = daynight::TTNight;
                        value = 0;
                        nightColor = imgColorForNight.getPixel(0, 0);
                }
        }
//NIGHT
        else if(timeType == daynight::TTNight)
        {
                clockDuration -= increment;
                if(clockDuration < 0)
                {//Set dusk
                        clockDuration = daynight::DAWN_DURATION;
                        timeType = daynight::TTDawn;
                        value = 0;
                }
                //nightColor = sf::Color(0, 0, 30, 255);
        }
//DAWN SUN RISE
        else if(timeType == daynight::TTDawn)
        {
                clockDuration -= increment;

                int percent = static_cast<double>(clockDuration) / daynight::DUSK_DURATION * 100;
                value = imgColorForNight.getSize().x - ((imgColorForNight.getSize().x / 100) * percent);
                if(value < 0)
                        value = 0;
                else if(value > imgColorForNight.getSize().x-1)
                        value = imgColorForNight.getSize().x-1;
                nightColor = imgColorForNight.getPixel(value, 0);

                if(clockDuration < 0)
                {//Set night
                        clockDuration = daynight::DAY_DURATION;
                        timeType = daynight::TTDay;
                        value = 0;
                        nightColor = imgColorForNight.getPixel(imgColorForNight.getSize().x - 1, 0);
                }
        }
        renTex.clear(nightColor);


        /*
        //Calculate dayNightClock value from time of day
        dayNightClock += increment;
        if(dayNightClock >= imgColorForNight.getSize().x)
        {
                increment = -1;
                dayNightClock = imgColorForNight.getSize().x-1;
        }
        else if(dayNightClock <= 0)
        {
                increment = 1;
                dayNightClock = 0;
        }
        nightColor = imgColorForNight.getPixel(dayNightClock, 0);
//Set colors appropriate to day
        renTex.clear(nightColor);
        */

}

void DayNight::Draw(sf::RenderWindow & renWin, sf::Vector2f & pos)
{
        renTex.display();
        sprNight.setTexture(renTex.getTexture());
        sprNight.setPosition(pos);
        renWin.draw(sprNight, renStat);
}
Light::Light()
{
        radius = 0;
        color = sf::Color(255, 255, 255, 255);
        posX = 0;
        posY = 0;

        isBindedToUnit = false;
        unitVecID = 0;
}

Light::Light(const int Radius, const sf::Color Color, const int PosX, const int PosY, bool IsBinded, int UnitVecID) :
        radius(Radius), color(Color), posX(PosX), posY(PosY), isBindedToUnit(IsBinded), unitVecID(UnitVecID)
{

}

//////////////////////////////////////////////////////////////////////////

LightHolder::LightHolder()
{
        verArrLight.setPrimitiveType(sf::PrimitiveType::Quads);
        if(texLight.loadFromFile(light::LIGHT_TEXTURE_DIR + "Light.png") == false)
        {
                glob::PrintError("Failed loading texture '"+ light::LIGHT_TEXTURE_DIR + "Light.png" + " at LightHolder::LightHolder");
        }
        renStatLight.texture = &texLight;
        renStatLight.blendMode = sf::BlendAdd;

        if(texReveal.loadFromFile(light::LIGHT_TEXTURE_DIR + "Reveal.png") == false)
        {
                glob::PrintError("Failed loading texture '"+ light::LIGHT_TEXTURE_DIR + "Reveal.png" + " at LightHolder::LightHolder");
        }
        //renStatReveal.texture = &texReveal;
        renStatReveal.texture = &texReveal;
        renStatReveal.blendMode = sf::BlendAdd;
}

void LightHolder::Loop(UnitList & objUnitList)
{
        for(unsigned int i = 0; i < lightList.size(); i++)
        {
                if(lightList[i].isBindedToUnit)
                {
                        lightList[i].posX = objUnitList.unitList[lightList[i].unitVecID].ubp.posX;
                        lightList[i].posY = objUnitList.unitList[lightList[i].unitVecID].ubp.posY;
                        MoveLight(i);                  
                }
        }
        //lightList[0].posX = objUnitList.unitList[0].unitProperties.posX;
        //lightList[0].posY = objUnitList.unitList[0].unitProperties.posY;
        //MoveLight(0);

        //lightList[1].posX = objUnitList.unitList[1].unitProperties.posX;
        //lightList[1].posY = objUnitList.unitList[1].unitProperties.posY;
        //MoveLight(1);
}

void LightHolder::DrawLight(sf::RenderTexture & renTex, sf::RenderWindow & renWin)
{
        sf::Uint8 alphaColor;
        if(verArrLight.getVertexCount() > 0)
                alphaColor = verArrLight[0].color.a;
//Draw to texture
        for(unsigned int i = 0; i < verArrLight.getVertexCount(); i++)
        {
                verArrLight[i].color.a = 255;
        }
        renTex.draw(verArrLight, renStatReveal);
//Draw to window
        for(unsigned int i = 0; i < verArrLight.getVertexCount(); i++)
        {
                verArrLight[i].color.a = alphaColor;
        }
        renWin.draw(verArrLight, renStatLight);
}

void LightHolder::AddLight(Light & light)
{
        //Check if empy list has a position
                //If has pick from it
                //else make a new position
        int vecID;
        if(lightListEmptyPos.size() > 0)
        {
                vecID = lightListEmptyPos[lightListEmptyPos.size() -1];
                lightListEmptyPos.pop_back();
                //Modify light
                lightList[vecID] = light;

                MoveLight(vecID);
        }
        else
        {//Create new positions
                vecID = lightList.size();
                //Add and modify light
                lightList.push_back(light);

                verArrLight.append(sf::Vertex(sf::Vector2f(light.posX, light.posY), light.color, sf::Vector2f(0, 0)));
                verArrLight.append(sf::Vertex(sf::Vector2f(light.posX, light.posY), light.color, sf::Vector2f(texLight.getSize().x, 0)));
                verArrLight.append(sf::Vertex(sf::Vector2f(light.posX, light.posY), light.color, sf::Vector2f(texLight.getSize().x, texLight.getSize().y)));
                verArrLight.append(sf::Vertex(sf::Vector2f(light.posX, light.posY), light.color, sf::Vector2f(0, texLight.getSize().y)));
                MoveLight(vecID);
        }
}

void LightHolder::RemoveLight(const int VecID)
{
        //Remove from Light
        //Remove from VA
        lightListEmptyPos.push_back(VecID);
        verArrLight[VecID*4].texCoords = sf::Vector2f(0, 0);
        verArrLight[VecID*4+1].texCoords = sf::Vector2f(0, 0);
        verArrLight[VecID*4+2].texCoords = sf::Vector2f(0, 0);
        verArrLight[VecID*4+3].texCoords = sf::Vector2f(0, 0);

        verArrLight[VecID*4].position = sf::Vector2f(0, 0);
        verArrLight[VecID*4+1].position = sf::Vector2f(0, 0);
        verArrLight[VecID*4+2].position = sf::Vector2f(0, 0);
        verArrLight[VecID*4+3].position = sf::Vector2f(0, 0);
}

void LightHolder::MoveLight(int VecID)
{
        Light & light = lightList[VecID];
        int VerID = VecID*4;
        verArrLight[VerID].position = sf::Vector2f(light.posX-light.radius, light.posY-light.radius);
        verArrLight[VerID+1].position = sf::Vector2f(light.posX+light.radius, light.posY-light.radius);
        verArrLight[VerID+2].position = sf::Vector2f(light.posX+light.radius, light.posY+light.radius);
        verArrLight[VerID+3].position = sf::Vector2f(light.posX-light.radius, light.posY+light.radius);
}
BaneTrapperDev@hotmail.com Programing, Coding
Projects: Not in development(unfinished/playable):
http://en.sfml-dev.org/forums/index.php?topic=11073.msg76266#msg76266
UP and in Development: The Wanderer - Lost in time
http://en.sfml-dev.org/forums/index.php?topic=14563.0