「スタティックメッシュ:OBJ」の編集履歴(バックアップ)一覧はこちら
「スタティックメッシュ:OBJ」(2011/03/11 (金) 21:31:10) の最新版変更点
追加された行は緑色になります。
削除された行は赤色になります。
<p><strong>OBJファイルを読み込んで表示します。</strong></p>
<p><a href="http://neo-arcadia.seesaa.net/"><strong>http://neo-arcadia.seesaa.net/</strong></a><strong><br />
こちらからモデルを借りてきて表示しています。</strong></p>
<p><strong><img alt="" src="http://www43.atwiki.jp/directx11?cmd=upload&act=open&pageid=20&file=obj.png" /></strong></p>
<table border="1" cellspacing="1" cellpadding="1" width="600"><tbody><tr><td>
<p>#pragma comment(lib,"d3d11.lib")<br />
#pragma comment(lib,"d3dx11.lib")<br />
#pragma comment(lib,"d3dx10.lib")<br />
#pragma comment(lib,"d3dCompiler.lib")<br />
#include <stdio.h><br />
#include <vector><br />
#include <d3dx11.h><br />
#include <d3dx10.h><br />
#include <d3dCompiler.h></p>
<p>#define FILE_NAME "axel.obj"</p>
<p>using namespace std;</p>
<p>//安全に解放する<br />
#define SAFE_RELEASE(x) if(x){x->Release(); x=NULL;}</p>
<p>//定数定義<br />
#define WINDOW_WIDTH 320 //ウィンドウ幅<br />
#define WINDOW_HEIGHT 240 //ウィンドウ高さ</p>
<p>//グローバル変数<br />
HWND hWnd=NULL;<br />
ID3D11Device* Device = NULL; //デバイス<br />
ID3D11DeviceContext* DeviceContext=NULL; //デバイスコンテキスト<br />
IDXGISwapChain* SwapChain = NULL; //スワップチェイン<br />
ID3D11RenderTargetView* RenderTargetView = NULL; //レンダーターゲットビュー<br />
ID3D11DepthStencilView* DepthStencilView = NULL;<br />
ID3D11Texture2D* DepthStencil = NULL;<br />
ID3D11InputLayout* VertexLayout=NULL;</p>
<p>ID3D11VertexShader* VertexShader=NULL;//頂点シェーダー<br />
ID3D11PixelShader* PixelShader=NULL;//ピクセルシェーダー</p>
<p>ID3D11Buffer* ConstantBuffer[2];//コンスタントバッファ</p>
<p>D3DXVECTOR3 LightDir(1,1,-1);//ライト方向</p>
<p>ID3D11SamplerState* SampleLinear=NULL;//テクスチャーのサンプラー<br />
ID3D11ShaderResourceView* Texture=NULL;//テクスチャー</p>
<p>//シェーダーに渡す値<br />
struct SHADER_GLOBAL0<br />
{<br />
D3DXMATRIX mW;//ワールド行列<br />
D3DXMATRIX mWVP;//ワールドから射影までの変換行列<br />
D3DXVECTOR4 vLightDir;//ライト方向<br />
D3DXVECTOR4 vEye;//カメラ位置<br />
};<br />
struct SHADER_GLOBAL1<br />
{<br />
D3DXVECTOR4 vAmbient;//アンビエント<br />
D3DXVECTOR4 vDiffuse;//ディフューズ<br />
D3DXVECTOR4 vSpecular;//鏡面反射<br />
};</p>
<p>//マテリアル構造体<br />
struct MATERIAL<br />
{<br />
CHAR Name[255];<br />
D3DXVECTOR4 Ka;//アンビエント<br />
D3DXVECTOR4 Kd;//ディフューズ<br />
D3DXVECTOR4 Ks;//スペキュラー<br />
CHAR TextureName[255];//テクスチャファイル名<br />
ID3D11ShaderResourceView* pTexture;//テクスチャデータ<br />
DWORD MaxFace;//ポリゴン数<br />
}mat;</p>
<p>//頂点構造体<br />
struct VERTEX<br />
{<br />
D3DXVECTOR3 Pos;//位置<br />
D3DXVECTOR3 Normal;//法線<br />
D3DXVECTOR2 UV;//UV<br />
}vert;</p>
<p>//.OBJファイルクラス<br />
class OBJ{<br />
protected:<br />
vector <MATERIAL> Material;//マテリアル<br />
vector <VERTEX> Vertex;//頂点構造体<br />
ID3D11Buffer* VertexBuffer;//頂点バッファ<br />
ID3D11Buffer** IndexBuffer;//インデックスバッファ<br />
HRESULT LoadMaterialFromFile(LPSTR FileName);//マテリアルファイル読み込み<br />
public:<br />
void Draw();//描画<br />
HRESULT Load(LPSTR FileName);//読み込み<br />
};</p>
<p>OBJ obj;</p>
<p>//メッシュの描画<br />
void OBJ::Draw()<br />
{<br />
//バーテックスバッファをセット<br />
UINT stride = sizeof( VERTEX );<br />
UINT offset = 0;<br />
DeviceContext->IASetVertexBuffers( 0, 1, &VertexBuffer, &stride,
&offset );<br />
//マテリアルの数だけ、それぞれのマテリアルのインデックスバッファを描画<br />
for(DWORD i=0;i<Material.size();i++)<br />
{<br />
//使用されていないマテリアル対策<br />
if(Material[i].MaxFace==0)<br />
{<br />
continue;<br />
}<br />
//インデックスバッファをセット<br />
DeviceContext->IASetIndexBuffer(IndexBuffer[i], DXGI_FORMAT_R32_UINT, 0
);<br />
//プリミティブ・トポロジーをセット<br />
DeviceContext->IASetPrimitiveTopology(
D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST );<br />
//マテリアルの各要素をシェーダーに渡す<br />
D3D11_MAPPED_SUBRESOURCE pData;<br />
if( SUCCEEDED( DeviceContext->Map( ConstantBuffer[1],0,
D3D11_MAP_WRITE_DISCARD, 0, &pData ) ) )<br />
{<br />
SHADER_GLOBAL1 sg; <br />
sg.vAmbient=Material[i].Ka;<br />
sg.vDiffuse=Material[i].Kd;<br />
sg.vSpecular=Material[i].Ks;<br />
memcpy_s( pData.pData, pData.RowPitch, (void*)&sg, sizeof(
SHADER_GLOBAL1 ) );<br />
DeviceContext->Unmap( ConstantBuffer[1], 0 );<br />
}<br />
DeviceContext->VSSetConstantBuffers(1,1,&ConstantBuffer[1] );<br />
DeviceContext->PSSetConstantBuffers(1,1,&ConstantBuffer[1] );<br />
//テクスチャをシェーダーに渡す<br />
if(Material[i].TextureName[0] != NULL)<br />
{<br />
DeviceContext->PSSetSamplers(0,1,&SampleLinear);<br />
DeviceContext->PSSetShaderResources(0,1,&Material[i].pTexture);<br />
}<br />
DeviceContext->DrawIndexed(Material[i].MaxFace*3 , 0 ,0);<br />
}<br />
}</p>
<p>//マテリアルファイルを読み込む関数<br />
HRESULT OBJ::LoadMaterialFromFile(LPSTR FileName)<br />
{<br />
FILE* fp=NULL;<br />
fopen_s(&fp,FileName,"rt");<br />
char key[255]={0};<br />
bool flag=false;<br />
D3DXVECTOR4 v(0,0,0,0);<br />
<br />
fseek(fp,SEEK_SET,0);</p>
<p> while(!feof(fp))<br />
{<br />
//キーワード読み込み<br />
fscanf_s(fp,"%s ",key,sizeof(key));<br />
//マテリアル名<br />
if(strcmp(key,"newmtl")==0)<br />
{<br />
if(flag)Material.push_back(mat);<br />
flag=true;<br />
fscanf_s(fp,"%s ",key,sizeof(key));<br />
strcpy_s(mat.Name,key);<br />
}<br />
//Ka アンビエント<br />
if(strcmp(key,"Ka")==0)<br />
{<br />
fscanf_s(fp,"%f %f %f",&v.x,&v.y,&v.z);<br />
mat.Ka=v;<br />
}<br />
//Kd ディフューズ<br />
if(strcmp(key,"Kd")==0)<br />
{<br />
fscanf_s(fp,"%f %f %f",&v.x,&v.y,&v.z);<br />
mat.Kd=v;<br />
}<br />
//Ks スペキュラー<br />
if(strcmp(key,"Ks")==0)<br />
{<br />
fscanf_s(fp,"%f %f %f",&v.x,&v.y,&v.z);<br />
mat.Ks=v;<br />
}<br />
//map_Kd テクスチャ<br />
if(strcmp(key,"map_Kd")==0)<br />
{<br />
fscanf_s(fp,"%s",&mat.TextureName,sizeof(mat.TextureName));<br />
//テクスチャを作成<br />
if(FAILED(D3DX11CreateShaderResourceViewFromFileA( Device, mat.TextureName,
NULL, NULL, &mat.pTexture, NULL )))<br />
{<br />
return E_FAIL;<br />
}<br />
}<br />
}<br />
fclose(fp);<br />
if(flag)Material.push_back(mat);<br />
<br />
return S_OK;<br />
}</p>
<p>//OBJファイルからメッシュに必要な情報を読み込む<br />
HRESULT OBJ::Load(LPSTR FileName)<br />
{<br />
//一時代入用<br />
D3DXVECTOR3 vec3d;<br />
D3DXVECTOR2 vec2d;<br />
vector <D3DXVECTOR3> Pos;<br />
vector <D3DXVECTOR3> Normal;<br />
vector <D3DXVECTOR2> UV;<br />
vector <int> FaceIndex;<br />
int v1=0,v2=0,v3=0;<br />
int vn1=0,vn2=0,vn3=0;<br />
int vt1=0,vt2=0,vt3=0;<br />
DWORD dwFCount=0;//読み込みカウンタ</p>
<p> char key[255]={0};<br />
//OBJファイルを開いて内容を読み込む<br />
FILE* fp=NULL;<br />
fopen_s(&fp,FileName,"rt");<br />
<br />
//読み込み <br />
fseek(fp,SEEK_SET,0);</p>
<p> while(!feof(fp))<br />
{<br />
//キーワード<br />
ZeroMemory(key,sizeof(key));<br />
fscanf_s(fp,"%s ",key,sizeof(key)); <br />
//マテリアル<br />
if(strcmp(key,"mtllib")==0)<br />
{<br />
fscanf_s(fp,"%s ",key,sizeof(key));<br />
LoadMaterialFromFile(key);<br />
}<br />
//頂点<br />
if(strcmp(key,"v")==0)<br />
{<br />
fscanf_s(fp,"%f %f %f",&vec3d.x,&vec3d.y,&vec3d.z);<br />
Pos.push_back(vec3d);<br />
Vertex.push_back(vert);<br />
}<br />
//法線<br />
if(strcmp(key,"vn")==0)<br />
{ <br />
fscanf_s(fp,"%f %f %f",&vec3d.x,&vec3d.y,&vec3d.z);<br />
Normal.push_back(vec3d);<br />
}<br />
//テクスチャ<br />
if(strcmp(key,"vt")==0)<br />
{ <br />
fscanf_s(fp,"%f %f",&vec2d.x,&vec2d.y);<br />
UV.push_back(-vec2d);<br />
}<br />
//フェイス<br />
if(strcmp(key,"f")==0)<br />
{<br />
FaceIndex.push_back(0);<br />
}<br />
} </p>
<p> //マテリアルの数だけインデックスバッファを作成<br />
IndexBuffer=new ID3D11Buffer*[Material.size()];</p>
<p> bool boFlag=false;<br />
for(DWORD i=0;i<Material.size();i++)<br />
{ <br />
fseek(fp,SEEK_SET,0);<br />
dwFCount=0;</p>
<p> while(!feof(fp))<br />
{<br />
//キーワード<br />
ZeroMemory(key,sizeof(key));<br />
fscanf_s(fp,"%s ",key,sizeof(key));</p>
<p> //フェイス 読み込み→頂点インデックスに<br />
if(strcmp(key,"usemtl")==0)<br />
{<br />
fscanf_s(fp,"%s ",key,sizeof(key));<br />
if(strcmp(key,Material[i].Name)==0)<br />
{<br />
boFlag=true;<br />
}<br />
else<br />
{<br />
boFlag=false;<br />
}<br />
}<br />
if(strcmp(key,"f")==0 && boFlag==true)<br />
{<br />
if(Material[i].pTexture!=NULL)//テクスチャーありサーフェイス<br />
{<br />
fscanf_s(fp,"%d/%d/%d %d/%d/%d
%d/%d/%d",&v1,&vt1,&vn1,&v2,&vt2,&vn2,&v3,&vt3,&vn3);<br />
}<br />
else//テクスチャー無しサーフェイス<br />
{<br />
fscanf_s(fp,"%d//%d %d//%d
%d//%d",&v1,&vn1,&v2,&vn2,&v3,&vn3);<br />
}<br />
FaceIndex[dwFCount*3]=v1-1;<br />
FaceIndex[dwFCount*3+1]=v2-1;<br />
FaceIndex[dwFCount*3+2]=v3-1;<br />
dwFCount++;<br />
//頂点構造体に代入<br />
Vertex[v1-1].Pos=Pos[v1-1];<br />
Vertex[v1-1].Normal=Normal[vn1-1];<br />
Vertex[v1-1].UV=UV[vt1-1];<br />
Vertex[v2-1].Pos=Pos[v2-1];<br />
Vertex[v2-1].Normal=Normal[vn2-1];<br />
Vertex[v2-1].UV=UV[vt2-1];<br />
Vertex[v3-1].Pos=Pos[v3-1];<br />
Vertex[v3-1].Normal=Normal[vn3-1];<br />
Vertex[v3-1].UV=UV[vt3-1];<br />
}<br />
}<br />
if(dwFCount==0)//使用されていないマテリアル対策<br />
{<br />
IndexBuffer[i]=NULL;<br />
continue;<br />
}</p>
<p> //インデックスバッファを作成<br />
D3D11_BUFFER_DESC bd;<br />
bd.Usage = D3D11_USAGE_DEFAULT;<br />
bd.ByteWidth = sizeof( int ) * dwFCount * 3;<br />
bd.BindFlags = D3D11_BIND_INDEX_BUFFER;<br />
bd.CPUAccessFlags = 0;<br />
bd.MiscFlags = 0;<br />
D3D11_SUBRESOURCE_DATA InitData;<br />
InitData.pSysMem = &FaceIndex[0];<br />
InitData.SysMemPitch=0;<br />
InitData.SysMemSlicePitch=0;<br />
if( FAILED( Device->CreateBuffer( &bd, &InitData,
&IndexBuffer[i] ) ) )return FALSE;<br />
Material[i].MaxFace=dwFCount; <br />
}<br />
FaceIndex.clear();<br />
fclose(fp);</p>
<p> //バーテックスバッファを作成<br />
D3D11_BUFFER_DESC bd;<br />
bd.Usage = D3D11_USAGE_DEFAULT;<br />
bd.ByteWidth = sizeof( VERTEX ) *Vertex.size();<br />
bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;<br />
bd.CPUAccessFlags = 0;<br />
bd.MiscFlags = 0;<br />
D3D11_SUBRESOURCE_DATA InitData;<br />
InitData.pSysMem = &Vertex[0];<br />
if( FAILED( Device->CreateBuffer( &bd, &InitData, &VertexBuffer
) ) )return FALSE; </p>
<p><br />
Pos.clear();<br />
Normal.clear();<br />
UV.clear();<br />
Vertex.clear(); </p>
<p> return S_OK;<br />
}</p>
<p>//Direct3Dの初期化関数<br />
HRESULT InitD3D(HWND hWnd)<br />
{<br />
// デバイスとスワップチェーンの作成<br />
DXGI_SWAP_CHAIN_DESC sd;<br />
ZeroMemory( &sd, sizeof(sd) );<br />
sd.BufferCount = 1; //バックバッファの数<br />
sd.BufferDesc.Width = WINDOW_WIDTH; //バッファの幅<br />
sd.BufferDesc.Height = WINDOW_HEIGHT; //バッファの高さ<br />
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; //バッファのフォーマット<br />
sd.BufferDesc.RefreshRate.Numerator = 60; //リフレッシュレート<br />
sd.BufferDesc.RefreshRate.Denominator = 1;<br />
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;<br />
sd.OutputWindow = hWnd;<br />
sd.SampleDesc.Count = 1;<br />
sd.SampleDesc.Quality = 0;<br />
sd.Windowed = TRUE;</p>
<p> D3D_FEATURE_LEVEL FeatureLevel = D3D_FEATURE_LEVEL_11_0;<br />
D3D_FEATURE_LEVEL* pFeatureLevel = NULL;</p>
<p><br />
if( FAILED( D3D11CreateDeviceAndSwapChain( NULL, D3D_DRIVER_TYPE_HARDWARE,
NULL,0,<br />
&FeatureLevel,1,D3D11_SDK_VERSION, &sd, &SwapChain,
&Device ,NULL,&DeviceContext) ) )<br />
{<br />
return FALSE;<br />
}<br />
//レンダーターゲットビューの作成<br />
ID3D11Texture2D *BackBuffer;<br />
SwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D
),(LPVOID*)&BackBuffer); <br />
Device->CreateRenderTargetView( BackBuffer, NULL, &RenderTargetView
);<br />
SAFE_RELEASE(BackBuffer);<br />
//深度ステンシルビューの作成<br />
D3D11_TEXTURE2D_DESC descDepth;<br />
descDepth.Width = WINDOW_WIDTH;<br />
descDepth.Height = WINDOW_HEIGHT;<br />
descDepth.MipLevels = 1;<br />
descDepth.ArraySize = 1;<br />
descDepth.Format = DXGI_FORMAT_D32_FLOAT;<br />
descDepth.SampleDesc.Count = 1;<br />
descDepth.SampleDesc.Quality = 0;<br />
descDepth.Usage = D3D11_USAGE_DEFAULT;<br />
descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL;<br />
descDepth.CPUAccessFlags = 0;<br />
descDepth.MiscFlags = 0;<br />
Device->CreateTexture2D( &descDepth, NULL, &DepthStencil );</p>
<p> Device->CreateDepthStencilView( DepthStencil, NULL,
&DepthStencilView );<br />
//レンダーターゲットビューと深度ステンシルビューをパイプラインにバインド <br />
DeviceContext->OMSetRenderTargets(1,
&RenderTargetView,DepthStencilView);</p>
<p> //ビューポートの設定<br />
D3D11_VIEWPORT vp;<br />
vp.Width = WINDOW_WIDTH;<br />
vp.Height = WINDOW_HEIGHT;<br />
vp.MinDepth = 0.0f;<br />
vp.MaxDepth = 1.0f;<br />
vp.TopLeftX = 0;<br />
vp.TopLeftY = 0;<br />
DeviceContext->RSSetViewports( 1, &vp );</p>
<p> //hlslファイル読み込み<br />
ID3DBlob *pCompiledShader=NULL;<br />
ID3DBlob *pErrors=NULL;<br />
//ブロブから頂点シェーダー作成<br />
if(FAILED(D3DX11CompileFromFile(L"shader.hlsl",NULL,NULL,"VS","vs_5_0",0,0,NULL,&pCompiledShader,&pErrors,NULL)))<br />
{<br />
MessageBox(0,L"頂点シェーダー読み込み失敗",NULL,MB_OK);<br />
return E_FAIL;<br />
}<br />
SAFE_RELEASE(pErrors);</p>
<p>
if(FAILED(Device->CreateVertexShader(pCompiledShader->GetBufferPointer(),pCompiledShader->GetBufferSize(),NULL,&VertexShader)))<br />
{<br />
SAFE_RELEASE(pCompiledShader);<br />
MessageBox(0,L"頂点シェーダー作成失敗",NULL,MB_OK);<br />
return E_FAIL;<br />
}<br />
//頂点インプットレイアウトを定義 <br />
D3D11_INPUT_ELEMENT_DESC layout[] =<br />
{<br />
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0,
D3D11_INPUT_PER_VERTEX_DATA, 0 },<br />
{ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12,
D3D11_INPUT_PER_VERTEX_DATA, 0 },<br />
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24,
D3D11_INPUT_PER_VERTEX_DATA, 0 },<br />
};<br />
UINT numElements = sizeof(layout)/sizeof(layout[0]);</p>
<p> //頂点インプットレイアウトを作成<br />
if( FAILED( Device->CreateInputLayout( layout, numElements,
pCompiledShader->GetBufferPointer(), pCompiledShader->GetBufferSize(),
&VertexLayout ) ) )<br />
return FALSE;<br />
//頂点インプットレイアウトをセット<br />
DeviceContext->IASetInputLayout( VertexLayout );</p>
<p> //ブロブからピクセルシェーダー作成<br />
if(FAILED(D3DX11CompileFromFile(L"shader.hlsl",NULL,NULL,"PS","ps_5_0",0,0,NULL,&pCompiledShader,&pErrors,NULL)))<br />
{<br />
MessageBox(0,L"ピクセルシェーダー読み込み失敗",NULL,MB_OK);<br />
return E_FAIL;<br />
}<br />
SAFE_RELEASE(pErrors);<br />
if(FAILED(Device->CreatePixelShader(pCompiledShader->GetBufferPointer(),pCompiledShader->GetBufferSize(),NULL,&PixelShader)))<br />
{<br />
SAFE_RELEASE(pCompiledShader);<br />
MessageBox(0,L"ピクセルシェーダー作成失敗",NULL,MB_OK);<br />
return E_FAIL;<br />
}<br />
SAFE_RELEASE(pCompiledShader);</p>
<p> //ラスタライズ設定<br />
D3D11_RASTERIZER_DESC rdc;<br />
ZeroMemory(&rdc,sizeof(rdc));<br />
rdc.CullMode=D3D11_CULL_NONE;<br />
rdc.FillMode=D3D11_FILL_SOLID;<br />
<br />
ID3D11RasterizerState* pIr=NULL;<br />
Device->CreateRasterizerState(&rdc,&pIr);<br />
DeviceContext->RSSetState(pIr);<br />
SAFE_RELEASE(pIr);<br />
//コンスタントバッファー作成 ここでは変換行列渡し用<br />
D3D11_BUFFER_DESC cb;<br />
cb.BindFlags= D3D11_BIND_CONSTANT_BUFFER;<br />
cb.ByteWidth= sizeof( SHADER_GLOBAL0 );<br />
cb.CPUAccessFlags=D3D11_CPU_ACCESS_WRITE;<br />
cb.MiscFlags =0;<br />
cb.StructureByteStride=0;<br />
cb.Usage=D3D11_USAGE_DYNAMIC;</p>
<p> if( FAILED(Device->CreateBuffer(
&cb,NULL,&ConstantBuffer[0])))<br />
{<br />
return E_FAIL;<br />
}<br />
//コンスタントバッファー作成 マテリアル渡し用<br />
cb.BindFlags= D3D11_BIND_CONSTANT_BUFFER;<br />
cb.ByteWidth= sizeof( SHADER_GLOBAL1 );<br />
cb.CPUAccessFlags=D3D11_CPU_ACCESS_WRITE;<br />
cb.MiscFlags =0;<br />
cb.StructureByteStride=0;<br />
cb.Usage=D3D11_USAGE_DYNAMIC;</p>
<p> if( FAILED(Device->CreateBuffer(
&cb,NULL,&ConstantBuffer[1])))<br />
{<br />
return E_FAIL;<br />
}<br />
//テクスチャー用サンプラー作成<br />
D3D11_SAMPLER_DESC SamDesc;<br />
ZeroMemory(&SamDesc,sizeof(D3D11_SAMPLER_DESC));</p>
<p> SamDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;<br />
SamDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;<br />
SamDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;<br />
SamDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;<br />
Device->CreateSamplerState( &SamDesc, &SampleLinear);<br />
//OBJファイルからオリジナルメッシュを作成<br />
obj.Load(FILE_NAME);</p>
<p> return S_OK;<br />
}</p>
<p>//レンダリング<br />
VOID Render()<br />
{<br />
float ClearColor[4] = {0,0,1,1 }; // クリア色作成 RGBAの順<br />
DeviceContext->ClearRenderTargetView( RenderTargetView, ClearColor
);//画面クリア<br />
DeviceContext->ClearDepthStencilView( DepthStencilView, D3D11_CLEAR_DEPTH,
1.0f, 0 );//深度バッファクリア</p>
<p> //変換行列作成<br />
D3DXMATRIX mWorld;<br />
D3DXMATRIX mView;<br />
D3DXMATRIX mProj;</p>
<p> //ワールド行列<br />
static float angle=0;<br />
angle+=0.03f;<br />
D3DXMATRIX mRot;<br />
D3DXMatrixRotationY(&mRot,(float)D3DXToRadian(angle));<br />
mWorld=mRot;<br />
//ビュー行列<br />
D3DXVECTOR3 Eye( 0.0f, 300.0f, -200.0f );<br />
D3DXVECTOR3 At( 0.0f, 0.0f, 0.0f );<br />
D3DXVECTOR3 Up( 0.0f, 1.0f, 0.0f );<br />
D3DXMatrixLookAtLH( &mView, &Eye, &At, &Up );</p>
<p> //プロジェクション行列<br />
D3DXMatrixPerspectiveFovLH( &mProj, ( float )D3DX_PI/4 ,
(float)WINDOW_WIDTH / (float)WINDOW_HEIGHT, 0.1f, 1000.0f );</p>
<p> //ワールド・ビュー・プロジェクション行列をシェーダーに渡す<br />
DeviceContext->VSSetConstantBuffers(0,1,&ConstantBuffer[0] );</p>
<p> D3D11_MAPPED_SUBRESOURCE pData;<br />
if( SUCCEEDED( DeviceContext->Map( ConstantBuffer[0], 0,
D3D11_MAP_WRITE_DISCARD, 0, &pData ) ) )<br />
{<br />
SHADER_GLOBAL0 sg;<br />
sg.mW=mWorld;<br />
D3DXMatrixTranspose( &sg.mW, &sg.mW );<br />
sg.mWVP=mWorld*mView*mProj;<br />
D3DXMatrixTranspose( &sg.mWVP, &sg.mWVP );<br />
sg.vLightDir=D3DXVECTOR4(LightDir.x,LightDir.y,LightDir.z,0.0f);<br />
sg.vEye=D3DXVECTOR4(Eye.x,Eye.y,Eye.z,0);<br />
memcpy_s( pData.pData, pData.RowPitch, (void*)&sg, sizeof( SHADER_GLOBAL0
) );<br />
DeviceContext->Unmap( ConstantBuffer[0], 0 );<br />
}<br />
DeviceContext->VSSetConstantBuffers(0,1,&ConstantBuffer[0] );<br />
DeviceContext->PSSetConstantBuffers(0,1,&ConstantBuffer[0] );<br />
//使用するシェーダーの登録<br />
DeviceContext->VSSetShader(VertexShader,NULL,0);<br />
DeviceContext->PSSetShader(PixelShader,NULL,0);<br />
//メッシュを描画<br />
obj.Draw();</p>
<p> SwapChain->Present( 0, 0 );//フリップ<br />
}</p>
<p>//終了時解放処理<br />
VOID Cleanup()<br />
{<br />
SAFE_RELEASE(SampleLinear);<br />
SAFE_RELEASE(Texture);<br />
SAFE_RELEASE(DepthStencil);<br />
SAFE_RELEASE(DepthStencilView);<br />
SAFE_RELEASE(VertexShader);<br />
SAFE_RELEASE(PixelShader);<br />
SAFE_RELEASE(ConstantBuffer[0]);<br />
SAFE_RELEASE(ConstantBuffer[1]);<br />
SAFE_RELEASE(VertexLayout); <br />
SAFE_RELEASE(SwapChain);<br />
SAFE_RELEASE(RenderTargetView);<br />
SAFE_RELEASE(DeviceContext);<br />
SAFE_RELEASE(Device);<br />
}</p>
<p>//メッセージプロシージャ<br />
LRESULT CALLBACK MsgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)<br />
{<br />
switch(msg)<br />
{<br />
case WM_DESTROY://終了時<br />
Cleanup();<br />
PostQuitMessage(0);<br />
break;<br />
}<br />
return DefWindowProc (hWnd, msg, wParam, lParam);<br />
}</p>
<p>//メイン関数<br />
INT WINAPI WinMain( HINSTANCE hInst,HINSTANCE hPrevInst,LPSTR szStr,INT
iCmdShow)<br />
{<br />
//ウインドウクラスの登録<br />
WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,<br />
GetModuleHandle(NULL), NULL, NULL, NULL, NULL,<br />
L"Window1", NULL };<br />
RegisterClassEx( &wc );<br />
//タイトルバーとウインドウ枠の分を含めてウインドウサイズを設定<br />
RECT rect;<br />
SetRect(&rect,0,0,WINDOW_WIDTH,WINDOW_HEIGHT);<br />
AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);<br />
rect.right=rect.right-rect.left;<br />
rect.bottom=rect.bottom-rect.top;<br />
rect.top=0;<br />
rect.left=0;<br />
//ウインドウの生成<br />
hWnd = CreateWindow( L"Window1", L"OBJローダ",<br />
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, rect.right,
rect.bottom,<br />
NULL, NULL, wc.hInstance, NULL );<br />
<br />
MSG msg;<br />
ZeroMemory(&msg,sizeof(msg));<br />
//Direct3D初期化<br />
if(SUCCEEDED(InitD3D(hWnd)))<br />
{<br />
//ウインドウ表示<br />
ShowWindow(hWnd,SW_SHOW);<br />
UpdateWindow(hWnd);<br />
while(msg.message!=WM_QUIT)<br />
{<br />
if( PeekMessage(&msg,NULL,0,0,PM_REMOVE))<br />
{<br />
TranslateMessage(&msg);<br />
DispatchMessage(&msg);<br />
}<br />
else<br />
{<br />
Render();<br />
}<br />
}<br />
}</p>
<p> //終了<br />
return 0;<br />
}</p>
</td>
</tr></tbody></table><p> </p>
<p><strong>OBJファイルを読み込んで表示します。</strong></p>
<p><a href="http://neo-arcadia.seesaa.net/"><strong>http://neo-arcadia.seesaa.net/</strong></a><strong><br />
こちらからモデルを借りてきて表示しています。</strong></p>
<p><strong><img alt="" src="http://www43.atwiki.jp/directx11?cmd=upload&act=open&pageid=20&file=obj.png" /></strong></p>
<p>shader.hlsl</p>
<table border="1" cellspacing="1" cellpadding="1" width="600"><tbody><tr><td>
<p>//グローバル<br />
Texture2D g_texDecal: register(t0);<br />
SamplerState g_samLinear : register(s0);</p>
<p>//グローバル<br />
cbuffer global_0:register(b0)<br />
{<br />
matrix g_mW;//ワールド行列<br />
matrix g_mWVP; //ワールドから射影までの変換行列<br />
float4 g_vLightDir; //ライトの方向ベクトル<br />
float4 g_vEye;//カメラ位置<br />
};</p>
<p>cbuffer global_1:register(b1)<br />
{<br />
float4 g_Ambient=float4(0,0,0,0);//アンビエント光<br />
float4 g_Diffuse=float4(1,0,0,0); //拡散反射(色)<br />
float4 g_Specular=float4(1,1,1,1);//鏡面反射<br />
};</p>
<p>//バーテックスバッファー出力構造体<br />
struct VS_OUTPUT<br />
{ <br />
float4 Pos : SV_POSITION;<br />
float4 Color : COLOR0;<br />
float3 Light : TEXCOORD0;<br />
float3 Normal : TEXCOORD1;<br />
float3 EyeVector : TEXCOORD2;<br />
float2 Tex : TEXCOORD3;<br />
};<br />
//<br />
//バーテックスシェーダー<br />
//<br />
VS_OUTPUT VS( float4 Pos : POSITION ,float4 Norm : NORMAL,float2 Tex :
TEXCOORD)<br />
{<br />
VS_OUTPUT output = (VS_OUTPUT)0;<br />
//射影変換(ワールド→ビュー→プロジェクション)<br />
//法線をワールド空間に<br />
output.Normal=mul(Norm, g_mW);<br />
output.Pos=mul(Pos,g_mWVP);<br />
//ライト方向<br />
output.Light=g_vLightDir;<br />
//視線ベクトル<br />
float3 PosWorld = normalize(output.Pos);<br />
output.EyeVector = g_vEye - PosWorld;<br />
<br />
float3 Normal = normalize(output.Normal);<br />
float3 LightDir = normalize(output.Light);<br />
float3 ViewDir = normalize(output.EyeVector);<br />
float4 NL = saturate(dot(Normal, LightDir));<br />
<br />
float3 Reflect = normalize(2 * NL * Normal - LightDir);<br />
float4 specular = pow(saturate(dot(Reflect, ViewDir)), 4);</p>
<p> output.Color= g_Diffuse * NL + specular*g_Specular;<br />
<br />
//テクスチャー座標<br />
output.Tex=Tex;</p>
<p> return output;<br />
}</p>
<p>//<br />
//ピクセルシェーダー<br />
//<br />
float4 PS( VS_OUTPUT input ) : SV_Target<br />
{<br />
float4 color=g_texDecal.Sample( g_samLinear, input.Tex );<br />
color+=input.Color;</p>
<p> return color;<br />
}</p>
</td>
</tr></tbody></table><p> </p>
<p>main.cpp</p>
<table border="1" cellspacing="1" cellpadding="1" width="600"><tbody><tr><td>
<p>#pragma comment(lib,"d3d11.lib")<br />
#pragma comment(lib,"d3dx11.lib")<br />
#pragma comment(lib,"d3dx10.lib")<br />
#pragma comment(lib,"d3dCompiler.lib")<br />
#include <stdio.h><br />
#include <vector><br />
#include <d3dx11.h><br />
#include <d3dx10.h><br />
#include <d3dCompiler.h></p>
<p>#define FILE_NAME "axel.obj"</p>
<p>using namespace std;</p>
<p>//安全に解放する<br />
#define SAFE_RELEASE(x) if(x){x->Release(); x=NULL;}</p>
<p>//定数定義<br />
#define WINDOW_WIDTH 320 //ウィンドウ幅<br />
#define WINDOW_HEIGHT 240 //ウィンドウ高さ</p>
<p>//グローバル変数<br />
HWND hWnd=NULL;<br />
ID3D11Device* Device = NULL; //デバイス<br />
ID3D11DeviceContext* DeviceContext=NULL; //デバイスコンテキスト<br />
IDXGISwapChain* SwapChain = NULL; //スワップチェイン<br />
ID3D11RenderTargetView* RenderTargetView = NULL; //レンダーターゲットビュー<br />
ID3D11DepthStencilView* DepthStencilView = NULL;<br />
ID3D11Texture2D* DepthStencil = NULL;<br />
ID3D11InputLayout* VertexLayout=NULL;</p>
<p>ID3D11VertexShader* VertexShader=NULL;//頂点シェーダー<br />
ID3D11PixelShader* PixelShader=NULL;//ピクセルシェーダー</p>
<p>ID3D11Buffer* ConstantBuffer[2];//コンスタントバッファ</p>
<p>D3DXVECTOR3 LightDir(1,1,-1);//ライト方向</p>
<p>ID3D11SamplerState* SampleLinear=NULL;//テクスチャーのサンプラー<br />
ID3D11ShaderResourceView* Texture=NULL;//テクスチャー</p>
<p>//シェーダーに渡す値<br />
struct SHADER_GLOBAL0<br />
{<br />
D3DXMATRIX mW;//ワールド行列<br />
D3DXMATRIX mWVP;//ワールドから射影までの変換行列<br />
D3DXVECTOR4 vLightDir;//ライト方向<br />
D3DXVECTOR4 vEye;//カメラ位置<br />
};<br />
struct SHADER_GLOBAL1<br />
{<br />
D3DXVECTOR4 vAmbient;//アンビエント<br />
D3DXVECTOR4 vDiffuse;//ディフューズ<br />
D3DXVECTOR4 vSpecular;//鏡面反射<br />
};</p>
<p>//マテリアル構造体<br />
struct MATERIAL<br />
{<br />
CHAR Name[255];<br />
D3DXVECTOR4 Ka;//アンビエント<br />
D3DXVECTOR4 Kd;//ディフューズ<br />
D3DXVECTOR4 Ks;//スペキュラー<br />
CHAR TextureName[255];//テクスチャファイル名<br />
ID3D11ShaderResourceView* pTexture;//テクスチャデータ<br />
DWORD MaxFace;//ポリゴン数<br />
}mat;</p>
<p>//頂点構造体<br />
struct VERTEX<br />
{<br />
D3DXVECTOR3 Pos;//位置<br />
D3DXVECTOR3 Normal;//法線<br />
D3DXVECTOR2 UV;//UV<br />
}vert;</p>
<p>//.OBJファイルクラス<br />
class OBJ{<br />
protected:<br />
vector <MATERIAL> Material;//マテリアル<br />
vector <VERTEX> Vertex;//頂点構造体<br />
ID3D11Buffer* VertexBuffer;//頂点バッファ<br />
ID3D11Buffer** IndexBuffer;//インデックスバッファ<br />
HRESULT LoadMaterialFromFile(LPSTR FileName);//マテリアルファイル読み込み<br />
public:<br />
void Draw();//描画<br />
HRESULT Load(LPSTR FileName);//読み込み<br />
};</p>
<p>OBJ obj;</p>
<p>//メッシュの描画<br />
void OBJ::Draw()<br />
{<br />
//バーテックスバッファをセット<br />
UINT stride = sizeof( VERTEX );<br />
UINT offset = 0;<br />
DeviceContext->IASetVertexBuffers( 0, 1, &VertexBuffer, &stride,
&offset );<br />
//マテリアルの数だけ、それぞれのマテリアルのインデックスバッファを描画<br />
for(DWORD i=0;i<Material.size();i++)<br />
{<br />
//使用されていないマテリアル対策<br />
if(Material[i].MaxFace==0)<br />
{<br />
continue;<br />
}<br />
//インデックスバッファをセット<br />
DeviceContext->IASetIndexBuffer(IndexBuffer[i], DXGI_FORMAT_R32_UINT, 0
);<br />
//プリミティブ・トポロジーをセット<br />
DeviceContext->IASetPrimitiveTopology(
D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST );<br />
//マテリアルの各要素をシェーダーに渡す<br />
D3D11_MAPPED_SUBRESOURCE pData;<br />
if( SUCCEEDED( DeviceContext->Map( ConstantBuffer[1],0,
D3D11_MAP_WRITE_DISCARD, 0, &pData ) ) )<br />
{<br />
SHADER_GLOBAL1 sg; <br />
sg.vAmbient=Material[i].Ka;<br />
sg.vDiffuse=Material[i].Kd;<br />
sg.vSpecular=Material[i].Ks;<br />
memcpy_s( pData.pData, pData.RowPitch, (void*)&sg, sizeof(
SHADER_GLOBAL1 ) );<br />
DeviceContext->Unmap( ConstantBuffer[1], 0 );<br />
}<br />
DeviceContext->VSSetConstantBuffers(1,1,&ConstantBuffer[1] );<br />
DeviceContext->PSSetConstantBuffers(1,1,&ConstantBuffer[1] );<br />
//テクスチャをシェーダーに渡す<br />
if(Material[i].TextureName[0] != NULL)<br />
{<br />
DeviceContext->PSSetSamplers(0,1,&SampleLinear);<br />
DeviceContext->PSSetShaderResources(0,1,&Material[i].pTexture);<br />
}<br />
DeviceContext->DrawIndexed(Material[i].MaxFace*3 , 0 ,0);<br />
}<br />
}</p>
<p>//マテリアルファイルを読み込む関数<br />
HRESULT OBJ::LoadMaterialFromFile(LPSTR FileName)<br />
{<br />
FILE* fp=NULL;<br />
fopen_s(&fp,FileName,"rt");<br />
char key[255]={0};<br />
bool flag=false;<br />
D3DXVECTOR4 v(0,0,0,0);<br />
<br />
fseek(fp,SEEK_SET,0);</p>
<p> while(!feof(fp))<br />
{<br />
//キーワード読み込み<br />
fscanf_s(fp,"%s ",key,sizeof(key));<br />
//マテリアル名<br />
if(strcmp(key,"newmtl")==0)<br />
{<br />
if(flag)Material.push_back(mat);<br />
flag=true;<br />
fscanf_s(fp,"%s ",key,sizeof(key));<br />
strcpy_s(mat.Name,key);<br />
}<br />
//Ka アンビエント<br />
if(strcmp(key,"Ka")==0)<br />
{<br />
fscanf_s(fp,"%f %f %f",&v.x,&v.y,&v.z);<br />
mat.Ka=v;<br />
}<br />
//Kd ディフューズ<br />
if(strcmp(key,"Kd")==0)<br />
{<br />
fscanf_s(fp,"%f %f %f",&v.x,&v.y,&v.z);<br />
mat.Kd=v;<br />
}<br />
//Ks スペキュラー<br />
if(strcmp(key,"Ks")==0)<br />
{<br />
fscanf_s(fp,"%f %f %f",&v.x,&v.y,&v.z);<br />
mat.Ks=v;<br />
}<br />
//map_Kd テクスチャ<br />
if(strcmp(key,"map_Kd")==0)<br />
{<br />
fscanf_s(fp,"%s",&mat.TextureName,sizeof(mat.TextureName));<br />
//テクスチャを作成<br />
if(FAILED(D3DX11CreateShaderResourceViewFromFileA( Device, mat.TextureName,
NULL, NULL, &mat.pTexture, NULL )))<br />
{<br />
return E_FAIL;<br />
}<br />
}<br />
}<br />
fclose(fp);<br />
if(flag)Material.push_back(mat);<br />
<br />
return S_OK;<br />
}</p>
<p>//OBJファイルからメッシュに必要な情報を読み込む<br />
HRESULT OBJ::Load(LPSTR FileName)<br />
{<br />
//一時代入用<br />
D3DXVECTOR3 vec3d;<br />
D3DXVECTOR2 vec2d;<br />
vector <D3DXVECTOR3> Pos;<br />
vector <D3DXVECTOR3> Normal;<br />
vector <D3DXVECTOR2> UV;<br />
vector <int> FaceIndex;<br />
int v1=0,v2=0,v3=0;<br />
int vn1=0,vn2=0,vn3=0;<br />
int vt1=0,vt2=0,vt3=0;<br />
DWORD dwFCount=0;//読み込みカウンタ</p>
<p> char key[255]={0};<br />
//OBJファイルを開いて内容を読み込む<br />
FILE* fp=NULL;<br />
fopen_s(&fp,FileName,"rt");<br />
<br />
//読み込み <br />
fseek(fp,SEEK_SET,0);</p>
<p> while(!feof(fp))<br />
{<br />
//キーワード<br />
ZeroMemory(key,sizeof(key));<br />
fscanf_s(fp,"%s ",key,sizeof(key)); <br />
//マテリアル<br />
if(strcmp(key,"mtllib")==0)<br />
{<br />
fscanf_s(fp,"%s ",key,sizeof(key));<br />
LoadMaterialFromFile(key);<br />
}<br />
//頂点<br />
if(strcmp(key,"v")==0)<br />
{<br />
fscanf_s(fp,"%f %f %f",&vec3d.x,&vec3d.y,&vec3d.z);<br />
Pos.push_back(vec3d);<br />
Vertex.push_back(vert);<br />
}<br />
//法線<br />
if(strcmp(key,"vn")==0)<br />
{ <br />
fscanf_s(fp,"%f %f %f",&vec3d.x,&vec3d.y,&vec3d.z);<br />
Normal.push_back(vec3d);<br />
}<br />
//テクスチャ<br />
if(strcmp(key,"vt")==0)<br />
{ <br />
fscanf_s(fp,"%f %f",&vec2d.x,&vec2d.y);<br />
UV.push_back(-vec2d);<br />
}<br />
//フェイス<br />
if(strcmp(key,"f")==0)<br />
{<br />
FaceIndex.push_back(0);<br />
}<br />
} </p>
<p> //マテリアルの数だけインデックスバッファを作成<br />
IndexBuffer=new ID3D11Buffer*[Material.size()];</p>
<p> bool boFlag=false;<br />
for(DWORD i=0;i<Material.size();i++)<br />
{ <br />
fseek(fp,SEEK_SET,0);<br />
dwFCount=0;</p>
<p> while(!feof(fp))<br />
{<br />
//キーワード<br />
ZeroMemory(key,sizeof(key));<br />
fscanf_s(fp,"%s ",key,sizeof(key));</p>
<p> //フェイス 読み込み→頂点インデックスに<br />
if(strcmp(key,"usemtl")==0)<br />
{<br />
fscanf_s(fp,"%s ",key,sizeof(key));<br />
if(strcmp(key,Material[i].Name)==0)<br />
{<br />
boFlag=true;<br />
}<br />
else<br />
{<br />
boFlag=false;<br />
}<br />
}<br />
if(strcmp(key,"f")==0 && boFlag==true)<br />
{<br />
if(Material[i].pTexture!=NULL)//テクスチャーありサーフェイス<br />
{<br />
fscanf_s(fp,"%d/%d/%d %d/%d/%d
%d/%d/%d",&v1,&vt1,&vn1,&v2,&vt2,&vn2,&v3,&vt3,&vn3);<br />
}<br />
else//テクスチャー無しサーフェイス<br />
{<br />
fscanf_s(fp,"%d//%d %d//%d
%d//%d",&v1,&vn1,&v2,&vn2,&v3,&vn3);<br />
}<br />
FaceIndex[dwFCount*3]=v1-1;<br />
FaceIndex[dwFCount*3+1]=v2-1;<br />
FaceIndex[dwFCount*3+2]=v3-1;<br />
dwFCount++;<br />
//頂点構造体に代入<br />
Vertex[v1-1].Pos=Pos[v1-1];<br />
Vertex[v1-1].Normal=Normal[vn1-1];<br />
Vertex[v1-1].UV=UV[vt1-1];<br />
Vertex[v2-1].Pos=Pos[v2-1];<br />
Vertex[v2-1].Normal=Normal[vn2-1];<br />
Vertex[v2-1].UV=UV[vt2-1];<br />
Vertex[v3-1].Pos=Pos[v3-1];<br />
Vertex[v3-1].Normal=Normal[vn3-1];<br />
Vertex[v3-1].UV=UV[vt3-1];<br />
}<br />
}<br />
if(dwFCount==0)//使用されていないマテリアル対策<br />
{<br />
IndexBuffer[i]=NULL;<br />
continue;<br />
}</p>
<p> //インデックスバッファを作成<br />
D3D11_BUFFER_DESC bd;<br />
bd.Usage = D3D11_USAGE_DEFAULT;<br />
bd.ByteWidth = sizeof( int ) * dwFCount * 3;<br />
bd.BindFlags = D3D11_BIND_INDEX_BUFFER;<br />
bd.CPUAccessFlags = 0;<br />
bd.MiscFlags = 0;<br />
D3D11_SUBRESOURCE_DATA InitData;<br />
InitData.pSysMem = &FaceIndex[0];<br />
InitData.SysMemPitch=0;<br />
InitData.SysMemSlicePitch=0;<br />
if( FAILED( Device->CreateBuffer( &bd, &InitData,
&IndexBuffer[i] ) ) )return FALSE;<br />
Material[i].MaxFace=dwFCount; <br />
}<br />
FaceIndex.clear();<br />
fclose(fp);</p>
<p> //バーテックスバッファを作成<br />
D3D11_BUFFER_DESC bd;<br />
bd.Usage = D3D11_USAGE_DEFAULT;<br />
bd.ByteWidth = sizeof( VERTEX ) *Vertex.size();<br />
bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;<br />
bd.CPUAccessFlags = 0;<br />
bd.MiscFlags = 0;<br />
D3D11_SUBRESOURCE_DATA InitData;<br />
InitData.pSysMem = &Vertex[0];<br />
if( FAILED( Device->CreateBuffer( &bd, &InitData, &VertexBuffer
) ) )return FALSE; </p>
<p><br />
Pos.clear();<br />
Normal.clear();<br />
UV.clear();<br />
Vertex.clear(); </p>
<p> return S_OK;<br />
}</p>
<p>//Direct3Dの初期化関数<br />
HRESULT InitD3D(HWND hWnd)<br />
{<br />
// デバイスとスワップチェーンの作成<br />
DXGI_SWAP_CHAIN_DESC sd;<br />
ZeroMemory( &sd, sizeof(sd) );<br />
sd.BufferCount = 1; //バックバッファの数<br />
sd.BufferDesc.Width = WINDOW_WIDTH; //バッファの幅<br />
sd.BufferDesc.Height = WINDOW_HEIGHT; //バッファの高さ<br />
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; //バッファのフォーマット<br />
sd.BufferDesc.RefreshRate.Numerator = 60; //リフレッシュレート<br />
sd.BufferDesc.RefreshRate.Denominator = 1;<br />
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;<br />
sd.OutputWindow = hWnd;<br />
sd.SampleDesc.Count = 1;<br />
sd.SampleDesc.Quality = 0;<br />
sd.Windowed = TRUE;</p>
<p> D3D_FEATURE_LEVEL FeatureLevel = D3D_FEATURE_LEVEL_11_0;<br />
D3D_FEATURE_LEVEL* pFeatureLevel = NULL;</p>
<p><br />
if( FAILED( D3D11CreateDeviceAndSwapChain( NULL, D3D_DRIVER_TYPE_HARDWARE,
NULL,0,<br />
&FeatureLevel,1,D3D11_SDK_VERSION, &sd, &SwapChain,
&Device ,NULL,&DeviceContext) ) )<br />
{<br />
return FALSE;<br />
}<br />
//レンダーターゲットビューの作成<br />
ID3D11Texture2D *BackBuffer;<br />
SwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D
),(LPVOID*)&BackBuffer); <br />
Device->CreateRenderTargetView( BackBuffer, NULL, &RenderTargetView
);<br />
SAFE_RELEASE(BackBuffer);<br />
//深度ステンシルビューの作成<br />
D3D11_TEXTURE2D_DESC descDepth;<br />
descDepth.Width = WINDOW_WIDTH;<br />
descDepth.Height = WINDOW_HEIGHT;<br />
descDepth.MipLevels = 1;<br />
descDepth.ArraySize = 1;<br />
descDepth.Format = DXGI_FORMAT_D32_FLOAT;<br />
descDepth.SampleDesc.Count = 1;<br />
descDepth.SampleDesc.Quality = 0;<br />
descDepth.Usage = D3D11_USAGE_DEFAULT;<br />
descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL;<br />
descDepth.CPUAccessFlags = 0;<br />
descDepth.MiscFlags = 0;<br />
Device->CreateTexture2D( &descDepth, NULL, &DepthStencil );</p>
<p> Device->CreateDepthStencilView( DepthStencil, NULL,
&DepthStencilView );<br />
//レンダーターゲットビューと深度ステンシルビューをパイプラインにバインド <br />
DeviceContext->OMSetRenderTargets(1,
&RenderTargetView,DepthStencilView);</p>
<p> //ビューポートの設定<br />
D3D11_VIEWPORT vp;<br />
vp.Width = WINDOW_WIDTH;<br />
vp.Height = WINDOW_HEIGHT;<br />
vp.MinDepth = 0.0f;<br />
vp.MaxDepth = 1.0f;<br />
vp.TopLeftX = 0;<br />
vp.TopLeftY = 0;<br />
DeviceContext->RSSetViewports( 1, &vp );</p>
<p> //hlslファイル読み込み<br />
ID3DBlob *pCompiledShader=NULL;<br />
ID3DBlob *pErrors=NULL;<br />
//ブロブから頂点シェーダー作成<br />
if(FAILED(D3DX11CompileFromFile(L"shader.hlsl",NULL,NULL,"VS","vs_5_0",0,0,NULL,&pCompiledShader,&pErrors,NULL)))<br />
{<br />
MessageBox(0,L"頂点シェーダー読み込み失敗",NULL,MB_OK);<br />
return E_FAIL;<br />
}<br />
SAFE_RELEASE(pErrors);</p>
<p>
if(FAILED(Device->CreateVertexShader(pCompiledShader->GetBufferPointer(),pCompiledShader->GetBufferSize(),NULL,&VertexShader)))<br />
{<br />
SAFE_RELEASE(pCompiledShader);<br />
MessageBox(0,L"頂点シェーダー作成失敗",NULL,MB_OK);<br />
return E_FAIL;<br />
}<br />
//頂点インプットレイアウトを定義 <br />
D3D11_INPUT_ELEMENT_DESC layout[] =<br />
{<br />
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0,
D3D11_INPUT_PER_VERTEX_DATA, 0 },<br />
{ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12,
D3D11_INPUT_PER_VERTEX_DATA, 0 },<br />
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24,
D3D11_INPUT_PER_VERTEX_DATA, 0 },<br />
};<br />
UINT numElements = sizeof(layout)/sizeof(layout[0]);</p>
<p> //頂点インプットレイアウトを作成<br />
if( FAILED( Device->CreateInputLayout( layout, numElements,
pCompiledShader->GetBufferPointer(), pCompiledShader->GetBufferSize(),
&VertexLayout ) ) )<br />
return FALSE;<br />
//頂点インプットレイアウトをセット<br />
DeviceContext->IASetInputLayout( VertexLayout );</p>
<p> //ブロブからピクセルシェーダー作成<br />
if(FAILED(D3DX11CompileFromFile(L"shader.hlsl",NULL,NULL,"PS","ps_5_0",0,0,NULL,&pCompiledShader,&pErrors,NULL)))<br />
{<br />
MessageBox(0,L"ピクセルシェーダー読み込み失敗",NULL,MB_OK);<br />
return E_FAIL;<br />
}<br />
SAFE_RELEASE(pErrors);<br />
if(FAILED(Device->CreatePixelShader(pCompiledShader->GetBufferPointer(),pCompiledShader->GetBufferSize(),NULL,&PixelShader)))<br />
{<br />
SAFE_RELEASE(pCompiledShader);<br />
MessageBox(0,L"ピクセルシェーダー作成失敗",NULL,MB_OK);<br />
return E_FAIL;<br />
}<br />
SAFE_RELEASE(pCompiledShader);</p>
<p> //ラスタライズ設定<br />
D3D11_RASTERIZER_DESC rdc;<br />
ZeroMemory(&rdc,sizeof(rdc));<br />
rdc.CullMode=D3D11_CULL_NONE;<br />
rdc.FillMode=D3D11_FILL_SOLID;<br />
<br />
ID3D11RasterizerState* pIr=NULL;<br />
Device->CreateRasterizerState(&rdc,&pIr);<br />
DeviceContext->RSSetState(pIr);<br />
SAFE_RELEASE(pIr);<br />
//コンスタントバッファー作成 ここでは変換行列渡し用<br />
D3D11_BUFFER_DESC cb;<br />
cb.BindFlags= D3D11_BIND_CONSTANT_BUFFER;<br />
cb.ByteWidth= sizeof( SHADER_GLOBAL0 );<br />
cb.CPUAccessFlags=D3D11_CPU_ACCESS_WRITE;<br />
cb.MiscFlags =0;<br />
cb.StructureByteStride=0;<br />
cb.Usage=D3D11_USAGE_DYNAMIC;</p>
<p> if( FAILED(Device->CreateBuffer(
&cb,NULL,&ConstantBuffer[0])))<br />
{<br />
return E_FAIL;<br />
}<br />
//コンスタントバッファー作成 マテリアル渡し用<br />
cb.BindFlags= D3D11_BIND_CONSTANT_BUFFER;<br />
cb.ByteWidth= sizeof( SHADER_GLOBAL1 );<br />
cb.CPUAccessFlags=D3D11_CPU_ACCESS_WRITE;<br />
cb.MiscFlags =0;<br />
cb.StructureByteStride=0;<br />
cb.Usage=D3D11_USAGE_DYNAMIC;</p>
<p> if( FAILED(Device->CreateBuffer(
&cb,NULL,&ConstantBuffer[1])))<br />
{<br />
return E_FAIL;<br />
}<br />
//テクスチャー用サンプラー作成<br />
D3D11_SAMPLER_DESC SamDesc;<br />
ZeroMemory(&SamDesc,sizeof(D3D11_SAMPLER_DESC));</p>
<p> SamDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;<br />
SamDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;<br />
SamDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;<br />
SamDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;<br />
Device->CreateSamplerState( &SamDesc, &SampleLinear);<br />
//OBJファイルからオリジナルメッシュを作成<br />
obj.Load(FILE_NAME);</p>
<p> return S_OK;<br />
}</p>
<p>//レンダリング<br />
VOID Render()<br />
{<br />
float ClearColor[4] = {0,0,1,1 }; // クリア色作成 RGBAの順<br />
DeviceContext->ClearRenderTargetView( RenderTargetView, ClearColor
);//画面クリア<br />
DeviceContext->ClearDepthStencilView( DepthStencilView, D3D11_CLEAR_DEPTH,
1.0f, 0 );//深度バッファクリア</p>
<p> //変換行列作成<br />
D3DXMATRIX mWorld;<br />
D3DXMATRIX mView;<br />
D3DXMATRIX mProj;</p>
<p> //ワールド行列<br />
static float angle=0;<br />
angle+=0.03f;<br />
D3DXMATRIX mRot;<br />
D3DXMatrixRotationY(&mRot,(float)D3DXToRadian(angle));<br />
mWorld=mRot;<br />
//ビュー行列<br />
D3DXVECTOR3 Eye( 0.0f, 300.0f, -200.0f );<br />
D3DXVECTOR3 At( 0.0f, 0.0f, 0.0f );<br />
D3DXVECTOR3 Up( 0.0f, 1.0f, 0.0f );<br />
D3DXMatrixLookAtLH( &mView, &Eye, &At, &Up );</p>
<p> //プロジェクション行列<br />
D3DXMatrixPerspectiveFovLH( &mProj, ( float )D3DX_PI/4 ,
(float)WINDOW_WIDTH / (float)WINDOW_HEIGHT, 0.1f, 1000.0f );</p>
<p> //ワールド・ビュー・プロジェクション行列をシェーダーに渡す<br />
DeviceContext->VSSetConstantBuffers(0,1,&ConstantBuffer[0] );</p>
<p> D3D11_MAPPED_SUBRESOURCE pData;<br />
if( SUCCEEDED( DeviceContext->Map( ConstantBuffer[0], 0,
D3D11_MAP_WRITE_DISCARD, 0, &pData ) ) )<br />
{<br />
SHADER_GLOBAL0 sg;<br />
sg.mW=mWorld;<br />
D3DXMatrixTranspose( &sg.mW, &sg.mW );<br />
sg.mWVP=mWorld*mView*mProj;<br />
D3DXMatrixTranspose( &sg.mWVP, &sg.mWVP );<br />
sg.vLightDir=D3DXVECTOR4(LightDir.x,LightDir.y,LightDir.z,0.0f);<br />
sg.vEye=D3DXVECTOR4(Eye.x,Eye.y,Eye.z,0);<br />
memcpy_s( pData.pData, pData.RowPitch, (void*)&sg, sizeof( SHADER_GLOBAL0
) );<br />
DeviceContext->Unmap( ConstantBuffer[0], 0 );<br />
}<br />
DeviceContext->VSSetConstantBuffers(0,1,&ConstantBuffer[0] );<br />
DeviceContext->PSSetConstantBuffers(0,1,&ConstantBuffer[0] );<br />
//使用するシェーダーの登録<br />
DeviceContext->VSSetShader(VertexShader,NULL,0);<br />
DeviceContext->PSSetShader(PixelShader,NULL,0);<br />
//メッシュを描画<br />
obj.Draw();</p>
<p> SwapChain->Present( 0, 0 );//フリップ<br />
}</p>
<p>//終了時解放処理<br />
VOID Cleanup()<br />
{<br />
SAFE_RELEASE(SampleLinear);<br />
SAFE_RELEASE(Texture);<br />
SAFE_RELEASE(DepthStencil);<br />
SAFE_RELEASE(DepthStencilView);<br />
SAFE_RELEASE(VertexShader);<br />
SAFE_RELEASE(PixelShader);<br />
SAFE_RELEASE(ConstantBuffer[0]);<br />
SAFE_RELEASE(ConstantBuffer[1]);<br />
SAFE_RELEASE(VertexLayout); <br />
SAFE_RELEASE(SwapChain);<br />
SAFE_RELEASE(RenderTargetView);<br />
SAFE_RELEASE(DeviceContext);<br />
SAFE_RELEASE(Device);<br />
}</p>
<p>//メッセージプロシージャ<br />
LRESULT CALLBACK MsgProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)<br />
{<br />
switch(msg)<br />
{<br />
case WM_DESTROY://終了時<br />
Cleanup();<br />
PostQuitMessage(0);<br />
break;<br />
}<br />
return DefWindowProc (hWnd, msg, wParam, lParam);<br />
}</p>
<p>//メイン関数<br />
INT WINAPI WinMain( HINSTANCE hInst,HINSTANCE hPrevInst,LPSTR szStr,INT
iCmdShow)<br />
{<br />
//ウインドウクラスの登録<br />
WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,<br />
GetModuleHandle(NULL), NULL, NULL, NULL, NULL,<br />
L"Window1", NULL };<br />
RegisterClassEx( &wc );<br />
//タイトルバーとウインドウ枠の分を含めてウインドウサイズを設定<br />
RECT rect;<br />
SetRect(&rect,0,0,WINDOW_WIDTH,WINDOW_HEIGHT);<br />
AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);<br />
rect.right=rect.right-rect.left;<br />
rect.bottom=rect.bottom-rect.top;<br />
rect.top=0;<br />
rect.left=0;<br />
//ウインドウの生成<br />
hWnd = CreateWindow( L"Window1", L"OBJローダ",<br />
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, rect.right,
rect.bottom,<br />
NULL, NULL, wc.hInstance, NULL );<br />
<br />
MSG msg;<br />
ZeroMemory(&msg,sizeof(msg));<br />
//Direct3D初期化<br />
if(SUCCEEDED(InitD3D(hWnd)))<br />
{<br />
//ウインドウ表示<br />
ShowWindow(hWnd,SW_SHOW);<br />
UpdateWindow(hWnd);<br />
while(msg.message!=WM_QUIT)<br />
{<br />
if( PeekMessage(&msg,NULL,0,0,PM_REMOVE))<br />
{<br />
TranslateMessage(&msg);<br />
DispatchMessage(&msg);<br />
}<br />
else<br />
{<br />
Render();<br />
}<br />
}<br />
}</p>
<p> //終了<br />
return 0;<br />
}</p>
</td>
</tr></tbody></table><p> </p>