「C言語/C++/DxMandelbrot」の編集履歴(バックアップ)一覧はこちら

C言語/C++/DxMandelbrot」(2014/06/06 (金) 09:48:50) の最新版変更点

追加された行は緑色になります。

削除された行は赤色になります。

|開発環境|Microsoft Visual Studio Express 2013 for Windows Desktop| |実行環境|Microsoft Windows 8.1 (64bit)| |プロジェクトの種類|Visual C++/Win32/Win32 プロジェクト| |プロジェクト名|DxMandelbrot| |アプリケーションの種類|Windows アプリケーション| |追加のオプション|空のプロジェクト、SDLチェック| #table_zebra(project, #fff, #eee) 参考 -[[プログラマブル・シェーダによる積極的なGPUの活用 - @IT>http://www.atmarkit.co.jp/fdotnet/directxworld/directxworld07/directxworld07_01.html]] DxMandelbrot.cpp #highlight(cpp){{ #pragma comment(lib, "d3d11") #pragma comment(lib, "d3dcompiler") #include <d3d11.h> #include <d3dcompiler.h> #include <DirectXColors.h> using namespace DirectX; #define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } #define WINDOW_WIDTH 640 #define WINDOW_HEIGHT 480 struct CustomVertex { XMFLOAT2 Position; XMFLOAT2 UV; }; // 外部変数 ID3D11Device *pDevice; ID3D11DeviceContext *pDeviceContext; IDXGISwapChain *pSwapChain; ID3D11RenderTargetView *pRenderTargetView; ID3D11InputLayout *pVertexLayout; ID3D11Buffer *pVertexBuffer; ID3D11Buffer *pConstBuffer; ID3D11VertexShader *pVertexShader; ID3D11PixelShader *pPixelShader; XMFLOAT4 center; // 関数プロトタイプ宣言 HWND InitWnd(HINSTANCE hInstance, int nCmdShow); HRESULT InitDevice(HWND hWnd); HRESULT CompileShaderFromFile(LPCTSTR pFileName, LPCSTR pEntrypoint, LPCSTR pTarget, ID3DBlob **ppCode); HRESULT CreateShaderBuffer(); void Render(); void CleanupDevice(); LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); //============================================================================== int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow) { // ウィンドウ初期化 HWND hWnd = InitWnd(hInstance, nCmdShow); if (hWnd == NULL) { return 0; } // デバイス初期化 if (FAILED(InitDevice(hWnd))) { return 0; } // メインループ MSG msg = { 0 }; while (msg.message != WM_QUIT) { if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } else { // 描画 Render(); } } // デバイスのクリーンアップ CleanupDevice(); return msg.wParam; } HWND InitWnd(HINSTANCE hInstance, int nCmdShow) { WNDCLASSEX wc; ZeroMemory(&wc, sizeof wc); wc.cbSize = sizeof wc; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; wc.hInstance = hInstance; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.lpszClassName = L"DxMandelbrot"; RegisterClassEx(&wc); DWORD dwStyle = WS_OVERLAPPEDWINDOW ^ WS_MAXIMIZEBOX ^ WS_THICKFRAME; RECT rc = { 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT }; AdjustWindowRect(&rc, dwStyle, FALSE); HWND hWnd = CreateWindow( wc.lpszClassName, L"DxMandelbrot", dwStyle, CW_USEDEFAULT, 0, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, hInstance, NULL); ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return hWnd; } HRESULT InitDevice(HWND hWnd) { // ドライバータイプ D3D_DRIVER_TYPE DriverType[] = { D3D_DRIVER_TYPE_HARDWARE, D3D_DRIVER_TYPE_WARP, D3D_DRIVER_TYPE_REFERENCE, }; // 機能レベル D3D_FEATURE_LEVEL FeatureLevels[] = { D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0, // D3D_FEATURE_LEVEL_10_1, // D3D_FEATURE_LEVEL_10_0, }; // スワップチェインの設定 DXGI_SWAP_CHAIN_DESC sd; ZeroMemory(&sd, sizeof sd); sd.BufferCount = 1; sd.BufferDesc.Width = WINDOW_WIDTH; sd.BufferDesc.Height = WINDOW_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; // デバイスとスワップチェインを作成 HRESULT hr; for (int i = 0; i < ARRAYSIZE(DriverType); i++) { D3D_FEATURE_LEVEL FeatureLevel; hr = D3D11CreateDeviceAndSwapChain(NULL, DriverType[i], NULL, 0, FeatureLevels, ARRAYSIZE(FeatureLevels), D3D11_SDK_VERSION, &sd, &pSwapChain, &pDevice, &FeatureLevel, &pDeviceContext); if (SUCCEEDED(hr)) break; } if (FAILED(hr)) { return hr; } // バックバッファを取得 ID3D11Texture2D *pBackBuffer; hr = pSwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer)); // レンダーターゲットを生成 hr = pDevice->CreateRenderTargetView(pBackBuffer, NULL, &pRenderTargetView); pBackBuffer->Release(); // 出力マネージャにレンダーターゲットを設定 pDeviceContext->OMSetRenderTargets(1, &pRenderTargetView, NULL); // ビューポートの設定 D3D11_VIEWPORT vp; vp.Width = WINDOW_WIDTH; vp.Height = WINDOW_HEIGHT; vp.MinDepth = 0.0f; vp.MaxDepth = 1.0f; vp.TopLeftX = 0; vp.TopLeftY = 0; // デバイスコンテキストにビューポートを設定 pDeviceContext->RSSetViewports(1, &vp); // 頂点シェーダをコンパイル ID3DBlob *pCode; if (FAILED(CompileShaderFromFile(L"shader.fx", "VS", "vs_5_0", &pCode))) { return E_FAIL; } // 頂点シェーダ生成 hr = pDevice->CreateVertexShader( pCode->GetBufferPointer(), pCode->GetBufferSize(), NULL, &pVertexShader); if (FAILED(hr)) { return hr; } // 入力レイアウトの定義 D3D11_INPUT_ELEMENT_DESC layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; // 入力レイアウトを生成 hr = pDevice->CreateInputLayout(layout, ARRAYSIZE(layout), pCode->GetBufferPointer(), pCode->GetBufferSize(), &pVertexLayout); SAFE_RELEASE(pCode); if (FAILED(hr)) { return hr; } // 入力アセンブラ(input-assembler)に入力レイアウトを設定 pDeviceContext->IASetInputLayout(pVertexLayout); // ピクセルシェーダをコンパイル hr = CompileShaderFromFile(L"shader.fx", "PS", "ps_5_0", &pCode); if (FAILED(hr)) { return hr; } // ピクセルシェーダ生成 hr = pDevice->CreatePixelShader( pCode->GetBufferPointer(), pCode->GetBufferSize(), NULL, &pPixelShader); SAFE_RELEASE(pCode); if (FAILED(hr)) { return hr; } // 頂点の定義 CustomVertex vertices[] = { { XMFLOAT2(-1, 1), XMFLOAT2(0, 1) },// LU { XMFLOAT2(1, 1), XMFLOAT2(1, 1) }, // RU { XMFLOAT2(-1, -1), XMFLOAT2(0, 0) }, // LD { XMFLOAT2(1, -1), XMFLOAT2(1, 0) }, // RD }; // 頂点バッファの設定 D3D11_BUFFER_DESC bd; ZeroMemory(&bd, sizeof bd); bd.ByteWidth = sizeof vertices; bd.Usage = D3D11_USAGE_DEFAULT; bd.BindFlags = D3D11_BIND_VERTEX_BUFFER; // サブリソースの設定 D3D11_SUBRESOURCE_DATA InitData; ZeroMemory(&InitData, sizeof InitData); InitData.pSysMem = vertices; // 頂点バッファの生成 hr = pDevice->CreateBuffer(&bd, &InitData, &pVertexBuffer); if (FAILED(hr)) { return hr; } // 入力アセンブラに頂点バッファを設定 UINT stride = sizeof CustomVertex; UINT offset = 0; pDeviceContext->IASetVertexBuffers(0, 1, &pVertexBuffer, &stride, &offset); // ピクセルシェーダのシェーダ変数 CreateShaderBuffer(); // プリミティブの種類を設定 pDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); return S_OK; } HRESULT CompileShaderFromFile(LPCTSTR pFileName, LPCSTR pEntrypoint, LPCSTR pTarget, ID3DBlob **ppCode) { ID3DBlob *pErrorMsgs; HRESULT hr = D3DCompileFromFile( pFileName, NULL, D3D_COMPILE_STANDARD_FILE_INCLUDE, pEntrypoint, pTarget, 0, 0, ppCode, &pErrorMsgs); return hr; } HRESULT CreateShaderBuffer() { center = { 0, 0, 1, (float)WINDOW_HEIGHT / WINDOW_WIDTH }; D3D11_BUFFER_DESC bd; bd.ByteWidth = sizeof center; bd.Usage = D3D11_USAGE_DEFAULT; bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER; bd.CPUAccessFlags = 0; bd.MiscFlags = 0; bd.StructureByteStride = 0; D3D11_SUBRESOURCE_DATA InitData; InitData.pSysMem = &center; InitData.SysMemPitch = 0; InitData.SysMemSlicePitch = 0; HRESULT hr = pDevice->CreateBuffer(&bd, &InitData, &pConstBuffer); return hr; } void Render() { // ビューをクリアする pDeviceContext->ClearRenderTargetView(pRenderTargetView, Colors::CornflowerBlue); // シェーダを設定して描画 pDeviceContext->VSSetShader(pVertexShader, NULL, 0); pDeviceContext->PSSetShader(pPixelShader, NULL, 0); pDeviceContext->UpdateSubresource(pConstBuffer, 0, NULL, &center, 0, 0); pDeviceContext->PSSetConstantBuffers(0, 1, &pConstBuffer); // 描画 pDeviceContext->Draw(4, 0); // 描画結果を表示 pSwapChain->Present(0, 0); } void CleanupDevice() { // ステートをクリアし、デフォルト状態にする if (pDeviceContext) { pDeviceContext->ClearState(); pDeviceContext->Flush(); } SAFE_RELEASE(pVertexShader); SAFE_RELEASE(pPixelShader); SAFE_RELEASE(pConstBuffer); SAFE_RELEASE(pVertexBuffer); SAFE_RELEASE(pVertexLayout); SAFE_RELEASE(pRenderTargetView); SAFE_RELEASE(pSwapChain); SAFE_RELEASE(pDeviceContext); SAFE_RELEASE(pDevice); } LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_KEYDOWN: switch (wParam) { case VK_ESCAPE: DestroyWindow(hWnd); break; case VK_UP: center.z *= 0.9f; break; case VK_DOWN: center.z *= 1.1f; break; case 'W': center.y += center.z * 0.1f; break; case 'S': center.y -= center.z * 0.1f; break; case 'A': center.x -= center.z * 0.1f; break; case 'D': center.x += center.z * 0.1f; break; } return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hWnd, uMsg, wParam, lParam); } }} プロジェクトには追加しない。 カレントディレクトリに置く。 shader.fx #highlight(fx){{ float4 center : register(ps, c0); struct VertexIn { float2 Pos : POSITION; float2 UV : TEXCOORD; }; struct VertexOut { float4 ScreenPos : SV_Position; float2 UV : TEXCOORD; }; VertexOut VS(VertexIn input) { VertexOut output; output.ScreenPos = float4(input.Pos, 0, 1); output.UV = input.UV; return output; } float4 PS(VertexOut input) : SV_Target { const int MaxIterate = 254; const double2 c = (input.UV - 0.5) * double2(1.0, center.w) * center.z + center.xy; double2 p = 0; int n; for (n = 0; n < MaxIterate && dot(p, p) < 4.0; n++) { p = double2(p.x * p.x - p.y * p.y, 2.0 * p.x * p.y) + c; } float4 color; if (n < MaxIterate) { float u = (float)n / (float)MaxIterate; color.rgb = float3(u, u, 1.0 - u); } else { color.rgb = 0.0; } color.a = 1.0; return color; } }}
|開発環境|Microsoft Visual Studio Express 2013 for Windows Desktop| |実行環境|Microsoft Windows 8.1 (64bit)| |プロジェクトの種類|Visual C++/Win32/Win32 プロジェクト| |プロジェクト名|DxMandelbrot| |アプリケーションの種類|Windows アプリケーション| |追加のオプション|空のプロジェクト、SDLチェック| #table_zebra(project, #fff, #eee) 参考 -[[プログラマブル・シェーダによる積極的なGPUの活用 - @IT>http://www.atmarkit.co.jp/fdotnet/directxworld/directxworld07/directxworld07_01.html]] DxMandelbrot.cpp #highlight(cpp){{ #pragma comment(lib, "d3d11") #pragma comment(lib, "d3dcompiler") #include <d3d11.h> #include <d3dcompiler.h> #include <DirectXColors.h> using namespace DirectX; #define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } #define WINDOW_WIDTH 640 #define WINDOW_HEIGHT 480 struct CustomVertex { XMFLOAT2 Position; XMFLOAT2 UV; }; // 外部変数 ID3D11Device *pDevice; ID3D11DeviceContext *pDeviceContext; IDXGISwapChain *pSwapChain; ID3D11RenderTargetView *pRenderTargetView; ID3D11InputLayout *pVertexLayout; ID3D11Buffer *pVertexBuffer; ID3D11Buffer *pConstBuffer; ID3D11VertexShader *pVertexShader; ID3D11PixelShader *pPixelShader; double offsetx; double offsety; double zoom = 4; XMFLOAT4 center; // 関数プロトタイプ宣言 HWND InitWnd(HINSTANCE hInstance, int nCmdShow); HRESULT InitDevice(HWND hWnd); HRESULT CompileShaderFromFile(LPCTSTR pFileName, LPCSTR pEntrypoint, LPCSTR pTarget, ID3DBlob **ppCode); HRESULT CreateShaderBuffer(); void Render(); void CleanupDevice(); LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); //============================================================================== int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow) { // ウィンドウ初期化 HWND hWnd = InitWnd(hInstance, nCmdShow); if (hWnd == NULL) { return 0; } // デバイス初期化 if (FAILED(InitDevice(hWnd))) { return 0; } // メインループ MSG msg = { 0 }; while (msg.message != WM_QUIT) { if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } else { // 描画 Render(); } } // デバイスのクリーンアップ CleanupDevice(); return msg.wParam; } HWND InitWnd(HINSTANCE hInstance, int nCmdShow) { WNDCLASSEX wc; ZeroMemory(&wc, sizeof wc); wc.cbSize = sizeof wc; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; wc.hInstance = hInstance; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.lpszClassName = L"DxMandelbrot"; RegisterClassEx(&wc); DWORD dwStyle = WS_OVERLAPPEDWINDOW ^ WS_MAXIMIZEBOX ^ WS_THICKFRAME; RECT rc = { 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT }; AdjustWindowRect(&rc, dwStyle, FALSE); HWND hWnd = CreateWindow( wc.lpszClassName, L"DxMandelbrot", dwStyle, CW_USEDEFAULT, 0, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, hInstance, NULL); ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return hWnd; } HRESULT InitDevice(HWND hWnd) { // ドライバータイプ D3D_DRIVER_TYPE DriverType[] = { D3D_DRIVER_TYPE_HARDWARE, D3D_DRIVER_TYPE_WARP, D3D_DRIVER_TYPE_REFERENCE, }; // 機能レベル D3D_FEATURE_LEVEL FeatureLevels[] = { D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0, // D3D_FEATURE_LEVEL_10_1, // D3D_FEATURE_LEVEL_10_0, }; // スワップチェインの設定 DXGI_SWAP_CHAIN_DESC sd; ZeroMemory(&sd, sizeof sd); sd.BufferCount = 1; sd.BufferDesc.Width = WINDOW_WIDTH; sd.BufferDesc.Height = WINDOW_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; // デバイスとスワップチェインを作成 HRESULT hr; for (int i = 0; i < ARRAYSIZE(DriverType); i++) { D3D_FEATURE_LEVEL FeatureLevel; hr = D3D11CreateDeviceAndSwapChain(NULL, DriverType[i], NULL, 0, FeatureLevels, ARRAYSIZE(FeatureLevels), D3D11_SDK_VERSION, &sd, &pSwapChain, &pDevice, &FeatureLevel, &pDeviceContext); if (SUCCEEDED(hr)) break; } if (FAILED(hr)) { return hr; } // バックバッファを取得 ID3D11Texture2D *pBackBuffer; hr = pSwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer)); // レンダーターゲットを生成 hr = pDevice->CreateRenderTargetView(pBackBuffer, NULL, &pRenderTargetView); pBackBuffer->Release(); // 出力マネージャにレンダーターゲットを設定 pDeviceContext->OMSetRenderTargets(1, &pRenderTargetView, NULL); // ビューポートの設定 D3D11_VIEWPORT vp; vp.Width = WINDOW_WIDTH; vp.Height = WINDOW_HEIGHT; vp.MinDepth = 0.0f; vp.MaxDepth = 1.0f; vp.TopLeftX = 0; vp.TopLeftY = 0; // デバイスコンテキストにビューポートを設定 pDeviceContext->RSSetViewports(1, &vp); // 頂点シェーダをコンパイル ID3DBlob *pCode; if (FAILED(CompileShaderFromFile(L"shader.fx", "VS", "vs_5_0", &pCode))) { return E_FAIL; } // 頂点シェーダ生成 hr = pDevice->CreateVertexShader( pCode->GetBufferPointer(), pCode->GetBufferSize(), NULL, &pVertexShader); if (FAILED(hr)) { return hr; } // 入力レイアウトの定義 D3D11_INPUT_ELEMENT_DESC layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; // 入力レイアウトを生成 hr = pDevice->CreateInputLayout(layout, ARRAYSIZE(layout), pCode->GetBufferPointer(), pCode->GetBufferSize(), &pVertexLayout); SAFE_RELEASE(pCode); if (FAILED(hr)) { return hr; } // 入力アセンブラ(input-assembler)に入力レイアウトを設定 pDeviceContext->IASetInputLayout(pVertexLayout); // ピクセルシェーダをコンパイル hr = CompileShaderFromFile(L"shader.fx", "PS", "ps_5_0", &pCode); if (FAILED(hr)) { return hr; } // ピクセルシェーダ生成 hr = pDevice->CreatePixelShader( pCode->GetBufferPointer(), pCode->GetBufferSize(), NULL, &pPixelShader); SAFE_RELEASE(pCode); if (FAILED(hr)) { return hr; } // 頂点の定義 CustomVertex vertices[] = { { XMFLOAT2(-1, 1), XMFLOAT2(0, 1) },// LU { XMFLOAT2(1, 1), XMFLOAT2(1, 1) }, // RU { XMFLOAT2(-1, -1), XMFLOAT2(0, 0) }, // LD { XMFLOAT2(1, -1), XMFLOAT2(1, 0) }, // RD }; // 頂点バッファの設定 D3D11_BUFFER_DESC bd; ZeroMemory(&bd, sizeof bd); bd.ByteWidth = sizeof vertices; bd.Usage = D3D11_USAGE_DEFAULT; bd.BindFlags = D3D11_BIND_VERTEX_BUFFER; // サブリソースの設定 D3D11_SUBRESOURCE_DATA InitData; ZeroMemory(&InitData, sizeof InitData); InitData.pSysMem = vertices; // 頂点バッファの生成 hr = pDevice->CreateBuffer(&bd, &InitData, &pVertexBuffer); if (FAILED(hr)) { return hr; } // 入力アセンブラに頂点バッファを設定 UINT stride = sizeof CustomVertex; UINT offset = 0; pDeviceContext->IASetVertexBuffers(0, 1, &pVertexBuffer, &stride, &offset); // ピクセルシェーダのシェーダ変数 CreateShaderBuffer(); // プリミティブの種類を設定 pDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); return S_OK; } HRESULT CompileShaderFromFile(LPCTSTR pFileName, LPCSTR pEntrypoint, LPCSTR pTarget, ID3DBlob **ppCode) { ID3DBlob *pErrorMsgs; HRESULT hr = D3DCompileFromFile( pFileName, NULL, D3D_COMPILE_STANDARD_FILE_INCLUDE, pEntrypoint, pTarget, 0, 0, ppCode, &pErrorMsgs); return hr; } HRESULT CreateShaderBuffer() { center = { (float)offsetx, (float)offsety, (float)zoom, (float)WINDOW_HEIGHT / WINDOW_WIDTH }; D3D11_BUFFER_DESC bd; bd.ByteWidth = sizeof center; bd.Usage = D3D11_USAGE_DEFAULT; bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER; bd.CPUAccessFlags = 0; bd.MiscFlags = 0; bd.StructureByteStride = 0; D3D11_SUBRESOURCE_DATA InitData; InitData.pSysMem = &center; InitData.SysMemPitch = 0; InitData.SysMemSlicePitch = 0; HRESULT hr = pDevice->CreateBuffer(&bd, &InitData, &pConstBuffer); pDeviceContext->PSSetConstantBuffers(0, 1, &pConstBuffer); return hr; } void Render() { // ビューをクリアする pDeviceContext->ClearRenderTargetView(pRenderTargetView, Colors::CornflowerBlue); // シェーダを設定して描画 pDeviceContext->VSSetShader(pVertexShader, NULL, 0); pDeviceContext->PSSetShader(pPixelShader, NULL, 0); center = { (float)offsetx, (float)offsety, (float)zoom, (float)WINDOW_HEIGHT / WINDOW_WIDTH }; pDeviceContext->UpdateSubresource(pConstBuffer, 0, NULL, &center, 0, 0); // 描画 pDeviceContext->Draw(4, 0); // 描画結果を表示 pSwapChain->Present(0, 0); } void CleanupDevice() { // ステートをクリアし、デフォルト状態にする if (pDeviceContext) { pDeviceContext->ClearState(); pDeviceContext->Flush(); } SAFE_RELEASE(pVertexShader); SAFE_RELEASE(pPixelShader); SAFE_RELEASE(pConstBuffer); SAFE_RELEASE(pVertexBuffer); SAFE_RELEASE(pVertexLayout); SAFE_RELEASE(pRenderTargetView); SAFE_RELEASE(pSwapChain); SAFE_RELEASE(pDeviceContext); SAFE_RELEASE(pDevice); } LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_KEYDOWN: switch (wParam) { case VK_ESCAPE: DestroyWindow(hWnd); break; case VK_UP: zoom *= 0.9; break; case VK_DOWN: zoom *= 1.1; break; case 'W': offsety += zoom * 0.1; break; case 'S': offsety -= zoom * 0.1; break; case 'A': offsetx -= zoom * 0.1; break; case 'D': offsetx += zoom * 0.1; break; } return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hWnd, uMsg, wParam, lParam); } }} プロジェクトには追加しない。 カレントディレクトリに置く。 shader.fx #highlight(fx){{ float4 center : register(ps, c0); // xy=Offset z=Zoom w=Aspect struct VertexIn { float2 Pos : POSITION; float2 UV : TEXCOORD; }; struct VertexOut { float4 ScreenPos : SV_Position; float2 UV : TEXCOORD; }; VertexOut VS(VertexIn input) { VertexOut output; output.ScreenPos = float4(input.Pos, 0, 1); output.UV = input.UV; return output; } float4 PS(VertexOut input) : SV_Target { const double2 c = (input.UV - 0.5) * double2(1.0, center.w) * center.z + center.xy; double2 p = 0; int n; for (n = 0; n < 511 && dot(p, p) < 4.0; n++) { p = double2(p.x * p.x - p.y * p.y, 2.0 * p.x * p.y) + c; } float4 color; float u = (float)n / 1024.0; // 0 <= u < 0.5 switch (n % 4) { case 0: color.rgb = float3(1.0 - u, 1.0 - u, 0.5); break; case 1: color.rgb = float3(1.0 - u, 1.0 - u, 1.0 - u); break; case 2: color.rgb = float3(0.5, 1.0 - u, 1.0 - u); break; case 3: color.rgb = float3(0.5 - u, 0.5 - u, 0.5 - u); break; } color.a = 1.0; return color; } }}

表示オプション

横に並べて表示:
変化行の前後のみ表示: