 /* '04 Main.cpp' */

 /* Nagłowek szkieletu okna Mirus */
#include "mrWindow.h"
 /* Nagłówek Direct3D */
#include <d3d8.h>
 /* Nagłówek funkcji matematycznych C++ */
#include <math.h>

 /* Nasza własna struktura wierzchołka */
class kCustomVertex
{
public:
  /* Pozycja przetransformowana */ 
 FLOAT x, y, z, rhw;
  /* Kolor */
 DWORD Color;
  /* Współrzędne tekstury */
 FLOAT tU, tV;
};

 /* Nasz własny typ wierzchołka */
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1)

 /* Własna klasa potomna  */
class D3DWindow : public mrWindow
{
  /* Interfejsy Direct 3D */
 LPDIRECT3D8             m_pD3D;
 LPDIRECT3DDEVICE8       m_pD3DDevice;

  /* Interfejs tekstur Direct3D */
 LPDIRECT3DTEXTURE8      m_pD3DTexture;
  /* Bieżący format Direct3D  */
 mrUInt32                m_iD3DFormat;

  /* Wierchołki */
 mrUInt32                m_iColorMod;

public:
  /* Konstruktor / Destruktor */
 D3DWindow (void) {};
 ~D3DWindow (void) {};

  /* Inicjalizacja i zamykanie Direct3D */
 HRESULT SetupDirect3D (void);
 HRESULT KillDirect3D (void);

  /* Funkcje obsługi okien  */
 mrBool32 Frame (void);
};

 /* Inicjalizuje Direct3D */
HRESULT D3DWindow::SetupDirect3D (void)
{
  /* Utwórz obiekt Direct3D */
 if (NULL == (m_pD3D = Direct3DCreate8 (D3D_SDK_VERSION) ) )
 {
  return E_FAIL;
 }
 
  /* Pobiera bieżący tryb ekranu, abyśmy poznali 
     bieżącą głębię kolorów */
 D3DDISPLAYMODE d3ddm;
 if (FAILED (m_pD3D->GetAdapterDisplayMode (D3DADAPTER_DEFAULT, 
                                            &d3ddm) ) )
 {
  return E_FAIL;
 }
 
  /* Wprowadź parametry prezentacji */
 D3DPRESENT_PARAMETERS d3dpp; 
 ZeroMemory( &d3dpp, sizeof(d3dpp) );
  /* Wybieramy tryb niepełnoekranowy */
 d3dpp.Windowed   = TRUE;
  /* Odrzuć to */
 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
 /* Zapisz format jako format bieżący 
     (pobieramy go z g_pD3D->GetAdapterDisplayMode)  */
 d3dpp.BackBufferFormat = d3ddm.Format;
  /* Zapisz format */
 m_iD3DFormat = d3ddm.Format;
 
  /* Utwórz urządzenie */
 if (FAILED (m_pD3D->CreateDevice (D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
                                   m_hWindow, 
                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                                   &d3dpp, 
                                   &m_pD3DDevice ) ) )
 {
  return E_FAIL;
 }

  /* Utwórz teksturę */  
 if (FAILED (m_pD3DDevice->CreateTexture (128, 128, 0, 0, 
                                          (D3DFORMAT) m_iD3DFormat,
                                          D3DPOOL_MANAGED, 
                                          &m_pD3DTexture ) ) )

 {
  return E_FAIL;
 }

  /* Zablokuj teksturę */
 D3DLOCKED_RECT kLockedRect;
 m_pD3DTexture->LockRect (0, &kLockedRect, NULL, 0);

/* Rzutuj wskaźnik tak, aby wskazywał na pierwszy piksel */
 DWORD * piSurfaceBuffer = (DWORD *) kLockedRect.pBits;

  /* Wypełnij teksturę */
 int iX, iY;
 for (iY=0; iY<128; iY++)
 {
  for (iX=0; iX<128; iX++)
  {
    /* Utwórz wzór */
   int iPower = (int)(sin (iY * iX) * 128 + cos (iY * -iX) * 128);
   piSurfaceBuffer [iX + iY* (kLockedRect.Pitch >> 2)] = 
                    D3DCOLOR_XRGB (iPower, iPower, iPower);
  }
 }
  
  /* Odblokuj */
 m_pD3DTexture->UnlockRect (0);

  /* Wyłącz wybieranie wielokątów */
 m_pD3DDevice->SetRenderState (D3DRS_CULLMODE, D3DCULL_NONE);

  /* Wyłącz oświetlenie */
 m_pD3DDevice->SetRenderState (D3DRS_LIGHTING, FALSE);

  /* Używaj wygładzania alfa */
 m_pD3DDevice->SetRenderState (D3DRS_ALPHABLENDENABLE,   TRUE);
 m_pD3DDevice->SetRenderState (D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
 m_pD3DDevice->SetRenderState (D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
 
 return D3D_OK;
}

 /* Zamyka Direct3D */
HRESULT D3DWindow::KillDirect3D (void)
{
   /* Jeżeli istnieją jakieś obiekty Direct3D, uwolnij je */
 if (NULL != m_pD3D)
 {
  m_pD3D->Release ();
 }
 if (NULL != m_pD3DDevice)
 {
  m_pD3DDevice->Release ();
 }
 if (NULL != m_pD3DTexture)
 {
  m_pD3DTexture->Release ();
 }

 return D3D_OK;
}

 /* Narysuj cały kadr */
mrBool32 D3DWindow::Frame (void)
{
  /* Wyzeruj ekran na kolor niebieski */
 m_pD3DDevice->Clear (0, NULL, D3DCLEAR_TARGET, 
                      D3DCOLOR_XRGB (0,0,255), 1.0f, 0);

  /* Pętla poprzez wartości alfa */
 m_iColorMod += 1;
 if (m_iColorMod > 255)
 {
  m_iColorMod = 0;
 }

  /* Ustaw tymczasowe informacje o wierzchołkach */
 kCustomVertex kVertices [] =
 {  /* x, y, z, w, kolor, współrzędne tekstury (u,v) */
  {0.0f,  0.0f,  0.5f, 1.0f, D3DCOLOR_ARGB (m_iColorMod, 255, 255, 255),
          0, 0},
  {50.0f, 0.0f,  0.5f, 1.0f, D3DCOLOR_ARGB (m_iColorMod, 255, 255, 255),
          1, 0},
  {50.0f, 50.0f, 0.5f, 1.0f, D3DCOLOR_ARGB (m_iColorMod, 255, 255, 255), 
          1, 1},
  {0.0f,  50.0f, 0.5f, 1.0f, D3DCOLOR_ARGB (m_iColorMod, 255, 255, 255), 
          0, 1},
 };

  /* Rozpocznij renderowanie */
 m_pD3DDevice->BeginScene();

  /* Ustaw źródło tekstury */
 m_pD3DDevice->SetTexture (0, m_pD3DTexture);
  
  /* Ustaw stan tesktury */
 m_pD3DDevice->SetTextureStageState (0, D3DTSS_COLOROP,   D3DTOP_MODULATE);
 m_pD3DDevice->SetTextureStageState (0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
 m_pD3DDevice->SetTextureStageState (0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
 m_pD3DDevice->SetTextureStageState (0, D3DTSS_ALPHAOP,   D3DTOP_DISABLE);

  /* Ustaw źródło wierzchołków */
 m_pD3DDevice->SetVertexShader (D3DFVF_CUSTOMVERTEX) ;
 m_pD3DDevice->DrawPrimitiveUP (D3DPT_TRIANGLEFAN, 2, kVertices, sizeof (kCustomVertex));

  /* Zakończ renderowanie */
 m_pD3DDevice->EndScene();

  /* Wyświetl zrenderowany obraz na ekranie */
 m_pD3DDevice->Present (NULL, NULL, NULL, NULL);

 return mrTrue;
}

 /* "WinMain kontra main" */
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInst, 
                    LPSTR lpCmdLine, int nShowCmd)
{
  /* Nasze okno */
 D3DWindow  kWindow;

  /* Utwórz okno */
 kWindow.Create (hInstance, "Blending Fun");

  /* Zainicjalizuj Direct3D */
 kWindow.SetupDirect3D ();

  /* Wejdź w pętlę komunikatów */
 kWindow.Run ();

  /* Zamknij Direct3D */
 kWindow.KillDirect3D ();

 return 0;
}