공부 중 메모/DirectX

12. StagingTextureToResouce

라이피 (Lypi) 2019. 1. 30. 21:54
반응형

불러온 이미지를 CPU에서 수정해서 화면에 뿌리는 예제


core class에서 다 해결하는게 지저분해서 sample class를 만들었다.


이전 포스트에서 중요하게 달라진 부분은 obj class와 추가된 UserTexture class.


obj class가 어떻게 돌아가고 있는지 잡고 있어야지 바뀐 부분을 캐치하고 수정하고 다시 정리할 수 있을 것이다.



core.h

 #pragma once
#include "wndC.h"

#include "timer.h"
#include "write.h"
#include "input.h"

#include "sample.h"

class coreC_DX : public wndC_DX
{
	timerC_DX m_GameTimer;
	writeC_DX m_Font;

	sample scene;

	ID3D11RasterizerState* m_pRSSolid;

private:
	bool m_swTimerRender;
	bool m_swKeyRender;

	HRESULT SetRasterizerState();

public:
	//게임 전체적인 처리 순서에 대한 함수들. 게임에 관한 부분과 윈도우 생성에 관한 부분을 분리
	bool gameInit() override;
	bool gameRun() override;
	bool gameFrame() override;
	bool gamePreRender() override;
	bool gameRender() override;
	bool gamePostRender() override;
	bool gameRelease() override;

public:
	bool Init();
	bool Frame();
	bool Render();
	bool Release();

public:
	coreC_DX(LPCTSTR LWndName);
	virtual ~coreC_DX();
};

core.cpp

 #include "core.h"

float g_dSPF;

coreC_DX::coreC_DX(LPCTSTR LWndName) : wndC_DX(LWndName)
{
	m_swTimerRender = false;
	m_swKeyRender = false;
}

HRESULT coreC_DX::SetRasterizerState()
{
	HRESULT hr;
	D3D11_RASTERIZER_DESC desc;
	ZeroMemory(&desc, sizeof(D3D11_RASTERIZER_DESC));
	desc.FillMode = D3D11_FILL_SOLID;
	desc.CullMode = D3D11_CULL_NONE;
	desc.DepthClipEnable = TRUE;

	hr = g_pD3dDevice->CreateRasterizerState(&desc, &m_pRSSolid);
	return hr;
}

bool coreC_DX::gameInit()
{
	//디바이스 생성 작업 실행.
	InitDevice();
	m_GameTimer.Init();

	//SwapChain의 백버퍼 정보로 DXWrite객체 생성 
	IDXGISurface1* pBackBuffer = nullptr;
	HRESULT hr = g_pSwapChain->GetBuffer(0, __uuidof(IDXGISurface), (void**)&pBackBuffer);
	m_Font.Init();
	m_Font.Set(pBackBuffer);

	if (pBackBuffer) {
		pBackBuffer->Release();
	}

	//DXInput Device 생성
	if (!I_Input.InitDirectInput(true, true)) {
		return false;
	}

	//DXInput 초기화
	if (!I_Input.Init()) {
		return false;
	}

	g_pWindow->CenterWindow(); //윈도우를 화면 중앙으로 이동시킨다.

	SetRasterizerState();
	
	//init
	Init();

	return true;
}

bool coreC_DX::gameRun()
{
	gameFrame();
	gamePreRender();
	gameRender();
	gamePostRender();
	return true;
}

bool coreC_DX::gameFrame()
{
	m_GameTimer.Frame();

	g_dSPF = m_GameTimer.getSPF();
	I_Input.Frame();


	if (I_Input.IsKeyDown(DIK_9)) {
		//중단점 설정
		m_swTimerRender = !m_swTimerRender;
	}

	if (I_Input.IsKeyDown(DIK_0)) {
		//중단점 설정
		m_swKeyRender = !m_swKeyRender;
	}

	//frame
	Frame();



	return true;
}

bool coreC_DX::gamePreRender()
{
	m_Font.DrawTextBegin();
	return true;
}

bool coreC_DX::gameRender()
{
	//ID3D11RenderTargetView 객체에 컬러를 채운다. (BackBuffer를 지운다.)
	float r = 0.21f;
	float g = 0.32f;
	float b = 0.45f;

	float ClearColor[4] = { r, g, b, 0.0f }; //r,g,b,a
	g_pD3dContext->ClearRenderTargetView(m_pRenderTagetView, ClearColor);

	Render();

	TCHAR pBuffer[256];
	memset(pBuffer, 0, sizeof(TCHAR) * 256);

	m_Font.SetTextPos();
	m_Font.SetlayoutRt(0, 0, (FLOAT)g_rtClient.right, (FLOAT)g_rtClient.bottom);

	if (m_swTimerRender) {
		m_Font.SetAlignment(DWRITE_TEXT_ALIGNMENT_LEADING, DWRITE_PARAGRAPH_ALIGNMENT_NEAR);
		m_Font.SetTextColor(ColorF(1, 1, 1, 1));

		_stprintf_s(pBuffer, _T("FPS:%d, SPF:%10.5f, GameTime:%10.2f"),
			m_GameTimer.getFPS(), m_GameTimer.getSPF(), m_GameTimer.getGameTime());
		m_Font.DrawText(pBuffer);
	}

	if (m_swKeyRender) {
		m_Font.SetAlignment(DWRITE_TEXT_ALIGNMENT_LEADING, DWRITE_PARAGRAPH_ALIGNMENT_NEAR);
		//m_Font.SetTextPos(Matrix3x2F::Rotation(g_GameTimer*100, Point2F(400, 300)));
		m_Font.SetTextColor(ColorF(1, 0.3f, 0, 1));

		int iCount = 0;

		MouseInfo Mouse = I_Input.getMouseInfo();

		_stprintf_s(pBuffer, _T("Mouse X:%ld, Y:%ld"), Mouse.xy.x, Mouse.xy.y);

		UINT iStartX = 0;
		UINT iStartY = 30 + (20 * iCount);
		m_Font.SetlayoutRt((FLOAT)iStartX, (FLOAT)iStartY, (FLOAT)g_rtClient.right, (FLOAT)g_rtClient.bottom);
		m_Font.DrawText(pBuffer);
		iCount++;

		for (int iKey = 0; iKey < KeyStateCount; iKey++) {
			if (I_Input.m_KeyCurState[iKey] & 0x80) {
				_stprintf_s(pBuffer, _T("Key State : 0x%02x : %d"), iKey, I_Input.m_KeyCurState[iKey]);
				UINT iStartX = 0;
				UINT iStartY = 30 + (20 * iCount);
				m_Font.SetlayoutRt((FLOAT)iStartX, (FLOAT)iStartY, (FLOAT)g_rtClient.right, (FLOAT)g_rtClient.bottom);
				m_Font.DrawText(pBuffer);

				iCount++;
			}
		}
	}

	//render
	g_pD3dContext->RSSetState(m_pRSSolid);
	


	return true;
}

bool coreC_DX::gamePostRender()
{
	//IDXGISwapChain 객체를 사용하여 시연(출력)한다.
	//모든 렌더링 작업들은 present앞에서 이뤄져야 한다.
	m_Font.DrawTextEnd();
	g_pSwapChain->Present(0, 0);
	return true;
}

bool coreC_DX::gameRelease()
{
	Release();

	if (!I_Input.Release()) { return false; }
	if (!m_Font.Release()) { return false; }
	if (!m_GameTimer.Release()) { return false; }
	if (!CreanupDevice()) { return false; }
	return true;
}

bool coreC_DX::Init()
{
	scene.Init();

	return true;
}

bool coreC_DX::Frame()
{
	I_Input.Frame();
	scene.Frame();
	return true;
}

bool coreC_DX::Render()
{
	scene.Render();
	return true;
}

bool coreC_DX::Release()
{
	scene.Release();
	return true;
}

coreC_DX::~coreC_DX()
{
}


sample.h

 #pragma once
#include "obj.h"

class sample
{
	Object_DX m_obj;
	
public:
	bool Init();
	bool Frame();
	bool Render();
	bool Release();

public:
	sample();
	~sample();
};

sample.cpp

 #include "sample.h"



sample::sample()
{

}

bool sample::Init()
{
	m_obj.Create(L"Desert.jpg");
	m_obj.SetPosition({ 0,0,1500,750 });
	m_obj.ImagePartialSelect({ 0,0,1,1 }, { 1,1 });
	m_obj.Color();

	return true;
}

bool sample::Frame()
{
	m_obj.Frame();

	return true;
}

bool sample::Render()
{
	m_obj.Render();

	return true;
}

bool sample::Release()
{
	m_obj.Release();

	return true;
}

sample::~sample()
{

}


obj.h

 #pragma once
#include "header.h"
#include "input.h"

#include "UserTexture.h"

class Object_DX
{
protected:
	ID3D11Buffer * m_pVertexBuffer;   // 정점 버퍼
	ID3D11VertexShader*         m_pVS;             // 정점 쉐이더
	ID3D11PixelShader*          m_pPS;             // 픽셀 쉐이더
	ID3D11InputLayout*          m_pInputLayout;    // 인풋 레이아웃
	ID3D11ShaderResourceView*   m_pTextureSRV;     // 텍스쳐 SRV
	ID3D11BlendState*           m_pAlphaBlend;

	//sampler 변수
	ID3D11SamplerState*         m_pSamplerState;
	UINT                        m_idxFilter;
	D3D11_FILTER                m_dxFilter;
	UINT                        m_iTexAddressMode;
	FLOAT                       m_MinLod;

	int                         m_i;

protected:
	PNCT_VERTEX m_pVertexList[4];

	uWH   m_uImageSize;
	iLTRB m_uImagePart;

	fLTRB m_fPRegion;

	POINT m_ptCenter;
	D3DXVECTOR3 m_v3Center;

public:
	iLTRB m_uSRegion;

	bool m_bExist;

	//텍스쳐 객체 생성
	UserTexture                 m_Texture;
	ID3D11Texture2D*            m_pCopyTexture;
	ID3D11ShaderResourceView*   m_pCopyTextureSRV;

private:
	void transStoP(); //화면 -> 투영
	void transPtoS(); //투영 -> 화면
	void UpdateCP(); //중점 갱신
	void UpdateVertexList(); //정점 리스트 갱신

	HRESULT setSamplerState();



public:
	HRESULT Create(const TCHAR* pTexFile);
	void ImagePartialSelect(iXYWH imgXYWH, uWH imgSize);
	void SetPosition(iXYWH _xywh);

	void CreateFullImgObj(iXYWH _xywh, const TCHAR* pTexFile);
	void CreatePartImgObj(iXYWH _xywh, iXYWH imgXYWH, uWH imgSize, const TCHAR* pTexFile);

	void ImagePartialChange(iXYWH);

	void ImageFileChange(const TCHAR* pTexFile);

	void MoveX(float fDis);
	void MoveY(float fDis);

	iLTRB getPos();

	void spin(float fAngle);
	void scale(float size);

	void ColorChange(float r, float g, float b, float a);
	void Color();

public:
	virtual bool Init();
	virtual bool Frame();
	virtual bool Render();
	virtual bool Release();

public:
	Object_DX();
	virtual ~Object_DX();

};

obj.cpp

 #include "obj.h"

Object_DX::Object_DX()
{
	m_i = 1;

}

//화면좌표계 -> 투영좌표게
void Object_DX::transStoP()
{
	m_fPRegion.left = (m_uSRegion.left / ((float)g_rtClient.right)) * 2 - 1.0f;
	m_fPRegion.top = -((m_uSRegion.top / ((float)g_rtClient.bottom)) * 2 - 1.0f);
	m_fPRegion.right = (m_uSRegion.right / ((float)g_rtClient.right)) * 2 - 1.0f;
	m_fPRegion.bottom = -((m_uSRegion.bottom / ((float)g_rtClient.bottom)) * 2 - 1.0f);
}

//투영좌표계 -> 화면좌표계
void Object_DX::transPtoS()
{
	m_uSRegion.left = (UINT)((m_fPRegion.left + 1.0f) / 2 * ((float)g_rtClient.right));
	m_uSRegion.top = (UINT)((m_fPRegion.top - 1.0f) / -2 * ((float)g_rtClient.bottom));
	m_uSRegion.right = (UINT)((m_fPRegion.right + 1.0f) / 2 * ((float)g_rtClient.right));
	m_uSRegion.bottom = (UINT)((m_fPRegion.bottom - 1.0f) / -2 * ((float)g_rtClient.bottom));
}

//중점 갱신
void Object_DX::UpdateCP()
{
	m_ptCenter.x = (m_uSRegion.right + m_uSRegion.left) / 2;
	m_ptCenter.y = (m_uSRegion.bottom + m_uSRegion.top) / 2;

	m_v3Center.x = 0.0f;
	m_v3Center.y = 0.0f;
	m_v3Center.z = 0.0f;

	for (int iV = 0; iV < 4; iV++) {
		m_v3Center.x += m_pVertexList[iV].p.x;
		m_v3Center.y += m_pVertexList[iV].p.y;
	}

	m_v3Center.x /= 4;
	m_v3Center.y /= 4;
}

//정점 리스트 갱신
void Object_DX::UpdateVertexList()
{
	m_pVertexList[0].p = D3DXVECTOR3(m_fPRegion.left, m_fPRegion.top, 0.0f);
	m_pVertexList[1].p = D3DXVECTOR3(m_fPRegion.left, m_fPRegion.bottom, 0.0f);
	m_pVertexList[2].p = D3DXVECTOR3(m_fPRegion.right, m_fPRegion.top, 0.0f);
	m_pVertexList[3].p = D3DXVECTOR3(m_fPRegion.right, m_fPRegion.bottom, 0.0f);


	for (int pl = 0; pl < 4; pl++) {
		m_pVertexList[pl].c = D3DXVECTOR4(1, 1, 1, 1);
	}

	//중점 갱신
	UpdateCP();
}



//생성 위치 지정하기
void Object_DX::SetPosition(iXYWH _xywh)
{
	//화면 좌표계 저장
	m_uSRegion = _xywh;

	//투영 좌표계 변환
	transStoP();

	//정점 리스트 저장
	UpdateVertexList();
}

//이미지 자르기
void Object_DX::ImagePartialSelect(iXYWH imgXYWH, uWH imgSize)
{
	m_uImagePart = imgXYWH;
	m_uImageSize = imgSize;

	fLTRB fImageUV;
	//이미지 화면 좌표를 uv좌표로 변환
	fImageUV.left = (float)m_uImagePart.left / m_uImageSize.width;
	fImageUV.top = (float)m_uImagePart.top / m_uImageSize.Height;
	fImageUV.right = (float)m_uImagePart.right / m_uImageSize.width;
	fImageUV.bottom = (float)m_uImagePart.bottom / m_uImageSize.Height;

	m_pVertexList[0].t = D3DXVECTOR2(fImageUV.left, fImageUV.top);
	m_pVertexList[1].t = D3DXVECTOR2(fImageUV.left, fImageUV.bottom);
	m_pVertexList[2].t = D3DXVECTOR2(fImageUV.right, fImageUV.top);
	m_pVertexList[3].t = D3DXVECTOR2(fImageUV.right, fImageUV.bottom);
}

HRESULT Object_DX::setSamplerState()
{
	HRESULT hr;

	D3D11_SAMPLER_DESC samplerDesc;
	samplerDesc.Filter = m_dxFilter;
	samplerDesc.AddressU = (D3D11_TEXTURE_ADDRESS_MODE)m_iTexAddressMode;
	samplerDesc.AddressV = (D3D11_TEXTURE_ADDRESS_MODE)m_iTexAddressMode;
	samplerDesc.AddressW = (D3D11_TEXTURE_ADDRESS_MODE)m_iTexAddressMode;
	samplerDesc.MipLODBias = 0.0f;
	samplerDesc.MaxAnisotropy = 16;
	samplerDesc.ComparisonFunc = D3D11_COMPARISON_EQUAL;
	samplerDesc.BorderColor[0] = 0.0f;
	samplerDesc.BorderColor[1] = 0.0f;
	samplerDesc.BorderColor[2] = 0.0f;
	samplerDesc.BorderColor[3] = 0.0f;
	samplerDesc.MinLOD = m_MinLod;
	samplerDesc.MaxLOD = m_MinLod + 1;

	hr = g_pD3dDevice->CreateSamplerState(&samplerDesc, &m_pSamplerState);
	if (FAILED(hr)) {
		return hr;
	}

	return hr;
}


//오브젝트 생성하기
HRESULT Object_DX::Create(const TCHAR* pTexFile)
{
	HRESULT hr;

	// 정점 버퍼 생성
	D3D11_BUFFER_DESC sDesc;
	ZeroMemory(&sDesc, sizeof(D3D11_BUFFER_DESC));
	sDesc.Usage = D3D11_USAGE_DEFAULT;
	sDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
	sDesc.ByteWidth = sizeof(PNCT_VERTEX) * 4;

	D3D11_SUBRESOURCE_DATA sInitData;
	ZeroMemory(&sInitData, sizeof(D3D11_SUBRESOURCE_DATA));
	sInitData.pSysMem = m_pVertexList;

	if (FAILED(hr = g_pD3dDevice->CreateBuffer(&sDesc, &sInitData, &m_pVertexBuffer))) {
		return hr;
	}

	//정점 쉐이더 생성
	ID3DBlob*  pErrorBlob;
	ID3DBlob*  pVSBlob;

	hr = D3DX11CompileFromFile(L"shader.vsh", NULL, NULL, "VS", "vs_5_0", NULL, NULL, NULL, &pVSBlob, &pErrorBlob, NULL);
	if (FAILED(hr)) {
		OutputDebugStringA((char*)pErrorBlob->GetBufferPointer());
		return false;
	}

	hr = g_pD3dDevice->CreateVertexShader(pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), NULL, &m_pVS);
	if (FAILED(hr)) {
		return hr;
	}

	//레이아웃 생성
	if (pVSBlob == NULL) { return E_FAIL; }

	D3D11_INPUT_ELEMENT_DESC ied[] = {
		{ "POS", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
		{ "NO", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
		{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 },
		{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 40, D3D11_INPUT_PER_VERTEX_DATA, 0 },
	};

	int iNumElement = sizeof(ied) / sizeof(D3D11_INPUT_ELEMENT_DESC);

	hr = g_pD3dDevice->CreateInputLayout(ied, iNumElement, pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), &m_pInputLayout);
	if (FAILED(hr)) {
		return hr;
	}

	//픽셀 쉐이더 생성
	ID3DBlob*  pPSBlop;
	hr = D3DX11CompileFromFile(L"shader.psh", NULL, NULL, "PS", "ps_5_0", NULL, NULL, NULL, &pPSBlop, &pErrorBlob, NULL);
	if (FAILED(hr)) {
		OutputDebugStringA((char*)pErrorBlob->GetBufferPointer());
		return false;
	}

	hr = g_pD3dDevice->CreatePixelShader(pPSBlop->GetBufferPointer(), pPSBlop->GetBufferSize(), NULL, &m_pPS);
	if (FAILED(hr)) {
		SAFE_RELEASE(pPSBlop);
		return NULL;
	}

	SAFE_RELEASE(pErrorBlob);
	SAFE_RELEASE(pPSBlop);
	SAFE_RELEASE(pVSBlob);

	//블렌드 스테이트 생성
	D3D11_BLEND_DESC BlendState;
	ZeroMemory(&BlendState, sizeof(D3D11_BLEND_DESC));

	BlendState.AlphaToCoverageEnable = FALSE;
	BlendState.IndependentBlendEnable = FALSE;

	BlendState.RenderTarget[0].BlendEnable = TRUE;

	BlendState.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;

	BlendState.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
	BlendState.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;

	BlendState.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
	BlendState.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
	BlendState.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;

	BlendState.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;

	if (FAILED(hr = g_pD3dDevice->CreateBlendState(&BlendState, &m_pAlphaBlend)))
	{
		return hr;
	}


	m_dxFilter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
	m_iTexAddressMode = D3D11_TEXTURE_ADDRESS_CLAMP;
	

	D3D11_SAMPLER_DESC samplerDesc;
	samplerDesc.Filter = m_dxFilter;
	samplerDesc.AddressU = (D3D11_TEXTURE_ADDRESS_MODE)m_iTexAddressMode;
	samplerDesc.AddressV = (D3D11_TEXTURE_ADDRESS_MODE)m_iTexAddressMode;
	samplerDesc.AddressW = (D3D11_TEXTURE_ADDRESS_MODE)m_iTexAddressMode;
	samplerDesc.MipLODBias = 0.0f;
	samplerDesc.MaxAnisotropy = 16;
	samplerDesc.ComparisonFunc = D3D11_COMPARISON_EQUAL;
	samplerDesc.BorderColor[0] = 0.0f;
	samplerDesc.BorderColor[1] = 0.0f;
	samplerDesc.BorderColor[2] = 0.0f;
	samplerDesc.BorderColor[3] = 0.0f;
	samplerDesc.MinLOD = 0;
	samplerDesc.MaxLOD = 0;

	hr = g_pD3dDevice->CreateSamplerState(&samplerDesc, &m_pSamplerState);
	if (FAILED(hr)) {
		return hr;
	}

	//텍스쳐 로드
	hr = D3DX11CreateShaderResourceViewFromFile(g_pD3dDevice, pTexFile, NULL, NULL, &m_pTextureSRV, NULL);
	if (FAILED(hr)) {
		return hr;
	}

	// 로드된 텍스처를 CPU가 편집해서 다시 리소스뷰 생성하며 전달.
	m_pCopyTexture = m_Texture.GetTexture2DFromFile(L"Desert.jpg");
	m_pCopyTextureSRV = m_Texture.StagingCopyTextureFromSV(m_pCopyTexture);

	return hr;
}

void Object_DX::ImageFileChange(const TCHAR* pTexFile)
{
	D3DX11CreateShaderResourceViewFromFile(g_pD3dDevice, pTexFile, NULL, NULL, &m_pTextureSRV, NULL);
}

//전체 이미지 오브젝트 생성
void Object_DX::CreateFullImgObj(iXYWH _xywh, const TCHAR* pTexFile) 
{
	SetPosition(_xywh);
	ImagePartialSelect({ 0,0,1,1 }, { 1,1 });
	Create(pTexFile);
}

//부분 이미지 오브젝트 생성
void Object_DX::CreatePartImgObj(iXYWH _xywh, iXYWH imgXYWH, uWH imgSize, const TCHAR* pTexFile)
{
	SetPosition(_xywh);
	ImagePartialSelect(imgXYWH, imgSize);
	Create(pTexFile);
}

//이미지 선택 영역 변경
void Object_DX::ImagePartialChange(iXYWH _uXYWH)
{
	ImagePartialSelect(_uXYWH, m_uImageSize);
}

iLTRB Object_DX::getPos()
{
	return m_uSRegion;
}

//x축 이동
void Object_DX::MoveX(float fDis)
{
	for (int iV = 0; iV < 4; iV++) {
		m_pVertexList[iV].p.x += fDis * g_dSPF;
	}

	m_fPRegion.left += fDis * g_dSPF;
	m_fPRegion.right += fDis * g_dSPF;

	transPtoS();

	UpdateCP();
}

//y축 이동
void Object_DX::MoveY(float fDis)
{
	for (int iV = 0; iV < 4; iV++) {
		m_pVertexList[iV].p.y += fDis * g_dSPF;
	}

	m_fPRegion.top += fDis * g_dSPF;
	m_fPRegion.bottom += fDis * g_dSPF;

	transPtoS();

	UpdateCP();
}

//회전
void Object_DX::spin(float fAngle)
{
	float S = sinf(fAngle);
	float C = cosf(fAngle);

	for (int iV = 0; iV < 4; iV++) {

		D3DXVECTOR3 vertex = m_pVertexList[iV].p;

		m_pVertexList[iV].p.x -= m_v3Center.x;
		m_pVertexList[iV].p.y -= m_v3Center.y;

		vertex.x = m_pVertexList[iV].p.x * C + m_pVertexList[iV].p.y * S / 2;
		vertex.y = m_pVertexList[iV].p.x * -S * 2 + m_pVertexList[iV].p.y * C;

		vertex.x += m_v3Center.x;
		vertex.y += m_v3Center.y;

		m_pVertexList[iV].p = vertex;

	}
}

//크기 조절
void Object_DX::scale(float size)
{//값 넣을 때 주의

	for (int iV = 0; iV < 4; iV++) {
		m_pVertexList[iV].p.x -= m_v3Center.x;
		m_pVertexList[iV].p.y -= m_v3Center.y;

		m_pVertexList[iV].p.x *= size;
		m_pVertexList[iV].p.y *= size;

		m_pVertexList[iV].p.x += m_v3Center.x;
		m_pVertexList[iV].p.y += m_v3Center.y;
	}
}

void Object_DX::ColorChange(float r, float g, float b, float a)
{
	for (int pl = 0; pl < 4; pl++) {
		m_pVertexList[pl].c = D3DXVECTOR4(r, g, b, a);
	}
}

void Object_DX::Color() {
	m_pVertexList[0].c = D3DXVECTOR4(1.0f, 0.0f, 0.0f, 1.0f);
	m_pVertexList[1].c = D3DXVECTOR4(0.0f, 1.0f, 0.0f, 1.0f);
	m_pVertexList[2].c = D3DXVECTOR4(0.0f, 0.0f, 1.0f, 1.0f);
	m_pVertexList[3].c = D3DXVECTOR4(1.0f, 0.0f, 1.0f, 1.0f);
}

bool Object_DX::Init()
{

	return true;
}

bool Object_DX::Frame()
{
	g_pD3dContext->UpdateSubresource(m_pVertexBuffer, 0, NULL, m_pVertexList, 0, 0);
	
	if (I_Input.IsKeyDown(DIK_4) == true)
	{//중단점 설정
		m_i++;

		fLTRB fImageUV;
		//이미지 화면 좌표를 uv좌표로 변환
		fImageUV.left = (float)m_uImagePart.left / m_uImageSize.width;
		fImageUV.top = (float)m_uImagePart.top / m_uImageSize.Height;
		fImageUV.right = (float)m_uImagePart.right * m_i / m_uImageSize.width;
		fImageUV.bottom = (float)m_uImagePart.bottom * m_i / m_uImageSize.Height;

		m_pVertexList[0].t = D3DXVECTOR2(fImageUV.left, fImageUV.top);
		m_pVertexList[1].t = D3DXVECTOR2(fImageUV.left, fImageUV.bottom);
		m_pVertexList[2].t = D3DXVECTOR2(fImageUV.right, fImageUV.top);
		m_pVertexList[3].t = D3DXVECTOR2(fImageUV.right, fImageUV.bottom);
	}

	if (I_Input.IsKeyDown(DIK_5) == true)
	{//중단점 설정
		m_idxFilter++;
		switch (m_idxFilter)
		{
			case 1:
			{
				m_dxFilter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
				setSamplerState();
			}break;
			case 2:
			{
				m_dxFilter = D3D11_FILTER_ANISOTROPIC;
				setSamplerState();
			}break;

			default:
			m_dxFilter = D3D11_FILTER_MIN_MAG_MIP_POINT;
			m_idxFilter = 0;
			setSamplerState();
			break;
		}
	}

	if (I_Input.IsKeyDown(DIK_6) == true)
	{//중단점 설정
		m_iTexAddressMode++;
		if (m_iTexAddressMode > 5)
		{
			m_iTexAddressMode = 1;
		}
		setSamplerState();
	}
	if (I_Input.IsKeyDown(DIK_7) == true)
	{//중단점 설정
		m_MinLod++;
		setSamplerState();
	}
	return true;
	
	return true;
}

bool Object_DX::Render()
{
	UINT pStrides = sizeof(PNCT_VERTEX);
	UINT pOffsets = 0;

	ID3D11SamplerState* SS[1];
	SS[0] = m_pSamplerState;

	g_pD3dContext->IASetVertexBuffers(0, 1, &m_pVertexBuffer, &pStrides, &pOffsets);
	g_pD3dContext->IASetInputLayout(m_pInputLayout);
	g_pD3dContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
	g_pD3dContext->VSSetShader(m_pVS, NULL, NULL);
	g_pD3dContext->PSSetShader(m_pPS, NULL, NULL);
	g_pD3dContext->PSSetShaderResources(0, 1, &m_pTextureSRV);
	g_pD3dContext->PSSetShaderResources(0, 1, &m_pCopyTextureSRV);
	g_pD3dContext->PSSetSamplers(0, 1, SS);
	g_pD3dContext->OMSetBlendState(m_pAlphaBlend, 0, -1);

	g_pD3dContext->Draw(4, 0);

	return true;
}

bool Object_DX::Release()
{
	SAFE_RELEASE(m_pCopyTexture);
	SAFE_RELEASE(m_pCopyTextureSRV);


	SAFE_RELEASE(m_pVertexBuffer);
	SAFE_RELEASE(m_pVS);
	SAFE_RELEASE(m_pPS);
	SAFE_RELEASE(m_pInputLayout);
	SAFE_RELEASE(m_pTextureSRV);

	return true;
}




Object_DX::~Object_DX()
{

}


UserTexture.h

 #pragma once
#include "header.h"

class UserTexture
{
public:
	
	void                        WriteDotPixel(ID3D11Texture2D* pTexDest);
	
	ID3D11Texture2D*            GetTexture2DFromFile(LPCWSTR filename);
	ID3D11ShaderResourceView*   StagingCopyTextureFromSV(ID3D11Texture2D* pSrcTexture);

public:
	UserTexture();
	~UserTexture();
};

UserTexture.cpp

 #include "UserTexture.h"


UserTexture::UserTexture()
{

}

void UserTexture::WriteDotPixel(ID3D11Texture2D* pTexDest)
{
	HRESULT hr;
	D3D11_TEXTURE2D_DESC desc;
	pTexDest->GetDesc(&desc);

	D3D11_MAPPED_SUBRESOURCE MappedFaceDest;
	//GPU리소스를 응용프로그램에서 편집하기 위해서는 Map으로 묶어줄 필요가 있다.
	hr = g_pD3dContext->Map((ID3D11Resource*)pTexDest, 0, D3D11_MAP_READ_WRITE, 0, &MappedFaceDest);
	if (SUCCEEDED(hr))
	{
		BYTE* pDestBytes = (BYTE*)MappedFaceDest.pData;

		for (UINT y = 0; y < desc.Height; y++) {
			if (y % 10 == 0) {
				pDestBytes += MappedFaceDest.RowPitch;
				continue;
			}
			BYTE* pDest = pDestBytes;

			for (UINT x = 0; x < desc.Width; x++) {
				if (x % 2 == 0) {
					*pDest++ = 200;
					*pDest++ = 20;
					*pDest++ = 0;
					*pDest++ = 255;
				}
				else {
					pDest += 4;
				}
			}
			pDestBytes += MappedFaceDest.RowPitch;
		}
		//Map작업이 끝났으면 Unmap을 해줘야 다시 GPU에서 작업이 가능하다.
		g_pD3dContext->Unmap(pTexDest, 0);
	}
}


ID3D11Texture2D* UserTexture::GetTexture2DFromFile(LPCWSTR filename)
{
	HRESULT hr;

	ID3D11Texture2D* texture = nullptr;
	ID3D11Resource* pRes = nullptr;

	hr = D3DX11CreateTextureFromFile(g_pD3dDevice, filename, nullptr, nullptr, &pRes, nullptr);
	if (FAILED(hr)) {
		return nullptr;
	}

	pRes->QueryInterface(__uuidof(ID3D11Texture2D), (LPVOID*)&texture);
	pRes->Release();

	return texture;
}


ID3D11ShaderResourceView* UserTexture::StagingCopyTextureFromSV(ID3D11Texture2D* pSrcTexture)
{
	HRESULT hr;
	
	D3D11_TEXTURE2D_DESC Srcdesc;
	pSrcTexture->GetDesc(&Srcdesc);

	D3D11_TEXTURE2D_DESC desc;
	desc.Width = Srcdesc.Width;
	desc.Height = Srcdesc.Height;
	desc.MipLevels = Srcdesc.MipLevels;
	desc.ArraySize = 1;
	desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; 
	desc.SampleDesc.Count = 1;
	desc.SampleDesc.Quality = 0;
	//쉐이더 리소스 뷰를 만드려면 반드시 D3D11_USAGE_DEFAULT여야 한다.
	desc.Usage = D3D11_USAGE_DEFAULT;
	desc.CPUAccessFlags = 0;
	//원본 이미지에 대한 밉맵이 생성되도록 설정한다.
	desc.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS;
	//이 때, D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET을 함께 사용해야한다. 
	desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
	//그러면 디바이스 콘텍스트에서 ->GenerateMips(pTextureRV)를 호출하면 밉맵이 생성된다.


	//쉐이더리소스뷰를 만들 수 있는 pTex2D생성
	ID3D11Texture2D* pTex2D;
	hr = g_pD3dDevice->CreateTexture2D(&desc, nullptr, &pTex2D);
	if (FAILED(hr)) {
		H(hr);
		return nullptr;
	}

	//편집용 pStaging2D제작.
	//D3D11_USAGE_STAGING는 CPU에서 텍스쳐를 수정할 수 있게 만든다는 것이다. 
	//단 이를 이용하면 쉐이더 리소스 뷰는 생성할 수 없다.
	desc.Usage = D3D11_USAGE_STAGING;
	desc.BindFlags = 0;
	desc.MiscFlags = 0;
	desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE | D3D11_CPU_ACCESS_READ;
	
	ID3D11Texture2D* pStaging2D;
	hr = g_pD3dDevice->CreateTexture2D(&desc, nullptr, &pStaging2D);
	if (FAILED(hr)) {
		H(hr);
		return nullptr;
	}

	//인자로 받은 원본인 pSrcTexture를 pStaging2D에 복사한다.
	//이 때, 복사가 이뤄지려면 둘의 밉맵 레벨은 서로 같아야 한다.
	g_pD3dContext->CopyResource(pStaging2D, pSrcTexture);

	//텍스쳐를 편집한다.
	//0번 퀄리티 텍스쳐 서피스면을 수정(빨간 줄로 표시)
	WriteDotPixel(pStaging2D);

	//수정한 이미지를 텍스쳐뷰를 생성할 수 있게 만들어진 pTex2D에 복사한다.
	g_pD3dContext->CopyResource(pTex2D, pStaging2D);
	
	if (pStaging2D) {
		pStaging2D->Release(); //pStaging2D의 역할은 끝이므로 릴리즈.
	}

	//쉐이더 리소스뷰 데스크를 채운다.
	D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc;
	ZeroMemory(&SRVDesc, sizeof(SRVDesc));
	SRVDesc.Format = desc.Format;
	SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
	SRVDesc.Texture2D.MipLevels = desc.MipLevels;

	ID3D11ShaderResourceView* pTexSRV;
	hr = g_pD3dDevice->CreateShaderResourceView(pTex2D, &SRVDesc, &pTexSRV); //(리소스, 리소스뷰정보, 리소스뷰)
	if (FAILED(hr)) {
		H(hr);
		pTex2D->Release(); //에러가 났지만 생성했던건 해제한다.
		return nullptr; //에러가 난 상황이므로 리턴시킴
	}

	if (pTex2D) {
		pTex2D->Release(); //어쨌든 잘가라.
	}

	//새로운 밉맵을 생성한다. (0번이 바뀌면 적용해야 하층 밉맵도 바뀐다.??)
	g_pD3dContext->GenerateMips(pTexSRV);

	return pTexSRV;
}





UserTexture::~UserTexture()
{

}



반응형