# Equation for pulsating a light

This topic is 4991 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hi all, Should be a simple question for the math aware here. What would be the correct equation to use for pulsating something like a light over a regular period of say 2 seconds, where the light fades in and out but doesn't fade out to black completely? I am using OpenGL so I guess I would need to apply the function to the Red, Green, and Blue values individually. I am working with this: sin(((360.0/pulseCycleTime)*pulseAccTime)*(PI/180.0))*pulseRedValue (where pulseCycleTime is the total time of the pulse cycle, pulseAccTime is the currently accumulated time of the pulse, and pulseRedValue is the target red value. I also do the same for the Green and Blue values) but it doesn't look quite right since the sine function oscilates from 1 to -1 and even adjusting/clamping the range it still dips to 0 - or black. I am probably overthinking this again, so any insights would be helpful. Thanks, F451 [Edited by - Fahrenheit451 on May 23, 2005 8:46:17 AM]

##### Share on other sites
(sin(((360.0/pulseCycleTime)*pulseAccTime)*(PI/180.0)) * .5 + .5) * RedValue
(sin(((360.0/pulseCycleTime)*pulseAccTime)*(PI/180.0)) * .5 + .5) * GreenValue
(sin(((360.0/pulseCycleTime)*pulseAccTime)*(PI/180.0)) * .5 + .5) * BlueValue

##### Share on other sites
Thanks. I have similar clamping in place that puts it into the range 0.0~1.0. I was hoping to tweak the equation or find an alternative equation that does not dip to zero and go black... just dim slightly I suppose. Your clamping did give me some ideas though, and I ended up with this:

BlueValue-((sin(((360.0/pulseCycleTime)*pulseAccTime)*(M_PI/180.0))*.5+.5)*.5);

which works better. There are likely simpler solutions to this, but for the time being it works fine. Thanks again!

F451

##### Share on other sites
ColourValue * (0.75 - cos((2 * M_PI) * (pulseAccTime / pulseCycleTime)) * 0.25)

oscillates between 0.5 and 1.0 intesnsity, and its more readable

##### Share on other sites
I don't know if this would be useful to you, but here's the wave class from my Q3 renderer:

// --------------------------------------------------------------------------------------// FILE: Wave.h// --------------------------------------------------------------------------------------#ifndef WAVE_H#define WAVE_Hclass Parser;class Wave{public:    enum {SIN,          TRIANGLE,          SQUARE,          SAWTOOTH,          INVSAWTOOTH,          NOISE,          NUMTYPES};    Wave();    Wave(int type, float offset, float amplitude, float phase, float frequency);	    void Set(int type, float offset, float amplitude, float phase, float frequency);	    float Evaluate(float time) const;	    bool Parse(Parser& parser, int line);private:    int		m_type;    float	m_offset;    float	m_amplitude;    float	m_phase;    float	m_frequency;};#endif// --------------------------------------------------------------------------------------// FILE: Wave.cpp// --------------------------------------------------------------------------------------#include "Wave.h"#include "Parser.h"#include "MathUtil.h"#include "Log.h"#include "stricmp.h"// --------------------------------------------------------------------------------------using namespace std;// --------------------------------------------------------------------------------------Wave::Wave(){    // Default to sin in range 0, 1    Set(SIN, 0.5f, 0.5f, 0.0f, 1.0f);}// --------------------------------------------------------------------------------------Wave::Wave(int type, float offset, float amplitude, float phase, float frequency){    Set(type, offset, amplitude, phase, frequency);}// --------------------------------------------------------------------------------------void Wave::Set(int type, float offset, float amplitude, float phase, float frequency){    m_type = type;    m_offset = offset;    m_amplitude = amplitude;    m_phase = phase;    m_frequency = frequency;}// --------------------------------------------------------------------------------------float Wave::Evaluate(float time) const{    // Evaluate y = offset + amplitude * f((time + phase) * frequency)    float x = (time + m_phase) * m_frequency;    x -= floorf(x); // Normalize	    float y;	    switch (m_type)    {        case SIN:            y = sinf(x * Math::TWO_PI);            break;        case TRIANGLE:            x < 0.5f ? y = 4.0f * x - 1.0f : y = -4.0f * x + 3.0f;            break;        case SQUARE:            x < 0.5f ? y = 1.0f : y = -1.0f;            break;        case SAWTOOTH:            y = x;            break;        case INVSAWTOOTH:            y = 1.0f - x;            break;        case NOISE:            y = (float)rand() / (float)RAND_MAX;            break;    }	    return y * m_amplitude + m_offset;}// --------------------------------------------------------------------------------------bool Wave::Parse(Parser& parser, int line){    // Type    if (!parser.FindNextToken())    {        Log::Get()->Print("Warning, parameter expected in line %d", line);        return false;    }    if (!stricmp(parser.GetCurrText(), "sin"))        m_type = SIN;    else if (!stricmp(parser.GetCurrText(), "triangle"))        m_type = TRIANGLE;    else if (!stricmp(parser.GetCurrText(), "square"))        m_type = SQUARE;    else if (!stricmp(parser.GetCurrText(), "sawtooth"))        m_type = SAWTOOTH;    else if (!stricmp(parser.GetCurrText(), "inversesawtooth"))        m_type = INVSAWTOOTH;    else if (!stricmp(parser.GetCurrText(), "noise"))        m_type = NOISE;    else    {        Log::Get()->Print("Warning, unknown wave type \"%s\" in line %d", parser.GetCurrText(), line);        return false;    }	    // Parameters    if (!parser.FindNextToken())    {        Log::Get()->Print("Warning, parameter expected in line %d", line);        return false;    }    m_offset = atof(parser.GetCurrText());    if (!parser.FindNextToken())    {        Log::Get()->Print("Warning, parameter expected in line %d", line);        return false;    }    m_amplitude = atof(parser.GetCurrText());    if (!parser.FindNextToken())    {        Log::Get()->Print("Warning, parameter expected in line %d", line);        return false;    }    m_phase = atof(parser.GetCurrText());    if (!parser.FindNextToken())    {        Log::Get()->Print("Warning, parameter expected in line %d", line);        return false;    }    m_frequency = atof(parser.GetCurrText());    if (parser.FindNextToken())    {        Log::Get()->Print("Warning, too many parameters in line %d", line);        return false;    }	    return true;	}// --------------------------------------------------------------------------------------

It supports sin, triangle, square, sawtooth, inverse sawtooth, and random wave types. By adjusting the parameters you can set the 'range' of the wave, to, for example, dim a light rather than going to full black, as you mentioned.

##### Share on other sites
why don't you clamp the answer between the smallest fade in/out value?
therefore it will vary its intensity then just cut off.

edit: I understood the question wrong. multiply the output by .5 and add .5 and delta to it
(A / 2.0) + delta + (1.0/2.0)

where delta is your minimum value

##### Share on other sites
You guys are all great! Thanks a lot. Got it working perfectly.

• ### What is your GameDev Story?

In 2019 we are celebrating 20 years of GameDev.net! Share your GameDev Story with us.

• 15
• 9
• 11
• 9
• 9
• ### Forum Statistics

• Total Topics
634134
• Total Posts
3015751
×