diff Render.cpp @ 49:25fabc49627b

Слияние
author Ritor1
date Tue, 23 Oct 2012 17:34:20 +0600
parents 8a8dd0164b12
children fde5c5acb66e
line wrap: on
line diff
--- a/Render.cpp	Tue Oct 23 17:33:33 2012 +0600
+++ b/Render.cpp	Tue Oct 23 17:34:20 2012 +0600
@@ -63,6 +63,7 @@
 
 
 
+void SetBillboardBlendOptions(RenderBillboardD3D::OpacityType a1);
 
 
 /*  384 */
@@ -173,11 +174,7 @@
 //----- (00440CB8) --------------------------------------------------------
 void Render::DrawBillboardList_BLV()
 {
-  int v0; // ebx@1
-  char *v1; // esi@2
   __int16 v2; // ax@3
-  unsigned __int16 *v3; // eax@6
-  char v4; // zf@6
   int v5; // eax@11
   RenderBillboardTransform_local0 soft_billboard; // [sp+4h] [bp-50h]@1
 
@@ -189,46 +186,38 @@
   soft_billboard.uViewportY = pBLVRenderParams->uViewportY;
   soft_billboard.uViewportZ = pBLVRenderParams->uViewportZ - 1;
   soft_billboard.uViewportW = pBLVRenderParams->uViewportW;
-  v0 = 0;
-  pOutdoorCamera->field_3C = uNumBillboardsToDraw;
-  if ( (signed int)uNumBillboardsToDraw > 0 )
-  {
-    v1 = (char *)&pBillboardRenderList[0].field_28;
-    do
-    {
-      soft_billboard.field_8 = *((short *)v1 - 1);
-      soft_billboard.uParentBillboardID = v0;
-      soft_billboard.field_C = *(short *)v1;
-      soft_billboard.field_10 = *((int *)v1 - 10);
-      soft_billboard.field_14 = *((int *)v1 - 9);
-      soft_billboard.field_28 = *((int *)v1 - 6);
-      soft_billboard.uFlags = *((short *)v1 - 5);
-      soft_billboard.uTintColor = *((int *)v1 + 1);
-      v2 = *((short *)v1 - 8);
+
+  pOutdoorCamera->uNumBillboards = uNumBillboardsToDraw;
+
+  for (uint i = 0; i < uNumBillboardsToDraw; ++i)
+  {
+    auto p = pBillboardRenderList + i;
+
+      soft_billboard.uScreenSpaceX = p->uScreenSpaceX;
+      soft_billboard.uParentBillboardID = i;
+      soft_billboard.uScreenSpaceY = p->uScreenSpaceY;
+      soft_billboard.field_10 = p->field_0;
+      soft_billboard.field_14 = p->field_4;
+      soft_billboard.sZValue = p->sZValue;
+      soft_billboard.uFlags = p->field_1E;
+      soft_billboard.uTintColor = p->uTintColor;
+      v2 = p->uHwSpriteID;
       if ( v2 != -1 )
       {
         if ( pRenderer->pRenderD3D )
-        {
-          pRenderer->_4A43B1(&soft_billboard, &pSprites_LOD->pHardwareSprites[v2], *((short *)v1 + 1));
-        }
+          pRenderer->DrawBillboard_Indoor(&soft_billboard, &pSprites_LOD->pHardwareSprites[v2], p->uPaletteSubindex);
         else
         {
-          v3 = PaletteManager::Get_Dark_or_Red_LUT(*((short *)v1 - 7), *((short *)v1 + 1), 1);
-          v4 = (*(v1 - 9) & 1) == 0;
-          soft_billboard.pPalette = v3;
-          if ( !v4 )
-            soft_billboard.pPalette = pPaletteManager->field_261600[*((short *)v1 - 7)];
+          soft_billboard.pPalette = PaletteManager::Get_Dark_or_Red_LUT(p->uPalette, p->uPaletteSubindex, 1);
+          if (p->field_1E & 0x0100)
+            soft_billboard.pPalette = pPaletteManager->field_261600[p->uPalette];
           if ( !(soft_billboard.uFlags & 0x40) && soft_billboard.uFlags & 0x80 )
-            soft_billboard.pPalette2 = PaletteManager::Get_Dark_or_Red_LUT(*((short *)v1 - 7), 0, 1);
-          v5 = *((short *)v1 - 8);
+            soft_billboard.pPalette2 = PaletteManager::Get_Dark_or_Red_LUT(p->uPalette, 0, 1);
+          v5 = p->uHwSpriteID;
           if ( v5 >= 0 )
             pSprites_LOD->pSpriteHeaders[v5]._4ACC38(&soft_billboard, 1);
         }
       }
-      ++v0;
-      v1 += 52;
-    }
-    while ( v0 < (signed int)uNumBillboardsToDraw );
   }
 }
 
@@ -2904,17 +2893,17 @@
   billboard.uViewportZ = pViewport->uViewportZ - 1;
   billboard.uViewportW = pViewport->uViewportW;
   v0 = 0;
-  pOutdoorCamera->field_3C = uNumBillboardsToDraw;
+  pOutdoorCamera->uNumBillboards = uNumBillboardsToDraw;
   v16 = 0;
   if ( (signed int)uNumBillboardsToDraw > 0 )
   {
     v17 = 0;
-    v1 = (char *)&pBillboardRenderList[0].field_28;
+    v1 = (char *)&pBillboardRenderList[0].uScreenSpaceY;
     do
     {
-      billboard.field_8 = *((short *)v1 - 1);
+      billboard.uScreenSpaceX = *((short *)v1 - 1);
       v2 = *((short *)v1 - 5);
-      billboard.field_C = *(short *)v1;
+      billboard.uScreenSpaceY = *(short *)v1;
       v3 = *((int *)v1 - 10);
       billboard.uParentBillboardID = v0;
       v4 = *((int *)v1 + 1);
@@ -2924,14 +2913,14 @@
       v6 = *((short *)v1 - 8);
       billboard.field_14 = v5;
       v7 = *((int *)v1 - 6);
-      billboard.field_28 = *((int *)v1 - 6);
+      billboard.sZValue = *((int *)v1 - 6);
       billboard.uFlags = v2;
       if ( v6 != -1 )
       {
         v8 = *((short *)v1 + 1);
         if ( pRenderer->pRenderD3D )
         {
-          billboard.field_28 = v7;
+          billboard.sZValue = v7;
           billboard.uFlags = v2;
           pRenderer->TransformBillboard(
             &billboard,
@@ -3141,17 +3130,17 @@
                   v3->pSpriteFrame = v28;
                   v3->field_4 = v26;
                   v3->field_1E = v46;
-                  v3->field_20 = x;
-                  v3->field_22 = y;
-                  v3->field_24 = z;
-                  v3->field_26 = v35;
-                  v3->field_28 = v32;
+                  v3->some_x = x;
+                  v3->some_y = y;
+                  v3->some_z = z;
+                  v3->uScreenSpaceX = v35;
+                  v3->uScreenSpaceY = v32;
                   HIWORD(v26) = HIWORD(v42);
                   LOWORD(v26) = 0;
                   v27 = (*(v0 - 2) & 0x20) == 0;
                   v3->sZValue = v26 + (8 * v41 | 2);
-                  v3->field_2A = 0;
-                  v3->field_2C_prolly_tint = 0;
+                  v3->uPaletteSubindex = 0;
+                  v3->uTintColor = 0;
                   if ( !v27 )
                   {
                     if ( !pRenderer->pRenderD3D )
@@ -3573,22 +3562,22 @@
                     v27->field_0 = v26;
                     v27->field_4 = v26;
                     v29 = v38;
-                    v27->field_26 = v25;
+                    v27->uScreenSpaceX = v25;
                     HIBYTE(v29) |= 2u;
                     v27->uPalette = v28;
                     v27->field_1E = v29;
-                    v27->field_20 = x;
-                    v27->field_22 = y;
-                    v27->field_24 = v36;
-                    v27->field_28 = v40;
+                    v27->some_x = x;
+                    v27->some_y = y;
+                    v27->some_z = v36;
+                    v27->uScreenSpaceY = v40;
                     HIWORD(v30) = HIWORD(v39);
                     v31 = 8 * v35 | 5;
                     LOWORD(v30) = 0;
                     v27->uIndoorSectorID = 0;
                     v27->sZValue = v30 + v31;
-                    v27->field_2A = 0;
+                    v27->uPaletteSubindex = 0;
                     v27->pSpriteFrame = v9;
-                    v27->field_2C_prolly_tint = 0;
+                    v27->uTintColor = 0;
                   }
                 }
                 goto LABEL_38;
@@ -3627,7 +3616,7 @@
           local_0.flt_14 = 0.0;
           local_0.flt_18 = 0.0;
           local_0.flt_28 = 1.0;
-          local_0.field_20 = (rand() & 0x80) + 128;
+          local_0.timeToLive = (rand() & 0x80) + 128;
           local_0.uTextureID = pBitmaps_LOD->LoadTexture("effpar01");
           pGame->pParticleEngine->AddParticle(&local_0);
         }
@@ -4511,7 +4500,7 @@
               *(int *)v34 = 0;
               v34 += 32;
               --v33;
-              *((int *)v34 - 9) = LODWORD(pRenderer->uFogColor) | v35 & 0xFF000000;
+              *((int *)v34 - 9) = pRenderer->uFogColor | v35 & 0xFF000000;
             }
             while ( v33 );
           }
@@ -4624,6 +4613,8 @@
   LOBYTE(v1->field_103668) = 0;
   v1->field_1036B8 = 0;
   v1->_gpu_memory_used = 0;
+  uNumBillboardsToDraw = 0;
+  bFogEnabled = false;
 }
 
 bool Render::Initialize(bool bWindowed, uint uDefaultDevice,
@@ -7116,29 +7107,10 @@
 }
 
 //----- (004A1EB6) --------------------------------------------------------
-void Render::SetGameRenderStates()
-{
-  Render *v1; // esi@1
-  unsigned int v2; // eax@1
-  RenderD3D *v3; // ecx@2
-  unsigned int uFogColor; // edi@6
-  IDirect3DDevice3 *v5; // eax@8
-  //IDirect3DDevice3Vtbl *v6; // ecx@8
-  RenderD3D *v7; // eax@9
-  RenderD3D *v8; // eax@9
-  std::string v9; // [sp-14h] [bp-2Ch]@4
-  IDirect3DDevice3 *v10; // [sp-8h] [bp-20h]@9
-  signed int v11; // [sp-4h] [bp-1Ch]@4
-  int v12; // [sp+0h] [bp-18h]@4
-  std::string *v13; // [sp+10h] [bp-8h]@4
-  int a3; // [sp+17h] [bp-1h]@4
-
-  v1 = this;
-  v2 = this->uNumD3DSceneBegins;
-  this->uNumD3DSceneBegins = v2 + 1;
-  if ( !v2 )
-  {
-    v3 = this->pRenderD3D;
+void Render::BeginSceneD3D()
+{
+  if (!uNumD3DSceneBegins++)
+  {
     if (pRenderD3D)
     {
       pRenderD3D->ClearTarget(1u, 0, 1u, 1.0);
@@ -7152,42 +7124,27 @@
         uFogColor = GetLevelFogColor();
       else
         uFogColor = 0;
-      v5 = v1->pRenderD3D->pDevice;
-      //v6 = v5->lpVtbl;
+
       if ( uFogColor & 0xFF000000 )
       {
-        v12 = 1;
-        v11 = 28;
-        v10 = v5;
-        pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, 1u);
-        //v7 = v1->pRenderD3D;
-        v12 = uFogColor & 0xFFFFFF;
-        v11 = 34;
-        //v10 = v7->pDevice;
+        pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, 1);
         pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGCOLOR, uFogColor & 0xFFFFFF);
-        v8 = v1->pRenderD3D;
-        *(float *)&v12 = 0.0;
-        v11 = 35;
-        //v10 = v8->pDevice;
         pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGTABLEMODE, 0);
-        v1->bUsingSpecular = 1;
+        bUsingSpecular = true;
       }
       else
       {
-        *(float *)&v12 = 0.0;
-        v11 = 28;
-        v10 = v5;
         pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, 0);
-        v1->bUsingSpecular = 0;
+        bUsingSpecular = 0;
       }
     }
     else
     {
-      LockRenderSurface((void **)&v1->pTargetSurface, &v1->uTargetSurfacePitch);
-      if ( v1->pTargetSurface )
-        v1->field_18_locked_pitch = v1->uTargetSurfacePitch;
+      LockRenderSurface((void **)&pTargetSurface, &uTargetSurfacePitch);
+      if (pTargetSurface)
+        field_18_locked_pitch = uTargetSurfacePitch;
       else
-        --v1->uNumD3DSceneBegins;
+        --uNumD3DSceneBegins;
     }
   }
 }
@@ -7195,23 +7152,19 @@
 //----- (004A1FE1) --------------------------------------------------------
 void Render::DrawBillboards_And_MaybeRenderSpecialEffects_And_EndScene()
 {
-  char v1; // zf@1
-
-  v1 = this->uNumD3DSceneBegins-- == 1;
-  if ( v1 )
-  {
-    if ( this->pRenderD3D )
-    {
-      pGame->draw_debug_outlines();
-      DoRenderBillboards_D3D();
-      pGame->pStru6Instance->RenderSpecialEffects();
-      pRenderD3D->pDevice->EndScene();
-    }
-    else
-    {
-      pGame->pStru6Instance->RenderSpecialEffects();
-    }
-  }
+  --uNumD3DSceneBegins;
+  if (uNumD3DSceneBegins)
+    return;
+
+  if (pRenderD3D)
+  {
+    pGame->draw_debug_outlines();
+    DoRenderBillboards_D3D();
+    pGame->pStru6Instance->RenderSpecialEffects();
+    pRenderD3D->pDevice->EndScene();
+  }
+  else
+    pGame->pStru6Instance->RenderSpecialEffects();
 }
 
 
@@ -7479,7 +7432,7 @@
               *(int *)v38 = 0;
               v38 += 32;
               --v37;
-              *((int *)v38 - 9) = LODWORD(pRenderer->uFogColor) | v39 & 0xFF000000;
+              *((int *)v38 - 9) = pRenderer->uFogColor | v39 & 0xFF000000;
             }
             while ( v37 );
           }
@@ -7866,7 +7819,7 @@
 
 
 //----- (004A43B1) --------------------------------------------------------
-void Render::_4A43B1(RenderBillboardTransform_local0 *pSoftBillboard, Sprite *a3, int a4)
+void Render::DrawBillboard_Indoor(RenderBillboardTransform_local0 *pSoftBillboard, Sprite *a3, int uPaletteSubindex)
 {
   RenderBillboardTransform_local0 *v4; // ebx@2
   double v5; // st7@2
@@ -7903,23 +7856,23 @@
   if ( this->uNumD3DSceneBegins )
   {
     v4 = pSoftBillboard;
-    v5 = (double)HIWORD(pSoftBillboard->field_28);
+    v5 = (double)HIWORD(pSoftBillboard->sZValue);
     pSoftBillboarda = v5;
     v6 = v5;
     v7 = Billboard_ProbablyAddToListAndSortByZOrder(LODWORD(v6));
-    v8 = a4;
+    v8 = uPaletteSubindex;
     v9 = v7;
-    v28 = a4 & 0xFF000000;
-    if ( a4 & 0xFF000000 )
-      pBillboardRenderListD3D[v9].bOpaque = 3;
+    v28 = uPaletteSubindex & 0xFF000000;
+    if ( uPaletteSubindex & 0xFF000000 )
+      pBillboardRenderListD3D[v9].uOpacity = RenderBillboardD3D::Opaque_3;
     else
-      pBillboardRenderListD3D[v9].bOpaque = 0;
+      pBillboardRenderListD3D[v9].uOpacity = RenderBillboardD3D::Transparent;
     v10 = a3;
     pBillboardRenderListD3D[v9].field_90 = v4->field_44;
-    pBillboardRenderListD3D[v9].field_94 = v4->field_28;
+    pBillboardRenderListD3D[v9].sZValue = v4->sZValue;
     pBillboardRenderListD3D[v9].uParentBillboardID = v4->uParentBillboardID;
-    v25 = v4->field_8;
-    v24 = v4->field_C;
+    v25 = v4->uScreenSpaceX;
+    v24 = v4->uScreenSpaceY;
     a1 = (double)(v4->field_10 & 0xFFFF) * 0.000015260186 + (double)HIWORD(v4->field_10);
     v29 = (double)(v4->field_14 & 0xFFFF) * 0.000015260186 + (double)HIWORD(v4->field_14);
     v31 = (double)((v10->uBufferWidth >> 1) - v10->uAreaX);
@@ -7956,39 +7909,39 @@
       v17 = v17 * -1.0;
     pBillboardRenderListD3D[v9].pQuards[1].specular = 0;
     pBillboardRenderListD3D[v9].pQuards[1].diffuse = v12;
-    *(float *)(v9 * 156 + 15684320) = v13 - v17 * a1;
-    *(float *)(v9 * 156 + 15684324) = v32 - v18 * v29;
-    *(float *)(v9 * 156 + 15684328) = v15;
-    *(float *)(v9 * 156 + 15684332) = v16;
-    *(float *)(v9 * 156 + 15684344) = 0.0;
-    *(float *)(v9 * 156 + 15684348) = 1.0;
+    pBillboardRenderListD3D[v9].pQuards[1].pos.x = v13 - v17 * a1;
+    pBillboardRenderListD3D[v9].pQuards[1].pos.y = v32 - v18 * v29;
+    pBillboardRenderListD3D[v9].pQuards[1].pos.z = v15;
+    pBillboardRenderListD3D[v9].pQuards[1].rhw = v16;
+    pBillboardRenderListD3D[v9].pQuards[1].texcoord.x = 0.0;
+    pBillboardRenderListD3D[v9].pQuards[1].texcoord.y = 1.0;
     v19 = v10->uBufferHeight - v10->uAreaY - v10->uAreaHeight;
     v20 = (double)(v10->uAreaX + v10->uAreaWidth + (v10->uBufferWidth >> 1) - v10->uBufferWidth);
     if ( v4->uFlags & 4 )
       v20 = v20 * -1.0;
     pBillboardRenderListD3D[v9].pQuards[2].specular = 0;
     pBillboardRenderListD3D[v9].pQuards[2].diffuse = v12;
-    *(float *)(v9 * 156 + 15684352) = v20 * a1 + v13;
-    *(float *)(v9 * 156 + 15684356) = v32 - (double)v19 * v29;
-    *(float *)(v9 * 156 + 15684360) = v15;
-    *(float *)(v9 * 156 + 15684364) = v16;
-    *(float *)(v9 * 156 + 15684376) = 1.0;
-    *(float *)(v9 * 156 + 15684380) = 1.0;
+    pBillboardRenderListD3D[v9].pQuards[2].pos.x = v20 * a1 + v13;
+    pBillboardRenderListD3D[v9].pQuards[2].pos.y = v32 - (double)v19 * v29;
+    pBillboardRenderListD3D[v9].pQuards[2].pos.z = v15;
+    pBillboardRenderListD3D[v9].pQuards[2].rhw = v16;
+    pBillboardRenderListD3D[v9].pQuards[2].texcoord.x = 1.0;
+    pBillboardRenderListD3D[v9].pQuards[2].texcoord.y = 1.0;
     v21 = v10->uBufferHeight - v10->uAreaY;
     v22 = (double)(v10->uAreaX + v10->uAreaWidth + (v10->uBufferWidth >> 1) - v10->uBufferWidth);
     if ( v4->uFlags & 4 )
       v22 = v22 * -1.0;
     pBillboardRenderListD3D[v9].pQuards[3].specular = 0;
     pBillboardRenderListD3D[v9].pQuards[3].diffuse = v12;
-    *(float *)(v9 * 156 + 15684384) = v22 * a1 + v13;
-    *(float *)(v9 * 156 + 15684388) = v32 - (double)v21 * v29;
-    *(float *)(v9 * 156 + 15684392) = v15;
-    *(float *)(v9 * 156 + 15684396) = v16;
-    *(float *)(v9 * 156 + 15684408) = 1.0;
-    *(float *)(v9 * 156 + 15684412) = 0.0;
+    pBillboardRenderListD3D[v9].pQuards[3].pos.x = v22 * a1 + v13;
+    pBillboardRenderListD3D[v9].pQuards[3].pos.y = v32 - (double)v21 * v29;
+    pBillboardRenderListD3D[v9].pQuards[3].pos.z = v15;
+    pBillboardRenderListD3D[v9].pQuards[3].rhw = v16;
+    pBillboardRenderListD3D[v9].pQuards[3].texcoord.x = 1.0;
+    pBillboardRenderListD3D[v9].pQuards[3].texcoord.y = 0.0;
     v23 = v10->pTexture;
     pBillboardRenderListD3D[v9].uNumVertices = 4;
-    *(float *)(v9 * 156 + 15684416) = pSoftBillboarda;
+    pBillboardRenderListD3D[v9].flt_88 = pSoftBillboarda;
     pBillboardRenderListD3D[v9].pTexture = v23;
   }
 }
@@ -8043,18 +7996,18 @@
 
   if ( this->uNumD3DSceneBegins )
   {
-    if ( HIWORD(a2->field_28) )
-    {
-      v5 = (double)HIWORD(a2->field_28);
+    if ( HIWORD(a2->sZValue) )
+    {
+      v5 = (double)HIWORD(a2->sZValue);
       v6 = v5;
       v7 = v5;
       v8 = Billboard_ProbablyAddToListAndSortByZOrder(LODWORD(v7));
-      pBillboardRenderListD3D[v8].bOpaque = 1;
+      pBillboardRenderListD3D[v8].uOpacity = RenderBillboardD3D::Opaque_1;
       pBillboardRenderListD3D[v8].field_90 = a2->field_44;
-      pBillboardRenderListD3D[v8].field_94 = a2->field_28;
+      pBillboardRenderListD3D[v8].sZValue = a2->sZValue;
       pBillboardRenderListD3D[v8].uParentBillboardID = a2->uParentBillboardID;
-      v9 = a2->field_8;
-      v10 = a2->field_C;
+      v9 = a2->uScreenSpaceX;
+      v10 = a2->uScreenSpaceY;
       v11 = (double)(a2->field_10 & 0xFFFF) * 0.000015260186 + (double)HIWORD(a2->field_10);
       v12 = (double)v9;
       v13 = v12;
@@ -8077,7 +8030,7 @@
            + ((double)(unsigned __int16)v20 * 0.000015259022 + (double)(v20 >> 16)) * v16
            - 12.0)
           * v11
-          + (double)a2->field_C;
+          + (double)a2->uScreenSpaceY;
       pBillboardRenderListD3D[v8].pQuards[0].specular = 0;
       pBillboardRenderListD3D[v8].pQuards[0].diffuse = uDiffuse;
       pBillboardRenderListD3D[v8].pQuards[0].pos.y = v22;
@@ -8085,8 +8038,8 @@
       pBillboardRenderListD3D[v8].pQuards[0].rhw = 1.0 / v6;
       pBillboardRenderListD3D[v8].pQuards[0].texcoord.x = 0.0;
       pBillboardRenderListD3D[v8].pQuards[0].texcoord.y = 0.0;
-      v23 = (double)(a2->field_8 - 12) - v13;
-      v24 = (double)a2->field_C - v15;
+      v31 = (double)(a2->uScreenSpaceX + 12) - v13;
+      v32 = (double)a2->uScreenSpaceY - v15;
       v25 = stru_5C6E00->SinCos(angle);
       v26 = stru_5C6E00->SinCos(angle - stru_5C6E00->uIntegerHalfPi);
       v27 = stru_5C6E00->SinCos(angle - stru_5C6E00->uIntegerHalfPi);
@@ -8102,7 +8055,7 @@
            + ((double)(unsigned __int16)v27 * 0.000015259022 + (double)(v27 >> 16)) * v23
            - 12.0)
           * v11
-          + (double)a2->field_C;
+          + (double)a2->uScreenSpaceY;
       pBillboardRenderListD3D[v8].pQuards[1].pos.z = pRenderer->pBillboardRenderListD3D[v8].pQuards[0].pos.z;
       v30 = pBillboardRenderListD3D[v8].pQuards[0].rhw;
       pBillboardRenderListD3D[v8].pQuards[1].pos.y = v29;
@@ -8111,8 +8064,8 @@
       pBillboardRenderListD3D[v8].pQuards[1].diffuse = uDiffuse;
       pBillboardRenderListD3D[v8].pQuards[1].texcoord.x = 0.0;
       pBillboardRenderListD3D[v8].pQuards[1].texcoord.y = 1.0;
-      v31 = (double)(a2->field_8 + 12) - v13;
-      v32 = (double)a2->field_C - v15;
+      v23 = (double)(a2->uScreenSpaceX - 12) - v13;
+      v24 = (double)a2->uScreenSpaceY - v15;
       v33 = stru_5C6E00->SinCos(angle);
       v34 = stru_5C6E00->SinCos(angle - stru_5C6E00->uIntegerHalfPi);
       v35 = stru_5C6E00->SinCos(angle - stru_5C6E00->uIntegerHalfPi);
@@ -8129,7 +8082,7 @@
            + ((double)(unsigned __int16)v35 * 0.000015259022 + (double)(v35 >> 16)) * v31
            - 12.0)
           * v11
-          + (double)a2->field_C;
+          + (double)a2->uScreenSpaceY;
       pBillboardRenderListD3D[v8].pQuards[2].specular = 0;
       pBillboardRenderListD3D[v8].pQuards[2].pos.z = v37;
       pBillboardRenderListD3D[v8].pQuards[2].rhw = pBillboardRenderListD3D[v8].pQuards[0].rhw;
@@ -8137,8 +8090,8 @@
       pBillboardRenderListD3D[v8].pQuards[2].pos.y = v38;
       pBillboardRenderListD3D[v8].pQuards[2].texcoord.x = 1.0;
       pBillboardRenderListD3D[v8].pQuards[2].texcoord.y = 1.0;
-      v39 = (double)(a2->field_8 + 12) - v13;
-      v40 = (double)(a2->field_C - 25) - v15;
+      v39 = (double)(a2->uScreenSpaceX + 12) - v13;
+      v40 = (double)(a2->uScreenSpaceY - 25) - v15;
       v41 = stru_5C6E00->SinCos(angle);
       v42 = stru_5C6E00->SinCos(angle - stru_5C6E00->uIntegerHalfPi);
       v43 = stru_5C6E00->SinCos(angle - stru_5C6E00->uIntegerHalfPi);
@@ -8154,7 +8107,7 @@
            + ((double)(unsigned __int16)v43 * 0.000015259022 + (double)(v43 >> 16)) * v39
            - 12.0)
           * v11
-          + (double)a2->field_C;
+          + (double)a2->uScreenSpaceY;
       v46 = pBillboardRenderListD3D[v8].pQuards[0].pos.z;
       pBillboardRenderListD3D[v8].pQuards[3].specular = 0;
       pBillboardRenderListD3D[v8].pQuards[3].pos.z = v46;
@@ -8219,16 +8172,16 @@
 
   if ( this->uNumD3DSceneBegins )
   {
-    v5 = (double)HIWORD(a2->field_28);
+    v5 = (double)HIWORD(a2->sZValue);
     v6 = v5;
     v7 = v5;
     v8 = Billboard_ProbablyAddToListAndSortByZOrder(LODWORD(v7));
-    pBillboardRenderListD3D[v8].bOpaque = 1;
+    pBillboardRenderListD3D[v8].uOpacity = RenderBillboardD3D::Opaque_1;
     pBillboardRenderListD3D[v8].field_90 = a2->field_44;
-    pBillboardRenderListD3D[v8].field_94 = a2->field_28;
+    pBillboardRenderListD3D[v8].sZValue = a2->sZValue;
     pBillboardRenderListD3D[v8].uParentBillboardID = a2->uParentBillboardID;
-    v9 = a2->field_8;
-    v10 = a2->field_C;
+    v9 = a2->uScreenSpaceX;
+    v10 = a2->uScreenSpaceY;
     v11 = (double)(a2->field_10 & 0xFFFF) * 0.000015260186 + (double)HIWORD(a2->field_10);
     v12 = (double)v9;
     v13 = v12;
@@ -8252,7 +8205,7 @@
          + ((double)(unsigned __int16)v21 * 0.000015259022 + (double)(v21 >> 16)) * v16
          - 12.0)
         * v11
-        + (double)a2->field_C;
+        + (double)a2->uScreenSpaceY;
     pBillboardRenderListD3D[v8].pQuards[0].specular = 0;
     pBillboardRenderListD3D[v8].pQuards[0].diffuse = uDiffuse;
     pBillboardRenderListD3D[v8].pQuards[0].pos.y = v23;
@@ -8262,8 +8215,8 @@
     pBillboardRenderListD3D[v8].pQuards[0].rhw = v25;
     pBillboardRenderListD3D[v8].pQuards[0].texcoord.x = 0.0;
     pBillboardRenderListD3D[v8].pQuards[0].texcoord.y = 0.0;
-    v26 = (double)(a2->field_8 - 12) - v13;
-    v27 = (double)a2->field_C - v15;
+    v26 = (double)(a2->uScreenSpaceX - 12) - v13;
+    v27 = (double)a2->uScreenSpaceY - v15;
     v28 = stru_5C6E00->SinCos(angle);
     v29 = stru_5C6E00->SinCos(v19);
     v30 = stru_5C6E00->SinCos(v19);
@@ -8279,7 +8232,7 @@
          + ((double)(unsigned __int16)v30 * 0.000015259022 + (double)(v30 >> 16)) * v26
          - 12.0)
         * v11
-        + (double)a2->field_C;
+        + (double)a2->uScreenSpaceY;
     pBillboardRenderListD3D[v8].pQuards[1].pos.z = v24;
     pBillboardRenderListD3D[v8].pQuards[1].pos.y = v32;
     pBillboardRenderListD3D[v8].pQuards[1].specular = 0;
@@ -8287,8 +8240,8 @@
     pBillboardRenderListD3D[v8].pQuards[1].diffuse = uDiffuse;
     pBillboardRenderListD3D[v8].pQuards[1].texcoord.x = 0.0;
     pBillboardRenderListD3D[v8].pQuards[1].texcoord.y = 1.0;
-    v33 = (double)(a2->field_8 + 12) - v13;
-    v34 = (double)a2->field_C - v15;
+    v33 = (double)(a2->uScreenSpaceX + 12) - v13;
+    v34 = (double)a2->uScreenSpaceY - v15;
     v35 = stru_5C6E00->SinCos(angle);
     v36 = stru_5C6E00->SinCos(v19);
     v37 = stru_5C6E00->SinCos(v19);
@@ -8304,7 +8257,7 @@
          + ((double)(unsigned __int16)v37 * 0.000015259022 + (double)(v37 >> 16)) * v33
          - 12.0)
         * v11
-        + (double)a2->field_C;
+        + (double)a2->uScreenSpaceY;
     pBillboardRenderListD3D[v8].pQuards[2].specular = 0;
     pBillboardRenderListD3D[v8].pQuards[2].pos.z = v24;
     pBillboardRenderListD3D[v8].pQuards[2].rhw = v25;
@@ -8312,8 +8265,8 @@
     pBillboardRenderListD3D[v8].pQuards[2].pos.y = v39;
     pBillboardRenderListD3D[v8].pQuards[2].texcoord.x = 1.0;
     pBillboardRenderListD3D[v8].pQuards[2].texcoord.y = 1.0;
-    v40 = (double)(a2->field_8 + 12) - v13;
-    v41 = (double)(a2->field_C - 25) - v15;
+    v40 = (double)(a2->uScreenSpaceX + 12) - v13;
+    v41 = (double)(a2->uScreenSpaceY - 25) - v15;
     v42 = stru_5C6E00->SinCos(angle);
     v43 = stru_5C6E00->SinCos(v19);
     v44 = stru_5C6E00->SinCos(v19);
@@ -8329,7 +8282,7 @@
          + ((double)(unsigned __int16)v44 * 0.000015259022 + (double)(v44 >> 16)) * v40
          - 12.0)
         * v11
-        + (double)a2->field_C;
+        + (double)a2->uScreenSpaceY;
     pBillboardRenderListD3D[v8].pQuards[3].specular = 0;
     pBillboardRenderListD3D[v8].pQuards[3].pos.z = v24;
     pBillboardRenderListD3D[v8].pQuards[3].rhw = v25;
@@ -8383,20 +8336,20 @@
   if ( a1->uNumD3DSceneBegins )
   {
     v5 = a2;
-    v6 = (double)HIWORD(a2->field_28);
+    v6 = (double)HIWORD(a2->sZValue);
     v31 = v6;
     v7 = v6;
     v8 = Billboard_ProbablyAddToListAndSortByZOrder(LODWORD(v7));
     if ( BYTE3(v5->uTintColor) )
-      pBillboardRenderListD3D[v8].bOpaque = 3;
+      pBillboardRenderListD3D[v8].uOpacity = RenderBillboardD3D::Opaque_3;
     else
-      pBillboardRenderListD3D[v8].bOpaque = 0;
+      pBillboardRenderListD3D[v8].uOpacity = RenderBillboardD3D::Transparent;
     v9 = pSprite;
     pBillboardRenderListD3D[v8].field_90 = v5->field_44;
-    pBillboardRenderListD3D[v8].field_94 = v5->field_28;
+    pBillboardRenderListD3D[v8].sZValue = v5->sZValue;
     pBillboardRenderListD3D[v8].uParentBillboardID = v5->uParentBillboardID;
-    v24 = v5->field_8;
-    v23 = v5->field_C;
+    v24 = v5->uScreenSpaceX;
+    v23 = v5->uScreenSpaceY;
     v30 = (double)(v5->field_10 & 0xFFFF) * 0.000015260186 + (double)HIWORD(v5->field_10);
     v29 = (double)(v5->field_14 & 0xFFFF) * 0.000015260186 + (double)HIWORD(v5->field_14);
     pSpritea = (double)((v9->uBufferWidth >> 1) - v9->uAreaX);
@@ -8481,7 +8434,7 @@
 
 
 //----- (004A48E4) --------------------------------------------------------
-int Render::_4A48E4(int a2, int a3, int a4, int a5, int a6)
+int Render::MakeParticleBillboardAndPush_BLV_Software(int screenSpaceX, int screenSpaceY, int z, int lightColor, int a6)
 {
   int v6; // ecx@1
   int v7; // ebx@1
@@ -8498,8 +8451,8 @@
   unsigned int v18; // [sp+28h] [bp+Ch]@1
   int v19; // [sp+34h] [bp+18h]@1
 
-  v6 = a2;
-  v7 = (a6 >> 1) + a3;
+  v6 = screenSpaceX;
+  v7 = (a6 >> 1) + screenSpaceY;
   v17 = 0;
   v15 = 0;
   v8 = (a6 >> 1) + v6;
@@ -8507,22 +8460,22 @@
   v9 = 2 * (a6 >> 1);
   v10 = (a6 >> 1) * ((a6 >> 1) - 1);
   x = v8 - (a6 >> 1);
-  v16 = (a6 >> 1) + a3 - v8;
+  v16 = (a6 >> 1) + screenSpaceY - v8;
   v19 = a6 >> 1;
   v13 = v9;
   v18 = v8;
   do
   {
-    sub_4A46E6(x, v16 + v18, a4, 2 * v19, a5);
+    sr_4A46E6_draw_particle_segment(x, v16 + v18, z, 2 * v19, lightColor);
     if ( v15 )
-      sub_4A46E6(x, v17 + v7, a4, 2 * v19, a5);
+      sr_4A46E6_draw_particle_segment(x, v17 + v7, z, 2 * v19, lightColor);
     v14 -= v15;
     if ( v14 <= v10 )
     {
       if ( v19 != v17 )
       {
-        sub_4A46E6(v18, v16 + x, a4, 2 * v17, a5);
-        sub_4A46E6(v18, v19 + v7, a4, 2 * v17, a5);
+        sr_4A46E6_draw_particle_segment(v18, v16 + x, z, 2 * v17, lightColor);
+        sr_4A46E6_draw_particle_segment(v18, v19 + v7, z, 2 * v17, lightColor);
       }
       --v19;
       v13 -= 2;
@@ -8713,7 +8666,7 @@
     v6 = 0;
     pBillboardRenderListD3D[v5].field_90 = 0;
     pBillboardRenderListD3D[v5].uParentBillboardID = -1;
-    pBillboardRenderListD3D[v5].bOpaque = 2;
+    pBillboardRenderListD3D[v5].uOpacity = RenderBillboardD3D::Opaque_2;
     if ( a1->field_10 > 0 )
     {
       v7 = (char *)&a1->field_14[62];
@@ -8755,22 +8708,12 @@
 //----- (004A4DE1) --------------------------------------------------------
 bool Render::LoadTexture(const char *pName, unsigned int bMipMaps, IDirectDrawSurface4 **pOutSurface, IDirect3DTexture2 **pOutTexture)
 {
-  //const char *v5; // ebx@1
-  //Render *v6; // edi@1
-  //HWLTexture *pHWLTexture; // esi@1
-  //signed int result; // eax@1
-  //IDirectDrawSurface **v9; // ebx@9
-  //IDirectDrawSurface4 *v10; // edi@11
-  //int v11; // ebx@11
   HRESULT v12; // eax@14
   unsigned __int16 *v13; // ecx@19
   unsigned __int16 *v14; // eax@19
   DWORD v15; // edx@20
   HRESULT v16; // eax@23
   stru350 Dst; // [sp+Ch] [bp-F8h]@12
-  //DDSURFACEDESC2 desc; // [sp+6Ch] [bp-98h]@13
-  //DDSCAPS2 v19; // [sp+E8h] [bp-1Ch]@13
-  //int v20; // [sp+100h] [bp-4h]@12
 
   auto pHWLTexture = pD3DBitmaps.LoadTexture(pName, bMipMaps);
   if ( pHWLTexture )
@@ -11269,4 +11212,101 @@
   fread(pSpriteOffsets, 4, uNumItems, pFile);
 
   return true;
-}
\ No newline at end of file
+}
+
+
+
+
+
+
+
+
+
+//----- (004A1C1E) --------------------------------------------------------
+void DoRenderBillboards_D3D()
+{
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_ADDRESS, 3u));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, 1u));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, 0));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, 1u));
+
+  for (uint i = pRenderer->uNumBillboardsToDraw - 1; i != (uint)-1; --i)
+  {
+    auto p = pRenderer->pBillboardRenderListD3D + i;
+
+    if (p->uOpacity != RenderBillboardD3D::InvalidOpacity)
+      SetBillboardBlendOptions(p->uOpacity);
+    
+    ErrD3D(pRenderer->pRenderD3D->pDevice->SetTexture(0, p->pTexture));
+    ErrD3D(pRenderer->pRenderD3D->pDevice->DrawPrimitive(D3DPT_TRIANGLEFAN,
+        D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX1,
+        p->pQuards,
+        p->uNumVertices,
+        D3DDP_DONOTLIGHT | D3DDP_DONOTUPDATEEXTENTS));
+  }
+
+  if (pRenderer->bFogEnabled)
+  {
+    pRenderer->bFogEnabled = false;
+    ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, 1));
+    ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGCOLOR, GetLevelFogColor() & 0xFFFFFF));
+    ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGTABLEMODE, 0));
+  }
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, 2));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, 1));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, 0));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, 2u));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, 1u));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DITHERENABLE, 1u));
+}
+
+
+
+
+
+//----- (004A1DA8) --------------------------------------------------------
+void SetBillboardBlendOptions(RenderBillboardD3D::OpacityType a1)
+{
+  switch (a1)
+  {
+    case RenderBillboardD3D::Transparent:
+    {
+      if (pRenderer->bFogEnabled)
+      {
+        pRenderer->bFogEnabled = false;
+        ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, 1u));
+        ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGCOLOR, GetLevelFogColor() & 0xFFFFFF));
+        ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGTABLEMODE, 0));
+      }
+
+      ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, 5));
+      ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, 6u));
+      ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DITHERENABLE, 1));
+    }
+    break;
+
+    case RenderBillboardD3D::Opaque_1:
+    case RenderBillboardD3D::Opaque_2:
+    case RenderBillboardD3D::Opaque_3:
+    {
+      if (pRenderer->bUsingSpecular)
+      {
+        if (!pRenderer->bFogEnabled)
+        {
+          pRenderer->bFogEnabled = true;
+          ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, 0));
+        }
+      }
+
+      ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, 2));
+      ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, 2u));
+      ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DITHERENABLE, 0));
+    }
+    break;
+
+    default:
+      Log::Warning(L"SetBillboardBlendOptions: invalid opacity type (%u)", a1);
+    break;
+  }
+}
+