前回、頂点カラーを設定してポリゴンに色をつけられるようになりました。
その際、ColorはRGBAの値で設定しましたが、A(=Alpha)値については1.0(不透明)固定のままいじりませんでした。
というのも、Alpha値に関しては、単純にシェーダーでカラー出力すれば終わり、というものではなくブレンドの設定が必要となるためです。
ということで、今回はAlphaブレンド(半透明処理)ができるようにしていきます。
前回の記事:
【3Dゲーム開発#05】ポリゴンの座標変換② : 移動・回転・スケールの2D変換
前回までで、DirectXMathを使って行列の用意、シェーダーで座標変換、ができました。今回は、「移動」「回転」「スケール」それぞれの2D変換について詳しく見ていきましょう。また、座標変換は、単体で終わるものではなく、移動・回転・スケール...
3Dゲーム開発記事のまとめ:「3Dゲーム開発」
ブレンドステートを設定して半透明処理をする
BlendStateオブジェクトの作成
冒頭でも書きましたが、半透明処理にはブレンドの設定が必要となります。
具体的には
- D3D11_BLEND_DESC型構造体にブレンドパラメータ設定
- CreateBlendStateメソッドでBlendStateオブジェクト作成
そのために、ID3D11BlendState
型のBlendStateオブジェクトを作成します。
// RenderTarget0へのAlphaブレンド描画設定
D3D11_BLEND_DESC BlendState;
ZeroMemory(&BlendState, sizeof(D3D11_BLEND_DESC));
BlendState.AlphaToCoverageEnable = FALSE;
BlendState.IndependentBlendEnable = FALSE;
BlendState.RenderTarget[0].BlendEnable = TRUE;
BlendState.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
BlendState.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
BlendState.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
BlendState.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
BlendState.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
BlendState.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
BlendState.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
hr = pD3DDevice_->CreateBlendState(&BlendState, &pBlendState_);
if (FAILED(hr)) {
//TRACE(L"InitDirect3D g_pD3DDevice->CreateBlendState", hr);
return false;
}
詳しいパラメータは以下の公式ドキュメントを参照ください。
D3D11_BLEND_DESC (d3d11.h) - Win32 apps
Describes the blend state that you use in a call to ID3D11Device::CreateBlendState to create a blend-state object.
この処理をRenderTargetの生成と合わせてやっておきましょう。
ですので、今までのプロジェクトのRenderer::initBackBuffer()
で追記しておけばよいです。
BlendStateオブジェクトを設定
作成したBlendStateオブジェクトは、以下のメソッドで設定することで有効となります。
BlendFactorは、上記Blend設定で、RGBA個別にブレンド具体を指定したい場合の係数値です。かなり特殊なBlendをしようとしない限り使わないのであまり気にしなくてよいです。
第3引数は、どのRenderTargetをサンプルするかのMask(ビットフラグ)で、今はRenderTargetは1つなので基本的に考慮不要で0xffffffffを指定しておけばよいです(実際には1でよいです、0ではだめです)。
参考:公式:ID3D11DeviceContext::OMSetBlendState method
描画設定としてRenderer::Draw
で呼び出しておきます。
void Renderer::Draw()
{
...
// OMにブレンドステートオブジェクトを設定
FLOAT BlendFactor[4] = { 0.f, 0.f, 0.f, 0.f };
pImmediateContext_->OMSetBlendState(pBlendState_, BlendFactor, 0xffffffff);
...
}
参考:出力マージャー(OutputMerger)とは
上記のインターフェースの通り、BlendStateはOM(出力マージャ)に設定しました。
出力マージャーとは、描画パイプラインでのほぼ最後のステージに相当して、ピクセルシェーダーで出力されたピクセルの色をRenderTargetへどう描き込むか決めるステージです。
ですので、Blend処理は、ピクセルシェーダーまではBlendStateとは無関係に色を計算し、この出力マージャー時点で、設定されたBlendStateに合わせて描き込まれる、ということです。
BlendState以外にも、Depth/Stencil(深度・ステンシル)テストの結果によって、そのピクセル描画をマスクするか、といったことも、出力マージャーステージで行う処理です。
BlendStateオブジェクトの破棄
生成したBlendStateオブジェクトは、他のDirectXリソースの破棄と同様にTerminateで破棄します。
void Renderer::Terminate()
{
...
DX_SAFE_RELEASE(pBlendState_);
...
}
結果
ということで、TriangleでのAlpha値を適当に変えれば半透明(RenderTargetのクリア色の黒とアルファブレンド)になり、以下のように薄い色で描画されます。
ソースコード
以下が今回の実装があるコードです。
https://github.com/prog-log/GameDev/blob/master/04-VertexColor/RenderParam.cpp
struct PS_INPUT {
float4 Pos : SV_POSITION; // 頂点座標(モデル座標系)
float4 Col : COLOR; // 頂点色
};
float4 main(PS_INPUT input) : SV_TARGET
{
return input.Col;
}
#include "Application.h"
void Application::Initialize(HINSTANCE hInst)
{
window_.Initialize(hInst);
renderer_.Initialize(window_.GetWindowHandle());
}
void Application::Loop()
{
while (true) {
bool result = window_.MessageLoop();
if (result == false) break;
bool ret = gameLoop();
if (ret == false) break;
}
}
void Application::Terminate()
{
renderer_.Terminate();
window_.Terminate();
}
bool Application::gameLoop()
{
renderer_.Draw();
renderer_.Swap();
return true;
}
#pragma once
#include "Window.h"
#include "Renderer.h"
class Application
{
public:
void Initialize(HINSTANCE hInst);
void Loop();
void Terminate();
private:
// アプリのメインループ
bool gameLoop();
private:
Window window_;
Renderer renderer_;
};
#pragma once
struct CbTransform
{
XMFLOAT4X4 Transform;
};
struct CbTransformSet
{
CbTransform Data;
ID3D11Buffer* pBuffer = nullptr;
};
#pragma once
#include "ConstantBuffer.h"
struct RenderParam
{
CbTransformSet CbTransformSet;
bool Initialize(Renderer& renderer);
void Terminate(Renderer& renderer);
private:
bool initConstantBuffer(Renderer& renderer);
};
#pragma once
#include "Shader.h"
#include "Triangle.h"
#include "RenderParam.h"
class Renderer
{
public:
Renderer();
~Renderer();
bool Initialize(HWND hWindow);
void Terminate();
void Draw();
void Swap();
ID3D11Device* GetDevice() { return pD3DDevice_; }
ID3D11DeviceContext* GetDeviceContext() { return pImmediateContext_; }
RenderParam& GetRenderParam() { return renderParam_; }
bool CompileShader(const WCHAR* vsPath, const WCHAR* psPath, Shader& outShader);
private:
bool initDeviceAndSwapChain(HWND hWindow);
bool initBackBuffer();
private:
//! 機能レベルの配列
static const UINT FEATURE_LEVELS_NUM = 4;
D3D_FEATURE_LEVEL pFeatureLevels_[FEATURE_LEVELS_NUM] = {};
//! デバイス作成時に返される機能レベル
D3D_FEATURE_LEVEL featureLevelsSupported_;
//! デバイス
ID3D11Device* pD3DDevice_ = nullptr;
//! デバイスコンテキスト
ID3D11DeviceContext* pImmediateContext_ = nullptr;
//! スワップ・チェイン
IDXGISwapChain* pSwapChain_ = nullptr;
//! 描画ターゲット・ビュー
ID3D11RenderTargetView* pRenderTargetView_ = nullptr;
//! ビューポート
D3D11_VIEWPORT viewPort_[1];
//! ブレンド・ステート・オブジェクト
ID3D11BlendState* pBlendState_ = nullptr;
UINT backBufferNum_ = 3;
UINT screenWidth_ = 0;
UINT screenHeight_ = 0;
Shader defaultShader_;
Triangle sampleTriangle_;
RenderParam renderParam_;
};
#pragma once
struct Shader
{
Shader() {}
~Shader() {}
void Terminate() {
DX_SAFE_RELEASE(pVertexShader);
DX_SAFE_RELEASE(pPixelShader);
DX_SAFE_RELEASE(pInputLayout);
}
ID3D11VertexShader* pVertexShader = nullptr;
ID3D11PixelShader* pPixelShader = nullptr;
ID3D11InputLayout* pInputLayout = nullptr;
};
#pragma once
struct Triangle
{
static constexpr size_t VERTEX_NUM = 3;
Vertex Vertices[VERTEX_NUM];
ID3D11Buffer* VertexBuffer = nullptr;
Triangle();
~Triangle();
bool CreateVertexBuffer(Renderer& renderer);
void DestroyVertexBuffer();
void Draw(Renderer& renderer);
private:
void updateTransform();
void setupTransform(Renderer& renderer);
private:
float translateX_ = 0.f;
float translateY_ = 0.f;
float angle_ = 0.f;
float scale_ = 1.f;
};
#pragma once
struct Vertex
{
DirectX::XMFLOAT3 Position = {};
DirectX::XMFLOAT4 Color = {};
Vertex() {}
Vertex(float x, float y, float z) {
Position.x = x;
Position.y = y;
Position.z = z;
}
};
#include
#include "Application.h"
int WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, int)
{
Application* application = new Application();
application->Initialize(hInst);
application->Loop();
application->Terminate();
delete(application);
return 0;
}
#pragma once
#include
class Window
{
public:
Window();
virtual ~Window();
bool Initialize(HINSTANCE hInst);
bool Terminate();
bool MessageLoop();
static LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
void OnResize(UINT width, UINT height);
HWND GetWindowHandle() { return hWindow_; }
private:
WNDCLASS wc_;
HWND hWindow_ = nullptr;
SIZE sizeWindow_;
MSG msg_ = {};
};
#include "RenderParam.h"
#include "Renderer.h"
bool RenderParam::Initialize(Renderer& renderer)
{
auto result = initConstantBuffer(renderer);
if (result == false) return false;
return true;
}
void RenderParam::Terminate(Renderer& renderer)
{
DX_SAFE_RELEASE(CbTransformSet.pBuffer);
}
bool RenderParam::initConstantBuffer(Renderer& renderer)
{
// 定数バッファの定義
D3D11_BUFFER_DESC cBufferDesc;
cBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
cBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
cBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
cBufferDesc.MiscFlags = 0;
cBufferDesc.StructureByteStride = 0;
// 定数バッファ①の作成
cBufferDesc.ByteWidth = sizeof(CbTransform); // バッファ・サイズ
auto hr = renderer.GetDevice()->CreateBuffer(&cBufferDesc, nullptr, &CbTransformSet.pBuffer);
if (FAILED(hr)) {
// DXTRACE_ERR(L"InitDirect3D g_pD3DDevice->CreateBuffer", hr);
return false;
}
return true;
}
#include "Renderer.h"
#include
#pragma comment(lib, "d3dcompiler.lib")
Renderer::Renderer()
{
pFeatureLevels_[0] = D3D_FEATURE_LEVEL_11_1;
pFeatureLevels_[1] = D3D_FEATURE_LEVEL_11_0;
pFeatureLevels_[2] = D3D_FEATURE_LEVEL_10_1;
pFeatureLevels_[3] = D3D_FEATURE_LEVEL_10_0;
}
Renderer::~Renderer()
{
}
bool Renderer::Initialize(HWND hWindow)
{
// Windowに合わせてスクリーンサイズ初期化
RECT rc;
GetClientRect(hWindow, &rc);
screenWidth_ = rc.right - rc.left;
screenHeight_ = rc.bottom - rc.top;
initDeviceAndSwapChain(hWindow);
initBackBuffer();
CompileShader(L"VertexShader.hlsl", L"PixelShader.hlsl", defaultShader_);
renderParam_.Initialize(*this);
sampleTriangle_.CreateVertexBuffer(*this);
return true;
}
void Renderer::Terminate()
{
sampleTriangle_.DestroyVertexBuffer();
renderParam_.Terminate(*this);
// デバイス・ステートのクリア
if(pImmediateContext_)
pImmediateContext_->ClearState();
// スワップ チェインをウインドウ モードにする
if (pSwapChain_)
pSwapChain_->SetFullscreenState(FALSE, nullptr);
DX_SAFE_RELEASE(pRenderTargetView_);
DX_SAFE_RELEASE(pBlendState_);
DX_SAFE_RELEASE(pSwapChain_);
DX_SAFE_RELEASE(pImmediateContext_);
DX_SAFE_RELEASE(pD3DDevice_);
defaultShader_.Terminate();
}
void Renderer::Draw()
{
if (!pImmediateContext_ || !pRenderTargetView_) return;
pImmediateContext_->OMSetRenderTargets(1, &pRenderTargetView_, nullptr);
// OMにブレンドステートオブジェクトを設定
FLOAT BlendFactor[4] = { 0.f, 0.f, 0.f, 0.f };
pImmediateContext_->OMSetBlendState(pBlendState_, nullptr, 1);
float color[] = { 0.f, 0.f, 0.f, 0.f };
pImmediateContext_->ClearRenderTargetView(pRenderTargetView_, color);
pImmediateContext_->IASetInputLayout(defaultShader_.pInputLayout);
pImmediateContext_->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
pImmediateContext_->VSSetShader(defaultShader_.pVertexShader, nullptr, 0);
pImmediateContext_->PSSetShader(defaultShader_.pPixelShader, nullptr, 0);
sampleTriangle_.Draw(*this);
}
void Renderer::Swap()
{
// バックバッファの表示(画面をすぐに更新)
HRESULT hr = pSwapChain_->Present(0, 0);
if (FAILED(hr)) {
//TRACE("Swap failed(%0x08x)\n", hr);
return;
}
}
bool Renderer::CompileShader(const WCHAR* vsPath, const WCHAR* psPath, Shader& outShader)
{
ID3DBlob* vsBlob = nullptr;
ID3DBlob* errBlob = nullptr;
auto pDevice = GetDevice();
// シェーダーコンパイル
auto hr = D3DCompileFromFile(
vsPath,
nullptr,
D3D_COMPILE_STANDARD_FILE_INCLUDE,
"main",
"vs_4_0",
D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION,
0,
&vsBlob,
&errBlob
);
if (FAILED(hr)) return false;
// 頂点シェーダ作成(シェーダオブジェクト作成)
ID3D11VertexShader* pVertexShader = nullptr;
hr = pDevice->CreateVertexShader(
vsBlob->GetBufferPointer(),
vsBlob->GetBufferSize(),
nullptr,
&pVertexShader
);
if (FAILED(hr)) return false;
// 入力レイアウトオブジェクト作成
ID3D11InputLayout* pInputLayout = nullptr;
D3D11_INPUT_ELEMENT_DESC layout[] = {
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
hr = pDevice->CreateInputLayout(
layout,
_countof(layout),
vsBlob->GetBufferPointer(),
vsBlob->GetBufferSize(),
&pInputLayout
);
if (FAILED(hr)) return false;
// ピクセルシェーダー作成
ID3DBlob* psBlob = nullptr;
hr = D3DCompileFromFile(
psPath,
nullptr,
D3D_COMPILE_STANDARD_FILE_INCLUDE,
"main",
"ps_4_0",
D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION,
0,
&psBlob,
&errBlob
);
ID3D11PixelShader* pPixelShader = nullptr;
hr = pDevice->CreatePixelShader(
psBlob->GetBufferPointer(),
psBlob->GetBufferSize(),
nullptr,
&pPixelShader
);
if (FAILED(hr)) return false;
outShader.pVertexShader = pVertexShader;
outShader.pPixelShader = pPixelShader;
outShader.pInputLayout = pInputLayout;
return true;
}
bool Renderer::initDeviceAndSwapChain(HWND hWindow)
{
// デバイスとスワップ・チェイン作成
DXGI_SWAP_CHAIN_DESC sd;
ZeroMemory(&sd, sizeof(sd));
sd.BufferCount = backBufferNum_; // バックバッファの数
sd.BufferDesc.Width = screenWidth_; // バックバッファの幅
sd.BufferDesc.Height = screenHeight_; // バックバッファの高さ
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; // フォーマット
sd.BufferDesc.RefreshRate.Numerator = 60; // リフレッシュレート(分母)
sd.BufferDesc.RefreshRate.Denominator = 1; // リフレッシュレート(分子)
sd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE;
sd.BufferDesc.Scaling = DXGI_MODE_SCALING_CENTERED;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; // バックバッファの使用法
sd.OutputWindow = hWindow; // 関連付けるウィンドウ
sd.SampleDesc.Count = 1; // マルチサンプル(アンチエイリアス)の数
sd.SampleDesc.Quality = 0; // マルチサンプル(アンチエイリアス)のクオリティ
sd.Windowed = TRUE; // ウィンドウモード(TRUEがウィンドウモード)
sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; // モード自動切り替え
#if defined(DEBUG) || defined(_DEBUG)
UINT createDeviceFlags = D3D11_CREATE_DEVICE_DEBUG;
#else
UINT createDeviceFlags = 0;
#endif
const D3D_DRIVER_TYPE DriverTypes[] = {
D3D_DRIVER_TYPE_HARDWARE,
D3D_DRIVER_TYPE_WARP,
D3D_DRIVER_TYPE_REFERENCE,
};
HRESULT hr;
for (auto type : DriverTypes) {
// ハードウェアデバイスを作成
hr = D3D11CreateDeviceAndSwapChain(
nullptr, type, nullptr, createDeviceFlags,
pFeatureLevels_, FEATURE_LEVELS_NUM, D3D11_SDK_VERSION, &sd,
&pSwapChain_, &pD3DDevice_, &featureLevelsSupported_, &pImmediateContext_);
if (SUCCEEDED(hr)) {
break;
}
}
if (FAILED(hr)) return false;
return true;
}
bool Renderer::initBackBuffer()
{
HRESULT hr;
// スワップ・チェインから最初のバック・バッファを取得する
ID3D11Texture2D *pBackBuffer; // バッファのアクセスに使うインターフェイス
hr = pSwapChain_->GetBuffer(
0, // バック・バッファの番号
__uuidof(ID3D11Texture2D), // バッファにアクセスするインターフェイス
(LPVOID*)&pBackBuffer); // バッファを受け取る変数
if (FAILED(hr)) {
//TRACE("InitBackBuffer g_pSwapChain->GetBuffer(%0x08x)\n", hr); // 失敗
return false;
}
// バック・バッファの情報
D3D11_TEXTURE2D_DESC descBackBuffer;
pBackBuffer->GetDesc(&descBackBuffer);
// バック・バッファの描画ターゲット・ビューを作る
hr = pD3DDevice_->CreateRenderTargetView(
pBackBuffer, // ビューでアクセスするリソース
nullptr, // 描画ターゲット・ビューの定義
&pRenderTargetView_); // 描画ターゲット・ビューを受け取る変数
DX_SAFE_RELEASE(pBackBuffer); // 以降、バック・バッファは直接使わないので解放
if (FAILED(hr)) {
//TRACE("InitBackBuffer g_pD3DDevice->CreateRenderTargetView(%0x08x)\n", hr); // 失敗
return false;
}
// RenderTarget0へのAlphaブレンド描画設定
D3D11_BLEND_DESC BlendState;
//ZeroMemory(&BlendState, sizeof(D3D11_BLEND_DESC));
BlendState.AlphaToCoverageEnable = FALSE;
BlendState.IndependentBlendEnable = FALSE;
BlendState.RenderTarget[0].BlendEnable = TRUE;
BlendState.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
BlendState.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
BlendState.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
BlendState.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
BlendState.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
BlendState.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
BlendState.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
hr = pD3DDevice_->CreateBlendState(&BlendState, &pBlendState_);
if (FAILED(hr)) {
//TRACE(L"InitDirect3D g_pD3DDevice->CreateBlendState", hr);
return false;
}
// ビューポートの設定
viewPort_[0].TopLeftX = 0.0f; // ビューポート領域の左上X座標。
viewPort_[0].TopLeftY = 0.0f; // ビューポート領域の左上Y座標。
viewPort_[0].Width = static_cast(screenWidth_); // ビューポート領域の幅
viewPort_[0].Height = static_cast(screenHeight_); // ビューポート領域の高さ
viewPort_[0].MinDepth = 0.0f; // ビューポート領域の深度値の最小値
viewPort_[0].MaxDepth = 1.0f; // ビューポート領域の深度値の最大値
pImmediateContext_->RSSetViewports(1, &viewPort_[0]);
return true;
}
#include "Triangle.h"
#include "Renderer.h"
Triangle::Triangle()
{
// √3
auto sqrt3 = sqrtf(3);
Vertices[0] = { 0.f, sqrt3 / 3.f, 0.f };
Vertices[1] = { 0.5f, -sqrt3 / 6.f, 0.f };
Vertices[2] = { -0.5f, -sqrt3 / 6.f, 0.f };
constexpr float ALPHA = 0.3f;
Vertices[0].Color = { 1.f, 0.f, 0.f, ALPHA };
Vertices[1].Color = { 0.f, 1.f, 0.f, ALPHA };
Vertices[2].Color = { 0.f, 0.f, 1.f, ALPHA };
}
Triangle::~Triangle()
{
DestroyVertexBuffer();
}
bool Triangle::CreateVertexBuffer(Renderer& renderer)
{
D3D11_BUFFER_DESC vertexBufferDesc = {};
vertexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
vertexBufferDesc.ByteWidth = sizeof(Vertex) * 3;
vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
D3D11_SUBRESOURCE_DATA vertexSubData;
vertexSubData.pSysMem = Vertices;
auto hr = renderer.GetDevice()->CreateBuffer(
&vertexBufferDesc,
&vertexSubData,
&VertexBuffer
);
if (FAILED(hr)) return false;
return true;
}
void Triangle::DestroyVertexBuffer()
{
DX_SAFE_RELEASE(VertexBuffer);
}
void Triangle::Draw(Renderer& renderer)
{
updateTransform();
setupTransform(renderer);
auto pDeviceContext = renderer.GetDeviceContext();
uint32_t strides[1] = { sizeof(Vertex) };
uint32_t offsets[1] = { 0 };
pDeviceContext->IASetVertexBuffers(0, 1, &VertexBuffer, strides, offsets);
pDeviceContext->Draw(VERTEX_NUM, 0);
}
void Triangle::updateTransform()
{
// 平行移動
//translateX_ += 0.0001f;
//if (translateX_ >= 1.f) translateX_ = -1.f;
//translateY_ += 0.0001f;
//if (translateY_ >= 1.f) translateY_ = -1.f;
translateX_ = 0.5f;
// 回転
//angle_ += XM_PI / 60000.f;
angle_ = XM_PI / 2.f;
// スケール
//scale_ += 0.0001f;
//if (scale_ >= 2.0f) scale_ = 0.5f;
scale_ = 2.f;
}
void Triangle::setupTransform(Renderer& renderer)
{
// WorldMatrixを定数バッファに設定
auto& cb = renderer.GetRenderParam().CbTransformSet;
//auto mtxS = XMMatrixScaling(scale_, scale_, 1.f);
//auto mtxR = XMMatrixRotationX(angle_);
//auto mtxR = XMMatrixRotationY(angle_);
//auto mtxR = XMMatrixRotationZ(angle_);
//auto mtxT = XMMatrixTranslation(translateX_, translateY_, 0);
auto mtx = XMMatrixIdentity();
// 左から変換が適用される
//auto mtx = mtxT * mtxS;
//auto mtx = mtxS * mtxT;
//auto mtx = mtxT * mtxR;
//auto mtx = mtxR * mtxT;
XMStoreFloat4x4(&cb.Data.Transform, XMMatrixTranspose(mtx));
//DirectX::XMStoreFloat4x4(&cb.Data.Transform, translate);
D3D11_MAPPED_SUBRESOURCE mappedResource;
auto pDeviceContext = renderer.GetDeviceContext();
// CBufferにひもづくハードウェアリソースマップ取得(ロックして取得)
HRESULT hr = pDeviceContext->Map(
cb.pBuffer,
0,
D3D11_MAP_WRITE_DISCARD,
0,
&mappedResource);
if (FAILED(hr)) {
//DXTRACE_ERR(L"DrawSceneGraph failed", hr);
return;
}
CopyMemory(mappedResource.pData, &cb.Data, sizeof(cb.Data));
// マップ解除
pDeviceContext->Unmap(cb.pBuffer, 0);
pDeviceContext->VSSetConstantBuffers(0, 1, &cb.pBuffer);
}
#include "Window.h"
#include
Window::Window()
: sizeWindow_()
{
sizeWindow_.cx = 480;
sizeWindow_.cy = 480;
}
Window::~Window()
{
}
bool Window::Initialize(HINSTANCE hInst)
{
// ウインドウ クラスの登録
wc_.style = CS_HREDRAW | CS_VREDRAW;
wc_.lpfnWndProc = (WNDPROC)Window::MainWndProc;
wc_.cbClsExtra = 0;
wc_.cbWndExtra = 0;
wc_.hInstance = hInst;
wc_.hIcon = LoadIcon(hInst, IDI_APPLICATION);
wc_.hCursor = LoadCursor(hInst, IDC_ARROW);
wc_.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
wc_.lpszMenuName = nullptr;
wc_.lpszClassName = _T("VertexColor");
if (!RegisterClass(&wc_)) {
return false;
}
// メイン ウインドウ作成
RECT rect;
rect.top = 0;
rect.left = 0;
rect.right = sizeWindow_.cx;
rect.bottom = sizeWindow_.cy;
AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);
hWindow_ = CreateWindow(wc_.lpszClassName, _T("VertexColor"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
rect.right - rect.left, rect.bottom - rect.top,
nullptr, nullptr, hInst, nullptr);
if (hWindow_ == nullptr) {
return false;
}
// ウインドウ表示
ShowWindow(hWindow_, SW_SHOWNORMAL);
UpdateWindow(hWindow_);
return true;
}
bool Window::Terminate()
{
DestroyWindow(GetWindowHandle());
// ウインドウ クラスの登録解除
UnregisterClass(wc_.lpszClassName, wc_.hInstance);
hWindow_ = nullptr;
return true;
}
bool Window::MessageLoop()
{
// Windowsメッセージループ処理
if (PeekMessage(&msg_, nullptr, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg_); DispatchMessage(&msg_);
}
// アプリケーションが終わるときにmessageがWM_QUITになる
if (msg_.message == WM_QUIT) {
return false;
}
return true;
}
/*static*/ LRESULT CALLBACK Window::MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg) {
case WM_DESTROY:
// アプリ終了
PostQuitMessage(0);
return 0;
default:
break;
}
// デフォルト処理(必須)
return DefWindowProc(hWnd, msg, wParam, lParam);
}
void Window::OnResize(UINT width, UINT height)
{
sizeWindow_.cx = width;
sizeWindow_.cy = height;
}
#pragma once
#include
#pragma comment(lib, "d3d11.lib")
#include
#define DX_SAFE_RELEASE(x) { if(x) { (x)->Release(); (x)=nullptr; } }
#include "Vertex.h"
using namespace DirectX;
class Renderer;
cbuffer cbTransform : register(b0) { // 常にスロット「0」を使う
matrix Transform;
};
struct VS_INPUT {
float3 Pos : POSITION; // 頂点座標(モデル座標系)
float4 Col : COLOR; // 頂点色
};
struct VS_OUTPUT {
float4 Pos : SV_POSITION;
float4 Col : COLOR;
};
VS_OUTPUT main(VS_INPUT input)
{
VS_OUTPUT output;
float4 pos = float4(input.Pos, 1.0);
output.Pos = mul(pos, Transform);
output.Col = input.Col;
return output;
}
コメント