반응형
불러온 이미지를 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()
{
}
반응형