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