Calculating Linear and Quadratic Equation Coefficients

Uwaga! Informacje na tej stronie mają ponad 6 lat. Nadal je udostępniam, ale prawdopodobnie nie odzwierciedlają one mojej aktualnej wiedzy ani przekonań.

Sun
30
Aug 2009

Some time ago I've written about formulas to calculate coefficients of linear and quadratic equation [pl] when having 2 or 3 given points (x,y). Yesterday I suddenly noticed that my code needs to do it every frame so I need functions to calculate these coefficients. Below you can find the code of my functions. They are templates, so they work with many types including float, double, as well as vectors of any dimmension and other types which have addition, subtraction and assignment operators, as well as multiplication and divistion by float scalar.

template <typename T>
bool CalcLinearFactors(
  T &outA, T &outB,
  float x1, float x2,
  const T &y1, const T &y2)
{
  float d = x2-x1;
  if (d == 0.f)
    return false;
  outA = (y2 - y1) / d;
  outB = (y1*x2 - y2*x1) / d;
  return true;
}

template <typename T>
bool CalcQuadraticFactors(
  T &outA, T &outB, T &outC,
  float x1, float x2, float x3,
  const T &y1, const T &y2, const T &y3)
{
  float x1_sq = x1 * x1;
  float x2_sq = x2 * x2;
  float x3_sq = x3 * x3;
  float w = x1_sq*(x2-x3) + x2_sq*(x3-x1) + x3_sq*(x1-x2);
  if (w == 0.0f)
    return false;
  outA = ( y1*(x2-x3) + y2*(x3-x1) + y3*(x1-x2) ) / w;
  outB = ( y1*(x3_sq-x2_sq) + y2*(x1_sq-x3_sq) + y3*(x2_sq-x1_sq) ) / w;
  outC = ( y1*(x2_sq*x3-x3_sq*x2) + y2*(x3_sq*x1-x1_sq*x3) + y3*(x1_sq*x2-x2_sq*x1) ) / w;
  return true;
}

Their usage is quite simple. Whenever you need to calculate something that can be approximated by linear or quadratic equation many times (e.g. inside a shader), most efficient way to do it is to precalculate coefficients for the equation. For example, let's say you want to calculate fog effect, so inside your pixel shader you want to calculate a fog density for each pixel. You want your fog to start (to have 0 density) at distance Z_Far*0.7f and fully cover geometry at the far clipping plane (density 1 at distance Z_Far). The solution is to precalculate linear function coefficients with my function like this:

float x1 = Z_Far*0.7f, x2 = Z_Far;
float y1 = 0.f,        y2 = 1.f;
float a, b;
CalcLinearFactors<float>(a, b, x1, x2, y1, y2);
MyEffect->SetVector("FogParams", &D3DXVECTOR4(a, b, 0.f, 0.f));

And here is the code for pixel shader that actually does the linear function computations:

float2 FogParams; // a, b

void MainPS(...
{
  float FogDensity = FogParams.x*distance + FogParams.y;

Don't forget to saturate(FogDensity) to limit its value to 0..1. When using quadratic equation, also don't forget to apply optimization known as Horner scheme, according to the simple law:

a*(x*x) + b*x + c = (a*x + b)*x + c

Comments | #rendering #math #algorithms Share

Comments

[Download] [Dropbox] [pub] [Mirror] [Privacy policy]
Copyright © 2004-2024