(VS2012)プロジェクトをダウンロード
【DX11_Sprite.cpp】
//----------------------------------------------------------
//
// Application
// DX11_Sprite
//
// First Edition : October 21 2016
// Author Mr.K
//
#include "stdafx.h"
#include <stdio.h>
#include <crtdbg.h>
#include <D3D11.h>
#include <directxmath.h>
#include <D3Dcompiler.h>
using namespace DirectX;
#include "TextureLoader.h"
#include "D3D11Sprite.h"
#include "D3D11Font.h"
// import libraries
#pragma comment(lib,"d3d11.lib")
#pragma comment(lib,"d3dcompiler.lib")
#define MAX_LOADSTRING 100
#define SAFE_DELETE(o) if (o){ delete (o); o = NULL; }
#define SAFE_DELETE_ARRAY(o) if (o){ delete [] (o); o = NULL; }
#define SAFE_RELEASE(o) if(o){ (o)->Release(); o = NULL; }
// Globals
TCHAR *g_pDriverType = NULL;
TCHAR *g_pFeatureLevel = NULL;
UINT g_uiCount=0;
//
// prototypes
//
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HRESULT GetBackBufferSize(IDXGISwapChain *pSwapChain, DWORD *pWidth, DWORD *pHeight);
HRESULT CreateDepthStencilView(
ID3D11Device *pDevice,
INT width,
INT height,
DXGI_FORMAT fmtDepthStencil,
ID3D11DepthStencilView **ppDepthStencilView,
ID3D11Texture2D **ppDepthStencilTexture,
ID3D11ShaderResourceView **ppDepthStencilShaderResourceView
);
HRESULT CreateRenderTargetView(
ID3D11Device *pDevice,
IDXGISwapChain *pSwapChain,
ID3D11RenderTargetView **ppRenderTargetView,
ID3D11ShaderResourceView **ppRenderTargetShaderResourceView
);
HRESULT CreateDeviceContextAndSwapChain(
HWND hWnd,
ID3D11Device **ppDevice,
ID3D11DeviceContext **ppContext,
IDXGISwapChain **ppSwapChain,
D3D_DRIVER_TYPE *pDriverType,
D3D_FEATURE_LEVEL *pFeatureLevel
);
TCHAR *GetDriverTypeText(D3D_DRIVER_TYPE dt);
TCHAR *GetFeatureLevelText(D3D_FEATURE_LEVEL fl);
//
// WinMain
// the entry point of windows application
//
int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPTSTR lpCmdLine,
_In_ int nCmdShow)
{
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
MSG msg;
// 変数宣言
WNDCLASSEX wcex; // ウィンドウクラス構造体
HWND hWnd; // ウィンドウハンドル
RECT bounds,client; // RECT 構造体
// (1)-a ウィンドウクラスの登録
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)WndProc; // ウィンドウプロシージャの登録
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance; // アプリケーションインスタンス
wcex.hIcon = LoadIcon(NULL, MAKEINTRESOURCE(IDI_APPLICATION));
wcex.hCursor = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = _T("D3D11_Sprite"); // ウィンドウクラス名
wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
RegisterClassEx(&wcex);
// (1)-b ウィンドウの生成
hWnd = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW,wcex.lpszClassName,_T("D3D11_Sprite"),
WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX,
CW_USEDEFAULT,0,640,480,NULL,NULL,hInstance,NULL);
if( !hWnd )
return FALSE;
// ウィンドウサイズの調整
// ここは無くても動く
GetWindowRect(hWnd,&bounds);
GetClientRect(hWnd,&client);
MoveWindow(hWnd,bounds.left,bounds.top,
640 * 2 - client.right,
480 * 2 - client.bottom,
false );
// ウィンドウの再表示
ShowWindow( hWnd, nCmdShow );
UpdateWindow( hWnd );
//==========Direct3D11 の初期化処理===================
CoInitializeEx(NULL,COINIT_APARTMENTTHREADED); // COM を初期化
D3D_DRIVER_TYPE DriverType = D3D_DRIVER_TYPE_NULL;
ID3D11DeviceContext *pContext = NULL; // 描画環境
ID3D11Device *pDevice = NULL; // 仮想アダプタ(ハードウエア固有処理)
IDXGISwapChain *pSwapChain = NULL; // スワップチェイン
ID3D11RenderTargetView *pRenderTargetView = NULL; // レンダーターゲット
ID3D11DepthStencilView *pDepthStencilView = NULL; // 深度ステンシルバッファ
ID3D11Texture2D *pDepthStencilTexture = NULL; // 深度ステンシルサーフェイス
ID3D11ShaderResourceView *pRenderTargetShaderResourceView = NULL; //
ID3D11ShaderResourceView *pDepthStencilShaderResourceView = NULL; //
D3D_FEATURE_LEVEL FeatureLevel;
DWORD width, height; // Screen width, Screen height
CD3D11Font *pFont = NULL; // D3DFont
CD3D11Sprite *pSprite = NULL; // Sprite
HRESULT hr;
// デバイスとスワップチェインを生成
hr = CreateDeviceContextAndSwapChain(hWnd,&pDevice,&pContext,&pSwapChain,&DriverType,&FeatureLevel);
if ( FAILED( hr ) )
goto ERROR_EXIT;
// RenderTaget を生成
hr = CreateRenderTargetView(pDevice,pSwapChain,&pRenderTargetView,&pRenderTargetShaderResourceView);
if ( FAILED( hr ) )
goto ERROR_EXIT;
// 深度ステンシルバッファ生成のため Backbuffer のサイズを取得
hr = GetBackBufferSize(pSwapChain,&width, &height);
if ( FAILED( hr ) )
goto ERROR_EXIT;
// サイズとフォーマットを指定して、深度ステンシルバッファを生成
hr = CreateDepthStencilView(pDevice,width,height,DXGI_FORMAT_D16_UNORM,&pDepthStencilView,&pDepthStencilTexture,&pDepthStencilShaderResourceView);
if ( FAILED( hr ) )
goto ERROR_EXIT;
// デバイスコンテキストにレンダーターゲットと深度ステンシルを設定
pContext->OMSetRenderTargets( 1, &pRenderTargetView,pDepthStencilView);
// ビューポートの設定.
D3D11_VIEWPORT vp;
vp.Width = (FLOAT)width;
vp.Height = (FLOAT)height;
vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f;
vp.TopLeftX = 0;
vp.TopLeftY = 0;
// デバイスコンテキストにビューポートを設定.
pContext->RSSetViewports( 1, &vp );
//==========各種オブジェクト生成===================
// スプライトの作成
CTextureLoader::Initialize();
pSprite = new CD3D11Sprite();
pSprite->SetTexture(0,_T("res\\smile2.rle.tga"));
pSprite->RestoreDeviceObjects(pContext);
 
// フォントの作成
pFont = new CD3D11Font(pContext);
// デバッグ表示の用意
g_pDriverType = ::GetDriverTypeText(DriverType);
g_pFeatureLevel = GetFeatureLevelText(FeatureLevel);;
g_uiCount=0;
//=================================================
// メイン メッセージ ループ:
// (2)メッセージループ
FLOAT fAngle = 0;
while(true){
if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)){
if(msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}else{
// 指定色で画面クリア
float ClearColor[4] = { 0.0f, 0.125f, 0.3f, 1.0f }; //red,green,blue,alpha
pContext->ClearRenderTargetView( pRenderTargetView, ClearColor );
pContext->ClearDepthStencilView( pDepthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0 );
// スプライト描画
static int k = 0, animframe;
pSprite->SetDiffuse(1.0f,1.0f,1.0f,1.0f);
pSprite->Render(pContext,64.0f,100.0f,256.0f,256.0f,0); // 画像全体描画
// 画像一部描画(アニメーション)
k = (k+1) % 120;
animframe = 0;
if (k >= 96){
animframe = (k - 96)/6;
if (animframe >= 4){
animframe = 6 - animframe;
}
}
pSprite->Render(pContext,400.0f,210.0f,64.0f,64.0f,animframe*64.0f,0.0f,64.0f,64.0f,0);
// フォントを描画
FLOAT x = 0.0f, y = 0.0f;
TCHAR tmp[32];
int frame, sec, min, hour, day;
frame = g_uiCount % 60;
sec = (g_uiCount / 60) % 60;
min = (g_uiCount / 3600) % 60;
hour = (g_uiCount / (3600*60)) % 24;
day = (g_uiCount / (3600*60*24)) % 99;
_stprintf_s(tmp,_T("%02d:%02d:%02d:%02d:%02d"),day,hour,min,sec,frame);
pFont->DrawAnkText(pContext,tmp,XMFLOAT4(1.0f,1.0f,1.0f,0.75f),x,y);
pFont->DrawAnkText(pContext,g_pDriverType,XMFLOAT4(1.0f,0.25f,0.25f,1.0f),x,y+=24.f);
pFont->DrawAnkText(pContext,g_pFeatureLevel,XMFLOAT4(0.25f,1.0f,0.25f,1.0f),x,y+=24.f);
g_uiCount++;
// 結果をウインドウに反映
if (FAILED(hr = pSwapChain->Present( 1, 0 ))){
// デバイスロストへの対処は可能だが、ここでは単に終了する事にする
if (hr == DXGI_ERROR_DEVICE_RESET || hr == DXGI_ERROR_DEVICE_REMOVED){
MessageBox(NULL,_T("Device が失われましたので終了します"),_T("Assert"),MB_OK);
break;
}
}
}
}
ERROR_EXIT:
CTextureLoader::Destroy();
SAFE_DELETE(pSprite);
SAFE_DELETE(pFont);
if (pContext){
pContext->ClearState();
pContext->Flush();
}
SAFE_RELEASE(pRenderTargetShaderResourceView);
SAFE_RELEASE(pDepthStencilTexture);
SAFE_RELEASE(pDepthStencilShaderResourceView);
SAFE_RELEASE(pRenderTargetView);
SAFE_RELEASE(pDepthStencilView);
SAFE_RELEASE(pSwapChain);
SAFE_RELEASE(pContext);
SAFE_RELEASE(pDevice);
CoUninitialize(); // COM の終了
return (int) msg.wParam;
}
//
// 関数:WndProc
// 説明:ウインドウに渡されたイベントのハンドラ
//
LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
{
switch (message){
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
以下の関数は
初回と同じなので内容省略します。
【CreateDeviceContextAndSwapChain・・・デバイスとスワップチェインの生成】
・・・省略
【CreateRenderTargetView・・・レンダーターゲットの生成】
・・・省略
【CreateDepthStencilView・・・深度ステンシルバッファの生成】
・・・省略
【GetBackBufferSize・・・バックバッファサイズの取得】
・・・省略
【デバッグ用関数】
・・・省略
クラス CD3D11Sprite
【D3D11Sprite.h】
#pragma once
struct SpriteDataContext;
class CD3D11Sprite
{
public:
CD3D11Sprite(void);
virtual ~CD3D11Sprite(void);
virtual void SetTexture(INT no, TCHAR *pFilename);
virtual HRESULT RestoreDeviceObjects(ID3D11DeviceContext *pContext);
virtual HRESULT ReleaseDeviceObjects(ID3D11DeviceContext *pContext);
virtual void Render(ID3D11DeviceContext *pContext, FLOAT x, FLOAT y, FLOAT w, FLOAT h, INT no);
virtual void Render(ID3D11DeviceContext *pContext, FLOAT x, FLOAT y, FLOAT w, FLOAT h, FLOAT tx, FLOAT ty, FLOAT tw, FLOAT th, INT no);
virtual void SetDiffuse(FLOAT r, FLOAT g, FLOAT b, FLOAT a);
virtual INT GetNumTextures();
// keep 16-byte aligned
void *operator new(size_t size){
return _mm_malloc(size,16);
}
void operator delete(void *p){
return _mm_free(p);
}
protected:
HRESULT CompileShaderFromMemory(BYTE *code, DWORD dwSize, LPCSTR szEntryPoint,LPCSTR szShaderModel, ID3DBlob **ppBlobOut);
void InitFields();
SpriteDataContext *m_pDataContext;
ID3D11DeviceContext *m_pDeviceContext;
ID3D11Device *m_pDevice;
ID3D11SamplerState *m_pTextureSamplerState;
ID3D11VertexShader *m_pVertexShader;
ID3D11PixelShader *m_pPixelShader;
ID3D11PixelShader *m_pPixelShaderNoTex;
ID3D11InputLayout *m_pInputLayout;
ID3D11BlendState *m_pBlendState;
ID3D11Buffer *m_pVertexBuffer;
ID3D11Buffer *m_pConstantBuffer;
DirectX::XMMATRIX m_matProj;
DirectX::XMFLOAT4 m_vecDiffuse;
};
【D3D11Sprite.cpp】
//
// class CD3D11Sprite
// Desc: This class implements 2D sprites on Direct3D11
//
#include "stdafx.h"
#include <d3d11.h>
#include <directxmath.h>
#include <D3Dcompiler.h>
#include "D3D11Sprite.h"
#include "TextureLoader.h"
#include <vector>
//
#define SAFE_DELETE(o) if (o){ delete (o); o = NULL; }
#define SAFE_DELETE_ARRAY(o) if (o){ delete [] (o); o = NULL; }
#define SAFE_RELEASE(o) if (o){ (o)->Release(); o = NULL; }
static char shadercode[]="\
//-----------------------------------------------------------------------------------\n\
// texture sampler\n\
//-----------------------------------------------------------------------------------\n\
SamplerState textureSampler : register(s0);\n\
Texture2D diffuseTexture : register(t0);\n\
\n\
\n\
//-----------------------------------------------------------------------------------\n\
// Constant buffer\n\
//-----------------------------------------------------------------------------------\n\
cbuffer VSConstantBuffer : register( b0 )\n\
{\n\
matrix Proj; // 射影行列\n\
float4 Color; // モジュレ―トする色\n\
};\n\
\n\
\n\
//-----------------------------------------------------------------------------------\n\
// VSInput structure\n\
//-----------------------------------------------------------------------------------\n\
struct VSInput\n\
{\n\
float3 Position : POSITION; // 位置座標\n\
float2 texCoord : TEXCOORD0; // テクスチャ座標\n\
};\n\
\n\
//-----------------------------------------------------------------------------------\n\
// GSPSInput structure\n\
//-----------------------------------------------------------------------------------\n\
struct GSPSInput\n\
{\n\
float4 Position : SV_POSITION; // 位置座標\n\
float2 texCoord : TEXCOORD0; // テクスチャ座標\n\
float4 diffuse : COLOR; // 文字色\n\
};\n\
\n\
//-----------------------------------------------------------------------------------\n\
// 頂点シェーダエントリーポイント\n\
//-----------------------------------------------------------------------------------\n\
GSPSInput VSFunc( VSInput input )\n\
{\n\
GSPSInput output = (GSPSInput)0;\n\
\n\
// 入力データをfloat4 へ変換.\n\
float4 pos = float4( input.Position, 1.0f );\n\
\n\
// 射影空間に変換.\n\
float4 projPos = mul( Proj, pos );\n\
\n\
output.Position = projPos;\n\
output.texCoord = input.texCoord;\n\
output.diffuse = Color;\n\
return output;\n\
}\n\
\n\
//------------------------------------------------------------------------------------\n\
// ピクセルシェーダエントリーポイント\n\
//------------------------------------------------------------------------------------\n\
float4 PSFunc( GSPSInput psin ) : SV_TARGET0\n\
{\n\
float4 pixel = diffuseTexture.Sample(textureSampler, psin.texCoord);\n\
pixel = psin.diffuse * pixel;\n\
return pixel;\n\
}\n\
float4 PSFuncNoTex( GSPSInput psin ) : SV_TARGET0\n\
{\n\
return psin.diffuse;\n\
}\n\
\n";
// テクスチャ管理用のノード構造体
struct SpriteTexture{
TCHAR *pFilename;
ID3D11Texture2D *pTexture;
ID3D11ShaderResourceView *pTextureShaderResourceView;
DWORD dwSrcWidth;
DWORD dwSrcHeight;
SpriteTexture(){
pFilename = NULL;
pTexture = NULL;
pTextureShaderResourceView = NULL;
}
~SpriteTexture(){
SAFE_DELETE(pFilename);
SAFE_RELEASE(pTexture);
SAFE_RELEASE(pTextureShaderResourceView);
}
};
// テクスチャ管理用データ
// stl の展開を局所化するためローカルデータ構造としておく
struct SpriteDataContext{
std::vector<SpriteTexture *> pSpriteTextures;
};
// Vertex Structure
typedef struct {
DirectX::XMFLOAT3 position; // 位置座標
DirectX::XMFLOAT2 texture; // テクスチャ座標
} SpriteVertex;
// Constant buffer structure
typedef struct {
DirectX::XMMATRIX matProj;
DirectX::XMFLOAT4 color;
} SpriteConstantBuffer;
//
// constructor
//
CD3D11Sprite::CD3D11Sprite(void)
{
InitFields();
m_pDataContext = new SpriteDataContext;
}
//
// destructor
//
CD3D11Sprite::~CD3D11Sprite(void)
{
ReleaseDeviceObjects(m_pDeviceContext);
std::vector<SpriteTexture *>::iterator it;
it = m_pDataContext->pSpriteTextures.begin();
while(it != m_pDataContext->pSpriteTextures.end()){
SAFE_DELETE(*it);
++it;
}
SAFE_DELETE(m_pDataContext);
}
// 全フィールドの初期化
void CD3D11Sprite::InitFields(){
m_pDataContext = NULL;
m_pDeviceContext = NULL;
m_pDevice = NULL;
m_pTextureSamplerState = NULL;
m_pVertexShader = NULL;
m_pPixelShader = NULL;
m_pPixelShaderNoTex = NULL;
m_pInputLayout = NULL;
m_pBlendState = NULL;
m_pVertexBuffer = NULL;
m_pConstantBuffer = NULL;
}
//
// Restore device dependent objects.
//
HRESULT CD3D11Sprite::RestoreDeviceObjects(ID3D11DeviceContext *pContext){
ID3DBlob *pShader = NULL;
HRESULT hr = E_FAIL;
pContext->AddRef();
ReleaseDeviceObjects(pContext);
m_pDeviceContext = pContext;
m_pDeviceContext->GetDevice(&m_pDevice);
if (m_pDataContext){
std::vector<SpriteTexture*>::iterator it;
it = m_pDataContext->pSpriteTextures.begin();
while (it != m_pDataContext->pSpriteTextures.end()){
if (*it != NULL){
ID3D11Texture2D *pTexture = NULL;
ID3D11ShaderResourceView *pTextureShaderResourceView = NULL;
hr = CTextureLoader::CreateTextureFromFile(pContext,
(*it)->pFilename, &pTexture,
&(*it)->dwSrcWidth, &(*it)->dwSrcHeight
);
// シェーダリソースビューを生成.
if (SUCCEEDED(hr)){
D3D11_SHADER_RESOURCE_VIEW_DESC srvd;
D3D11_TEXTURE2D_DESC texDesc;
ZeroMemory( &srvd, sizeof( D3D11_SHADER_RESOURCE_VIEW_DESC ) );
pTexture->GetDesc(&texDesc);
srvd.Format = texDesc.Format;
srvd.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
srvd.Texture2D.MipLevels = texDesc.MipLevels;
srvd.Texture2D.MostDetailedMip = 0;
hr = m_pDevice->CreateShaderResourceView( pTexture, &srvd, &pTextureShaderResourceView);
}
if (FAILED(hr)){
SAFE_RELEASE(pTexture);
SAFE_RELEASE(pTextureShaderResourceView);
}
(*it)->pTexture = pTexture;
(*it)->pTextureShaderResourceView = pTextureShaderResourceView;
}
++it;
}
}
// 頂点シェーダの生成
hr = CompileShaderFromMemory((BYTE*)shadercode,sizeof(shadercode),"VSFunc","vs_4_0",&pShader);
if (FAILED(hr)){
return hr;
}
hr = m_pDevice->CreateVertexShader(pShader->GetBufferPointer(),pShader->GetBufferSize(),NULL,&m_pVertexShader);
if (FAILED(hr)){
return hr;
}
// 入力レイアウトの定義.
D3D11_INPUT_ELEMENT_DESC layout[] = {
{
"POSITION",
0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0
},
{
"TEXCOORD",
0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0
}
};
UINT numElements = ARRAYSIZE( layout );
// 入力レイアウトを生成.
hr = m_pDevice->CreateInputLayout(
layout,
numElements,
pShader->GetBufferPointer(),
pShader->GetBufferSize(),
&m_pInputLayout
);
SAFE_RELEASE(pShader);
if ( FAILED( hr ) )
{
return hr;
}
// 入力アセンブラに入力レイアウトを設定.
m_pDeviceContext->IASetInputLayout( m_pInputLayout );
// ピクセルシェーダの生成
hr = CompileShaderFromMemory((BYTE*)shadercode,sizeof(shadercode),"PSFunc","ps_4_0",&pShader);
if (FAILED(hr))
return hr;
hr = m_pDevice->CreatePixelShader(pShader->GetBufferPointer(),pShader->GetBufferSize(),NULL,&m_pPixelShader);
SAFE_RELEASE(pShader);
if (FAILED(hr))
return hr;
// ピクセルシェーダの生成
hr = CompileShaderFromMemory((BYTE*)shadercode,sizeof(shadercode),"PSFuncNoTex","ps_4_0",&pShader);
if (FAILED(hr))
return hr;
hr = m_pDevice->CreatePixelShader(pShader->GetBufferPointer(),pShader->GetBufferSize(),NULL,&m_pPixelShaderNoTex);
SAFE_RELEASE(pShader);
if (FAILED(hr))
return hr;
// テクスチャサンプラ―のセットアップ
{
D3D11_SAMPLER_DESC samplerDesc;
samplerDesc.Filter = D3D11_FILTER_ANISOTROPIC; // サンプリング時に使用するフィルタ。ここでは異方性フィルターを使用する。
samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; // 0 〜 1 の範囲外にある u テクスチャー座標の描画方法
samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; // 0 〜 1 の範囲外にある v テクスチャー座標
samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; // 0 〜 1 の範囲外にある w テクスチャー座標
samplerDesc.MipLODBias = 0; // 計算されたミップマップ レベルからのバイアス
samplerDesc.MaxAnisotropy = 16; // サンプリングに異方性補間を使用している場合の限界値。有効な値は 1 〜 16 。
samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; // 比較オプション。
memcpy((void*)&samplerDesc.BorderColor,(void*)&DirectX::XMFLOAT4(0,0,0,0),4*sizeof(FLOAT));
samplerDesc.MinLOD = 0; // アクセス可能なミップマップの下限値
samplerDesc.MaxLOD = D3D11_FLOAT32_MAX; // アクセス可能なミップマップの上限値
// ID3D11Device::CreateSamplerState
hr = m_pDevice->CreateSamplerState( &samplerDesc, &m_pTextureSamplerState );
if( FAILED( hr ) )
return hr;
}
// 頂点バッファの設定.
{
// 頂点の定義.
SpriteVertex vertices[] = {
{ DirectX::XMFLOAT3( -0.5f, 0.5f, 0.0f ), DirectX::XMFLOAT2( 0.0f, 0.0f ) },
{ DirectX::XMFLOAT3( 0.5f, 0.5f, 0.0f ), DirectX::XMFLOAT2( 1.0f, 0.0f ) },
{ DirectX::XMFLOAT3( -0.5f, -0.5f, 0.0f ), DirectX::XMFLOAT2( 0.0f, 1.0f ) },
{ DirectX::XMFLOAT3( 0.5f, -0.5f, 0.0f ), DirectX::XMFLOAT2( 1.0f, 1.0f ) },
};
D3D11_BUFFER_DESC bd;
ZeroMemory( &bd, sizeof( D3D11_BUFFER_DESC ) );
bd.Usage = D3D11_USAGE_DEFAULT;
bd.ByteWidth = sizeof( SpriteVertex ) * 4;
bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bd.CPUAccessFlags = 0;
// サブリソースの設定.
D3D11_SUBRESOURCE_DATA initData;
ZeroMemory( &initData, sizeof( D3D11_SUBRESOURCE_DATA ) );
initData.pSysMem = vertices;
// 頂点バッファの生成.
hr = m_pDevice->CreateBuffer( &bd, &initData, &m_pVertexBuffer );
if ( FAILED( hr ) )
{
return hr;
}
}
// 定数バッファの生成.
{
// 定数バッファの設定.
D3D11_BUFFER_DESC bd;
ZeroMemory( &bd, sizeof( D3D11_BUFFER_DESC ) );
bd.ByteWidth = sizeof( SpriteConstantBuffer );
bd.Usage = D3D11_USAGE_DEFAULT;
bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
bd.CPUAccessFlags = 0;
// 定数バッファを生成.
hr = m_pDevice->CreateBuffer( &bd, NULL, &m_pConstantBuffer );
if ( FAILED( hr ) )
{
return hr;
}
}
{
// アルファ抜きブレンドステートの生成
D3D11_BLEND_DESC BlendDesc;
ZeroMemory( &BlendDesc, sizeof( BlendDesc ) );
BlendDesc.AlphaToCoverageEnable = FALSE;
BlendDesc.IndependentBlendEnable = FALSE;
BlendDesc.RenderTarget[0].BlendEnable = TRUE;
BlendDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
BlendDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
BlendDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
BlendDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
BlendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
BlendDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
BlendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
for (int i = 1 ; i < 8 ; ++i){
BlendDesc.RenderTarget[i] = BlendDesc.RenderTarget[0];
}
hr = m_pDevice->CreateBlendState( &BlendDesc, &m_pBlendState );
if ( FAILED( hr ) )
{
return hr;
}
}
// 行列の設定.
{
// non scaled ortho matrix (2D)
m_matProj = DirectX::XMMatrixIdentity();
m_matProj.r[0].m128_f32[0] = 1.0f;
m_matProj.r[1].m128_f32[1] = 1.0f;
m_matProj.r[2].m128_f32[2] = 0.0f;
m_matProj.r[2].m128_f32[3] = 1.0f;
m_matProj.r[3].m128_f32[2] = 0.0f;
m_matProj.r[3].m128_f32[3] = 0.0f;
}
hr = S_OK;
return hr;
}
//
// Release device dependent objects.
//
HRESULT CD3D11Sprite::ReleaseDeviceObjects(ID3D11DeviceContext *pContext){
if (m_pDataContext){
std::vector<SpriteTexture*>::iterator it;
it = m_pDataContext->pSpriteTextures.begin();
while (it != m_pDataContext->pSpriteTextures.end()){
if (*it != NULL){
SAFE_RELEASE((*it)->pTexture);
SAFE_RELEASE((*it)->pTextureShaderResourceView);
}
++it;
}
}
SAFE_RELEASE(m_pDeviceContext);
SAFE_RELEASE(m_pDevice);
SAFE_RELEASE(m_pTextureSamplerState);
SAFE_RELEASE(m_pVertexShader);
SAFE_RELEASE(m_pPixelShader);
SAFE_RELEASE(m_pPixelShaderNoTex);
SAFE_RELEASE(m_pInputLayout);
SAFE_RELEASE(m_pBlendState);
SAFE_RELEASE(m_pVertexBuffer);
SAFE_RELEASE(m_pConstantBuffer);
return S_OK;
}
//
// method : SetTexture
// @param:
// no : texture no
// pFilename : filename
//
void CD3D11Sprite::SetTexture(INT no, TCHAR *pFilename){
int count = m_pDataContext->pSpriteTextures.size();
int len;
SpriteTexture *pTextureNode;
if (no >= count){
int add = count - no + 1;
for ( int i = 0; i < add ; ++i){
m_pDataContext->pSpriteTextures.push_back(NULL);
}
}
pTextureNode = m_pDataContext->pSpriteTextures[no];
if (pTextureNode == NULL){
pTextureNode = new SpriteTexture;
m_pDataContext->pSpriteTextures[no] = pTextureNode;
}else{
SAFE_DELETE_ARRAY(pTextureNode->pFilename);
SAFE_RELEASE(pTextureNode->pTexture);
SAFE_RELEASE(pTextureNode->pTextureShaderResourceView);
}
len = _tcslen(pFilename) + 1;
len = (len + 3)&0xfffffffc;
pTextureNode->pFilename = new TCHAR[len];
_tcscpy_s(pTextureNode->pFilename,len,pFilename);
}
INT CD3D11Sprite::GetNumTextures(){
INT num = 0;
if (m_pDataContext){
num = m_pDataContext->pSpriteTextures.size();
}
return num;
}
//
// method : Render
// @param :
// pContext : D3D11 context
// x : position - x
// y : position - y
// w : sprite width
// h : sprire height
// no : texture no
//
void CD3D11Sprite::Render(ID3D11DeviceContext *pContext, FLOAT x, FLOAT y, FLOAT w, FLOAT h, INT no){
Render(pContext,x,y,w,h,0.0f,0.0f,FLT_MAX,FLT_MAX,no);
}
//
// method : Render
// @param :
// pContext : D3D11 context
// x : position - x
// y : position - y
// w : sprite width
// h : sprire height
// tx : texture-coord.x
// ty : texture-coord.y
// tw : texture width
// th : texture height
// no : texture no
//
void CD3D11Sprite::Render(ID3D11DeviceContext *pContext, FLOAT x, FLOAT y, FLOAT w, FLOAT h,
FLOAT tx, FLOAT ty, FLOAT tw, FLOAT th, INT no){
SpriteTexture *pSpriteTexture = NULL;
ID3D11Texture2D *pTexture = NULL;
ID3D11ShaderResourceView *pTextureShaderResourceView = NULL;
if (m_pDataContext == NULL)
return;
if (no >= 0 && no < (INT)m_pDataContext->pSpriteTextures.size()){
pSpriteTexture = m_pDataContext->pSpriteTextures[no];
if (pSpriteTexture != NULL){
pTexture = pSpriteTexture->pTexture;
pTextureShaderResourceView = pSpriteTexture->pTextureShaderResourceView;
}
}
if (pSpriteTexture == NULL)
return;
// シェーダを設定して描画.
pContext->VSSetShader( m_pVertexShader, NULL, 0 );
pContext->GSSetShader( NULL, NULL, 0 );
if (pTextureShaderResourceView == NULL){
pContext->PSSetShader( m_pPixelShaderNoTex, NULL, 0 ); // テクスチャ無し
}else{
pContext->PSSetShader( m_pPixelShader, NULL, 0 ); // テクスチャ有り
}
// 定数バッファの設定.
SpriteConstantBuffer cb;
cb.matProj = m_matProj;
cb.color = m_vecDiffuse;
// サブリソースを更新.
pContext->UpdateSubresource( m_pConstantBuffer, 0, NULL, &cb, 0, 0 );
// ジオメトリシェーダに定数バッファを設定.
pContext->VSSetConstantBuffers( 0, 1, &m_pConstantBuffer );
float blendFactor[4] = {0.0f, 0.0f, 0.0f, 0.0f};
pContext->OMSetBlendState( m_pBlendState, blendFactor, 0xffffffff );
// 頂点バッファの設定.
{
D3D11_VIEWPORT vp;
UINT uiNumViewport = 1;
m_pDeviceContext->RSGetViewports(&uiNumViewport,&vp);
if (uiNumViewport != 1)
return;
// transform 2D -> clipping space
FLOAT l = x;
FLOAT t = y;
FLOAT r = l + w;
FLOAT b = t + h;
FLOAT z = 1.0f;
FLOAT tx1, ty1;
FLOAT tx2, ty2;
l /= vp.Width*0.5f;
t /= vp.Height*0.5f;
r /= vp.Width*0.5f;
b /= vp.Height*0.5f;
l -= 1.0f;
r -= 1.0f;
t = 1.0f - t;
b = 1.0f - b;
tx1 = ty1 = 0.0f;
tx2 = ty2 = tx1;
if (pTexture != NULL){
D3D11_TEXTURE2D_DESC desc;
FLOAT texW, texH;
pTexture->GetDesc(&desc);
texW = (FLOAT)desc.Width;
texH = (FLOAT)desc.Height;
tx1 = tx / texW;
ty1 = ty / texH;
if (tw == FLT_MAX){
tx2 = (FLOAT)pSpriteTexture->dwSrcWidth / texW;
ty2 = (FLOAT)pSpriteTexture->dwSrcHeight / texH;
}else{
tx2 = tx1 + tw / texW;
ty2 = ty1 + th / texH;
}
}
// 頂点の定義.
SpriteVertex vertices[] = {
{ DirectX::XMFLOAT3( l, t, z ), DirectX::XMFLOAT2( tx1, ty1 ) },
{ DirectX::XMFLOAT3( r, t, z ), DirectX::XMFLOAT2( tx2, ty1 ) },
{ DirectX::XMFLOAT3( l, b, z ), DirectX::XMFLOAT2( tx1, ty2 ) },
{ DirectX::XMFLOAT3( r, b, z ), DirectX::XMFLOAT2( tx2, ty2 ) },
};
pContext->UpdateSubresource( m_pVertexBuffer, 0, NULL, vertices, 0, 0 );
}
// 入力アセンブラに頂点バッファを設定.
UINT stride = sizeof( SpriteVertex );
UINT offset = 0;
pContext->IASetVertexBuffers( 0, 1, &m_pVertexBuffer, &stride, &offset );
// プリミティブの種類を設定.
pContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP );
ID3D11ShaderResourceView* ppShaderResourceViews[] = { pTextureShaderResourceView, 0 };
ID3D11SamplerState *ppSamplerStates[] = { m_pTextureSamplerState, 0 };
pContext->PSSetShaderResources(0, 1, ppShaderResourceViews);
pContext->PSSetSamplers( 0, 1, ppSamplerStates );
pContext->Draw(4,0); // Draw 4 vertices.
ppSamplerStates[0] = NULL;
ppShaderResourceViews[0] = NULL;
pContext->PSSetSamplers( 0, 1, ppSamplerStates );
pContext->PSSetShaderResources(0, 1, ppShaderResourceViews);
// ブレンドステートを元に戻す
pContext->OMSetBlendState( NULL, blendFactor, 0xffffffff );
}
//
// Set diffuse color.
//
void CD3D11Sprite::SetDiffuse(FLOAT r, FLOAT g, FLOAT b, FLOAT a){
m_vecDiffuse.x = r;
m_vecDiffuse.y = g;
m_vecDiffuse.z = b;
m_vecDiffuse.w = a;
}
#define D3D_COMPILE_STANDARD_FILE_INCLUDE ((ID3DInclude*)(UINT_PTR)1)
HRESULT CD3D11Sprite::CompileShaderFromMemory(BYTE* pCode, DWORD dwSize, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob **ppBlobOut){
// リターンコードを初期化.
HRESULT hr = S_OK;
// コンパイルフラグ.
DWORD dwShaderFlags = D3DCOMPILE_ENABLE_STRICTNESS;
#if defined(DEBUG) || defined(_DEBUG)
dwShaderFlags |= D3DCOMPILE_DEBUG;
#endif//defiend(DEBUG) || defined(_DEBUG)
#if defined(NDEBUG) || defined(_NDEBUG)
//dwShaderFlags |= D3DCOMPILE_OPTIMIZATION_LEVEL3;
#endif//defined(NDEBUG) || defined(_NDEBUG)
ID3DBlob* pErrorBlob = NULL;
// シェーダをコンパイル.
hr = D3DCompile(pCode,dwSize,NULL,NULL,D3D_COMPILE_STANDARD_FILE_INCLUDE,
szEntryPoint,szShaderModel,dwShaderFlags,0,ppBlobOut,&pErrorBlob);
// エラーチェック.
if ( FAILED( hr ) )
{
// エラーメッセージを出力.
if ( pErrorBlob != NULL )
{ OutputDebugStringA( (char*)pErrorBlob->GetBufferPointer() ); }
}
// 解放処理.
if ( pErrorBlob )
{
pErrorBlob->Release();
pErrorBlob = NULL;
}
// リターンコードを返却.
return hr;
}
クラス CTextureLoader
【TextureLoader.h】
#pragma once
struct IWICImagingFactory;
class CTextureLoader
{
private:
CTextureLoader(void);
virtual ~CTextureLoader(void);
public:
static void Initialize();
static CTextureLoader *GetInstance();
static void Destroy();
static HRESULT CreateTextureFromFile(ID3D11DeviceContext *pContext, TCHAR *pFilename, ID3D11Texture2D **ppTexture, DWORD *pSrcWidth, DWORD *pSrcHeight);
protected:
IWICImagingFactory *m_pFactory;
private:
static CTextureLoader *m_pInstance;
};
【TextureLoader.cpp】
//
// class CTextureLoader
//
// Desc : This program loads images via
// WIC ( Windows Imaging Component ) and
// creates 2D Textures
//
#include "stdafx.h"
#include <stdio.h>
#include <D3D11.h>
#include <D2D1.h>
#include <ddraw.h>
#include <wincodec.h>
#include "TextureLoader.h"
#include "ddsfunctions.h"
#include "tgafunctions.h"
#undef SAFE_RELEASE
#undef SAFE_DELETE
#undef SAFE_DELETE_ARRAY
#define SAFE_RELEASE(o) if (o){ (o)->Release(); o = NULL; }
#define SAFE_DELETE(o) if (o){ delete (o); o = NULL; }
#define SAFE_DELETE_ARRAY(o) if (o){ delete [] (o); o = NULL; }
CTextureLoader *CTextureLoader::m_pInstance = NULL;
CTextureLoader::CTextureLoader(void)
{
HRESULT hr = CoCreateInstance(
CLSID_WICImagingFactory,
nullptr,
CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&m_pFactory)
);
}
CTextureLoader::~CTextureLoader(void)
{
if (m_pFactory != NULL){
m_pFactory->Release();
m_pFactory = NULL;
}
//SAFE_RELEASE(m_pFactory);
}
void CTextureLoader::Initialize(){
if (m_pInstance != NULL)
return;
m_pInstance = new CTextureLoader();
}
CTextureLoader *CTextureLoader::GetInstance(){
if (m_pInstance == NULL){
Initialize();
}
return m_pInstance;
}
void CTextureLoader::Destroy(){
if (m_pInstance != NULL){
delete m_pInstance;
m_pInstance = NULL;
}
}
//
// function CopyBitmapSourceToTexture2D
// @param :
// pContext : Device's context
// pBitmapSource : BitmapSource to copy
// pTexture : The Texture to copy to
// stride : Texture's vertical stride
// size : Texture's size
//
HRESULT CopyBitmapSourceToTexture2D(ID3D11DeviceContext *pContext, IWICBitmapSource *pBitmapSource, ID3D11Texture2D *pTexture, UINT stride, UINT size){
D3D11_MAPPED_SUBRESOURCE hMappedResource;
HRESULT hr;
hr = pContext->Map(
pTexture,
0,
D3D11_MAP_WRITE_DISCARD,
0,
&hMappedResource );
if (SUCCEEDED(hr)){
// ここで書き込む
BYTE* pBits = (BYTE*)hMappedResource.pData;
hr = pBitmapSource->CopyPixels(NULL,stride, size, pBits);
pContext->Unmap(pTexture,0);
}
return hr;
}
//
// method: CreateTextureFromFile
// @param :
// pContext : (in)Device's context
// pFilename : (in)pathname of the image file
// ppTexture : (out) Load result
// pSrcWidth : (out) width of the source image ( != texture width )
// pSrcHight : (out) height of the source image ( != texture height )
//
// @return
// S_OK : succeeded
//
HRESULT CTextureLoader::CreateTextureFromFile(ID3D11DeviceContext *pContext, TCHAR *pFilename, ID3D11Texture2D **ppTexture, DWORD *pSrcWidth, DWORD *pSrcHeight){
IWICBitmapDecoder *pDecoder = NULL;
IWICBitmapFrameDecode *pFrame = NULL;
WICPixelFormatGUID pixelFormat;
ID3D11Texture2D *pOutput = NULL;
ID3D11Device *pDevice = NULL;
//IWICImagingFactory *pFactory;
HRESULT hr;
// Check if TGA
int len = _tcslen(pFilename);
if (len > 3){
TCHAR *pTale = pFilename;
pTale = pFilename + (len - 4);
#ifdef _TARGA_SUPPORTED_
if (0 == _tcsicmp(pTale,_T(".tga"))){
return CreateTextureFromTgaFile(pContext,pFilename,ppTexture,pSrcWidth,pSrcHeight);
}
#endif
#ifdef _DDS_SUPPORTED_
if (0 == _tcsicmp(pTale,_T(".dds"))){
// create texture from dds file
return CreateTextureFromDdsFile(pContext,pFilename,ppTexture,pSrcWidth,pSrcHeight);
}
#endif
}
// create texture using WIC
CTextureLoader *pInstance = GetInstance();
hr = pInstance->m_pFactory->CreateDecoderFromFilename(pFilename,0,
GENERIC_READ,WICDecodeMetadataCacheOnDemand,&pDecoder);
if (FAILED(hr))
goto ERROR_EXIT;
hr = pDecoder->GetFrame(0,&pFrame);
if (FAILED(hr))
goto ERROR_EXIT;
UINT width, height;
pFrame->GetSize(&width, &height);
// テクスチャの生成
D3D11_TEXTURE2D_DESC td;
UINT texWidth = 4, texHeight = 4;
while(texWidth < width)
texWidth <<= 1;
while(texHeight < height)
texHeight <<= 1;
ZeroMemory( &td, sizeof( D3D11_TEXTURE2D_DESC ) );
td.Width = texWidth;
td.Height = texHeight;
td.MipLevels = 1;
td.ArraySize = 1;
td.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
td.SampleDesc.Count = 1; // MULTI SAMPLE COUNT
td.SampleDesc.Quality = 0; // MULtI SAMPLE QUALITY
td.Usage = D3D11_USAGE_DYNAMIC; // Make it writeable
td.BindFlags = D3D11_BIND_SHADER_RESOURCE;
td.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
td.MiscFlags = 0;
pContext->GetDevice(&pDevice);
hr = pDevice->CreateTexture2D(&td,NULL,&pOutput);
if (FAILED(hr))
goto ERROR_EXIT;
// 読み込んだ画像のピクセルフォーマットを取得
hr = pFrame->GetPixelFormat(&pixelFormat);
if (FAILED(hr))
goto ERROR_EXIT;
if (pixelFormat != GUID_WICPixelFormat32bppBGRA){
IWICFormatConverter *pFC;
hr = m_pInstance->m_pFactory->CreateFormatConverter(&pFC);
if (FAILED(hr))
goto ERROR_EXIT;
// 画像変換の用意
hr = pFC->Initialize(pFrame,GUID_WICPixelFormat32bppBGRA, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom);
if (FAILED(hr)){
SAFE_RELEASE(pFC);
goto ERROR_EXIT;
}
// テクスチャに流し込み
CopyBitmapSourceToTexture2D(pContext,pFC,pOutput, 4*texWidth, 4 * texWidth* texHeight );
SAFE_RELEASE(pFC);
}else{
// 変換不要な時
CopyBitmapSourceToTexture2D(pContext,pFrame,pOutput, 4*texWidth, 4 * texWidth* texHeight );
}
ERROR_EXIT:
SAFE_RELEASE(pDevice);
if (FAILED(hr)){
SAFE_RELEASE(pOutput);
}else{
*ppTexture = pOutput;
*pSrcWidth = width;
*pSrcHeight = height;
}
SAFE_RELEASE(pFrame);
SAFE_RELEASE(pDecoder)
return hr;
}
Targa ファイルモジュール
【tgafunctions.h】
#pragma once
// Prototypes
HRESULT CreateTextureFromTgaFile(ID3D11DeviceContext *pContext, TCHAR *pFilename, ID3D11Texture2D **ppTexture, DWORD *pSrcWidth, DWORD *pSrcHeight);
#define _TARGA_SUPPORTED_
【tgafunctions.cpp】
//
// TrueVision Targa format module
//
#include "stdafx.h"
#include <stdio.h>
#include <D3D11.h>
#include <D2D1.h>
#include <ddraw.h>
#include <wincodec.h>
#include "tgafunctions.h"
//
// macros
//
#undef SAFE_RELEASE
#undef SAFE_DELETE
#undef SAFE_DELETE_ARRAY
#define SAFE_RELEASE(o) if (o){ (o)->Release(); o = NULL; }
#define SAFE_DELETE(o) if (o){ delete (o); o = NULL; }
#define SAFE_DELETE_ARRAY(o) if (o){ delete [] (o); o = NULL; }
//
// prototypes
//
HRESULT CopyTgaSourceToTexture2D(ID3D11DeviceContext *pContext, ID3D11Texture2D *pTexture, DWORD *pSource, UINT width, UINT height, UINT pitch, BYTE flags);
HRESULT DecodeTgaHeader(BYTE *pHeader, int *pPixelBits, BOOL *pRLE, BOOL *pBW, DWORD *pSrcWidth, DWORD *pSrcHeight, BYTE *pFlags);
HRESULT ConvertPixelsFromTgaFile(FILE *fp,DWORD *pBuffer, DWORD numPixels, BOOL bRLE, BOOL bBW, INT numBitsPerPixel);
//
// function CreateTextureFromTgaFile
// @param :
// pContext : (in)Device's context
// pFilename : (in)pathname of the image file
// ppTexture : (out) Load result
// pSrcWidth : (out) width of the source image ( != texture width )
// pSrcHight : (out) height of the source image ( != texture height )
//
HRESULT CreateTextureFromTgaFile(ID3D11DeviceContext *pContext, TCHAR *pFilename, ID3D11Texture2D **ppTexture, DWORD *pSrcWidth, DWORD *pSrcHeight){
FILE *fp = NULL;
errno_t err;
unsigned char header[256];
DWORD srcwidth,srcheight;
int pixelbits, row_pitch;
BOOL bRLE = false, bBW = false;
DWORD *pBuffer = NULL;
int num_elements = 0;
ID3D11Device *pDevice = NULL;
ID3D11Texture2D *pOutput = NULL;
HRESULT hr = E_FAIL;
int idlength;
BYTE src_descriptor;
err = _tfopen_s(&fp,pFilename,_T("rb"));
if (fp== NULL)
goto ERROR_EXIT;
// read the header;
fread_s(header,sizeof(header),1,1,fp);
idlength = ((int)header[0]) & 255;
if (idlength == 0)
idlength = 18;
fread_s(header+1,sizeof(header)-1,idlength-1,1,fp);
hr = DecodeTgaHeader(header,&pixelbits,&bRLE,&bBW,&srcwidth,&srcheight, &src_descriptor);
if (FAILED(hr)){
goto ERROR_EXIT;
}
num_elements = srcwidth * srcheight;
pBuffer = new DWORD[num_elements];
row_pitch = srcwidth * sizeof(DWORD);
// convert pixels
hr = ConvertPixelsFromTgaFile(fp,pBuffer,num_elements,bRLE,bBW,pixelbits);
if (FAILED(hr))
goto ERROR_EXIT;
// create an texture
D3D11_TEXTURE2D_DESC td;
UINT texWidth = 4, texHeight = 4;
while(texWidth < srcwidth)
texWidth <<= 1;
while(texHeight < srcheight)
texHeight <<= 1;
ZeroMemory( &td, sizeof( D3D11_TEXTURE2D_DESC ) );
td.Width = texWidth;
td.Height = texHeight;
td.MipLevels = 1;
td.ArraySize = 1;
td.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
td.SampleDesc.Count = 1; // MULTI SAMPLE COUNT
td.SampleDesc.Quality = 0; // MULtI SAMPLE QUALITY
td.Usage = D3D11_USAGE_DYNAMIC; // Make it writeable
td.BindFlags = D3D11_BIND_SHADER_RESOURCE;
td.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
td.MiscFlags = 0;
pContext->GetDevice(&pDevice);
hr = pDevice->CreateTexture2D(&td,NULL,&pOutput);
if (FAILED(hr))
goto ERROR_EXIT;
SAFE_RELEASE(pDevice);
// copy bits
hr = CopyTgaSourceToTexture2D(pContext,pOutput,pBuffer,srcwidth,srcheight,row_pitch, src_descriptor);
if (FAILED(hr))
goto ERROR_EXIT;
*pSrcWidth = srcwidth;
*pSrcHeight = srcheight;
*ppTexture = pOutput;
pOutput = NULL;
ERROR_EXIT:
if (fp != NULL)
fclose(fp);
SAFE_RELEASE(pOutput);
SAFE_RELEASE(pDevice);
SAFE_DELETE_ARRAY(pBuffer);
return hr;
}
//
// Decode TGA header
// @param:
// pHeader : (in)17 byte header
// pPixelBits : (out)bits per pixel
// pRLE : (out) is run length encoding
// pBW : (out) is black and white
// pSrcWidth : (out) width of source image.
// pSrcHeight : (out) height of source image.
//
HRESULT DecodeTgaHeader(BYTE *pHeader, int *pPixelBits, BOOL *pRLE, BOOL *pBW, DWORD *pSrcWidth, DWORD *pSrcHeight,BYTE *pFlags){
BOOL bRLE = false, bBW = false;
DWORD srcwidth,srcheight;
int pixelbits;
switch(pHeader[2] & 0xff){
case 0:
case 1:
case 9:
return E_FAIL;
case 2:
break;
case 3:
bBW = true;
break;
case 11:
bBW = true;
case 10:
bRLE = true;
break;
}
if (pHeader[1] != 0){
// we don't support color maps
return E_FAIL;
}
// picture size
srcwidth = ((DWORD)(*(unsigned short*)(pHeader+12)))&0xffffL;
srcheight = ((DWORD)(*(unsigned short*)(pHeader+14)))&0xffffL;
pixelbits = ((int)(pHeader[16])) & 0xff;
*pRLE = bRLE;
*pBW = bBW;
*pSrcWidth = srcwidth;
*pSrcHeight = srcheight;
*pPixelBits = pixelbits;
*pFlags = pHeader[17];
return S_OK;
}
//
// Convert pixels from TGA file
// @param:
// fp : FILE pointer
// pBuffer : (in-out) target buffer
// numPixels : (in) number of pixels
// bRLE : (in) iss run length encoding active
// bBW : (in) is black and white
// numBitsPerPixel : (in) number of bits per pixel
// flags : (in) tga's descriptor
//
HRESULT ConvertPixelsFromTgaFile(FILE *fp,DWORD *pBuffer, DWORD numPixels, BOOL bRLE, BOOL bBW, INT numBitsPerPixel){
DWORD current = 0;
int r, g, b, a;
if (!bRLE){ // without run length encoding
DWORD current = 0;
if (bBW){
BYTE pixel;
if (numBitsPerPixel != 8)
return E_FAIL;
while(current < numPixels){
if (1!= fread_s((void*)&pixel,1,1,1,fp))
return E_FAIL;
r = pixel & 255;
b = g = r;
a = 255;
pBuffer[current++] = (a << 24) + (r << 16) + (g << 8) + b;
}
}else{
switch(numBitsPerPixel){
case 8:
return E_FAIL;
case 16:
while(current < numPixels){
USHORT pixel;
if (1!= fread_s((void*)&pixel,2,2,1,fp))
return E_FAIL;
r = (((pixel >> 10) & 0x1f)*255)/31;
g = (((pixel >> 5 ) & 0x1f)*255)/31;
b = ((pixel & 0x1f) * 255) / 31;
a = ((pixel >> 15 ) & 0x1) * 255;
pBuffer[current++] = (a << 24) + (r << 16) + (g << 8) + b;
}
break;
case 24:
while(current < numPixels){
DWORD pixel = 0;
if (1!= fread_s((void*)&pixel,4,3,1,fp))
return E_FAIL;
r = (pixel >> 16) & 255;
g = (pixel >> 8) & 255;
b = pixel & 255;
a = 255;
pBuffer[current++] = (a << 24) + (r << 16) + (g << 8) + b;
}
break;
case 32:
while(current < numPixels){
DWORD pixel;
if (1!= fread_s((void*)&pixel,4,4,1,fp))
return E_FAIL;
r = (pixel >> 16) & 255;
g = (pixel >> 8) & 255;
b = pixel & 255;
a = (pixel >> 24) & 255;
pBuffer[current++] = (a << 24) + (r << 16) + (g << 8) + b;
}
break;
}
}
}else{ // with run length encodings.
BYTE byte;
int repeat;
DWORD targetPixel;
if (bBW){
BYTE pixel;
if (numBitsPerPixel != 8)
return E_FAIL;
while(current < numPixels){
if (1!= fread_s((void*)&byte,1,1,1,fp))
return E_FAIL;
repeat = byte & 0x7f;
++repeat;
if (byte & 0x80){
if (1!= fread_s((void*)&pixel,1,1,1,fp))
return E_FAIL;
r = pixel & 255;
b = g = r;
a = 255;
targetPixel = (a << 24) + (r << 16) + (g << 8) + b;
for (int i = 0; i < repeat && current < numPixels; ++i){
pBuffer[current++] = targetPixel;
}
}else{
for (int i = 0; i < repeat && current < numPixels; ++i){
if (1!= fread_s((void*)&pixel,1,1,1,fp))
return E_FAIL;
r = pixel & 255;
b = g = r;
a = 255;
pBuffer[current++] = (a << 24) + (r << 16) + (g << 8) + b;
}
}
}
}else{
switch(numBitsPerPixel){
case 8:
return E_FAIL;
case 16:
while(current < numPixels){
USHORT pixel;
if (1!= fread_s((void*)&byte,1,1,1,fp))
return E_FAIL;
repeat = byte & 0x7f;
++repeat;
if (byte & 0x80){
if (1!= fread_s((void*)&pixel,2,2,1,fp))
return E_FAIL;
r = (((pixel >> 10) & 0x1f)*255)/31;
g = (((pixel >> 5 ) & 0x1f)*255)/31;
b = ((pixel & 0x1f) * 255) / 31;
a = ((pixel >> 15 ) & 0x1) * 255;
targetPixel = (a << 24) + (r << 16) + (g << 8) + b;
for (int i = 0; i < repeat && current < numPixels; ++i){
pBuffer[current++] = targetPixel;
}
}else{
for (int i = 0; i < repeat && current < numPixels; ++i){
if (1!= fread_s((void*)&pixel,2,2,1,fp))
return E_FAIL;
r = (((pixel >> 10) & 0x1f)*255)/31;
g = (((pixel >> 5 ) & 0x1f)*255)/31;
b = ((pixel & 0x1f) * 255) / 31;
a = ((pixel >> 15 ) & 0x1) * 255;
pBuffer[current++] = (a << 24) + (r << 16) + (g << 8) + b;
}
}
}
break;
case 24:
while(current < numPixels){
DWORD pixel = 0;
if (1!= fread_s((void*)&byte,1,1,1,fp))
return E_FAIL;
repeat = byte & 0x7f;
++repeat;
if (byte & 0x80){
if (1!= fread_s((void*)&pixel,4,3,1,fp))
return E_FAIL;
r = (pixel >> 16) & 255;
g = (pixel >> 8) & 255;
b = pixel & 255;
a = 255;
targetPixel = (a << 24) + (r << 16) + (g << 8) + b;
for (int i = 0; i < repeat && current < numPixels; ++i){
pBuffer[current++] = targetPixel;
}
}else{
for (int i = 0; i < repeat && current < numPixels; ++i){
if (1!= fread_s((void*)&pixel,4,3,1,fp))
return E_FAIL;
r = (pixel >> 16) & 255;
g = (pixel >> 8) & 255;
b = pixel & 255;
a = 255;
pBuffer[current++] = (a << 24) + (r << 16) + (g << 8) + b;
}
}
}
break;
case 32:
while(current < numPixels){
DWORD pixel;
if (1!= fread_s((void*)&byte,1,1,1,fp))
return E_FAIL;
repeat = byte & 0x7f;
++repeat;
if (byte & 0x80){
if (1!= fread_s((void*)&pixel,4,4,1,fp))
return E_FAIL;
r = (pixel >> 16) & 255;
g = (pixel >> 8) & 255;
b = pixel & 255;
a = (pixel >> 24) & 255;
targetPixel = (a << 24) + (r << 16) + (g << 8) + b;
for (int i = 0; i < repeat && current < numPixels; ++i){
pBuffer[current++] = targetPixel;
}
}else{
for (int i = 0; i < repeat && current < numPixels; ++i){
if (1!= fread_s((void*)&pixel,4,4,1,fp))
return E_FAIL;
r = (pixel >> 16) & 255;
g = (pixel >> 8) & 255;
b = pixel & 255;
a = (pixel >> 24) & 255;
pBuffer[current++] = (a << 24) + (r << 16) + (g << 8) + b;
}
}
}
break;
}
}
}
return S_OK;
}
//
// function CopyTgaSourceToTexture2D
// @param :
// pContext : Device's context
// pTexture : The Texture to copy to
// pSource : Source to copy
// width : width of source image
// height : height of source image
// flags : tga flags
//
HRESULT CopyTgaSourceToTexture2D(ID3D11DeviceContext *pContext, ID3D11Texture2D *pTexture, DWORD *pSource, UINT width, UINT height, UINT pitch, BYTE flags){
D3D11_MAPPED_SUBRESOURCE hMappedResource;
HRESULT hr;
D3D11_TEXTURE2D_DESC td;
BYTE *pRawSource = (BYTE*)pSource;
pTexture->GetDesc(&td);
hr = pContext->Map(
pTexture,
0,
D3D11_MAP_WRITE_DISCARD,
0,
&hMappedResource );
if (SUCCEEDED(hr)){
// ここで書き込む
BYTE* pBits = (BYTE*)hMappedResource.pData;
UINT x, y;
INT sourceX=0, sourceY=0;
int diffX=1, diffY=1;
INT x2;
if (flags&0x10){
diffX = -1;
sourceX = width-1;
}
if (0 == (flags&0x20)){
sourceY = height - 1;
diffY = -1;
}
for(y=0; y < height; y++ )
{
DWORD* pDst32 = (DWORD*)(pBits+(y * hMappedResource.RowPitch));
x2 = sourceX;
for(x = 0; x < width; x++ )
{
*pDst32++ = *((DWORD*)(pRawSource+(x2*sizeof(DWORD))+(sourceY * pitch)));
x2 += diffX;
}
while(x < td.Width){
*pDst32++ = 0L;
++x;
}
sourceY += diffY;
}
while( y < td.Height){
DWORD* pDst32 = (DWORD*)(pBits+(y * hMappedResource.RowPitch));
for(x = 0; x < td.Width; x++ )
{
*pDst32++ = 0L;
}
++y;
}
pContext->Unmap(pTexture,0);
}
return hr;
}
DDS ファイルモジュール
【ddsfunctions.h】
#pragma once
//
//prototypes
//
HRESULT CreateTextureFromDdsFile(ID3D11DeviceContext *pContext, TCHAR *pFilename, ID3D11Texture2D **ppTexture, DWORD *pSrcWidth, DWORD *pSrcHeight);
#define _DDS_SUPPORTED_
【ddsfunctions.cpp】
//
// DDS file format module
//
// Cube map is not supported now
//
#include "stdafx.h"
#include <stdio.h>
#include <D3D11.h>
#include <D2D1.h>
#include <ddraw.h>
#include <wincodec.h>
//
// macros
//
#undef SAFE_RELEASE
#undef SAFE_DELETE
#undef SAFE_DELETE_ARRAY
#define SAFE_RELEASE(o) if (o){ (o)->Release(); o = NULL; }
#define SAFE_DELETE(o) if (o){ delete (o); o = NULL; }
#define SAFE_DELETE_ARRAY(o) if (o){ delete [] (o); o = NULL; }
//
// prototypes.
//
DXGI_FORMAT GetCompressedPixelFormatFromDdsHeader(DDSURFACEDESC2 *pddsc);
HRESULT CreateTextureFromDdsRgbImage(ID3D11DeviceContext *pContext, DDSURFACEDESC2 *pddsc, VOID *pBuffer, ID3D11Texture2D **ppTexture);
HRESULT CreateTextureFromDdsLinearImage(ID3D11DeviceContext *pContext, DDSURFACEDESC2 *pddsc, DXGI_FORMAT fmt, VOID *pBuffer, DWORD dwLinearSize, ID3D11Texture2D **ppTexture);
//
// function CreateTextureFromDdsFile
// @param :
// pContext : (in)Device's context
// pFilename : (in)pathname of the image file
// ppTexture : (out) Load result
// pSrcWidth : (out) width of the source image ( != texture width )
// pSrcHight : (out) height of the source image ( != texture height )
//
HRESULT CreateTextureFromDdsFile(ID3D11DeviceContext *pContext, TCHAR *pFilename, ID3D11Texture2D **ppTexture, DWORD *pSrcWidth, DWORD *pSrcHeight){
FILE *fp = NULL;
errno_t err;
unsigned char header[256];
DWORD *pBuffer = NULL;
ID3D11Texture2D *pOutput = NULL;
HRESULT hr = E_FAIL;
int idlength;
DDSURFACEDESC2 *pddsc = NULL;
DWORD dwLinearSize = 0L;
DXGI_FORMAT texFormat = DXGI_FORMAT_UNKNOWN;
err = _tfopen_s(&fp,pFilename,_T("rb"));
if (fp== NULL)
goto ERROR_EXIT;
// read the header;
fread_s(header,sizeof(header),4,1,fp);
if (*(DWORD*)header != 0x20534444L) // check FOURCC "DDS "
goto ERROR_EXIT;
fread_s(header,sizeof(header),1,1,fp);
idlength = ((int)header[0]) & 255;
if (idlength != 0x7c)
goto ERROR_EXIT;
fread_s(header+1,sizeof(header)-1,idlength-1,1,fp);
pddsc = (DDSURFACEDESC2*)header;
if (pddsc->dwFlags & DDSD_PITCH){
dwLinearSize = (DWORD)pddsc->lPitch;
dwLinearSize *= pddsc->dwHeight;
pBuffer = new DWORD[(dwLinearSize+3) >> 2];
fread((void*)pBuffer,1,dwLinearSize, fp);
hr = CreateTextureFromDdsRgbImage(pContext,pddsc,pBuffer,&pOutput);
if (SUCCEEDED(hr)){
*pSrcWidth = pddsc->dwWidth;
*pSrcHeight = pddsc->dwHeight;
*ppTexture = pOutput;
pOutput = NULL;
}
}else if (pddsc->dwFlags & DDSD_LINEARSIZE){
dwLinearSize = (DWORD)pddsc->dwLinearSize;
texFormat = GetCompressedPixelFormatFromDdsHeader(pddsc);
if (texFormat == DXGI_FORMAT_UNKNOWN){
goto ERROR_EXIT;
}
pBuffer = new DWORD[(dwLinearSize+3) >> 2];
fread((void*)pBuffer,1,dwLinearSize, fp);
hr = CreateTextureFromDdsLinearImage(pContext,pddsc,texFormat,pBuffer,dwLinearSize,&pOutput);
SAFE_DELETE_ARRAY(pBuffer);
if (FAILED(hr))
goto ERROR_EXIT;
*pSrcWidth = pddsc->dwWidth;
*pSrcHeight = pddsc->dwHeight;
*ppTexture = pOutput;
pOutput = NULL;
}else if ((pddsc->dwFlags & DDSD_WIDTH) && (pddsc->dwFlags & DDSD_HEIGHT)){
// no pitch no linear size
texFormat = GetCompressedPixelFormatFromDdsHeader(pddsc);
if (texFormat != DXGI_FORMAT_UNKNOWN){
// compressed format
switch(texFormat){
case DXGI_FORMAT_BC1_UNORM:
dwLinearSize = pddsc->dwWidth * pddsc->dwHeight;
dwLinearSize = (dwLinearSize+1) >> 1;
break;
case DXGI_FORMAT_BC2_UNORM:
dwLinearSize = pddsc->dwWidth * pddsc->dwHeight;
break;
case DXGI_FORMAT_BC3_UNORM:
dwLinearSize = pddsc->dwWidth * pddsc->dwHeight;
break;
default:
goto ERROR_EXIT;
}
pBuffer = new DWORD[(dwLinearSize+3) >> 2];
fread((void*)pBuffer,1,dwLinearSize, fp);
hr = CreateTextureFromDdsLinearImage(pContext,pddsc,texFormat,pBuffer,dwLinearSize,&pOutput);
SAFE_DELETE_ARRAY(pBuffer);
if (FAILED(hr))
goto ERROR_EXIT;
*pSrcWidth = pddsc->dwWidth;
*pSrcHeight = pddsc->dwHeight;
*ppTexture = pOutput;
pOutput = NULL;
}else{
// uncompressed format
DWORD pixelSize = pddsc->ddpfPixelFormat.dwRGBBitCount;
pixelSize = (pixelSize + 7) >> 3; // byte size.
dwLinearSize = pixelSize * pddsc->dwWidth * pddsc->dwHeight;
pBuffer = new DWORD[(dwLinearSize+3) >> 2];
fread((void*)pBuffer,1,dwLinearSize, fp);
hr = CreateTextureFromDdsRgbImage(pContext,pddsc,pBuffer,&pOutput);
if (SUCCEEDED(hr)){
*pSrcWidth = pddsc->dwWidth;
*pSrcHeight = pddsc->dwHeight;
*ppTexture = pOutput;
pOutput = NULL;
}
}
}else
goto ERROR_EXIT; // can't calculate the size
ERROR_EXIT:
if (fp != NULL)
fclose(fp);
SAFE_RELEASE(pOutput);
SAFE_DELETE_ARRAY(pBuffer);
return hr;
}
//
// Create texture from DDS linear image
// @param
// pContext : (in) Device's context
// pddsc : (in) pointer to the direct draw surface
// fmt : (in) pixel format
// pBuffer : (in) image buffer
// dwLinearSize : (in) image data size
// ppTexture : (out) result texture.
//
HRESULT CreateTextureFromDdsLinearImage(ID3D11DeviceContext *pContext, DDSURFACEDESC2 *pddsc, DXGI_FORMAT fmt, VOID *pBuffer, DWORD dwLinearSize, ID3D11Texture2D **ppTexture){
HRESULT hr = E_FAIL;
D3D11_TEXTURE2D_DESC td;
D3D11_MAPPED_SUBRESOURCE hMappedResource;
ID3D11Device *pDevice = NULL;
ID3D11Texture2D *pOutput = NULL;
ZeroMemory( &td, sizeof( D3D11_TEXTURE2D_DESC ) );
td.Width = pddsc->dwWidth;
td.Height = pddsc->dwHeight;
td.MipLevels = (pddsc->dwFlags&DDSD_MIPMAPCOUNT)?pddsc->dwMipMapCount:1;
td.ArraySize = 1;
td.Format = fmt;
td.SampleDesc.Count = 1; // MULTI SAMPLE COUNT
td.SampleDesc.Quality = 0; // MULtI SAMPLE QUALITY
td.Usage = D3D11_USAGE_DYNAMIC; // Make it writeable
td.BindFlags = D3D11_BIND_SHADER_RESOURCE;
td.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
td.MiscFlags = 0;
pContext->GetDevice(&pDevice);
hr = pDevice->CreateTexture2D(&td,NULL,&pOutput);
if (SUCCEEDED(hr)){
hr = pContext->Map(
pOutput,
0,
D3D11_MAP_WRITE_DISCARD,
0,
&hMappedResource );
if (SUCCEEDED(hr)){
memcpy(hMappedResource.pData,pBuffer,dwLinearSize);
pContext->Unmap(pOutput,0);
*ppTexture = pOutput;
pOutput = NULL;
}
}
SAFE_RELEASE(pOutput);
SAFE_RELEASE(pDevice);
return hr;
}
//
// Get compressed pixel format from DDS Header
// @param
// pddsc : Direct Draw Surface Desc
// @return
// DXGI_FORMAT
// Note.
// if the format is uncompressed format returns DXGI_FORMAT_UNKNOWN
//
DXGI_FORMAT GetCompressedPixelFormatFromDdsHeader(DDSURFACEDESC2 *pddsc){
DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN;
if (pddsc->ddpfPixelFormat.dwFlags & DDPF_FOURCC){
switch(pddsc->ddpfPixelFormat.dwFourCC){
case FOURCC_DXT1:
format = DXGI_FORMAT_BC1_UNORM;
break;
case FOURCC_DXT2:
case FOURCC_DXT3:
format = DXGI_FORMAT_BC2_UNORM;
break;
case FOURCC_DXT4:
case FOURCC_DXT5:
format = DXGI_FORMAT_BC3_UNORM;
break;
}
}
return format;
}
//
// function CreateTextureFromDdsRgbImage
// @param
// pContext : (in)Device's context
// pddsc : (in)direct draw surface desc
// pBuffer : (in)image data
// ppTexture : (out) Load result
//
// Note:
// Create texture and put image with uncompressed format.
// converting pixel formats to DXGI_FORMAT_B8G8R8A8_UNORM
//
HRESULT CreateTextureFromDdsRgbImage(ID3D11DeviceContext *pContext, DDSURFACEDESC2 *pddsc, VOID *pBuffer, ID3D11Texture2D **ppTexture){
D3D11_TEXTURE2D_DESC td;
DWORD texWidth = 4;
DWORD texHeight = 4;
HRESULT hr = E_FAIL;
ID3D11Device *pDevice = NULL;
ID3D11Texture2D *pOutput = NULL;
D3D11_MAPPED_SUBRESOURCE hMappedResource;
if (0 == (pddsc->ddpfPixelFormat.dwFlags & DDPF_RGB)){
goto ERROR_EXIT;
}
while(texWidth < pddsc->dwWidth)
texWidth <<= 1;
while(texHeight < pddsc->dwHeight)
texHeight <<= 1;
ZeroMemory( &td, sizeof( D3D11_TEXTURE2D_DESC ) );
td.Width = texWidth;
td.Height = texHeight;
td.MipLevels = 1;
td.ArraySize = 1;
td.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
td.SampleDesc.Count = 1; // MULTI SAMPLE COUNT
td.SampleDesc.Quality = 0; // MULtI SAMPLE QUALITY
td.Usage = D3D11_USAGE_DYNAMIC; // Make it writeable
td.BindFlags = D3D11_BIND_SHADER_RESOURCE;
td.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
td.MiscFlags = 0;
pContext->GetDevice(&pDevice);
pDevice->CreateTexture2D(&td,NULL,&pOutput);
INT bitCount = (INT)pddsc->ddpfPixelFormat.dwRGBBitCount;
hr = pContext->Map(
pOutput,
0,
D3D11_MAP_WRITE_DISCARD,
0,
&hMappedResource );
if (FAILED(hr))
goto ERROR_EXIT;
hr = E_FAIL;
int r, g, b, a;
DWORD srcPitch;
DWORD srcWidth = pddsc->dwWidth;
DWORD srcHeight = pddsc->dwHeight;
DWORD x, y;
if (pddsc->dwFlags & DDSD_PITCH){
srcPitch = (DWORD)pddsc->lPitch;
}else{
DWORD pixelByte = (bitCount+7)>>3;
srcPitch = (DWORD)pddsc->dwWidth * ((bitCount+7)>>3);
}
BYTE *pDest = (BYTE*)hMappedResource.pData;
BYTE *pByte, *pSrc;
switch(bitCount){
case 32:
// A8R8G8B8 Just copy pixels
if ( (pddsc->ddpfPixelFormat.dwRBitMask == 0x00ff0000L)
&& (pddsc->ddpfPixelFormat.dwGBitMask == 0x0000ff00L)
&& (pddsc->ddpfPixelFormat.dwBBitMask == 0x000000ffL)
&& (pddsc->ddpfPixelFormat.dwRGBAlphaBitMask == 0xff000000L)){
// A8R8G8B8
for (y = 0; y < srcHeight ; ++y){
pByte = pDest + (y * hMappedResource.RowPitch);
pSrc = (BYTE*)pBuffer + (y * srcPitch);
for (x = 0; x < srcWidth ; ++x){
*(DWORD*)pByte = *(DWORD*)pSrc;
pSrc += sizeof(DWORD);
pByte += sizeof(DWORD);
}
while(x < texWidth){
*(DWORD*)pByte = 0L;
pByte += sizeof(DWORD);
++x;
}
}
while(y < texHeight){
pByte = pDest + (y * hMappedResource.RowPitch);
for (x = 0; x < texWidth ; ++x){
*(DWORD*)(pByte+sizeof(DWORD)*x) = 0L;
}
++y;
}
hr = S_OK;
}else if ( (pddsc->ddpfPixelFormat.dwRBitMask == 0x000000ffL)
&& (pddsc->ddpfPixelFormat.dwGBitMask == 0x0000ff00L)
&& (pddsc->ddpfPixelFormat.dwBBitMask == 0x00ff0000L)
&& (pddsc->ddpfPixelFormat.dwRGBAlphaBitMask == 0xff000000L)){
// A8B8G8R8 -> A8R8G8B8
for (y = 0; y < srcHeight ; ++y){
pByte = pDest + (y * hMappedResource.RowPitch);
pSrc = (BYTE*)pBuffer + (y * srcPitch);
for (x = 0; x < srcWidth ; ++x){
r = 0xff & (int)*pSrc++;
g = 0xff & (int)*pSrc++;
b = 0xff & (int)*pSrc++;
a = 0xff & (int)*pSrc++;
*(DWORD*)pByte = (a << 24)+(r << 16)+(g << 8) + b;
pByte += sizeof(DWORD);
}
while(x < texWidth){
*(DWORD*)pByte = 0L;
pByte += sizeof(DWORD);
++x;
}
}
while(y < texHeight){
pByte = pDest + (y * hMappedResource.RowPitch);
for (x = 0; x < texWidth ; ++x){
*(DWORD*)(pByte+sizeof(DWORD)*x) = 0L;
}
++y;
}
hr = S_OK;
}
break;
case 24:
if ( (pddsc->ddpfPixelFormat.dwRBitMask == 0xff0000L)
&& (pddsc->ddpfPixelFormat.dwGBitMask == 0x00ff00L)
&& (pddsc->ddpfPixelFormat.dwBBitMask == 0x0000ffL)
){
// R8G8B8 -> A8R8G8B8
for (y = 0; y < srcHeight ; ++y){
pByte = pDest + (y * hMappedResource.RowPitch);
pSrc = (BYTE*)pBuffer + (y * srcPitch);
for (x = 0; x < srcWidth ; ++x){
b = 0xff & (int)*pSrc++;
g = 0xff & (int)*pSrc++;
r = 0xff & (int)*pSrc++;
a = 255;
*(DWORD*)pByte = (a << 24)+(r << 16)+(g << 8) + b;
pByte += sizeof(DWORD);
}
while(x < texWidth){
*(DWORD*)pByte = 0L;
pByte += sizeof(DWORD);
++x;
}
}
while(y < texHeight){
pByte = pDest + (y * hMappedResource.RowPitch);
for (x = 0; x < texWidth ; ++x){
*(DWORD*)(pByte+sizeof(DWORD)*x) = 0L;
}
++y;
}
hr = S_OK;
}
break;
case 16:
if ( (pddsc->ddpfPixelFormat.dwRBitMask == 0x7c00L)
&& (pddsc->ddpfPixelFormat.dwGBitMask == 0x03e0L)
&& (pddsc->ddpfPixelFormat.dwBBitMask == 0x001fL)
&& (pddsc->ddpfPixelFormat.dwRGBAlphaBitMask == 0x8000L)
){
// A1R5G5B5 -> A8R8G8B8
USHORT usPixel;
for (y = 0; y < srcHeight ; ++y){
pByte = pDest + (y * hMappedResource.RowPitch);
pSrc = (BYTE*)pBuffer + (y * srcPitch);
for (x = 0; x < srcWidth ; ++x){
usPixel = *(USHORT*)pSrc;
r = (((usPixel >> 10)&0x1f)*255)/31;
g = (((usPixel >> 5) & 0x1f) * 255) / 31;
b = ((usPixel & 0x1f) * 255) / 31;
a = ((usPixel >> 15)&1) * 255;
*(DWORD*)pByte = (a << 24)+(r << 16)+(g << 8) + b;
pSrc += sizeof(USHORT);
pByte += sizeof(DWORD);
}
while(x < texWidth){
*(DWORD*)pByte = 0L;
pByte += sizeof(DWORD);
++x;
}
}
while(y < texHeight){
pByte = pDest + (y * hMappedResource.RowPitch);
for (x = 0; x < texWidth ; ++x){
*(DWORD*)(pByte+sizeof(DWORD)*x) = 0L;
}
++y;
}
hr = S_OK;
}else if ( (pddsc->ddpfPixelFormat.dwRBitMask == 0xf800L)
&& (pddsc->ddpfPixelFormat.dwGBitMask == 0x07e0L)
&& (pddsc->ddpfPixelFormat.dwBBitMask == 0x001fL)
){
// R5G6B5 -> A8R8G8B8
USHORT usPixel;
for (y = 0; y < srcHeight ; ++y){
pByte = pDest + (y * hMappedResource.RowPitch);
pSrc = (BYTE*)pBuffer + (y * srcPitch);
for (x = 0; x < srcWidth ; ++x){
usPixel = *(USHORT*)pSrc;
r = (((usPixel >> 11)&0x1f)*255)/31;
g = (((usPixel >> 5) & 0x3f) * 255) / 63;
b = ((usPixel & 0x1f) * 255) / 31;
a = 255;
*(DWORD*)pByte = (a << 24)+(r << 16)+(g << 8) + b;
pSrc += sizeof(USHORT);
pByte += sizeof(DWORD);
}
while(x < texWidth){
*(DWORD*)pByte = 0L;
pByte += sizeof(DWORD);
++x;
}
}
while(y < texHeight){
pByte = pDest + (y * hMappedResource.RowPitch);
for (x = 0; x < texWidth ; ++x){
*(DWORD*)(pByte+sizeof(DWORD)*x) = 0L;
}
++y;
}
hr = S_OK;
}
}
pContext->Unmap(pOutput,0);
if (SUCCEEDED(hr)){
*ppTexture = pOutput;
pOutput = NULL;
}
ERROR_EXIT:
SAFE_RELEASE(pOutput);
SAFE_RELEASE(pDevice);
return hr;
}
クラス CFont
Font のページを参照