Rendering/DayNight: Difference between revisions

From wowdev
Jump to navigation Jump to search
(Add initial reversal of DayNight::SetLightColors)
No edit summary
 
(11 intermediate revisions by 2 users not shown)
Line 1: Line 1:
= Overview =
In World of Warcraft, the <tt>DayNight</tt> system governs most of the general appearance of the world.
In World of Warcraft, the <tt>DayNight</tt> system governs most of the general appearance of the world.


Things like area lighting, zone lighting, clouds, the sky sphere (ie the color gradient of the sky), stars (ie sky boxes) are all managed by <tt>DayNight</tt>.
Things like area lighting, zone lighting, clouds, the sky sphere (ie the color gradient of the sky), stars (ie sky boxes) are all managed by <tt>DayNight</tt>.
= Utility Functions =
== InterpTable ==
Interpolate between table values of the tables used below.
count - the number of rows in the table (Vec2's), usually 4
dayProgression - internal time normalized (time / 2880f)
<syntaxhighlight lang="cpp">
double InterpTable(C2Vector[] table, uint count, float dayProgression)
{
    unsigned int idxA = 0;
    int idxB;
    if (count != 0)
    {
        do
        {
            if (dayProgression <= (double)(table[idxA].x))
            break;
            ++idxA;
        }
        while (idxA < count);
    }
    if (idxA == count)
    {
        idxA = 0;
        idxB = (int)(count - 1);
    }
    else if (idxA != 0)
    {
        idxB = (int)(idxA - 1);
    }
    else
    {
        idxB = (int)(count - 1);
    }
    double v6 = table[idxA].x - table[idxB].x;
    if (v6 < 0.0)
        v6 = v6 + 1.0;
    double v7 = dayProgression - table[idxB].x;
    if (v7 < 0.0)
        v7 = v7 + 1.0;
    double v8 = v7 / v6;
    if (table[idxA].y < table[idxB].y)
        return table[idxB].y - v8 * (table[idxB].y - table[idxA].y);
    else
        return table[idxB].y + v8 * (table[idxA].y - table[idxB].y);
}
</syntaxhighlight>


== DayNight::DarkenColor ==
== DayNight::DarkenColor ==
Line 33: Line 88:
}
}
</syntaxhighlight>
</syntaxhighlight>
= Lighting Functions =


== DayNight::SetDirection ==
== DayNight::SetDirection ==
Line 75: Line 132:
   }
   }


  // D38B04: float DNInfo->dayProgression (0.0 to 1.0)
   float phi = DayNight::InterpTable(&DayNight::phiTable, 4u, DayNight::g_dnInfo.dayProgression);
   float phi = DayNight::InterpTable(&DayNight::phiTable, 4u, flt_D38B04);
   float theta = DayNight::InterpTable(&DayNight::thetaTable, 4u, DayNight::g_dnInfo.dayProgression);
   float theta = DayNight::InterpTable(&DayNight::thetaTable, 4u, flt_D38B04);


   // Convert from spherical coordinates to XYZ
   // Convert from spherical coordinates to XYZ
Line 90: Line 146:
   float cosTheta = CMath::cosoid(theta);
   float cosTheta = CMath::cosoid(theta);


   // D38C9C: C3Vector sunDir
   DayNight::g_dnInfo.lightInfo.dir.x = sinPhi * cosTheta;
  dword_D38C9C.x = sinPhi * cosTheta;
   DayNight::g_dnInfo.lightInfo.dir.y = sinPhi * sinTheta;
   dword_D38C9C.y = sinPhi * sinTheta;
   DayNight::g_dnInfo.lightInfo.dir.z = cosPhi;
   dword_D38C9C.z = cosPhi;


}
}
Line 99: Line 154:


== DayNight::SetLightColors ==
== DayNight::SetLightColors ==
Sets up lighting colors in <tt>DNInfo->lightInfo</tt>. The colors in <tt>DNInfo->lightInfo</tt> directly feed the lighting for ADTs, M2s, WMOs, etc.
For WMO materials with the <tt>F_WINDOW</tt> flag set, the <tt>windowAmbColor</tt> and <<tt>windowDirColor</tt> are used.


<syntaxhighlight lang="cpp">
<syntaxhighlight lang="cpp">
void DayNight::SetLightColors() {
void DayNight::SetLightColors() {


   unsigned __int16 v0; // bx@1
   // Light colors
  int v1; // eax@1
  int v2; // ebx@1
  int v6; // [sp+28h] [bp-Ch]@1
  int v7; // [sp+2Ch] [bp-8h]@1
  int v8; // [sp+30h] [bp-4h]@1


   DayNight::g_dnInfo.lightInfo.dirColor = DayNight::g_dnInfo.light.dirColor;
   DayNight::g_dnInfo.lightInfo.dirColor = DayNight::g_dnInfo.light.dirColor;
   DayNight::g_dnInfo.lightInfo.ambColor = DayNight::g_dnInfo.light.ambColor;
   DayNight::g_dnInfo.lightInfo.ambColor = DayNight::g_dnInfo.light.ambColor;


   v7 = DayNight::g_dnInfo.light.dirColor.g;
   // Window light colors
   v8 = DayNight::g_dnInfo.light.ambColor.b;
  // MOMT.flags & F_WINDOW
   HIBYTE(v0) = DayNight::g_dnInfo.light.ambColor.r
 
            + ((unsigned __int16)(DayNight::g_dnInfo.light.dirColor.r - DayNight::g_dnInfo.light.ambColor.r) >> 1);
   CImVector windowDirColor = DayNight::g_dnInfo.light.dirColor;
   LOBYTE(v0) = DayNight::g_dnInfo.light.ambColor.g
 
            + ((unsigned __int16)(DayNight::g_dnInfo.light.dirColor.g - DayNight::g_dnInfo.light.ambColor.g) >> 1);
   CImVector::Blend255_(&windowDirColor, 128u, &DayNight::g_dnInfo.light.ambColor);
   v1 = (v0 << 8) | (unsigned __int8)(DayNight::g_dnInfo.light.ambColor.b
 
                                  + ((unsigned __int16)(DayNight::g_dnInfo.light.dirColor.b
   CImVector windowAmbColor = DayNight::g_dnInfo.light.ambColor;
                                                      - DayNight::g_dnInfo.light.ambColor.b) >> 1));
 
   HIBYTE(v0) = DayNight::g_dnInfo.light.dirColor.r
  CImVector::Blend255_(&windowAmbColor, 128u, &DayNight::g_dnInfo.light.dirColor);
            + ((unsigned __int16)(DayNight::g_dnInfo.light.ambColor.r - DayNight::g_dnInfo.light.dirColor.r) >> 1);
 
   LOBYTE(v0) = DayNight::g_dnInfo.light.dirColor.g
  windowAmbColor.r = std::min(windowAmbColor.r + 16u, 255u);
            + ((unsigned __int16)(DayNight::g_dnInfo.light.ambColor.g - DayNight::g_dnInfo.light.dirColor.g) >> 1);
   windowAmbColor.g = std::min(windowAmbColor.g + 16u, 255u);
  v2 = v0 << 8;
  windowAmbColor.b = std::min(windowAmbColor.b + 16u, 255u);
   windowAmbColor.a = windowAmbColor.a - 1; // 0 wraps to 255
 
   DayNight::g_dnInfo.lightInfo.windowDirColor = windowDirColor;
 
  DayNight::g_dnInfo.lightInfo.windowAmbColor = windowAmbColor;


   DayNight::g_dnInfo.lightInfo.windowAmbColor =
   // Shadow color
    (CImVector)((v1 - 0xEFEFF0 - (((v1 - 0xEFEFF0) ^ v1 ^ 0xFFFEFEFF) & 0x1010100)) | ((((v1 - 0xEFEFF0) ^ v1 ^ 0xFFFEFEFF) & 0x1010100) - ((((v1 - 0xEFEFF0) ^ v1 ^ 0xFFFEFEFF) & 0x1010100) >> 8)));
  // TODO: Clean up


   DayNight::g_dnInfo.lightInfo.windowDirColor =
   int v1;
    (CImVector)(v2 | (unsigned __int8)(DayNight::g_dnInfo.light.dirColor.b + ((unsigned __int16)(DayNight::g_dnInfo.light.ambColor.b - DayNight::g_dnInfo.light.dirColor.b) >> 1)));


   BYTE1(v1) = (unsigned __int16)(85 * (DayNight::g_dnInfo.light.ambColor.r + 3)) >> 8;
   BYTE1(v1) = (unsigned __int16)(85 * (DayNight::g_dnInfo.light.ambColor.r + 3)) >> 8;
Line 138: Line 197:
   DayNight::g_dnInfo.shadowColor = (CImVector)(*(_DWORD *)&DayNight::g_dnInfo.light.ambColor & 0xFF000000 | ((unsigned __int16)(85 * (DayNight::g_dnInfo.light.ambColor.b + 3)) >> 8) | ((unsigned __int16)v1 << 8));
   DayNight::g_dnInfo.shadowColor = (CImVector)(*(_DWORD *)&DayNight::g_dnInfo.light.ambColor & 0xFF000000 | ((unsigned __int16)(85 * (DayNight::g_dnInfo.light.ambColor.b + 3)) >> 8) | ((unsigned __int16)v1 << 8));
   DayNight::g_dnInfo.shadowColor.a = DayNight::g_dnInfo.light.shadowOpacity.r;
   DayNight::g_dnInfo.shadowColor.a = DayNight::g_dnInfo.light.shadowOpacity.r;
  // TODO: What is unkLightInfo?


   DayNight::g_dnInfo.unkLightInfo.dir.x = DayNight::g_dnInfo.lightInfo.dir.x;
   DayNight::g_dnInfo.unkLightInfo.dir.x = DayNight::g_dnInfo.lightInfo.dir.x;
Line 144: Line 205:


   DayNight::g_dnInfo.unkLightInfo.dirColor = DayNight::g_dnInfo.light.dirColor;
   DayNight::g_dnInfo.unkLightInfo.dirColor = DayNight::g_dnInfo.light.dirColor;
   DayNight::g_dnInfo.unkLightInfo.ambColor = DayNight::g_dnInfo.light.ambColor;
   DayNight::g_dnInfo.unkLightInfo.ambColor = DayNight::g_dnInfo.light.ambColor;


   DayNight::g_dnInfo.unkLightInfo.windowDirColor = DayNight::g_dnInfo.lightInfo.windowDirColor;
   DayNight::g_dnInfo.unkLightInfo.windowDirColor = DayNight::g_dnInfo.lightInfo.windowDirColor;
   DayNight::g_dnInfo.unkLightInfo.windowAmbColor = DayNight::g_dnInfo.lightInfo.windowAmbColor;
   DayNight::g_dnInfo.unkLightInfo.windowAmbColor = DayNight::g_dnInfo.lightInfo.windowAmbColor;


Line 153: Line 216:
   DayNight::g_dnInfo.unkLightInfo.shaderShadowColor.z = DayNight::g_dnInfo.lightInfo.shaderShadowColor.z;
   DayNight::g_dnInfo.unkLightInfo.shaderShadowColor.z = DayNight::g_dnInfo.lightInfo.shaderShadowColor.z;
   DayNight::g_dnInfo.unkLightInfo.shaderShadowColor.w = DayNight::g_dnInfo.lightInfo.shaderShadowColor.w;
   DayNight::g_dnInfo.unkLightInfo.shaderShadowColor.w = DayNight::g_dnInfo.lightInfo.shaderShadowColor.w;
  // Shader shadow color


   C3Vector rgb;
   C3Vector rgb;
Line 177: Line 242:
   DayNight::g_dnInfo.lightInfo.shaderShadowColor.z = rgb.z;
   DayNight::g_dnInfo.lightInfo.shaderShadowColor.z = rgb.z;
   DayNight::g_dnInfo.lightInfo.shaderShadowColor.w = 1.0;
   DayNight::g_dnInfo.lightInfo.shaderShadowColor.w = 1.0;
}
</syntaxhighlight>
= Stars =
<tt>DNStars</tt> controls the skybox (the model that overlays the sky sphere).
== DayNight::DNStars::Update ==
<syntaxhighlight lang="cpp">
void DayNight::DNStars::Update(DNStars *this) {
  DayNight::DNStars::s_fadeTable = {
    { 0.1250f, 1f },
    { 0.1875f, 0f },
    { 0.9374f, 0f },
    { 0.9999f, 1f }
  };
  this->pos.x = DayNight::g_dnInfo.cameraPos.x;
  this->pos.y = DayNight::g_dnInfo.cameraPos.y;
  this->pos.z = DayNight::g_dnInfo.cameraPos.z;
  float fade = DayNight::InterpTable(&DayNight::DNStars::s_fadeTable, 4u, DayNight::g_dnInfo.dayProgression);
  this->color.a = (signed int)(fade * 254.0 + 1.0);


}
}
</syntaxhighlight>
</syntaxhighlight>

Latest revision as of 15:31, 21 August 2021

Overview

In World of Warcraft, the DayNight system governs most of the general appearance of the world.

Things like area lighting, zone lighting, clouds, the sky sphere (ie the color gradient of the sky), stars (ie sky boxes) are all managed by DayNight.

Utility Functions

InterpTable

Interpolate between table values of the tables used below.

count - the number of rows in the table (Vec2's), usually 4

dayProgression - internal time normalized (time / 2880f)

double InterpTable(C2Vector[] table, uint count, float dayProgression)
{
    unsigned int idxA = 0;
    int idxB;

    if (count != 0)
    {
        do
        {
            if (dayProgression <= (double)(table[idxA].x))
            break;
            ++idxA;
        }
        while (idxA < count);
    }
    if (idxA == count)
    {
        idxA = 0;
        idxB = (int)(count - 1);
    }
    else if (idxA != 0)
    {
        idxB = (int)(idxA - 1);
    }
    else
    {
        idxB = (int)(count - 1);
    }
    double v6 = table[idxA].x - table[idxB].x;
    if (v6 < 0.0)
        v6 = v6 + 1.0;
    double v7 = dayProgression - table[idxB].x;
    if (v7 < 0.0)
        v7 = v7 + 1.0;
    double v8 = v7 / v6;
    if (table[idxA].y < table[idxB].y)
        return table[idxB].y - v8 * (table[idxB].y - table[idxA].y);
    else
        return table[idxB].y + v8 * (table[idxA].y - table[idxB].y);
}

DayNight::DarkenColor

CImVector DayNight::DarkenColor(CImVector const &clr, float amount) {

  C3Vector rgb;
  C3Vector hsv;

  rgb.x = clr->r / 255.0;
  rgb.y = clr->g / 255.0;
  rgb.z = clr->b / 255.0;

  hsv.x = 0.0;
  hsv.y = 0.0;
  hsv.z = 0.0;

  RGBtoHSV(&rgb, &hsv);

  hsv.z = hsv.z * amount;

  HSVtoRGB(&hsv, &rgb);

  CImVector result;

  CImVector::operator=(&result, &rgb);

  return result;

}

Lighting Functions

DayNight::SetDirection

DayNight::SetDirection calculates a C3Vector containing the direction vector for the global light, aka sunDir.

This direction vector is transformed by the view matrix prior to being uploaded to the shader.

void DayNight::SetDirection() {

  // Phi Table
  if ( !(dword_D39104 & 1) ) {

    dword_D39104 |= 1u;

    DayNight::phiTable = {

      { 0.0,  2.2165682 },
      { 0.25, 1.9198623 },
      { 0.5,  2.2165682 },
      { 0.75, 1.9198623 }

    };

  }

  // Theta Table
  if ( !(dword_D39104 & 2) ) {

    dword_D39104 |= 2;
    
    DayNight::thetaTable = {

      { 0.0,  3.926991 },
      { 0.25, 3.926991 },
      { 0.5,  3.926991 },
      { 0.75, 3.926991 }

    };

  }

  float phi = DayNight::InterpTable(&DayNight::phiTable, 4u, DayNight::g_dnInfo.dayProgression);
  float theta = DayNight::InterpTable(&DayNight::thetaTable, 4u, DayNight::g_dnInfo.dayProgression);

  // Convert from spherical coordinates to XYZ
  // x = rho * sin(phi) * cos(theta)
  // y = rho * sin(phi) * sin(theta)
  // z = rho * cos(phi)

  float sinPhi = CMath::sinoid(phi);
  float cosPhi = CMath::cosoid(phi);

  float sinTheta = CMath::sinoid(theta);
  float cosTheta = CMath::cosoid(theta);

  DayNight::g_dnInfo.lightInfo.dir.x = sinPhi * cosTheta;
  DayNight::g_dnInfo.lightInfo.dir.y = sinPhi * sinTheta;
  DayNight::g_dnInfo.lightInfo.dir.z = cosPhi;

}

DayNight::SetLightColors

Sets up lighting colors in DNInfo->lightInfo. The colors in DNInfo->lightInfo directly feed the lighting for ADTs, M2s, WMOs, etc.

For WMO materials with the F_WINDOW flag set, the windowAmbColor and <windowDirColor are used.

void DayNight::SetLightColors() {

  // Light colors

  DayNight::g_dnInfo.lightInfo.dirColor = DayNight::g_dnInfo.light.dirColor;

  DayNight::g_dnInfo.lightInfo.ambColor = DayNight::g_dnInfo.light.ambColor;

  // Window light colors
  // MOMT.flags & F_WINDOW

  CImVector windowDirColor = DayNight::g_dnInfo.light.dirColor;

  CImVector::Blend255_(&windowDirColor, 128u, &DayNight::g_dnInfo.light.ambColor);

  CImVector windowAmbColor = DayNight::g_dnInfo.light.ambColor;

  CImVector::Blend255_(&windowAmbColor, 128u, &DayNight::g_dnInfo.light.dirColor);

  windowAmbColor.r = std::min(windowAmbColor.r + 16u, 255u);
  windowAmbColor.g = std::min(windowAmbColor.g + 16u, 255u);
  windowAmbColor.b = std::min(windowAmbColor.b + 16u, 255u);
  windowAmbColor.a = windowAmbColor.a - 1; // 0 wraps to 255

  DayNight::g_dnInfo.lightInfo.windowDirColor = windowDirColor;

  DayNight::g_dnInfo.lightInfo.windowAmbColor = windowAmbColor;

  // Shadow color
  // TODO: Clean up

  int v1;

  BYTE1(v1) = (unsigned __int16)(85 * (DayNight::g_dnInfo.light.ambColor.r + 3)) >> 8;
  LOBYTE(v1) = (unsigned __int16)(85 * (DayNight::g_dnInfo.light.ambColor.g + 3)) >> 8;
  DayNight::g_dnInfo.shadowColor = (CImVector)(*(_DWORD *)&DayNight::g_dnInfo.light.ambColor & 0xFF000000 | ((unsigned __int16)(85 * (DayNight::g_dnInfo.light.ambColor.b + 3)) >> 8) | ((unsigned __int16)v1 << 8));
  DayNight::g_dnInfo.shadowColor.a = DayNight::g_dnInfo.light.shadowOpacity.r;

  // TODO: What is unkLightInfo?

  DayNight::g_dnInfo.unkLightInfo.dir.x = DayNight::g_dnInfo.lightInfo.dir.x;
  DayNight::g_dnInfo.unkLightInfo.dir.y = DayNight::g_dnInfo.lightInfo.dir.y;
  DayNight::g_dnInfo.unkLightInfo.dir.z = DayNight::g_dnInfo.lightInfo.dir.z;

  DayNight::g_dnInfo.unkLightInfo.dirColor = DayNight::g_dnInfo.light.dirColor;

  DayNight::g_dnInfo.unkLightInfo.ambColor = DayNight::g_dnInfo.light.ambColor;

  DayNight::g_dnInfo.unkLightInfo.windowDirColor = DayNight::g_dnInfo.lightInfo.windowDirColor;

  DayNight::g_dnInfo.unkLightInfo.windowAmbColor = DayNight::g_dnInfo.lightInfo.windowAmbColor;

  DayNight::g_dnInfo.unkLightInfo.shaderShadowColor.x = DayNight::g_dnInfo.lightInfo.shaderShadowColor.x;
  DayNight::g_dnInfo.unkLightInfo.shaderShadowColor.y = DayNight::g_dnInfo.lightInfo.shaderShadowColor.y;
  DayNight::g_dnInfo.unkLightInfo.shaderShadowColor.z = DayNight::g_dnInfo.lightInfo.shaderShadowColor.z;
  DayNight::g_dnInfo.unkLightInfo.shaderShadowColor.w = DayNight::g_dnInfo.lightInfo.shaderShadowColor.w;

  // Shader shadow color

  C3Vector rgb;

  rgb.x = DayNight::g_dnInfo.light.ambColor.r / 255.0f;
  rgb.y = DayNight::g_dnInfo.light.ambColor.g / 255.0f;
  rgb.z = DayNight::g_dnInfo.light.ambColor.b / 255.0f;

  C3Vector hsv;

  hsv.x = 0.0;
  hsv.y = 0.0;
  hsv.z = 0.0;

  RGBtoHSV(&rgb, &hsv);

  hsv.y = hsv.y * 0.33000001;
  hsv.z = hsv.z * 1.25;

  HSVtoRGB(&hsv, &rgb);

  DayNight::g_dnInfo.lightInfo.shaderShadowColor.x = rgb.x;
  DayNight::g_dnInfo.lightInfo.shaderShadowColor.y = rgb.y;
  DayNight::g_dnInfo.lightInfo.shaderShadowColor.z = rgb.z;
  DayNight::g_dnInfo.lightInfo.shaderShadowColor.w = 1.0;

}

Stars

DNStars controls the skybox (the model that overlays the sky sphere).

DayNight::DNStars::Update

void DayNight::DNStars::Update(DNStars *this) {


  DayNight::DNStars::s_fadeTable = {

    { 0.1250f, 1f },
    { 0.1875f, 0f },
    { 0.9374f, 0f },
    { 0.9999f, 1f }

  };


  this->pos.x = DayNight::g_dnInfo.cameraPos.x;
  this->pos.y = DayNight::g_dnInfo.cameraPos.y;
  this->pos.z = DayNight::g_dnInfo.cameraPos.z;

  float fade = DayNight::InterpTable(&DayNight::DNStars::s_fadeTable, 4u, DayNight::g_dnInfo.dayProgression);

  this->color.a = (signed int)(fade * 254.0 + 1.0);

}