Microsoft Visual 2017 Community C++ Direct3D 11.0( SM 5.0 ) DirectXTex texture processing library XMLLite DirectXMath |
■Direct3D11 Gerstner Waves | Prev Top Next |
関連ページ:Direct3D11 自作ライブラリ |
Aシェーダー系で使用するソースです。
GerstnerWaves_Pass0.hlsl | ジオメトリレベルで波を生成するシェーダーソース |
GerstnerWaves.h | GerstnerWavesクラスのヘッダーファイル |
GerstnerWaves.cpp | GerstnerWavesクラスのソースファイル |
B個別に使用するソースです。
PlaneMesh.h | 地面メッシュクラスのヘッダーファイル |
PlaneMesh.cpp | 地面メッシュクラスのソースファイル |
main.cpp | main関数のソースファイル |
// ************************************************************ // Gerstner Waves // ************************************************************ // 定数バッファ cbuffer cbBuffer_hull : register( b0 ) { float g_fTessFactor : packoffset( c0.x ); // パッチのエッジのテッセレーション係数 float g_fInsideTessFactor : packoffset( c0.y ); // パッチ内部のテッセレーション係数 }; cbuffer cbBuffer_domain : register( b1 ) { column_major float4x4 g_matCameraWorldViewProj : packoffset( c0 ); // カメラビューでのワールドとビューと射影行列 float4 g_vecWaveGeneratePosition[2] : packoffset( c4 ); // xyz:波の生成座標 float4 g_vecWaveParameters[2] : packoffset( c6 ); // x:振幅、y:波長、z:角度 }; cbuffer cbBuffer_pixel : register( b2 ) { float4 g_vecLightPos : packoffset( c0 ); // ローカル座標系での平行光源の位置ベクトル }; // 頂点シェーダーの入力パラメータ struct VS_IN { float3 pos : POSITION; float3 normal : NORMAL; float2 texel : TEXCOORD; }; // 頂点シェーダーの出力パラメータ struct VS_OUT_HS_IN { float3 pos : POSITION; float3 normal : NORMAL; float2 texel : TEXCOORD0; }; // ハルシェーダーのパッチ定数フェーズ用の出力パラメータ struct CONSTANT_HS_OUT_DS_IN { float Edges[3] : SV_TessFactor; // パッチのエッジのテッセレーション係数 float Inside : SV_InsideTessFactor; // パッチ内部のテッセレーション係数 }; // ハルシェーダーのコントロール ポイント フェーズ用の出力パラメータ struct CONTROL_HS_OUT_DS_IN { float3 pos : POSITION; float3 normal : NORMAL; float2 texel : TEXCOORD0; }; // ドメインシェーダーの出力パラメータ struct DS_OUT_PS_IN { float4 pos : SV_POSITION; float3 normal : NORMAL; float2 texel : TEXCOORD0; }; // テクスチャー Texture2D g_Tex : register( t0 ); // サンプラーステート SamplerState g_Sampler; // ***************************************************************************************** // 頂点シェーダー // ***************************************************************************************** VS_OUT_HS_IN GerstnerWaves_Pass0_VS_Main( VS_IN In ) { VS_OUT_HS_IN Out; Out.pos = In.pos; Out.normal = In.normal; Out.texel = In.texel; return Out; } // ***************************************************************************************** // ハルシェーダーのパッチ定数フェーズ // ***************************************************************************************** CONSTANT_HS_OUT_DS_IN GerstnerWaves_Pass0_ConstantHS( InputPatch<VS_OUT_HS_IN, 3> ip, uint PatchID : SV_PrimitiveID ) { CONSTANT_HS_OUT_DS_IN Out; Out.Edges[0] = Out.Edges[1] = Out.Edges[2] = g_fTessFactor; // パッチのエッジのテッセレーション係数 Out.Inside = g_fInsideTessFactor; // パッチ内部のテッセレーション係数 return Out; } // ***************************************************************************************** // ハルシェーダーのコントロール ポイント フェーズ // ***************************************************************************************** [domain("tri")] // テッセレートするメッシュの形状を指定する [partitioning("integer")] // パッチの分割に使用するアルゴリズムを指定する [outputtopology("triangle_ccw")] // メッシュの出力方法を指定する [outputcontrolpoints(3)] // ハルシェーダーのコントロール ポイント フェーズがコールされる回数 [patchconstantfunc("GerstnerWaves_Pass0_ConstantHS")] // 対応するハルシェーダーのパッチ定数フェーズのメイン関数 CONTROL_HS_OUT_DS_IN GerstnerWaves_Pass0_HS_Main( InputPatch<VS_OUT_HS_IN, 3> In, uint i : SV_OutputControlPointID, uint PatchID : SV_PrimitiveID ) { CONTROL_HS_OUT_DS_IN Out; Out.pos = In[i].pos; Out.normal = In[i].normal; Out.texel = In[i].texel; return Out; } // 波の高さを計算 float getHeight( float3 waveGeneratePos // 波の生成座標 , float3 localPos // 頂点座標 , float amplitude // 振幅 , float wavelength // 波長 , float angle // 角度 ) { float len = length( waveGeneratePos - localPos ); return amplitude * sin( len / wavelength + angle ); } // ***************************************************************************************** // ドメインシェーダー // ***************************************************************************************** [domain("tri")] DS_OUT_PS_IN GerstnerWaves_Pass0_DS_Main( CONSTANT_HS_OUT_DS_IN In, float3 uvw : SV_DomainLocation, const OutputPatch<CONTROL_HS_OUT_DS_IN, 3> patch ) { DS_OUT_PS_IN Out; float aroundh[4] = { 0, 0, 0, 0 }; float offset = 1.0f; // 適当に設定 float dx, dz, totalh = 0.0f; // 頂点座標 float3 p = patch[2].pos * uvw.x + patch[1].pos * uvw.y + patch[0].pos * uvw.z; for( int i=0; i<2; i++ ) { // 頂点と波の生成座標の距離 float len = length( g_vecWaveGeneratePosition[i].xyz - p ); // トロコイドの動円上の描画点の角度 float a = len / g_vecWaveParameters[i].y + g_vecWaveParameters[i].z; // 波の高さを計算 totalh += getHeight( g_vecWaveGeneratePosition[i].xyz, p, g_vecWaveParameters[i].x, g_vecWaveParameters[i].y, g_vecWaveParameters[i].z ); // x座標 p.x += dot( float3( -1, 0, 0 ), normalize( g_vecWaveGeneratePosition[i].xyz - p ) ) * g_vecWaveParameters[i].x * cos( a ); // y座標 p.z += dot( float3( 0, 0, -1 ), normalize( g_vecWaveGeneratePosition[i].xyz - p ) ) * g_vecWaveParameters[i].x * cos( a ); // 高さを合計する aroundh[0] += getHeight( g_vecWaveGeneratePosition[i].xyz, p + float3( offset, 0, 0.0f ), g_vecWaveParameters[i].x, g_vecWaveParameters[i].y, g_vecWaveParameters[i].z ); aroundh[1] += getHeight( g_vecWaveGeneratePosition[i].xyz, p + float3( 0.0f, 0, -offset ), g_vecWaveParameters[i].x, g_vecWaveParameters[i].y, g_vecWaveParameters[i].z ); aroundh[2] += getHeight( g_vecWaveGeneratePosition[i].xyz, p + float3( -offset, 0, 0.0f ), g_vecWaveParameters[i].x, g_vecWaveParameters[i].y, g_vecWaveParameters[i].z ); aroundh[3] += getHeight( g_vecWaveGeneratePosition[i].xyz, p + float3( 0.0f, 0, offset ), g_vecWaveParameters[i].x, g_vecWaveParameters[i].y, g_vecWaveParameters[i].z ); } p.y += totalh; // 行列変換後の頂点座標 Out.pos = mul( float4( p, 1.0f ), g_matCameraWorldViewProj ); // 高さの差を計算 dx = aroundh[2] - aroundh[0]; dz = aroundh[1] - aroundh[3]; // 法線ベクトル( yは適当に調整 ) Out.normal = float3( dx, 0.2f, dz ); // テクセル Out.texel = patch[2].texel * uvw.x + patch[1].texel * uvw.y + patch[0].texel * uvw.z; return Out; } // ***************************************************************************************** // ピクセルシェーダ // ***************************************************************************************** float4 GerstnerWaves_Pass0_PS_Main( DS_OUT_PS_IN In ) : SV_TARGET { // ハーフランバート float lambert = dot( g_vecLightPos.xyz, In.normal ); lambert = lambert * 0.5f + 0.5f; // return float4( In.normal.zzz * 0.5f + 0.5f, 1 ); return g_Tex.Sample( g_Sampler, In.texel ).bgra * lambert; }
#pragma once #include "../Common/UCommon.h" #include "../Common/UException.h" #include "../Common/UGraphicsPipeline.h" #include "../Common/UDirect3D11.h" class GerstnerWaves { private: // ハルシェーダー用 定数バッファ構造体 typedef struct _CBUFFER_HS { float fTessFactor; float fInsideTessFactor; float Dummy2; float Dummy3; }CBUFFER_HS; // ドメインシェーダー用 定数バッファ構造体 typedef struct _CBUFFER_DS { XMMATRIX matCameraWorldViewProj; // 波の生成位置 XMFLOAT4 vecWaveGeneratePosition[2]; // 0:振幅、1:波長、2:角度 XMFLOAT4 vecWaveParameters[2]; }CBUFFER_DS; // ピクセルシェーダー用 定数バッファ構造体 typedef struct _CBUFFER_PS { // 平行光源の位置ベクトル XMFLOAT4 vecLightPos; }CBUFFER_PS; public: typedef struct _WAVE { XMFLOAT4 vecWaveGeneratePosition; // 波の生成座標 float fAmplitude; // 振幅 float fWavelength; // 波長 float fAngle; // 角度 float fAngularVelocity; // 角速度 }WAVE; private: WAVE m_pWave[2]; // シェーダー用定数バッファ ID3D11Buffer* m_pConstantBuffers[3]; UGraphicsPipeline* m_pGraphicsPipeline[1]; int m_Pass; XMMATRIX m_MatCameraView, m_MatCameraProj; XMFLOAT4 m_VecLightPos; D3D11_FILL_MODE m_FillMode; public: GerstnerWaves(); virtual ~GerstnerWaves(); void Invalidate(); void Create(ID3D11Device* pD3DDevice, WAVE pWave[2]); void Begin(ID3D11Device* pD3DDevice, XMFLOAT4* pVecLightPos, XMMATRIX* pMatCameraView, XMMATRIX* pMatCameraProj, D3D11_FILL_MODE FillMode = D3D11_FILL_SOLID); void BeginPass(ID3D11DeviceContext* pD3DDeviceContext, UINT Pass); void SetConstantBuffers(ID3D11DeviceContext* pD3DDeviceContext, XMMATRIX* pMatWorld, float fTessFactor, float fInsideTessFactor); void EndPass(ID3D11DeviceContext* pD3DDeviceContext); void End(); inline UINT GetMaxPass(){ return 1; }; };
#include "../../Header/Shader/GerstnerWaves.h" #include "../../HLSL/GerstnerWaves_Pass0_VS_Main.h" #include "../../HLSL/GerstnerWaves_Pass0_HS_Main.h" #include "../../HLSL/GerstnerWaves_Pass0_DS_Main.h" #include "../../HLSL/GerstnerWaves_Pass0_PS_Main.h" GerstnerWaves::GerstnerWaves() { for (int i = 0; i<_countof(m_pGraphicsPipeline); i++) { m_pGraphicsPipeline[i] = nullptr; } for (int i = 0; i<_countof(m_pConstantBuffers); i++) { m_pConstantBuffers[i] = nullptr; } m_FillMode = D3D11_FILL_MODE::D3D11_FILL_SOLID; m_Pass = -2; } GerstnerWaves::~GerstnerWaves() { for (int i = 0; i < _countof(m_pGraphicsPipeline); i++) { SAFE_DELETE(m_pGraphicsPipeline[i]); } for (int i = 0; i < _countof(m_pConstantBuffers); i++) { SAFE_RELEASE(m_pConstantBuffers[i]); } } void GerstnerWaves::Create(ID3D11Device* pD3DDevice, WAVE pWave[2]) { m_FillMode = D3D11_FILL_MODE::D3D11_FILL_SOLID; ::CopyMemory(m_pWave, pWave, sizeof(m_pWave)); m_Pass = -2; // ******************************************************************************************************* // UGraphicsPipelineの作成 // ******************************************************************************************************* m_pGraphicsPipeline[0] = NEW UGraphicsPipeline(); // ラスタライザーステートを作成する m_pGraphicsPipeline[0]->CreateRasterizerState(pD3DDevice, D3D11_CULL_MODE::D3D11_CULL_BACK, m_FillMode); // 深度ステンシルステートを作成する m_pGraphicsPipeline[0]->CreateDepthStencilState(pD3DDevice, TRUE, D3D11_DEPTH_WRITE_MASK::D3D11_DEPTH_WRITE_MASK_ALL); // ブレンドステートを作成する UGraphicsPipeline::UEBLEND_STATE BlendStateType[1] = { UGraphicsPipeline::UEBLEND_STATE::NONE }; m_pGraphicsPipeline[0]->CreateBlendState(pD3DDevice, BlendStateType, 1); D3D11_INPUT_ELEMENT_DESC layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; // シェーダーを作成する #if defined(DEBUG) || defined(_DEBUG) m_pGraphicsPipeline[0]->CreateVertexShaderFromFile(pD3DDevice, _T("../HLSL/GerstnerWaves_Pass0.hlsl"), "GerstnerWaves_Pass0_VS_Main", layout, _countof(layout)); m_pGraphicsPipeline[0]->CreateHullShaderFromFile(pD3DDevice, _T("../HLSL/GerstnerWaves_Pass0.hlsl"), "GerstnerWaves_Pass0_HS_Main"); m_pGraphicsPipeline[0]->CreateDomainShaderFromFile(pD3DDevice, _T("../HLSL/GerstnerWaves_Pass0.hlsl"), "GerstnerWaves_Pass0_DS_Main"); m_pGraphicsPipeline[0]->CreatePixelShaderFromFile(pD3DDevice, _T("../HLSL/GerstnerWaves_Pass0.hlsl"), "GerstnerWaves_Pass0_PS_Main"); #else m_pGraphicsPipeline[0]->CreateVertexShaderFromMemory(pD3DDevice, (LPBYTE)g_GerstnerWaves_Pass0_VS_Main, sizeof(g_GerstnerWaves_Pass0_VS_Main), layout, _countof(layout)); m_pGraphicsPipeline[0]->CreateHullShaderFromMemory(pD3DDevice, (LPBYTE)g_GerstnerWaves_Pass0_HS_Main, sizeof(g_GerstnerWaves_Pass0_HS_Main)); m_pGraphicsPipeline[0]->CreateDomainShaderFromMemory(pD3DDevice, (LPBYTE)g_GerstnerWaves_Pass0_DS_Main, sizeof(g_GerstnerWaves_Pass0_DS_Main)); m_pGraphicsPipeline[0]->CreatePixelShaderFromMemory(pD3DDevice, (LPBYTE)g_GerstnerWaves_Pass0_PS_Main, sizeof(g_GerstnerWaves_Pass0_PS_Main)); #endif // 定数バッファを作成する m_pConstantBuffers[0] = m_pGraphicsPipeline[0]->CreateConstantBuffer(pD3DDevice, nullptr, sizeof(GerstnerWaves::CBUFFER_HS), D3D11_CPU_ACCESS_WRITE); m_pConstantBuffers[1] = m_pGraphicsPipeline[0]->CreateConstantBuffer(pD3DDevice, nullptr, sizeof(GerstnerWaves::CBUFFER_DS), D3D11_CPU_ACCESS_WRITE); m_pConstantBuffers[2] = m_pGraphicsPipeline[0]->CreateConstantBuffer(pD3DDevice, nullptr, sizeof(GerstnerWaves::CBUFFER_PS), D3D11_CPU_ACCESS_WRITE); } void GerstnerWaves::Begin(ID3D11Device* pD3DDevice, XMFLOAT4* pVecLightPos, XMMATRIX* pMatCameraView, XMMATRIX* pMatCameraProj, D3D11_FILL_MODE FillMode) { if (m_Pass != -2) { throw(UException(-1, _T("GerstnerWaves::Begin()はCreate()またはEnd()実行後に使用してください"))); } if (FillMode != m_FillMode) { m_FillMode = FillMode; m_pGraphicsPipeline[0]->CreateRasterizerState(pD3DDevice, D3D11_CULL_MODE::D3D11_CULL_BACK, m_FillMode); } m_VecLightPos = *pVecLightPos; m_MatCameraView = *pMatCameraView; m_MatCameraProj = *pMatCameraProj; // 波のアニメーション for (int i = 0; i < _countof(m_pWave); i++) { m_pWave[i].fAngle += m_pWave[i].fAngularVelocity; if (m_pWave[i].fAngle > XM_2PI) m_pWave[i].fAngle -= XM_2PI; } m_Pass = -1; } void GerstnerWaves::BeginPass(ID3D11DeviceContext* pD3DDeviceContext, UINT Pass) { if (m_Pass != -1) { throw(UException(-1, _T("GerstnerWaves::BeginPass()はCreate()またはEndPass()実行後に使用してください"))); } m_Pass = (int)Pass; switch (m_Pass) { case 0: { } break; default: throw(UException(-1, _T("GerstnerWaves::BeginPass()で無効なPassが指定されました"))); } // 各種ステートを設定する m_pGraphicsPipeline[0]->SetRasterizerState(pD3DDeviceContext); m_pGraphicsPipeline[0]->SetDepthStencilState(pD3DDeviceContext); m_pGraphicsPipeline[0]->SetBlendState(pD3DDeviceContext); // 各種グラフィックパイプラインを設定 m_pGraphicsPipeline[m_Pass]->SetVertexShader(pD3DDeviceContext); m_pGraphicsPipeline[m_Pass]->SetHullShader(pD3DDeviceContext); m_pGraphicsPipeline[m_Pass]->SetDomainShader(pD3DDeviceContext); m_pGraphicsPipeline[m_Pass]->SetGeometryShader(pD3DDeviceContext); m_pGraphicsPipeline[m_Pass]->SetPixelShader(pD3DDeviceContext); } void GerstnerWaves::SetConstantBuffers(ID3D11DeviceContext* pD3DDeviceContext, XMMATRIX* pMatWorld, float fTessFactor, float fInsideTessFactor) { HRESULT hr = E_FAIL; if (m_Pass == -1) { throw(UException(-1, _T("GerstnerWaves::SetConstantBuffers()はBeginPass()実行後に使用してください"))); } switch (m_Pass) { case 0: { XMMATRIX matCameraWorldViewProj = XMMatrixTranspose(*pMatWorld * m_MatCameraView * m_MatCameraProj); // 平行光源の位置ベクトルをローカル座標系に変換 XMMATRIX matInv = XMMatrixInverse(nullptr, *pMatWorld); XMVECTOR v = XMVector4Transform(XMLoadFloat4(&m_VecLightPos), matInv); XMVECTOR nv = XMVector3Normalize(v); XMFLOAT4 localLightPos; XMStoreFloat4(&localLightPos, nv); // 定数バッファを作成する D3D11_MAPPED_SUBRESOURCE mappedResource; // ハルシェーダー用定数バッファ if (FAILED(hr = pD3DDeviceContext->Map(m_pConstantBuffers[0], 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource))) { throw(UException(-1, _T("GerstnerWaves::SetConstantBuffers()でエラーが発生しました。Map()が失敗しました。"))); } GerstnerWaves::CBUFFER_HS* cbuffer_hs = (GerstnerWaves::CBUFFER_HS*)mappedResource.pData; cbuffer_hs->fTessFactor = fTessFactor; cbuffer_hs->fInsideTessFactor = fInsideTessFactor; pD3DDeviceContext->Unmap(m_pConstantBuffers[0], 0); // ドメインシェーダー用定数バッファ if (FAILED(hr = pD3DDeviceContext->Map(m_pConstantBuffers[1], 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource))) { throw(UException(-1, _T("GerstnerWaves::SetConstantBuffers()でエラーが発生しました。Map()が失敗しました。"))); } GerstnerWaves::CBUFFER_DS* cbuffer_ds = (GerstnerWaves::CBUFFER_DS*)mappedResource.pData; ::CopyMemory(&cbuffer_ds->matCameraWorldViewProj, &matCameraWorldViewProj, sizeof(XMMATRIX)); for (int i = 0; i < _countof(m_pWave); i++) { ::CopyMemory(&cbuffer_ds->vecWaveGeneratePosition[i], &m_pWave[i].vecWaveGeneratePosition, sizeof(XMFLOAT4)); cbuffer_ds->vecWaveParameters[i].x = m_pWave[i].fAmplitude; cbuffer_ds->vecWaveParameters[i].y = m_pWave[i].fWavelength; cbuffer_ds->vecWaveParameters[i].z = m_pWave[i].fAngle; } pD3DDeviceContext->Unmap(m_pConstantBuffers[1], 0); // ピクセルシェーダー用定数バッファ if (FAILED(hr = pD3DDeviceContext->Map(m_pConstantBuffers[2], 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource))) { throw(UException(-1, _T("GerstnerWaves::SetConstantBuffers()でエラーが発生しました。Map()が失敗しました。"))); } GerstnerWaves::CBUFFER_PS* cbuffer_ps = (GerstnerWaves::CBUFFER_PS*)mappedResource.pData; ::CopyMemory(&cbuffer_ps->vecLightPos, &localLightPos, sizeof(XMFLOAT4)); pD3DDeviceContext->Unmap(m_pConstantBuffers[2], 0); // 定数バッファを設定 pD3DDeviceContext->HSSetConstantBuffers(0, 1, &m_pConstantBuffers[0]); pD3DDeviceContext->DSSetConstantBuffers(1, 1, &m_pConstantBuffers[1]); pD3DDeviceContext->PSSetConstantBuffers(2, 1, &m_pConstantBuffers[2]); } break; } } void GerstnerWaves::EndPass(ID3D11DeviceContext*) { switch (m_Pass) { case 0: break; } m_Pass = -1; } void GerstnerWaves::End() { m_Pass = -2; }
#include "../Header/Common/UCommon.h" #include "../Header/Common/UException.h" #include "../Header/Common/UDirect3D11.h" #include "../Header/Shader/GerstnerWaves.h" #include "../Header/Common/UDebugFont.h" #include "../Header/Mesh/PlaneMesh.h" // アプリケーション名 TCHAR* AppName = _T("Direct3D11 Gerstner Waves"); // Direct3D関連の自作クラス UDirect3D11* g_pDirect3D11 = nullptr; GerstnerWaves* g_pEffectiveWaterSimulation = nullptr; PlaneMesh* g_pPlaneMesh = nullptr; UDebugFont* g_pDebugFont = nullptr; UFPS* g_pFPS = nullptr; DWORD g_Width = 640, g_Height = 480; float g_CameraZFar = 2000.0f, g_CameraZNear = 10.0f; // カメラビュー行列 XMMATRIX g_MatCameraView = XMMatrixIdentity(); // カメラビュー射影行列 XMMATRIX g_MatCameraProj = XMMatrixPerspectiveFovLH(XM_PI / 5.0f, (float)g_Width / (float)g_Height, g_CameraZNear, g_CameraZFar); // 平行光源の位置ベクトル XMFLOAT4 g_VecLightPos = XMFLOAT4(200.0f, 200.0f, 300.0f, 0); D3D11_FILL_MODE g_FillMode = D3D11_FILL_SOLID; float g_fTessFactor = 20.0f; // メモリ解放 void Invalidate() { SAFE_DELETE(g_pFPS); SAFE_DELETE(g_pDebugFont); SAFE_DELETE(g_pEffectiveWaterSimulation); SAFE_DELETE(g_pPlaneMesh); SAFE_DELETE(g_pDirect3D11); } // ウィンドウプロシージャ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, UINT wParam, LONG lParam) { switch (msg) { case WM_KEYUP: // アプリ終了 if (wParam == VK_ESCAPE) ::DestroyWindow(hWnd); else if (wParam == 'M') { if (g_FillMode == D3D11_FILL_SOLID) g_FillMode = D3D11_FILL_WIREFRAME; else g_FillMode = D3D11_FILL_SOLID; } break; case WM_DESTROY: ::PostQuitMessage(0); break; default: return ::DefWindowProc(hWnd, msg, wParam, lParam); } return 0L; } // Direct3Dの作成 void CreateDirect3D(HINSTANCE hInstance) { DXGI_MODE_DESC* pModeDescArray = nullptr; __try { DXGI_MODE_DESC ModeDesc; UINT num; // ディスプレイモード一覧の数を取得する g_pDirect3D11->GetDisplayMode(nullptr, &num); pModeDescArray = NEW DXGI_MODE_DESC[num]; // ディスプレイモード一覧を取得する g_pDirect3D11->GetDisplayMode(pModeDescArray, &num); bool find = false; for (UINT i = 0; i<num; i++) { // 適切な解像度のディスプレイモードを検索する if (pModeDescArray[i].Width == g_Width && pModeDescArray[i].Height == g_Height) { find = true; ::CopyMemory(&ModeDesc, &pModeDescArray[i], sizeof(DXGI_MODE_DESC)); break; } } if (find == false) throw(UException(-1, _T("InitDirect3D()でエラーが発生しました。適切なディスプレイモードの解像度を取得できません。"))); // ウィンドウの作成およびDirect3D の作成 g_pDirect3D11->CreateDirect3D11(AppName, hInstance, WndProc, &ModeDesc, TRUE, TRUE); g_pDebugFont->CreateMesh(g_pDirect3D11->m_pD3DDevice, 0.03f, 0.08f); // FPS描画クラス g_pFPS->CreateMesh(g_pDirect3D11->m_pD3DDevice); } __finally { SAFE_DELETE_ARRAY(pModeDescArray); } } void CreateGraphicePipeline() { GerstnerWaves::WAVE wave[2]; wave[0].vecWaveGeneratePosition = XMFLOAT4(3200.0f, 0.0f, 200.0f, 0); wave[0].fAmplitude = 30.0f; // 振幅 wave[0].fWavelength = 60.0f; // 波長 wave[0].fAngularVelocity = -0.001f; // 角速度 wave[0].fAngle = 0.0f; // 角度 wave[1].vecWaveGeneratePosition = XMFLOAT4(-200.0f, 0.0f, 3000.0f, 0); wave[1].fAmplitude = 20.0f; wave[1].fWavelength = 70.0f; wave[1].fAngularVelocity = -0.002f; wave[1].fAngle = 0.0f; g_pEffectiveWaterSimulation->Create(g_pDirect3D11->m_pD3DDevice, wave); } // メッシュを作成する void CreateMesh() { g_pPlaneMesh = NEW PlaneMesh(); g_pPlaneMesh->CreateMesh(g_pDirect3D11->m_pD3DDevice, 5, 5); } void CreateResource(HINSTANCE hInstance) { // Direct3D 関連自作クラスのインスタンスを作成 // CreateDirect3D()関数内でインスタンスの作成を行うと、C2712 エラーが発生するのでここで行う。 g_pDirect3D11 = NEW UDirect3D11(); g_pEffectiveWaterSimulation = NEW GerstnerWaves(); g_pDebugFont = NEW UDebugFont(); g_pFPS = NEW UFPS(); // Direct3Dの作成 CreateDirect3D(hInstance); // グラフィックパイプラインリソースの作成 CreateGraphicePipeline(); // リソースの作成 CreateMesh(); } void NextFrame() { // ビュー行列 if (GetKeyState(VK_UP) & 0x8000) g_MatCameraView *= XMMatrixTranslation(0, 0, -0.1f); if (GetKeyState(VK_DOWN) & 0x8000) g_MatCameraView *= XMMatrixTranslation(0, 0, 0.1f); if (GetKeyState(VK_RIGHT) & 0x8000) g_MatCameraView *= XMMatrixRotationY(-0.002f); if (GetKeyState(VK_LEFT) & 0x8000) g_MatCameraView *= XMMatrixRotationY(0.002f); if (GetKeyState('Q') & 0x8000) g_MatCameraView *= XMMatrixRotationX(0.002f); if (GetKeyState('A') & 0x8000) g_MatCameraView *= XMMatrixRotationX(-0.002f); // テッセレーション係数変更 if (GetKeyState('V') & 0x8000) { g_fTessFactor += 0.01f; } if (GetKeyState('B') & 0x8000) { g_fTessFactor -= 0.01f; if (g_fTessFactor < 1.0f) { g_fTessFactor = 1.0f; } } g_pFPS->NextFrame(); g_pPlaneMesh->NextFrame(); TCHAR str[100]; _stprintf_s(str, _T("%f\nV:Tessellation factor Up\nB:Tessellation factor Down\nM:Change Fill Mode"), g_fTessFactor); g_pDebugFont->NextFrame(str, &XMFLOAT2(-0.97f, 0.86f), &XMFLOAT4(1, 1, 1, 1)); } // 描画処理 HRESULT Render() { HRESULT hr = E_FAIL; static float ClearColor[4] = { 0.3f, 0.3f, 1.0f, 1.0f }; // バックバッファをクリアする。 g_pDirect3D11->ClearBackBuffer(ClearColor); // 深度バッファをクリアする。 g_pDirect3D11->ClearDepthStencilView(D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); g_pEffectiveWaterSimulation->Begin(g_pDirect3D11->m_pD3DDevice, &g_VecLightPos, &g_MatCameraView, &g_MatCameraProj, g_FillMode); for (UINT i = 0; i<g_pEffectiveWaterSimulation->GetMaxPass(); i++) { g_pEffectiveWaterSimulation->BeginPass(g_pDirect3D11->m_pD3DDeviceContext, i); // 定数バッファを設定 g_pEffectiveWaterSimulation->SetConstantBuffers(g_pDirect3D11->m_pD3DDeviceContext, g_pPlaneMesh->GetMatWorld(), g_fTessFactor, g_fTessFactor); // レンダリング g_pPlaneMesh->Render(g_pDirect3D11->m_pD3DDeviceContext, D3D11_PRIMITIVE_TOPOLOGY::D3D_PRIMITIVE_TOPOLOGY_3_CONTROL_POINT_PATCHLIST); g_pEffectiveWaterSimulation->EndPass(g_pDirect3D11->m_pD3DDeviceContext); } g_pEffectiveWaterSimulation->End(); g_pFPS->Render(g_pDirect3D11->m_pD3DDeviceContext); g_pDebugFont->Render(g_pDirect3D11->m_pD3DDeviceContext); // レンダリングされたイメージをユーザーに表示。 if (FAILED(hr = g_pDirect3D11->Present(0, 0))) throw(UException(hr, _T("IDXGISwapChain::Present()が失敗しました"))); return hr; } // メイン関数 int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE, LPTSTR, INT) { // メモリリーク検出 // _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF | CRTDBG_CHECK_ALWAYS_DF ); _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF | _CRTDBG_CHECK_EVERY_1024_DF); MSG msg = { 0 }; try { CreateResource(hInstance); ::ShowWindow(g_pDirect3D11->m_hWnd, SW_SHOW); ::UpdateWindow(g_pDirect3D11->m_hWnd); // メッセージループ do { if (::PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { ::TranslateMessage(&msg); ::DispatchMessage(&msg); } else { NextFrame(); Render(); } } while (msg.message != WM_QUIT); } catch (UException ex) { ::MessageBox(nullptr, ex.m_pErrorStr, _T("エラー"), MB_OK); } Invalidate(); ::UnregisterClass(AppName, hInstance); return msg.wParam; }
まあ基本形ということで。