DirectX/DirectX 2D_(구)
DX sampler_state
컴맹학자
2020. 11. 6. 21:22
728x90
1. 코드
Texture.hlsl 파일 생성
struct VertexInput
{
float4 position : POSITION0;
float2 uv : TEXCOORD0;
};
struct PixelInput
{
float4 position : SV_POSITION0; //SV : 중요한 정보라는 의미
float2 uv : TEXCOORD0;
};
cbuffer transfrombuffer : register(b0) // 슬롯의 갯수 0 ~ 13 상수 버퍼는 무족건 16byte 단위
{
matrix w;
matrix v;
matrix p;
};
PixelInput VS(VertexInput input)
{
//행렬 곱
PixelInput output;
output.position = mul(input.position, w);
output.position = mul(output.position, v);
output.position = mul(output.position, p);
output.uv = input.uv;
return output;
}
Texture2D source_texture1 : register(t0); // 원본의 모든 픽셀 정보가 들어 있음
Texture2D source_texture2 : register(t1); // 원본의 모든 픽셀 정보가 들어 있음
SamplerState samp : register(s0); // 임의의 데이터를 추출 0 ~ 15 슬롯 번호를 가짐
//RS 지정된 정점 갯수만큼만 돌아감
float4 PS(PixelInput input) : SV_Target
{
//float4 color = source_texture.Sample(samp, input.uv);
//float4 color = 0.0f;
//clip(color.a - 0.9f);
//if(color.a < 0.1f) discard;
//if(input.uv.x < 1.0f)
// color = source_texture1.Sample(samp, input.uv);
//else
// color = source_texture2.Sample(samp, float2(input.uv.x - 1.0f, input.uv.y));
float4 color = source_texture1.Sample(samp, input.uv);
return color;
}
Execute.h 수정
#pragma once
//관리 하는 클래스
struct VertexColor //정점 관련
{
D3DXVECTOR3 position;
D3DXCOLOR color;
};
struct VertexTexture
{
D3DXVECTOR3 position;
D3DXVECTOR2 UV; //Texture 좌표계
};
struct TRANSFROM_DATA //카메라 관련
{
D3DXMATRIX world;
D3DXMATRIX view;
D3DXMATRIX projection;
};
class Execute final
{
public:
Execute();
~Execute();
void Update();
void Render();
private:
class Graphics* graphics = nullptr; // 전방선언
//IS
VertexTexture* vertics = nullptr;
ID3D11Buffer* vertexbuffer = nullptr;
ID3D11InputLayout* input_layout = nullptr;
uint* indices = nullptr;
ID3D11Buffer* index_buffer = nullptr;
//VS
ID3D11VertexShader* vertex_shader = nullptr;
ID3DBlob* vs_blob = nullptr; // Binart Large Object
ID3D11PixelShader* pixel_shader = nullptr;
ID3DBlob* ps_blob = nullptr;
//공간
D3DXMATRIX world;
D3DXMATRIX view;
D3DXMATRIX projection;
TRANSFROM_DATA cpu_buffer;
ID3D11Buffer* gpu_buffer = nullptr; // Constant Buffer 상수 버퍼
//RS
ID3D11RasterizerState* raterizer_state = nullptr;
//ID3D11ShaderResourceView* shader_resource[2];
ID3D11ShaderResourceView* shader_resource;
ID3D11SamplerState* sampler_state = nullptr;
};
//IS - VS - RS - PS - OM
// NDC 좌표계
Execute.cpp 수정 및 추가
#include"stdafx.h"
#include"Execute.h"
#include "Graphics.h"
Execute::Execute()
{
graphics = new Graphics();
graphics->Initialize();
graphics->CreateBackBuffer(static_cast<uint>(Settings::Get().GetWidth()),static_cast<uint>(Settings::Get().GetHight()));
//UV
{
vertics = new VertexTexture[4];
vertics[0].position = D3DXVECTOR3(-0.5f, -0.5f, 0.0f); // 0
vertics[1].position = D3DXVECTOR3(-0.5f, +0.5f, 0.0f); // 1
vertics[2].position = D3DXVECTOR3(+0.5f, -0.5f, 0.0f); // 2
vertics[3].position = D3DXVECTOR3(+0.5f, +0.5f, 0.0f); // 3
vertics[0].UV = D3DXVECTOR2(0.0f, 1.0f); // 1
vertics[1].UV = D3DXVECTOR2(0.0f, 0.0f); // 0
vertics[2].UV = D3DXVECTOR2(1.0f, 1.0f); // 3
vertics[3].UV = D3DXVECTOR2(1.0f, 0.0f); // 2
}
//vertexbuffer 만드는곳 (리소스)
{
//껍데기 (버스)
D3D11_BUFFER_DESC desc;
ZeroMemory(&desc, sizeof(D3D11_BUFFER_DESC));
desc.Usage = D3D11_USAGE_IMMUTABLE; //cpu, gpu중 누가 처리 할것인지
desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; //어디다 연결 할것인지
desc.ByteWidth = sizeof(VertexTexture) * 4; //버퍼의 크기
//알맹이 (승객, 데이터)
D3D11_SUBRESOURCE_DATA sub_data;
ZeroMemory(&sub_data, sizeof(D3D11_SUBRESOURCE_DATA));
sub_data.pSysMem = vertics;
//만들어지는곳
auto hr = graphics->GetDevice()->CreateBuffer(&desc, &sub_data, &vertexbuffer);
assert(SUCCEEDED(hr));
}
//indexdata
{
indices = new uint[6]{0 , 1 ,2 ,2 ,1 ,3};
}
//indexbuffer
{
D3D11_BUFFER_DESC desc;
ZeroMemory(&desc, sizeof(D3D11_BUFFER_DESC));
desc.Usage = D3D11_USAGE_IMMUTABLE;
desc.BindFlags = D3D11_BIND_INDEX_BUFFER;
desc.ByteWidth = sizeof(uint) * 6;
D3D11_SUBRESOURCE_DATA sub_data;
ZeroMemory(&sub_data, sizeof(D3D11_SUBRESOURCE_DATA));
sub_data.pSysMem = indices;
auto hr = graphics->GetDevice()->CreateBuffer(&desc, &sub_data, &index_buffer);
assert(SUCCEEDED(hr));
}
//vertex_Shader (VS) (shader에다가 값을 넘겨줌)
{
//정의
auto hr = D3DX11CompileFromFileA
(
"Texture.hlsl", //파일이름
nullptr,
nullptr,
"VS",// Hsls 안에 있는 진입점
"vs_5_0",
0,
0,
nullptr,
&vs_blob,
nullptr,
nullptr
);
assert(SUCCEEDED(hr));
//만들기
hr = graphics->GetDevice()->CreateVertexShader(vs_blob->GetBufferPointer(),vs_blob->GetBufferSize(), nullptr, &vertex_shader);
assert(SUCCEEDED(hr));
}
//input layout (IA)
{
//hsls (Semantic 이름, 몰라도됨, 데이터 형태, 몰라도됨, 읽는 시작주소, 형태 , instancing )
//D3D11_INPUT_ELEMENT_DESC layout_desc[]
//{
// {"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 }
//};
D3D11_INPUT_ELEMENT_DESC layout_desc[]
{
{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0 , 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0 , 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }
};
//레이아웃 (layout_desc , 갯수, vs_blob 시작주소, 크기, input_layout)
auto hr = graphics->GetDevice()->CreateInputLayout(layout_desc, 2, vs_blob->GetBufferPointer(), vs_blob->GetBufferSize(), &input_layout);
assert(SUCCEEDED(hr));
}
//Pixel Shader (shader에서 처리된 데이터 값을 넘겨 받음)
{
auto hr = D3DX11CompileFromFileA
(
"Texture.hlsl",
nullptr,
nullptr,
"PS",
"ps_5_0",
0,
0,
nullptr,
&ps_blob,
nullptr,
nullptr
);
assert(SUCCEEDED(hr));
hr = graphics->GetDevice()->CreatePixelShader(ps_blob->GetBufferPointer(), ps_blob->GetBufferSize(),nullptr, &pixel_shader);
assert(SUCCEEDED(hr));
}
//Create World view Projection (공간) 크기, 회전, 위치
{
D3DXMatrixIdentity(&world); //항등행열 만들어지는곳
D3DXMatrixIdentity(&view);
D3DXMatrixIdentity(&projection);
//가상으로 만들어지는 카메라(눈) ,왼손 좌표(LH) , 오른손(RH)
//넣을 좌표, 눈의 위치, 바라볼 대상
D3DXMatrixLookAtLH(&view, &D3DXVECTOR3(0, 0, 0), &D3DXVECTOR3(0, 0, 1), &D3DXVECTOR3(0, 1, 0));
//원근, 직교 투영 2가지 방식이 존재 현재는 직교투영 (좌표계 설정)
//넣을 좌표, 윈도우사이즈 x, y, 시야 0 , 1
D3DXMatrixOrthoLH(&projection,Settings::Get().GetWidth(), Settings::Get().GetHight(), 0, 1); //dx 좌표
//D3DXMatrixOrthoOffCenterLH(&view, 0 , Settings::Get().GetWidth(), Settings::Get().GetHight(), 0 ,0 , 1); //window 좌표
//D3DXMatrixOrthoOffCenterLH(&view, 0 , Settings::Get().GetWidth(), 0, Settings::Get().GetHight(),0 , 1); //window 좌표
std::cout << "View Matrix " << std::endl;
std::cout << view._11 <<" " << view._12 << " "<< view._13 << " " << view._14 <<" "<< std::endl;
std::cout << view._21 <<" " << view._22 << " "<< view._23 << " " << view._24 <<" "<< std::endl;
std::cout << view._31 <<" " << view._32 << " "<< view._33 << " " << view._34 <<" "<< std::endl;
std::cout << view._41 <<" " << view._42 << " "<< view._43 << " " << view._44 <<" "<< std::endl;
std::cout << std::endl;
std::cout << "projection Matrix " << std::endl;
std::cout << projection._11 << " " << projection._12 << " " << projection._13 << " " << projection._14 << " " << std::endl;
std::cout << projection._21 << " " << projection._22 << " " << projection._23 << " " << projection._24 << " " << std::endl;
std::cout << projection._31 << " " << projection._32 << " " << projection._33 << " " << projection._34 << " " << std::endl;
std::cout << projection._41 << " " << projection._42 << " " << projection._43 << " " << projection._44 << " " << std::endl;
// world 크기, 사이즈 별도로 넣고 결합
D3DXMATRIX S;
D3DXMATRIX T;
D3DXMATRIX R;
D3DXMatrixScaling(&S, 500, 500 , 1);
D3DXMatrixTranslation(&T, 0, 0, 0);
D3DXMatrixRotationZ(&R, static_cast<float>(D3DXToRadian(45)));
// 곱하는 순서 주의 해야함 위치부터 곱하면 크기가 생략이됨
//스 * 자 * 이 * 공전 * 부모
// S 크기 * R 회전 * T 위치
world = S /** R*/ * T;
}
//create constant buffer
{
D3D11_BUFFER_DESC desc;
ZeroMemory(&desc, sizeof(D3D11_BUFFER_DESC));
desc.Usage = D3D11_USAGE_DYNAMIC; // cpu쓰고 , gpu읽기
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
desc.ByteWidth = sizeof(TRANSFROM_DATA);
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
auto hr = graphics->GetDevice()->CreateBuffer(&desc, nullptr, &gpu_buffer);
assert(SUCCEEDED(hr));
}
//create rasterizer state (좌표계를 변동)
{
D3D11_RASTERIZER_DESC desc;
ZeroMemory(&desc, sizeof(D3D11_RASTERIZER_DESC));
desc.FillMode = D3D11_FILL_SOLID; // 내부 다 채움
//desc.FillMode = D3D11_FILL_WIREFRAME; // 테두리만 보임
desc.CullMode = D3D11_CULL_BACK; // 뒷면을 자름
//desc.CullMode = D3D11_CULL_FRONT; // 앞면을 자름 (window 좌표)
//desc.CullMode = D3D11_CULL_NONE; // 앞면 뒷면 다 자름
desc.FrontCounterClockwise = false; // 앞면, 뒷면 여부
//cliping
//그리기 전에 자름
//culling
//그리고 후에 자름
auto hr = graphics->GetDevice()->CreateRasterizerState(&desc, &raterizer_state);
}
//create shader resource (그림을 담아둠)
{/*
auto hr = D3DX11CreateShaderResourceViewFromFileA
(
graphics->GetDevice(),
"Nine.png",
nullptr,
nullptr,
&shader_resource[0],
nullptr
);
assert(SUCCEEDED(hr));
hr = D3DX11CreateShaderResourceViewFromFileA
(
graphics->GetDevice(),
"Nine2.png",
nullptr,
nullptr,
&shader_resource[1],
nullptr
);*/
auto hr = D3DX11CreateShaderResourceViewFromFileA
(
graphics->GetDevice(),
"ion.jpg",
nullptr,
nullptr,
&shader_resource,
nullptr
);
assert(SUCCEEDED(hr));
}
//create sampler_state (UV 처리)
{
D3D11_SAMPLER_DESC desc;
ZeroMemory(&desc, sizeof(D3D11_SAMPLER_DESC));
//UV 좌표 넘어서는 그림을 어떻게 할 것인지
desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
//외각선
desc.BorderColor[0] = 1;
desc.BorderColor[1] = 0;
desc.BorderColor[2] = 0;
desc.BorderColor[3] = 1;
desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; // 이전, 현재 samp 비교해서 처리하는 방법
desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; // min max map 그리는 형태
desc.MaxAnisotropy = 16; // 3D에서 활용
desc.MaxLOD = std::numeric_limits<float>::max(); // 거리에 따른 선명함
desc.MinLOD = std::numeric_limits<float>::min(); // 거리에 따른 선명함
desc.MipLODBias = 0.0f; // MIP의 정보들
auto hr = graphics->GetDevice()->CreateSamplerState(&desc, &sampler_state);
assert(SUCCEEDED(hr));
}
}
Execute::~Execute()
{
SAFE_RELEASE(sampler_state);
SAFE_RELEASE(shader_resource);
//SAFE_RELEASE(shader_resource[0]);
//SAFE_RELEASE(shader_resource[1]);
SAFE_RELEASE(raterizer_state);
SAFE_RELEASE(gpu_buffer);
SAFE_RELEASE(pixel_shader);
SAFE_RELEASE(ps_blob);
SAFE_RELEASE(input_layout);
SAFE_RELEASE(vertex_shader);
SAFE_RELEASE(vs_blob);
SAFE_DELETE_ARRAY(indices);
SAFE_RELEASE(index_buffer);
SAFE_RELEASE(vertexbuffer);
SAFE_DELETE(graphics);
SAFE_DELETE_ARRAY(vertics);
}
void Execute::Update()
{
//부모 행열 3D에서 사용
//static float radian = 0.0f;
//radian += 0.01f;
//D3DXMATRIX P;
//D3DXMatrixRotationZ(&P, radian);
//world *= P;
D3DXMatrixTranspose(&cpu_buffer.world , &world);
D3DXMatrixTranspose(&cpu_buffer.view, &view);
D3DXMatrixTranspose(&cpu_buffer.projection, &projection);
// 상수 버퍼 자원을 갱신
D3D11_MAPPED_SUBRESOURCE mpped_subresource;
graphics->GetDeviceContext()->Map
(
gpu_buffer,
0,
D3D11_MAP_WRITE_DISCARD,
0,
&mpped_subresource
);
//카피
memcpy(mpped_subresource.pData, &cpu_buffer, sizeof(TRANSFROM_DATA));
graphics->GetDeviceContext()->Unmap(gpu_buffer, 0);
}
void Execute::Render()
{
UINT stride = sizeof(VertexTexture); // 정점의 하나의 크기
UINT offset = 0;
//그려질 시간
graphics->Begin();
{
//IA
graphics->GetDeviceContext()->IASetVertexBuffers(0, 1, &vertexbuffer, &stride, &offset); // Vertexbuffer 용
graphics->GetDeviceContext()->IASetIndexBuffer(index_buffer, DXGI_FORMAT_R32_UINT, 0); // indexbuffer 용
graphics->GetDeviceContext()->IASetInputLayout(input_layout);
graphics->GetDeviceContext()->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); //그렬질 용도
//VS 정점의 갯수 만큼만 돌아감 (정점이 많이 있으면 오래 걸리지만 GPU는 병렬 형식)
graphics->GetDeviceContext()->VSSetShader(vertex_shader, nullptr, 0);
graphics->GetDeviceContext()->VSSetConstantBuffers(0, 1, &gpu_buffer);
//RS
graphics->GetDeviceContext()->RSSetState(raterizer_state);
//PS
graphics->GetDeviceContext()->PSSetShader(pixel_shader, nullptr, 0);
graphics->GetDeviceContext()->PSSetShaderResources(0, 1, &shader_resource);
graphics->GetDeviceContext()->PSSetSamplers(0, 1, &sampler_state);
//Pipe line 끝나면 Draw 함수로 그려줘야함 (Vs 변경하면 여기도 갯수 수정)
//graphics->GetDeviceContext()->Draw(6, 0);
graphics->GetDeviceContext()->DrawIndexed(6, 0, 0); //인덱스용 , (인덱스 갯수, 몇번 부터 시작, 기본 시작)
}
//삭제
graphics->End();
}
2. 추가및 요약
ID3D11ShaderResourceView를 통해서 텍스쳐 자원 생성
텍스쳐 좌표계는 좌측 상단이 시작점 이고 0 ~ 1 범위로 정규화
HLSL에서는 Texture2D자료형으로 텍스쳐 자원을 받는다
해당 픽셀이 그려낼 텍스쳐 색상을 추출을 위해 sample 함수를 사용
투명한 픽셀 제거 (hlsl)
clip 함수를 이용해 제거 가능
if문과 discard 키워드를 이용해 제거한다
Sampler State 설정 및 세팅
filter에서는 세 가지만 기억 MIN 축소 MAG 확대 MIP 밉맵
point 에서는 끊어지는듯한 이미지 (도트) , Linear는 부드러운 이미지
clamp, wrap 등의 address mode 활용해서 확장된 uv공간을 처리