The implementation of Ripples

1.you need to set your VC++ include directory to be correct

include:your directx sdk include foler

lib:the same root folder as the above does but choose the x86 version so you will run everything very smoothly

 

 

 2.what type of shader are we writting and how it is applied

Type:vertex shader which processes every single vertex data we have desined in our program,while in this program the vertices are all on the XZ panel.so the input is only one 2d vector and the output is the screen space coordinate and color inofrmation

 How it is applied:

first:get the resource file like we load a binary file into our program

second:compile it 

third:set it to the d3ddevice pointer before we rendering the object we want to be applied on.

that is all Too easy!

3.the formula of ripple:

 

 4.be careful about the vertex data you designed:

they must be symmetrical or you will not see a circle clearly

and of course you need to calculate the adj index array by your self. 

so the code is here:

#include <d3d9.h>
#include <d3dx9.h>
#include <tchar.h>
#include <time.h>
#include <dinput.h>
#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9.lib")
#pragma comment(lib, "dinput8.lib")
#pragma comment(lib, "dxguid.lib")
#pragma comment(lib, "winmm.lib")
#define WINDOW_WIDTH    1920
#define WINDOW_HEIGHT    1080
 #define WINDOW_TITLE    L"Demo"
 #define SAFE_RELEASE(p) { if (p) { (p)->Release(); (p) = NULL; } }
 #define VERTS_PER_EDGE 64 
LPDIRECT3DDEVICE9                    g_pd3dDevice = NULL;
 LPDIRECT3DVERTEXBUFFER9         g_pVB = NULL;
 LPDIRECT3DINDEXBUFFER9          g_pIB = NULL;
 DWORD                           g_dwNumVertices = VERTS_PER_EDGE * VERTS_PER_EDGE;
 DWORD                           g_dwNumIndices = 6 * (VERTS_PER_EDGE - 1) * (VERTS_PER_EDGE - 1);
 LPDIRECT3DVERTEXSHADER9         g_pVertexShader = NULL;
 LPD3DXCONSTANTTABLE             g_pConstantTable = NULL;
LPDIRECT3DVERTEXDECLARATION9    g_pVertexDeclaration = NULL;

 LPDIRECTINPUT8                g_pDirectInput = NULL; //
LPDIRECTINPUTDEVICE8    g_pMouseDevice = NULL;
DIMOUSESTATE                    g_diMouseState = { 0 }; 
LPDIRECTINPUTDEVICE8    g_pKeyboardDevice = NULL;
char                                    g_pKeyStateBuffer[256] = { 0 };
 WCHAR ShaderPath[512] = L"HLSLwithoutEffects.vsh";

D3DXMATRIX g_worldMat;


LRESULT CALLBACK    WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);//窗口过程函数
HRESULT                    Direct3D_Init(HWND hwnd, HINSTANCE hInstance);
 HRESULT                    Objects_Init(HWND hwnd);
 VOID                            Direct3D_Render(HWND hwnd);
VOID                            Direct3D_CleanUp();




int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
 {
    
             WNDCLASSEX wndClass = { 0 };
         wndClass.cbSize = sizeof(WNDCLASSEX);
         wndClass.style = CS_HREDRAW | CS_VREDRAW;
         wndClass.lpfnWndProc = WndProc;
         wndClass.cbClsExtra = 0;
         wndClass.cbWndExtra = 0;
         wndClass.hInstance = hInstance;
        wndClass.hIcon = (HICON)::LoadImage(NULL, L"icon.ico", IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_LOADFROMFILE);
         wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
         wndClass.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);
         wndClass.lpszMenuName = NULL;
         wndClass.lpszClassName = L"ForTheDreamOfGameDevelop";
        if (!RegisterClassEx(&wndClass))
                 return -1;
    
        
             HWND hwnd = CreateWindow(L"ForTheDreamOfGameDevelop", WINDOW_TITLE,
                     WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, WINDOW_WIDTH,
               WINDOW_HEIGHT, NULL, NULL, hInstance, NULL);
    
        
             if (!(S_OK == Direct3D_Init(hwnd, hInstance)))
             {
                 MessageBox(hwnd, _T("Direct3D初始化失败~!"), _T("浅墨的消息窗口"), 0);
            }
         MoveWindow(hwnd, 250, 80, WINDOW_WIDTH, WINDOW_HEIGHT, true);
         ShowWindow(hwnd, nShowCmd);
         UpdateWindow(hwnd);
    
             PlaySound(L"永遠の誓い.wav", NULL, SND_FILENAME | SND_ASYNC | SND_LOOP);
    
        
             MSG msg = { 0 };
         while (msg.message != WM_QUIT)
             {
                 if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
                     {
                         TranslateMessage(&msg);
                         DispatchMessage(&msg);
                     }
                 else
                     {
                        Direct3D_Render(hwnd);
                    }
             }
         //【6】窗口类的注销
             UnregisterClass(L"ForTheDreamOfGameDevelop", wndClass.hInstance);
         return 0;
     }
 LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 {
         switch (message)                        //switch语句开始
             {
         case WM_PAINT:                        // 若是客户区重绘消息
                 Direct3D_Render(hwnd);                 //调用Direct3D渲染函数
                 ValidateRect(hwnd, NULL);        // 更新客户区的显示
                 break;                                    //跳出该switch语句
        
         case WM_KEYDOWN:                    // 若是键盘按下消息
                 if (wParam == VK_ESCAPE)    // 如果被按下的键是ESC
                         DestroyWindow(hwnd);        // 销毁窗口, 并发送一条WM_DESTROY消息
                 break;                                    //跳出该switch语句
        
         case WM_DESTROY:                    //若是窗口销毁消息
                 Direct3D_CleanUp();            //调用自定义的资源清理函数Game_CleanUp()进行退出前的资源清理
                 PostQuitMessage(0);            //向系统表明有个线程有终止请求。用来响应WM_DESTROY消息
                 break;                                    //跳出该switch语句
        
         default:                                        //若上述case条件都不符合,则执行该default语句
                 return DefWindowProc(hwnd, message, wParam, lParam);        //调用缺省的窗口过程
             }
    
             return 0;                                    //正常退出
     }
 HRESULT Direct3D_Init(HWND hwnd, HINSTANCE hInstance)
 {
    
             LPDIRECT3D9  pD3D = NULL;
         if (NULL == (pD3D = Direct3DCreate9(D3D_SDK_VERSION)))
                 return E_FAIL;
    
        
             D3DCAPS9 caps; int vp = 0;
         if (FAILED(pD3D->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps)))
             {
             return E_FAIL;
             }
         if (caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
                 vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
         else
                 vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
    
        
             D3DPRESENT_PARAMETERS d3dpp;
         ZeroMemory(&d3dpp, sizeof(d3dpp));
         d3dpp.BackBufferWidth = WINDOW_WIDTH;
         d3dpp.BackBufferHeight = WINDOW_HEIGHT;
         d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
         d3dpp.BackBufferCount = 1;
         d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
         d3dpp.MultiSampleQuality = 0;
         d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
         d3dpp.hDeviceWindow = hwnd;
         d3dpp.Windowed = true;
         d3dpp.EnableAutoDepthStencil = true;
         d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
         d3dpp.Flags = 0;
         d3dpp.FullScreen_RefreshRateInHz = 0;
         d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
    
        
             if (FAILED(pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
                     hwnd, vp, &d3dpp, &g_pd3dDevice)))
                 return E_FAIL;
         DirectInput8Create(hInstance, 0x0800, IID_IDirectInput8, (void**)&g_pDirectInput, NULL);
         g_pDirectInput->CreateDevice(GUID_SysKeyboard, &g_pMouseDevice, NULL);
         g_pDirectInput->CreateDevice(GUID_SysMouse, &g_pMouseDevice, NULL);
         g_pMouseDevice->SetDataFormat(&c_dfDIMouse);
         g_pMouseDevice->SetCooperativeLevel(hwnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE);
         g_pMouseDevice->Acquire();
         DirectInput8Create(hInstance, 0x0800, IID_IDirectInput8, (void**)&g_pDirectInput, NULL);
         g_pDirectInput->CreateDevice(GUID_SysKeyboard, &g_pKeyboardDevice, NULL);
         g_pKeyboardDevice->SetDataFormat(&c_dfDIKeyboard);
         g_pKeyboardDevice->SetCooperativeLevel(hwnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE);
         g_pKeyboardDevice->Acquire();
    
        
        
        
        
        
             if (!(S_OK == Objects_Init(hwnd))) return E_FAIL;
         SAFE_RELEASE(pD3D)
        
             g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
         g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
    
        
        
             return S_OK;
    
        
         }

 BOOL Device_Read(IDirectInputDevice8 *pDIDevice, void* pBuffer, long lSize)
 {
         HRESULT hr;
         while (true)
             {
                 pDIDevice->Poll();              // 轮询设备
                 pDIDevice->Acquire();           // 获取设备的控制权
                 if (SUCCEEDED(hr = pDIDevice->GetDeviceState(lSize, pBuffer))) break;
                 if (hr != DIERR_INPUTLOST || hr != DIERR_NOTACQUIRED) return FALSE;
                 if (FAILED(pDIDevice->Acquire())) return FALSE;
             }
         return TRUE;
     }

 void UpdateworldMat()
 {
         D3DXMATRIX mat;
         // 获取键盘消息并给予设置相应的填充模式  
             if (g_pKeyStateBuffer[DIK_1] & 0x80)         // 若数字键1被按下,进行实体填充  
                 g_pd3dDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
         if (g_pKeyStateBuffer[DIK_2] & 0x80)         // 若数字键2被按下,进行线框填充  
                 g_pd3dDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
    
             // 读取鼠标输入
             ::ZeroMemory(&g_diMouseState, sizeof(g_diMouseState));
         Device_Read(g_pMouseDevice, (LPVOID)&g_diMouseState, sizeof(g_diMouseState));
    
             // 读取键盘输入
             ::ZeroMemory(g_pKeyStateBuffer, sizeof(g_pKeyStateBuffer));
         Device_Read(g_pKeyboardDevice, (LPVOID)g_pKeyStateBuffer, sizeof(g_pKeyStateBuffer));
    
        
             // 按住鼠标左键并拖动,为平移操作
             static FLOAT fPosX = 0.0f, fPosY = 30.0f, fPosZ = 0.0f;
         if (g_diMouseState.rgbButtons[0] & 0x80)
             {
                 fPosX += g_diMouseState.lX *  0.08f;
                 fPosY += g_diMouseState.lY * -0.08f;
             }
    
             //鼠标滚轮,为观察点收缩操作
             fPosZ += g_diMouseState.lZ * 0.02f;
    
             // 平移物体
             if (g_pKeyStateBuffer[DIK_A] & 0x80) fPosX -= 0.005f;
         if (g_pKeyStateBuffer[DIK_D] & 0x80) fPosX += 0.005f;
         if (g_pKeyStateBuffer[DIK_W] & 0x80) fPosY += 0.005f;
         if (g_pKeyStateBuffer[DIK_S] & 0x80) fPosY -= 0.005f;
    
        
             D3DXMatrixTranslation(&mat, fPosX, fPosY, fPosZ);
    
        
             // 按住鼠标右键并拖动,为旋转操作
             static float fAngleX = 0.15f, fAngleY = -(float)D3DX_PI;
         if (g_diMouseState.rgbButtons[1] & 0x80)
             {
                 fAngleX += g_diMouseState.lY * -0.01f;
                 fAngleY += g_diMouseState.lX * -0.01f;
             }
         // 旋转物体
             if (g_pKeyStateBuffer[DIK_UP] & 0x80) fAngleX += 0.005f;
         if (g_pKeyStateBuffer[DIK_DOWN] & 0x80) fAngleX -= 0.005f;
         if (g_pKeyStateBuffer[DIK_LEFT] & 0x80) fAngleY -= 0.005f;
         if (g_pKeyStateBuffer[DIK_RIGHT] & 0x80) fAngleY += 0.005f;
    
        
             D3DXMATRIX Rx, Ry;
         D3DXMatrixRotationX(&Rx, fAngleX);
         D3DXMatrixRotationY(&Ry, fAngleY);
             
           g_worldMat = Rx * Ry * mat;
         g_pd3dDevice->SetTransform(D3DTS_WORLD, &g_worldMat);//设置世界矩阵
     }


 HRESULT Objects_Init(HWND hwnd)
 {
         WORD* pIndices;
    
             g_pd3dDevice->CreateIndexBuffer(g_dwNumIndices * sizeof(WORD),
                     0, D3DFMT_INDEX16,
                     D3DPOOL_DEFAULT, &g_pIB, NULL);
    
        
             g_pIB->Lock(0, 0, (void**)&pIndices, 0);
    
        
             DWORD y;
         for (y = 1; y < VERTS_PER_EDGE; y++)
             {
                 for (DWORD x = 1; x < VERTS_PER_EDGE; x++)
                     {
             * pIndices++ = (WORD)((y - 1) * VERTS_PER_EDGE + (x - 1));
             * pIndices++ = (WORD)((y - 0) * VERTS_PER_EDGE + (x - 1));
             * pIndices++ = (WORD)((y - 1) * VERTS_PER_EDGE + (x - 0));
            
                 * pIndices++ = (WORD)((y - 1) * VERTS_PER_EDGE + (x - 0));
             * pIndices++ = (WORD)((y - 0) * VERTS_PER_EDGE + (x - 1));
             * pIndices++ = (WORD)((y - 0) * VERTS_PER_EDGE + (x - 0));
                     }
             }
    
             g_pIB->Unlock();
    
             // Create and initialize vertex buffer
             g_pd3dDevice->CreateVertexBuffer(g_dwNumVertices * sizeof(D3DXVECTOR2),
                         0, 0,
                          D3DPOOL_DEFAULT, &g_pVB, NULL);
    
             D3DXVECTOR2* pVertices;
         g_pVB->Lock(0, 0, (void**)&pVertices, 0);
    
             for (y = 0; y < VERTS_PER_EDGE; y++)
             {
                 for (DWORD x = 0; x < VERTS_PER_EDGE; x++)
                     {
             * pVertices++ = D3DXVECTOR2(((float)x / (float)(VERTS_PER_EDGE - 1) - 0.5f)*D3DX_PI,
                                 ((float)y / (float)(VERTS_PER_EDGE - 1) - 0.5f)*D3DX_PI);
            
                         }
             }
    
             g_pVB->Unlock();
    
        
        
        
        
             LPD3DXBUFFER pCode;
    
             D3DVERTEXELEMENT9 decl[] =
             {
                 { 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
                     D3DDECL_END()
                 };
    
             g_pd3dDevice->CreateVertexDeclaration(decl, &g_pVertexDeclaration);
    
        
        
             DWORD dwShaderFlags = 0;
     #if defined(DEBUG) || defined(_DEBUG)
             dwShaderFlags |= D3DXSHADER_DEBUG;
     #endif
        
         #ifdef DEBUG_VS
             dwShaderFlags |= D3DXSHADER_SKIPOPTIMIZATION | D3DXSHADER_DEBUG;
     #endif
         #ifdef DEBUG_PS
             dwShaderFlags |= D3DXSHADER_SKIPOPTIMIZATION | D3DXSHADER_DEBUG;
     #endif
        
             D3DXCompileShaderFromFile(ShaderPath, NULL, NULL, "Ripple",
                     "vs_2_0", dwShaderFlags, &pCode,
                     NULL, &g_pConstantTable);
         if (FAILED(g_pd3dDevice->CreateVertexShader((DWORD*)pCode->GetBufferPointer(),
         & g_pVertexShader)))
             {
                 MessageBox(hwnd, L"Shader Compilation Fialed!", L"Shader", 0);
             }
         pCode->Release();
    
        
        
        
           return S_OK;
     }
 D3DXMATRIX SetCamera(D3DXVECTOR3 EyeLoc, D3DXVECTOR3 LookAt, D3DXVECTOR3 Up)
 {
         //Set the camera setting
             D3DXMATRIX matView; //定义一个矩阵
         D3DXMatrixLookAtLH(&matView, &EyeLoc, &LookAt, &Up); //计算出取景变换矩阵
         g_pd3dDevice->SetTransform(D3DTS_VIEW, &matView); //应用取景变换矩阵
         return matView;
     }

 D3DXMATRIX SetProjection()
 {
         //Projection setting
             D3DXMATRIX matProj; //定义一个矩阵
         D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI / 4.0f, 1.0f, 1.0f, 1000.0f); //计算投影变换矩阵
         g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &matProj);  //设置投影变换矩阵
         return matProj;
     }
 VOID SetViewPort(DWORD X, DWORD Y, DWORD Width, DWORD Height, float MinZ = 0.0f, float MaxZ = 1.0f)
 {
         D3DVIEWPORT9 vp;
         vp.X = X;
         vp.Y = Y;
         vp.Width = Width;
         vp.Height = Height;
         vp.MinZ = MinZ;
         vp.MaxZ = MaxZ;
         g_pd3dDevice->SetViewport(&vp);
    
         }
 VOID Draw(D3DVIEWPORT9 vp)
 {
         SetViewPort(vp.X, vp.Y, vp.Width, vp.Height);
         g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(255, 214, 158), 1.0f, 0);
         if (SUCCEEDED(g_pd3dDevice->BeginScene()))
             {
                 g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, g_dwNumVertices,
                         0, g_dwNumIndices / 3);
        
                     g_pd3dDevice->EndScene();
        
                 }
     }
 void Direct3D_Render(HWND hwnd)
 {
    
        
             if (::GetAsyncKeyState(0x31) & 0x8000f)
                 g_pd3dDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
        if (::GetAsyncKeyState(0x32) & 0x8000f)
                 g_pd3dDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
    
        
             D3DXMATRIX View = SetCamera(D3DXVECTOR3(0, 20, 0), D3DXVECTOR3(g_worldMat._41, g_worldMat._42, g_worldMat._43), D3DXVECTOR3(0, 0, 1));
         D3DXMATRIX Proj = SetProjection();
         UpdateworldMat();
         D3DXMATRIX mWorldViewProj = g_worldMat * View*Proj;
         g_pConstantTable->SetMatrix(g_pd3dDevice, "mWorldViewProj", &mWorldViewProj);
         g_pConstantTable->SetFloat(g_pd3dDevice, "fTime", ::timeGetTime() / 1000.0f / 2);
    
        
             g_pd3dDevice->SetVertexDeclaration(g_pVertexDeclaration);
         g_pd3dDevice->SetVertexShader(g_pVertexShader);
         g_pd3dDevice->SetStreamSource(0, g_pVB, 0, sizeof(D3DXVECTOR2));
         g_pd3dDevice->SetIndices(g_pIB);
    
        
             D3DVIEWPORT9 vp1;
         vp1.X = 0;
         vp1.Y = 0;
         vp1.Width = WINDOW_WIDTH;
         vp1.Height = WINDOW_HEIGHT;
         vp1.MinZ = 0.0f;
         vp1.MaxZ = 1.0f;
    
        
        
        
        
             Draw(vp1);
    
        
        
        
        
        
        
             g_pd3dDevice->Present(NULL, NULL, NULL, NULL);
     }
 void Direct3D_CleanUp()
 {
         SAFE_RELEASE(g_pVB)
             SAFE_RELEASE(g_pIB)
             SAFE_RELEASE(g_pd3dDevice)
             SAFE_RELEASE(g_pVertexDeclaration)
             SAFE_RELEASE(g_pVertexShader);
         SAFE_RELEASE(g_pConstantTable);
     }

 

 

 you can tweak the code to see more effects.

enjoy it!

 

posted @ 2020-09-04 17:53  Tonarinototoro  阅读(144)  评论(0编辑  收藏  举报