Jump to content
  • Advertisement
Sign in to follow this  
Fahrenheit451

Equation for pulsating a light

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

If you intended to correct an error in the post then please contact us.

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 this post


Link to post
Share on other sites
Advertisement
(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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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_H

class 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 this post


Link to post
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 this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!