ImGui 활용한 DirectX 11 3D를 이용한 2D를 만드는 내용입니다.
본 내용은 똑같이 사용할 수 없음을 알립니다. (참고및 공부자료로 만들어진 내용임을 밝힙니다.)
전 과정에 대해 이해를 해야 다음 이 부분에 대한 이해를 할 수 있음을 밝힙니다
이전 자료) https://ppatabox.tistory.com/31
목차-
1) Texture
이미지는 Pixel 단위 인데. 그래서 pixelshader 에서 다룬다.
정점 4개를 이용해서 사각형을 그린 후 생각해보자
VS = 정점 4개를 채우고
RS = 그 사이를 채운다
이 사이의 간격이 100이라 치고
그럼 텍스쳐 스크린은 얼마인지 모른다
비율에 대한 또하나의 좌표가 필요하다.
기준이 좌하단이라고 할때
일반적인 2D 는 텍스쳐를 뛰운 좌표 좌상단 (0, 0) 그대로 아래로 (0, 1)
(두 좌표간의 사이의 100을 한장으로 치겠다는 의미의 좌표 2면 2장 0.5면 반장 )
우리가 시스템을 처리하고 100인지 아닌지 모른다. 우상단은 (1, 0) 우 하단이 (1, 1)
ex_wstring textureFile = L"
CreateFile A / W 붙어 있는게 있는데
A = ANSI 1바이트 권 (아스키 코드 생각하면 됨)(영어권)
2바이트 이상권 Wide char는 (UNICODE)유니코드 라고 부른다. (비영어권)
전세계의 문자를 다 담을 수 있도록 제공 하고 있음
각 나라마다 다르다 (동남아, 인도, 아랍권, 태국, 중국 등등)
근데 문자조합이 제일 많은 나라가 우리나라다(표현자체가 너무 많아서 그럴 수 있음)
전부다 2바이트로 처리하기가 용량이크다
데이터를 주고 받아야 하는 상황에서 인터넷이 빠르면 상관없는데
글로벌 작업을 할때 다른나라의 인터넷 속도가 느린것을 판단해서 작업을 해야함
2바이트 표시 방법 두가지
1) MBCS : 영문이나 아스키코드 그건 1바이트 처리 하고 나머지 문자열은 2바이트
2) UNICODE : 무조건 2바이트로 처리하겠다
==
표기법
Ansi : " "
MBCS : L""
UNICODE : TEXT(" ")
NULL = 0 으로 표기 되어있고 조금 남아있는 개념 ()공간 있음)
nullptr = 댕글리 포인트 까지 체크 할려면 완전 없는 개념 (공간 자체가 없는것)
ANSI 문자와 유니코드 문자
- ANSIchar c = 'A'char szBuffer[100] = "A String"
- // 99개의 8비트 문자와 8비트 문자열 종결 문자(0)
- // 8비트 문자
- 유니코드wchar_t c = L'A'Wchar_t szBuffer[100] = L"A String
- // 99개의 16비트 문자와 16비트 문자열 종결 문자(0)
- // 16비트 문자
컴파일 시 ANSI 문자나 유니코드 문자를 사용하도록 변경 가능하게 소스코드를 작성하는 것도 가능하다.
윈도우 내에서 제공해주는 유니코드 함수와 ANSI함수가 있긴 한데 다루진 않겠음
그외로 따로 표가 있음
Texture.cpp / h 를 프로젝트 폴더에 넣어주자 wstring textureFile = L"../_Textures/" + file; 자신의 폴더 상대 경로 설정 현재 폴더안에 한칸 위에 _Textures폴더를 만들어주자 이미지를 이곳에 넣어주자
A : ANSIW : unicode아무것도 안치면 현재 프로젝트 설정에 따른것에 잡힘(현재는 unicode / D3DX11 임)
wstring textureFile = L"../_Textures/" + file;
HRESULT hr = D3DX11CreateShaderResourceViewFromFile(디바이스 , 소스파일정의(LPCW long point char배열로 넘겨줌) , NULL이미지(모름), NULL(쓰레드펌프:DX11특징을 나누는 것 멀티쓰레드 렌더링을 다루는 부분(실무가도 5년차 까지 안건드림어려워서), &srv(ID3D11Resource 2차포인터로 주셈) , NULL(Hresult 주소로) );
assert(SUCCEEDED(hr));
Texture.cpp
#include "stdafx.h"
#include "Texture.h"
Texture::Texture(wstring file)
{
vertices[0] = Vertex(D3DXVECTOR3(-0.5f, -0.5f, 0), D3DXVECTOR2(0, 1));
vertices[1] = Vertex(D3DXVECTOR3(-0.5f, +0.5f, 0), D3DXVECTOR2(0, 0));
vertices[2] = Vertex(D3DXVECTOR3(+0.5f, -0.5f, 0), D3DXVECTOR2(1, 1));
vertices[3] = Vertex(D3DXVECTOR3(+0.5f, -0.5f, 0), D3DXVECTOR2(1, 1));
vertices[4] = Vertex(D3DXVECTOR3(-0.5f, +0.5f, 0), D3DXVECTOR2(0, 0));
vertices[5] = Vertex(D3DXVECTOR3(+0.5f, +0.5f, 0), D3DXVECTOR2(1, 0));
D3D11_INPUT_ELEMENT_DESC layoutDesc[] =
{
"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0,
"UV", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0
};
UINT elementCount = ARRAYSIZE(layoutDesc);
shader = new Shader(L"effect.hlsl");
shader->CreateInputLayout(layoutDesc, elementCount);
vertexBuffer = new VertexBuffer(vertices, 6, sizeof(Vertex));
wvpBuffer = new ConstantBuffer(&wvp, sizeof(WVP));
D3DXMatrixIdentity(&wvp.World);
D3DXMatrixIdentity(&wvp.View);
D3DXMatrixIdentity(&wvp.Projection);
D3DXVECTOR3 eye(0, 0, -1);
D3DXVECTOR3 lookAt(0, 0, 0);
D3DXVECTOR3 up(0, 1, 0);
D3DXMatrixLookAtLH(&wvp.View, &eye, &lookAt, &up);
D3DXMatrixTranspose(&wvp.View, &wvp.View);
D3DXMatrixOrthoOffCenterLH(&wvp.Projection, 0, (float)Width, 0, (float)Height, -1, +1);
D3DXMatrixTranspose(&wvp.Projection, &wvp.Projection);
wstring textureFile = L"../_Textures/" + file;
HRESULT hr = D3DX11CreateShaderResourceViewFromFile(Device, textureFile.c_str(), NULL, NULL, &srv, NULL);
assert(SUCCEEDED(hr));
}
Texture::~Texture()
{
SAFE_RELEASE(srv);//new로 할당하는게 아니니까 Release
SAFE_DELETE(vertexBuffer);
SAFE_DELETE(wvpBuffer);
SAFE_DELETE(shader);
}
void Texture::Position(float x, float y, float z)
{
Position(D3DXVECTOR3(x, y, z));
}
void Texture::Position(const D3DXVECTOR3 & position)
{
this->position = position;
}
void Texture::Position(D3DXVECTOR3 * position)
{
memcpy(position, this->position, sizeof(D3DXVECTOR3));
}
void Texture::Scale(float x, float y, float z)
{
Scale(D3DXVECTOR3(x, y, z));
}
void Texture::Scale(const D3DXVECTOR3 & scale)
{
this->scale = scale;
}
void Texture::Scale(D3DXVECTOR3 * scale)
{
memcpy(scale, this->scale, sizeof(D3DXVECTOR3));
}
void Texture::Render()
{
D3DXMATRIX S, T;
D3DXMatrixScaling(&S, scale.x, scale.y, scale.z);
D3DXMatrixTranslation(&T, position.x, position.y, position.z);
wvp.World = S * T;
D3DXMatrixTranspose(&wvp.World, &wvp.World);
DeviceContext->PSSetShaderResources(0, 1, &srv); //(Device)GPU를 다루는것 이미지는 픽셀쉐이더
DeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
shader->Render();
vertexBuffer->Render();
wvpBuffer->Render();
DeviceContext->Draw(6, 0);
}
Uv를 받을 수 있도록 쉐이더를 수정하자. Effect.hlsl로 들어가서
이번에는 정점 구조가 2개 들어오고
원래 텍스쳐를 처리하기 위해서 samplerstate가 필요함 (2편에서 다루겠음)
Effect.hlsl
struct VertexInput
{
float4 Position : POSITION0;
float2 Uv : UV0;//레이아웃에 있는 것과 동일(Texture.h)
};
struct PixelInput
{
float4 Position : SV_POSITION;
float2 Uv : UV0; //Uv그대로 넘겨주기 위함 pixelshader로
};
cbuffer VS_Wvp : register(b0) //뒤에 b0 : buffer | 0 slot번호
{
matrix World;
matrix View;
matrix Projection;
}
PixelInput VS(VertexInput input)
{
PixelInput output;
output.Position = mul(input.Position, World);
output.Position = mul(output.Position, View);
output.Position = mul(output.Position, Projection);
output.Uv = input.Uv; //받은 Uv를 pixelshader로 넘겨주기 ]]
return output;
}
SamplerState Sampler : register(s0); //텍스쳐를 처리하기 위한2편에서 다루겠음 s0 : sampler | 0 slot번호 의미
Texture2D Texture : register(t0);
float4 PS(PixelInput input) : SV_TARGET
{
return Texture.Sample(Sampler, input.Uv); //우리가 넣어준 2D좌표
}
Main.cpp
#include "stdafx.h"
#include "System/Device.h"
#include "Utilities/Math.h"
#include "Text.h"
#include "Rect.h"
#include "Texture.h" //텍스쳐 만든거 추가
Texture* texture = NULL; // 초기화 원래 nullptr써야 됨
void InitScene()
{
texture = new Texture(L"SingleMario.png"); // 마리오 png 파일
texture->Position(200, 200); //위치 포지션
texture->Scale(100, 100); // 크기 지정
}
void DestroyScene()
{
SAFE_DELETE(texture);
}
void Update()
{
}
void Render()
{
texture->Render(); //텍스쳐 렌더
}
잘나오는 것을 볼 수 있다.
잘보면 반투명 처리 된거 같은데 그게아니라
마리오PNG바탕이 흰색이라서 그런다.
Device.cpp 로 넘어가서
Ctrl + G키를 눌러서 해당 번호로 이동할 수 있다)
D3DXCOLOR background 부분이 바탕화면인데
색상을 검은색으로 바꾸고 보니
마리오가 정확히 어떻게 띄어져 있는지 볼 수 있다.
다음시간에 sampler에 대해 알아보겠다.
2) Texture 추가 설명
D3D와 OpenGL에서 다르게 처리 된다고 말하고 어떤 사람은 동일 하다고 얘기
또는 텍스쳐가 로드 될때 수직으로 뒤집을 필요가 있다고 말한다.
고려해야 할 2가지 사항
1. 텍스쳐가 메모리에 저장되는 방식
2. UV좌표를 어디에 두었는지
D3D
- 텍스쳐는 메모리에서 하향식 이다. 텍스처 메모리의 첫번째 바이트는 이미지의 왼쪽 상단
- UV좌표는 하향식이다. (0, 0) 은 텍스쳐의 왼쪽 상단
OpenGL
- 텍스쳐는 메모리의 상향식 이다, 따라서 텍스쳐 메모리의 첫번째 바이트는 이미지 왼쪽 상단
- UV좌표는 상향식 , (0 , 0) 은 텍스쳐 왼쪽 하단
glTexImage2D 에 대한 것을 참조해라
https://heinleinsgame.tistory.com/9
만약 데이터가 D3D와 OpenGL에서 다르게 처리된 것이 사실 이라면
데이터가 실제 하드웨어에 도달하기 전에 어딘가에서 텍스쳐 데이터나 UV좌표를 뒤집어야 하므로
이것은 .. 미친얘기이다. 따라서 운전자는 항상 데이터를 동일한 방식으로 처리해야 한다.
모든 텍스쳐와 UV좌표가 OpenGl규칙에 따라 거꾸로 되어 있다는 것
대안은 업로드 될때 모든 텍스쳐를 뒤집고(실제 OpenGL방식) 로드 될때 모든 UV좌표도 뒤집는 것
다음시간)
'🅿🆁🅾🅶🆁🅰🅼🅼🅸🅽🅶 > DɪʀᴇᴄᴛX 2D' 카테고리의 다른 글
[C++] DirectX World|View|Projection 활용 구현 랜덤 사각형 (0) | 2021.11.20 |
---|---|
[C++] DirectX Constant_Buffer (0) | 2021.11.18 |
[C++] DirectX 쉐이더 와 삼각형과 사각형의 이용 Shader Class 및 World /Rectangle/Triangle (0) | 2021.11.12 |