Matrix Effect

 avatar
user_6919294
c_cpp
a year ago
8.6 kB
6
No Index
/* Ireneusz A. Matrix Effect

Ten kod tworzy podstawową strukturę aplikacji DirectX 11 w C++, która może być użyta do stworzenia efektu Matrixa. Oto kilka kluczowych punktów:

Używamy DirectX 11 do renderowania.
Tworzymy system cząstek, gdzie każda cząstka reprezentuje spadający znak.
W funkcji Update() aktualizujemy pozycje i stany cząstek.
Funkcja Render() jest odpowiedzialna za rysowanie cząstek na ekranie.

Aby użyć tego kodu:

- Utwórz nowy projekt Win32 w Visual Studio.
- Zastąp zawartość głównego pliku źródłowego powyższym kodem.
- Upewnij się, że masz zainstalowane DirectX SDK i że ścieżki do plików nagłówkowych i bibliotek są poprawnie ustawione w projekcie.
- Skompiluj i uruchom program.

Pamiętaj, że ten kod jest szkieletem i wymaga dodatkowej pracy:
- Musisz dodać shadery (vertex i pixel shader).
- Należy zaimplementować faktyczne renderowanie cząstek w funkcji Render().
- Warto dodać teksturę dla znaków, aby uzyskać lepszy efekt wizualny. */

#include <windows.h>
#include <d3d11.h>
#include <d3dx11.h>
#include <d3dcompiler.h>
#include <xnamath.h>
#include <vector>
#include <random>

#pragma comment (lib, "d3d11.lib")
#pragma comment (lib, "d3dx11.lib")
#pragma comment (lib, "d3dcompiler.lib")

// Struktury
struct SimpleVertex
{
    XMFLOAT3 Pos;
    XMFLOAT2 Tex;
};

struct ConstantBuffer
{
    XMMATRIX mWorld;
    XMMATRIX mView;
    XMMATRIX mProjection;
};

struct Particle
{
    XMFLOAT3 position;
    XMFLOAT3 velocity;
    XMFLOAT4 color;
    float size;
    float life;
};

// Globalne zmienne
IDXGISwapChain* g_pSwapChain = nullptr;
ID3D11Device* g_pd3dDevice = nullptr;
ID3D11DeviceContext* g_pImmediateContext = nullptr;
ID3D11RenderTargetView* g_pRenderTargetView = nullptr;
ID3D11VertexShader* g_pVertexShader = nullptr;
ID3D11PixelShader* g_pPixelShader = nullptr;
ID3D11InputLayout* g_pVertexLayout = nullptr;
ID3D11Buffer* g_pVertexBuffer = nullptr;
ID3D11Buffer* g_pIndexBuffer = nullptr;
ID3D11Buffer* g_pConstantBuffer = nullptr;
ID3D11ShaderResourceView* g_pTextureRV = nullptr;
ID3D11SamplerState* g_pSamplerLinear = nullptr;
XMMATRIX g_World;
XMMATRIX g_View;
XMMATRIX g_Projection;
std::vector<Particle> g_Particles;

// Funkcje
HRESULT InitDevice(HWND hWnd);
void CleanupDevice();
void Render();
void Update();

// Główna funkcja okna
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
}

// Funkcja główna
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    WNDCLASSEX wcex = { sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW, WndProc, 0, 0, hInstance, nullptr, nullptr, nullptr, nullptr, L"MatrixEffect", nullptr };
    RegisterClassEx(&wcex);

    RECT rc = { 0, 0, 800, 600 };
    AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE);
    HWND hWnd = CreateWindow(L"MatrixEffect", L"Matrix Effect", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, nullptr, nullptr, hInstance, nullptr);

    if (FAILED(InitDevice(hWnd)))
    {
        CleanupDevice();
        return 0;
    }

    ShowWindow(hWnd, nCmdShow);

    MSG msg = { 0 };
    while (WM_QUIT != msg.message)
    {
        if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else
        {
            Update();
            Render();
        }
    }

    CleanupDevice();
    return (int)msg.wParam;
}

// Inicjalizacja urządzenia DirectX
HRESULT InitDevice(HWND hWnd)
{
    HRESULT hr = S_OK;

    RECT rc;
    GetClientRect(hWnd, &rc);
    UINT width = rc.right - rc.left;
    UINT height = rc.bottom - rc.top;

    UINT createDeviceFlags = 0;
#ifdef _DEBUG
    createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif

    D3D_DRIVER_TYPE driverTypes[] =
    {
        D3D_DRIVER_TYPE_HARDWARE,
        D3D_DRIVER_TYPE_WARP,
        D3D_DRIVER_TYPE_REFERENCE,
    };
    UINT numDriverTypes = ARRAYSIZE(driverTypes);

    D3D_FEATURE_LEVEL featureLevels[] =
    {
        D3D_FEATURE_LEVEL_11_0,
        D3D_FEATURE_LEVEL_10_1,
        D3D_FEATURE_LEVEL_10_0,
    };
    UINT numFeatureLevels = ARRAYSIZE(featureLevels);

    DXGI_SWAP_CHAIN_DESC sd;
    ZeroMemory(&sd, sizeof(sd));
    sd.BufferCount = 1;
    sd.BufferDesc.Width = width;
    sd.BufferDesc.Height = height;
    sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    sd.BufferDesc.RefreshRate.Numerator = 60;
    sd.BufferDesc.RefreshRate.Denominator = 1;
    sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    sd.OutputWindow = hWnd;
    sd.SampleDesc.Count = 1;
    sd.SampleDesc.Quality = 0;
    sd.Windowed = TRUE;

    for (UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++)
    {
        D3D_DRIVER_TYPE driverType = driverTypes[driverTypeIndex];
        hr = D3D11CreateDeviceAndSwapChain(nullptr, driverType, nullptr, createDeviceFlags, featureLevels, numFeatureLevels,
            D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, nullptr, &g_pImmediateContext);
        if (SUCCEEDED(hr))
            break;
    }
    if (FAILED(hr))
        return hr;

    // Tworzenie render target view
    ID3D11Texture2D* pBackBuffer = nullptr;
    hr = g_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
    if (FAILED(hr))
        return hr;

    hr = g_pd3dDevice->CreateRenderTargetView(pBackBuffer, nullptr, &g_pRenderTargetView);
    pBackBuffer->Release();
    if (FAILED(hr))
        return hr;

    g_pImmediateContext->OMSetRenderTargets(1, &g_pRenderTargetView, nullptr);

    // Setup the viewport
    D3D11_VIEWPORT vp;
    vp.Width = (FLOAT)width;
    vp.Height = (FLOAT)height;
    vp.MinDepth = 0.0f;
    vp.MaxDepth = 1.0f;
    vp.TopLeftX = 0;
    vp.TopLeftY = 0;
    g_pImmediateContext->RSSetViewports(1, &vp);

    // Inicjalizacja cząstek
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_real_distribution<> dis(0.0, 1.0);

    for (int i = 0; i < 1000; i++)
    {
        Particle p;
        p.position = XMFLOAT3(dis(gen) * width, dis(gen) * height, 0.0f);
        p.velocity = XMFLOAT3(0.0f, 50.0f + dis(gen) * 50.0f, 0.0f);
        p.color = XMFLOAT4(0.0f, 0.5f + dis(gen) * 0.5f, 0.0f, 1.0f);
        p.size = 5.0f + dis(gen) * 10.0f;
        p.life = 1.0f + dis(gen) * 4.0f;
        g_Particles.push_back(p);
    }

    // Kompilacja shaderów, tworzenie bufora wierzchołków, itp. (pominięte dla zwięzłości)

    return S_OK;
}

// Czyszczenie zasobów
void CleanupDevice()
{
    if (g_pImmediateContext) g_pImmediateContext->ClearState();
    if (g_pConstantBuffer) g_pConstantBuffer->Release();
    if (g_pVertexBuffer) g_pVertexBuffer->Release();
    if (g_pIndexBuffer) g_pIndexBuffer->Release();
    if (g_pVertexLayout) g_pVertexLayout->Release();
    if (g_pVertexShader) g_pVertexShader->Release();
    if (g_pPixelShader) g_pPixelShader->Release();
    if (g_pRenderTargetView) g_pRenderTargetView->Release();
    if (g_pSwapChain) g_pSwapChain->Release();
    if (g_pImmediateContext) g_pImmediateContext->Release();
    if (g_pd3dDevice) g_pd3dDevice->Release();
}

// Aktualizacja cząstek
void Update()
{
    static float t = 0.0f;
    static DWORD dwTimeStart = 0;
    DWORD dwTimeCur = GetTickCount();
    if (dwTimeStart == 0)
        dwTimeStart = dwTimeCur;
    t = (dwTimeCur - dwTimeStart) / 1000.0f;

    for (auto& particle : g_Particles)
    {
        particle.position.x += particle.velocity.x * 0.016f;
        particle.position.y += particle.velocity.y * 0.016f;
        particle.life -= 0.016f;

        if (particle.life <= 0.0f || particle.position.y > 600.0f)
        {
            particle.position = XMFLOAT3((float)(rand() % 800), 0.0f, 0.0f);
            particle.velocity = XMFLOAT3(0.0f, 50.0f + (float)(rand() % 50), 0.0f);
            particle.color = XMFLOAT4(0.0f, 0.5f + (float)(rand() % 50) / 100.0f, 0.0f, 1.0f);
            particle.size = 5.0f + (float)(rand() % 10);
            particle.life = 1.0f + (float)(rand() % 4);
        }
    }
}

// Renderowanie
void Render()
{
    // Czyszczenie widoku
    float ClearColor[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
    g_pImmediateContext->ClearRenderTargetView(g_pRenderTargetView, ClearColor);

    // Renderowanie cząstek (uproszczone)
    for (const auto& particle : g_Particles)
    {
        // Tu powinno być renderowanie każdej cząstki
    }

    // Prezentacja widoku
    g_pSwapChain->Present(0, 0);
}
Editor is loading...
Leave a Comment