~プログラミング~ DirectX 11でフォン反射モデルのソースコードです。
CD3DTest.h
#define SAFE_RELEASE(p) { if( NULL != p ) { p->Release(); p = NULL; } } class CD3DTest { public: ID3D11Device* m_pDevice; ID3D11DeviceContext* m_pImmediateContext; IDXGISwapChain* m_pSwapChain; ID3D11Texture2D* m_pDepthStencilTexture; ID3D11RenderTargetView* m_pRenderTargetView; ID3D11DepthStencilView* m_pDepthStencilView; ID3D11Buffer* m_pVertexBuffer; ID3D11Buffer* m_pIndexBuffer; ID3D11Buffer* m_pMatrixBuffer; ID3D11Buffer* m_pLightBuffer; ID3D11InputLayout* m_pInputLayout; ID3D11VertexShader* m_pVertexShader; ID3D11PixelShader* m_pPixelShader; D3D11_VIEWPORT m_Viewport; int m_VertexCount; int m_IndexCount; float m_Angle; public: CD3DTest(); virtual ~CD3DTest(); virtual HRESULT Create( HWND hwnd ); virtual void Release(); virtual void Render(); };
CD3DTest.cpp
#include "stdafx.h" struct Vertex { float pos[ 3 ]; float nor[ 3 ]; }; D3D11_INPUT_ELEMENT_DESC g_VertexDesc[] { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; struct ConstantMatrixBuffer { XMFLOAT4X4 world; XMFLOAT4X4 view; XMFLOAT4X4 projection; }; struct ConstantLight { XMFLOAT4 pos; //座標(x,y,z) XMFLOAT4 diffuse; //拡散(r,g,b) XMFLOAT4 specular; //反射(r,g,b) XMFLOAT4 attenuate; //減衰(a,b,c) }; struct ConstantMaterial { XMFLOAT4 ambient; //環境(r,g,b) XMFLOAT4 diffuse; //拡散(r,g,b) XMFLOAT4 specular; //反射(r,g,b,光沢度係数) }; struct ConstantLightBuffer { XMFLOAT4 eyePos; //視点座標 XMFLOAT4 ambient; //環境光(r,g,b) ConstantLight pntLight; //点光源 ConstantMaterial material; //物体の質感 }; int SEGMENT = 36; CD3DTest::CD3DTest() { m_pDevice = NULL; m_pImmediateContext = NULL; m_pSwapChain = NULL; m_pDepthStencilTexture = NULL; m_pRenderTargetView = NULL; m_pDepthStencilView = NULL; m_pVertexBuffer = NULL; m_pIndexBuffer = NULL; m_pMatrixBuffer = NULL; m_pLightBuffer = NULL; m_pInputLayout = NULL; m_pVertexShader = NULL; m_pPixelShader = NULL; m_VertexCount = 0; m_IndexCount = 0; } CD3DTest::~CD3DTest() { Release(); } HRESULT CD3DTest::Create( HWND hwnd ) { Release(); HRESULT hr; CRect rect; DXGI_SWAP_CHAIN_DESC scDesc; ::GetClientRect( hwnd, &rect ); ::ZeroMemory( &scDesc, sizeof( scDesc ) ); scDesc.BufferCount = 1; scDesc.BufferDesc.Width = rect.Width(); scDesc.BufferDesc.Height = rect.Height(); scDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; scDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; scDesc.OutputWindow = hwnd; scDesc.SampleDesc.Count = 1; scDesc.SampleDesc.Quality = 0; scDesc.Windowed = TRUE; UINT flags = 0; #ifdef _DEBUG flags |= D3D11_CREATE_DEVICE_DEBUG; #endif D3D_FEATURE_LEVEL pLevels[] = { D3D_FEATURE_LEVEL_11_0 }; D3D_FEATURE_LEVEL level; hr = D3D11CreateDeviceAndSwapChain( NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, flags, pLevels, 1, D3D11_SDK_VERSION, &scDesc, &m_pSwapChain, &m_pDevice, &level, &m_pImmediateContext ); if ( FAILED( hr ) ) return hr; ID3D11Texture2D* pBackBuffer; hr = m_pSwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), (LPVOID*)&pBackBuffer ); if ( FAILED( hr ) ) return hr; hr = m_pDevice->CreateRenderTargetView( pBackBuffer, NULL, &m_pRenderTargetView ); pBackBuffer->Release(); if ( FAILED( hr ) ) return hr; //深度ステンシルバッファ作成 D3D11_TEXTURE2D_DESC txDesc; ZeroMemory( &txDesc, sizeof( txDesc ) ); txDesc.Width = rect.Width(); txDesc.Height = rect.Height(); txDesc.MipLevels = 1; txDesc.ArraySize = 1; txDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; txDesc.SampleDesc.Count = 1; txDesc.SampleDesc.Quality = 0; txDesc.Usage = D3D11_USAGE_DEFAULT; txDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; txDesc.CPUAccessFlags = 0; txDesc.MiscFlags = 0; hr = m_pDevice->CreateTexture2D( &txDesc, NULL, &m_pDepthStencilTexture ); if ( FAILED( hr ) ) return hr; D3D11_DEPTH_STENCIL_VIEW_DESC dsDesc; ZeroMemory( &dsDesc, sizeof( dsDesc ) ); dsDesc.Format = txDesc.Format; dsDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; dsDesc.Texture2D.MipSlice = 0; hr = m_pDevice->CreateDepthStencilView( m_pDepthStencilTexture, &dsDesc, &m_pDepthStencilView ); if ( FAILED( hr ) ) return hr; //頂点バッファ作成 int vcount = ( SEGMENT + 1 ) * ( SEGMENT / 2 + 1 ); Vertex* pVList = new Vertex[ vcount ]; for ( int i = 0; i <= ( SEGMENT / 2 ); ++ i ) { float irad = XM_PI * 2.0f / (float)SEGMENT * (float)i; float y = (float)cos( irad ); float r = (float)sin( irad ); for ( int j = 0; j <= SEGMENT; ++ j ) { float jrad = XM_PI * 2.0f / (float)SEGMENT * (float)j; float x = r * (float)cos( jrad ); float z = r * (float)sin( jrad ); int inx = i * ( SEGMENT + 1 ) + j; pVList[ inx ].pos[ 0 ] = x; pVList[ inx ].pos[ 1 ] = y; pVList[ inx ].pos[ 2 ] = z; pVList[ inx ].nor[ 0 ] = x; pVList[ inx ].nor[ 1 ] = y; pVList[ inx ].nor[ 2 ] = z; } } D3D11_BUFFER_DESC vbDesc; vbDesc.ByteWidth = sizeof( Vertex ) * vcount; vbDesc.Usage = D3D11_USAGE_DEFAULT; vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; vbDesc.CPUAccessFlags = 0; vbDesc.MiscFlags = 0; vbDesc.StructureByteStride = 0; D3D11_SUBRESOURCE_DATA vrData; vrData.pSysMem = pVList; vrData.SysMemPitch = 0; vrData.SysMemSlicePitch = 0; hr = m_pDevice->CreateBuffer( &vbDesc, &vrData, &m_pVertexBuffer ); if ( FAILED( hr ) ) { delete[] pVList; return hr; } delete[] pVList; //インデックスバッファ作成 int icount = SEGMENT * 3 + SEGMENT * ( SEGMENT / 2 - 1 ) * 6 + SEGMENT * 3; WORD* pIList = new WORD[ icount ]; icount = 0; int i = 0; for ( int j = 0; j < SEGMENT; ++ j ) { pIList[ icount ] = i * ( SEGMENT + 1 ) + j; pIList[ icount + 1 ] = ( i + 1 ) * ( SEGMENT + 1 ) + j + 1; pIList[ icount + 2 ] = ( i + 1 ) * ( SEGMENT + 1 ) + j; icount += 3; } for ( i = 1; i < SEGMENT / 2; ++ i ) { for ( int j = 0; j < SEGMENT; ++ j ) { pIList[ icount ] = i * ( SEGMENT + 1 ) + j; pIList[ icount + 1 ] = i * ( SEGMENT + 1 ) + j + 1; pIList[ icount + 2 ] = ( i + 1 ) * ( SEGMENT + 1 ) + j; icount += 3; pIList[ icount ] = i * ( SEGMENT + 1 ) + j + 1; pIList[ icount + 1 ] = ( i + 1 ) * ( SEGMENT + 1 ) + j + 1; pIList[ icount + 2 ] = ( i + 1 ) * ( SEGMENT + 1 ) + j; icount += 3; } } i = SEGMENT / 2; for ( int j = 0; j < SEGMENT; ++ j ) { pIList[ icount ] = i * ( SEGMENT + 1 ) + j; pIList[ icount + 1 ] = ( i + 1 ) * ( SEGMENT + 1 ) + j + 1; pIList[ icount + 2 ] = ( i + 1 ) * ( SEGMENT + 1 ) + j; icount += 3; } D3D11_BUFFER_DESC ibDesc; ibDesc.ByteWidth = sizeof( WORD ) * icount; ibDesc.Usage = D3D11_USAGE_DEFAULT; ibDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; ibDesc.CPUAccessFlags = 0; ibDesc.MiscFlags = 0; ibDesc.StructureByteStride = 0; D3D11_SUBRESOURCE_DATA irData; irData.pSysMem = pIList; irData.SysMemPitch = 0; irData.SysMemSlicePitch = 0; hr = m_pDevice->CreateBuffer( &ibDesc, &irData, &m_pIndexBuffer ); if ( FAILED( hr ) ) { delete[] pIList; return hr; } delete[] pIList; //定数バッファ作成 D3D11_BUFFER_DESC cbDesc; cbDesc.ByteWidth = sizeof( ConstantMatrixBuffer ); cbDesc.Usage = D3D11_USAGE_DEFAULT; cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; cbDesc.CPUAccessFlags = 0; cbDesc.MiscFlags = 0; cbDesc.StructureByteStride = 0; hr = m_pDevice->CreateBuffer( &cbDesc, NULL, &m_pMatrixBuffer ); if ( FAILED( hr ) ) return hr; cbDesc.ByteWidth = sizeof( ConstantLightBuffer ); cbDesc.Usage = D3D11_USAGE_DEFAULT; cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; cbDesc.CPUAccessFlags = 0; cbDesc.MiscFlags = 0; cbDesc.StructureByteStride = 0; hr = m_pDevice->CreateBuffer( &cbDesc, NULL, &m_pLightBuffer ); if ( FAILED( hr ) ) return hr; //頂点レイアウト作成 hr = m_pDevice->CreateInputLayout( g_VertexDesc, ARRAYSIZE( g_VertexDesc ), g_vs_main, sizeof( g_vs_main ), &m_pInputLayout ); if ( FAILED( hr ) ) return hr; //頂点シェーダー生成 hr = m_pDevice->CreateVertexShader( &g_vs_main, sizeof( g_vs_main ), NULL, &m_pVertexShader ); if ( FAILED( hr ) ) return hr; //ピクセルシェーダー生成 hr = m_pDevice->CreatePixelShader( &g_ps_main, sizeof( g_ps_main ), NULL, &m_pPixelShader ); if ( FAILED( hr ) ) return hr; //ビューポート設定 m_Viewport.TopLeftX = 0; m_Viewport.TopLeftY = 0; m_Viewport.Width = (FLOAT)rect.Width(); m_Viewport.Height = (FLOAT)rect.Height(); m_Viewport.MinDepth = 0.0f; m_Viewport.MaxDepth = 1.0f; m_VertexCount = vcount; m_IndexCount = icount; return hr; } void CD3DTest::Release() { if( m_pImmediateContext ) { m_pImmediateContext->ClearState(); } SAFE_RELEASE( m_pVertexBuffer ); SAFE_RELEASE( m_pIndexBuffer ); SAFE_RELEASE( m_pMatrixBuffer ); SAFE_RELEASE( m_pLightBuffer ); SAFE_RELEASE( m_pInputLayout ); SAFE_RELEASE( m_pVertexShader ); SAFE_RELEASE( m_pPixelShader ); SAFE_RELEASE( m_pRenderTargetView ); SAFE_RELEASE( m_pDepthStencilView ); SAFE_RELEASE( m_pDepthStencilTexture ); SAFE_RELEASE( m_pSwapChain ); SAFE_RELEASE( m_pImmediateContext ); SAFE_RELEASE( m_pDevice ); } void CD3DTest::Render() { XMMATRIX worldMatrix = XMMatrixTranslation( 0.0f, 0.0f, 0.0f ); XMVECTOR eye = XMVectorSet( 0.0f, 3.0f, -3.0f, 0.0f ); XMVECTOR focus = XMVectorSet( 0.0f, 0.0f, 0.0f, 0.0f ); XMVECTOR up = XMVectorSet( 0.0f, 1.0f, 0.0f, 0.0f ); XMMATRIX viewMatrix = XMMatrixLookAtLH( eye, focus, up ); float fov = XMConvertToRadians( 45.0f ); float aspect = m_Viewport.Width / m_Viewport.Height; float nearZ = 0.1f; float farZ = 100.0f; XMMATRIX projMatrix = XMMatrixPerspectiveFovLH( fov, aspect, nearZ, farZ ); XMVECTOR lightPosition = XMVectorSet( -2.0f, 2.0f, -1.0f, 0.0f ); XMVECTOR lightDiffuse = XMVectorSet( 1.0f, 1.0f, 1.0f, 0.0f ); XMVECTOR lightSpecular = XMVectorSet( 1.0f, 1.0f, 1.0f, 0.0f ); XMVECTOR lightAttenuate = XMVectorSet( 1.0f, 0.1f, 0.1f, 0.0f ); XMVECTOR lightAmbient = XMVectorSet( 0.2f, 0.2f, 0.2f, 0.0f ); XMVECTOR materialDiffuse = XMVectorSet( 0.6f, 0.8f, 0.4f, 0.0f ); XMVECTOR materialSpecular = XMVectorSet( 0.8f, 0.8f, 0.8f, 20.0f ); XMVECTOR materialAmbient = XMVectorSet( 0.6f, 0.8f, 0.4f, 0.0f ); ConstantMatrixBuffer cmb; XMStoreFloat4x4( &cmb.world, XMMatrixTranspose( worldMatrix ) ); XMStoreFloat4x4( &cmb.view, XMMatrixTranspose( viewMatrix ) ); XMStoreFloat4x4( &cmb.projection, XMMatrixTranspose( projMatrix ) ); ConstantLightBuffer clb; XMStoreFloat4( &clb.eyePos, eye ); XMStoreFloat4( &clb.ambient, lightAmbient ); XMStoreFloat4( &clb.pntLight.pos, lightPosition ); XMStoreFloat4( &clb.pntLight.diffuse, lightDiffuse ); XMStoreFloat4( &clb.pntLight.specular, lightSpecular ); XMStoreFloat4( &clb.pntLight.attenuate, lightAttenuate ); XMStoreFloat4( &clb.material.ambient, materialAmbient ); XMStoreFloat4( &clb.material.diffuse, materialDiffuse ); XMStoreFloat4( &clb.material.specular, materialSpecular ); m_pImmediateContext->UpdateSubresource( m_pMatrixBuffer, 0, NULL, &cmb, 0, 0 ); m_pImmediateContext->UpdateSubresource( m_pLightBuffer, 0, NULL, &clb, 0, 0 ); float clearColor[ 4 ] = { 0.0f, 0.0f, 0.0f, 1.0f }; //red,green,blue,alpha UINT strides = sizeof( Vertex ); UINT offsets = 0; m_pImmediateContext->IASetInputLayout( m_pInputLayout ); m_pImmediateContext->IASetVertexBuffers( 0, 1, &m_pVertexBuffer, &strides, &offsets ); m_pImmediateContext->IASetIndexBuffer( m_pIndexBuffer, DXGI_FORMAT_R16_UINT, 0 ); m_pImmediateContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST ); m_pImmediateContext->VSSetConstantBuffers( 0, 1, &m_pMatrixBuffer ); m_pImmediateContext->VSSetShader( m_pVertexShader, NULL, 0 ); m_pImmediateContext->RSSetViewports( 1, &m_Viewport ); m_pImmediateContext->PSSetConstantBuffers( 0, 1, &m_pLightBuffer ); m_pImmediateContext->PSSetShader( m_pPixelShader, NULL, 0 ); m_pImmediateContext->OMSetRenderTargets( 1, &m_pRenderTargetView, m_pDepthStencilView ); m_pImmediateContext->ClearRenderTargetView( m_pRenderTargetView, clearColor ); m_pImmediateContext->ClearDepthStencilView( m_pDepthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0 ); m_pImmediateContext->DrawIndexed( m_IndexCount, 0, 0 ); m_pSwapChain->Present( 0, 0 ); }
vs_test.vsh
struct VS_IN { float4 pos : POSITION0; float4 nor : NORMAL0; }; struct VS_OUT { float4 pos : SV_POSITION; float4 posw : POSITION0; float4 norw : NORMAL0; }; cbuffer ConstantBuffer { float4x4 world; //ワールド変換行列 float4x4 view; //ビュー変換行列 float4x4 projection; //透視射影変換行列 } VS_OUT vs_main( VS_IN input ) { VS_OUT output; float3 nor; float col; output.pos = mul(input.pos, world); output.pos = mul(output.pos, view); output.pos = mul(output.pos, projection); output.posw = mul(input.pos, world); output.norw = mul(input.nor, world); return output; }
ps_test.psh
struct PS_IN { float4 pos : SV_POSITION; float4 posw : POSITION0; //ワールド座標系の座標 float4 norw : NORMAL0; //ワールド座標系の法線 }; struct Light { float4 pos; //座標(x,y,z) float4 diffuse; //拡散(r,g,b) float4 specular; //反射(r,g,b) float4 attenuate; //減衰(a,b,c) }; struct Material { float4 ambient; //環境(r,g,b) float4 diffuse; //拡散(r,g,b) float4 specular; //反射(r,g,b,光沢度係数) }; cbuffer ConstantBuffer { float4 eyePos; //視点座標 float4 ambient; //環境光(r,g,b) Light pntLight; //点光源 Material material; //物体の質感 }; float4 ps_main( PS_IN input ) : SV_Target { float3 n; float3 v; float3 l; float3 r; float d; float a; float3 iA; float3 iD; float3 iS; n = normalize(input.norw.xyz); v = normalize(eyePos.xyz - input.posw.xyz); l = pntLight.pos.xyz - input.posw.xyz; d = length(l); //光源距離 l = normalize(l); //正規化光源ベクトル r = 2.0 * n * dot(n, l) - l; //正規化反射ベクトル a = saturate(1.0f / (pntLight.attenuate.x + pntLight.attenuate.y * d + pntLight.attenuate.z * d * d)); //減衰 iA = material.ambient.xyz * ambient.xyz; iD = saturate(dot(l, n)) * material.diffuse.xyz * pntLight.diffuse.xyz * a; iS = pow(saturate(dot(r, v)), material.specular.w) * material.specular.xyz * pntLight.specular.xyz * a; return float4(saturate(iA + iD + iS), 1.0); }
コメントをお書きください
Akira Mori (木曜日, 07 6月 2018 15:33)
DirectXプログラミングの全くの初心者ですが、本講義にて勉強させて頂いております。本当に感謝申し上げます。
このソースコードの中で、
g_VertexListとg_IndexListが定義されていなとのエラーメッセージが出て
困っております。
どうしたらよいのかよろしくご教示お願い致します。
AraramiStudio (木曜日, 07 6月 2018 18:19)
Akira Moriさん
ご指摘ありがとうございます。
本文中のソースコードに不要な行が含まれていました。申し訳ございません。
CD3DTest.cppの中の以下の2行は削除してください。
186行目: vrData.pSysMem = g_VertexList;
240行目: irData.pSysMem = g_IndexList;
Akira Mori (木曜日, 07 6月 2018 19:24)
AraramiStudio様
早速のご返事深く感謝申し上げます。
ご指示のとおりに訂正致しましたところ、成功致しました。
改めて御礼申し上げます。
全くのコピペで申し訳ありませんが、お蔭様にてDirectX11の素晴らしさを体験しております。
とある専門学生 (金曜日, 27 11月 2020 13:33)
DirectX初学者です。
シェーダー側のposやnorなどがfoat3ではなくfloat4である理由を知りたいです。
AraramiStudio (金曜日, 27 11月 2020 16:56)
とある専門学生さん
コメントありがとうございます。
座標変換を行う場合、変換行列を使います。
3D座標の場合、4×4の変換行列を使う事で回転・拡大縮小・移動の3つを一度に計算できるのでこれを使うのですが、float4x4の変換行列と演算する場合には座標もfloat4にする必要があります。
とある専門学生 (金曜日, 27 11月 2020 20:51)
迅速なご返答ありがとうございます。理解できました。