왼손 오른손 각 손가락이 가리키는 좌표축은 동일
x, y축을 정렬하면 왼손좌표계의 z축은 정면 방향을, 오른손좌표계의 z축은 후면 방향을 가리킴
임의의 위치벡터는 기저벡터의 조합으로 이루어짐
모델 제작 프로그램(3D MAX 등)마다 고유 좌표계 존재
모델과 엔진의 좌표에 대한 변환 필요
Wireframe : 대상을 선 정보만으로 표현
Polygon : Primitive 집합으로 표현
Solid : 모양 외에 다양한 성질을 표현
폴리곤 메쉬
매개변수 : 베지어, 스플라인 등
스위핑 : 평면도형이 지나가는 공간의 볼륨
솔리드 : 기본 객체의 집합(합, 차)
프랙탈
파티클
World에 표현된 Object를 2차원 평면에 투영하는 과정
기하변환, 좌표계 변환, 투영 변환 등(그래픽 렌더링 파이프라인)
일반적으로 World Object는 원근투영, UI는 직교투영
가려진 객체나 면을 제거하는 과정
색상, 명암, 입체감 부여
RGB, CMY, HSV
Flat 쉐이딩, Gouraud 쉐이딩, phong 쉐이딩
Diffuse 조명, Specular Reflection, 빛의 굴절(Refraction)
Object의 표면에 이미지 붙이기
장면 연출 영역 중 일정 범위만 출력 장치에 표현하는 것
Window client 일부 영역만 출력도 가능
뷰포트를 벗어나는 부분을 제외하는 알고리즘
사각형 단계는 코딩 불가능 - 원형 단계는 코딩 가능
Hull, Tessellation, Domain은 Tessellation 단계라고 칭함
Tesselation 단계와 Geomtry Stage를 설정하지 않아도 출력 가능
Rasterizer : Object에 투영된 NDC가 Display될 때 어느 픽셀에 대응되야 하는지 결정
화면에 독립적인 출력 좌표계
x, y축은 -1 ~ 1사이
z축은 openGL의 경우 -1 ~ 1, directx의 경우 0 ~ 1 사이
정점 정보가 저장된 버퍼
GPU 메모리에 저장되야 함
struct SimpleVertex
{
float x; // 위치
float y;
float z;
float r; // 컬러
float g;
float b;
float a;
};
bool CraeteVertexBuffer
{
HRESULT hr;
SimpleVertex vertices[] =
{
-1.0f, 1.0f, 0.0f, 0.0f,0.0f,0.0f,0.0f,// v0
+1.0f, 1.0f, 0.0f, 0.0f,0.0f,0.0f,0.0f,// v1
-1.0f, -1.0f, 0.0f, 0.0f,0.0f,0.0f,0.0f,// v2
};
D3D11_BUFFER_DESC bd;
ZeroMemory(&bd, sizeof(bd));
bd.ByteWidth = sizeof(SimpleVertex)*3; // 바이트 용량
// GPU 메모리에 할당
bd.Usage = D3D11_USAGE_DEFAULT; // 버퍼의 할당 장소 내지는 버퍼용도
bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
D3D11_SUBRESOURCE_DATA sd;
ZeroMemory(&sd, sizeof(sd));
sd.pSysMem = vertices;
// 버퍼 생성
hr=m_pd3dDevice->CreateBuffer(
&bd, // 버퍼 할당
&sd, // 초기 할당된 버퍼를 체우는 CPU메모리 주소
&m_pVertexBuffer);
// 정점쉐이더 컴파일
ID3DBlob* pErrorCode = nullptr;
// cpp 파일은 유니코드를 지원하지만 쉐이더 스크립트는 유니코드를 지원하지 않음
// #include <d3dcompiler.h>
// #pragma comment(lib, "d3dcompiler.lib")
hr = D3DCompileFromFile(
L"VertexShader.txt", // 쉐이터 스크립트 파일 이름
NULL,
NULL,
"main", // 쉐이더 스크립트의 시작 함수 이름
"vs_5_0", // 컴파일할 쉐이더 버전
0,
0,
&m_pVSCode, // 컴파일 된 Blob 코드
&pErrorCode); // 에러 발생 시 반환 코드
if (FAILED(hr))
{
if (pErrorCode)
{
OutputDebugStringA((char*)pErrorCode->GetBufferPointer());
// Release 수행하지 않을 시 메모리 누수 발생
pErrorCode->Release();
}
return false;
}
// 생성된 쉐이더 코드 Blob으로 쉐이더 생성
hr = m_pd3dDevice->CreateVertexShader(
m_pVSCode->GetBufferPointer(),
m_pVSCode->GetBufferSize(),
NULL,
&m_pVS);
// 픽쉘쉐이더 컴파일
hr = D3DCompileFromFile(
L"PixelShader.txt",
NULL,
NULL,
"PSMain",
"ps_5_0",
0,
0,
&m_pPSCode,
&pErrorCode);
if (FAILED(hr))
{
if (pErrorCode)
{
// Visual Studio 출력 창에 출력하는 함수
OutputDebugStringA((char*)pErrorCode->GetBufferPointer());
pErrorCode->Release();
}
return false;
}
hr = m_pd3dDevice->CreatePixelShader(
m_pPSCode->GetBufferPointer(),
m_pPSCode->GetBufferSize(),
NULL,
&m_pPS);
if (FAILED(hr))
{
if (pErrorCode)
{
OutputDebugStringA((char*)pErrorCode->GetBufferPointer());
pErrorCode->Release();
}
return false;
}
// 정점레이아웃은 정점쉐이더 밀접한 관련
// 정점레이아웃 생성시 사전에 정점쉐이더 생성이 필요
D3D11_INPUT_ELEMENT_DESC ied []=
{
{ "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},
};
UINT NumElements = sizeof(ied) / sizeof(ied[0]);
hr = m_pd3dDevice->CreateInputLayout(
ied,
NumElements,
m_pVSCode->GetBufferPointer(),
m_pVSCode->GetBufferSize(),
&m_pVertexLayout);
return hr;
}
bool Sample::Render()
{
// 삼각형 랜더링
UINT stride = sizeof(SimpleVertex); // 정점1개의 바이트용량
UINT offset = 0; // 정점버퍼에서 출발지점(바이트)
//SLOT(레지스터리)
m_pImmediateContext->IASetVertexBuffers(0, 1,
&m_pVertexBuffer, &stride, &offset);
m_pImmediateContext->IASetInputLayout(m_pVertexLayout);
m_pImmediateContext->VSSetShader(m_pVS, NULL, 0);
m_pImmediateContext->PSSetShader(m_pPS, NULL, 0);
m_pImmediateContext->Draw(3, 0);
return true;
}
// 버퍼 설명 구조체
typedef struct D3D11_BUFFER_DESC
{
UINT ByteWidth; // 버퍼의 전체 크기
D3D11_USAGE Usage; // 버퍼에 접근가능 유형(GPU, CPU) 및 읽기 쓰기 설정
UINT BindFlags; // 버퍼와 파이프라인 결합 방식(정점버퍼, 인덱스버퍼, depth-stencil 버퍼 등)
UINT CPUAccessFlags; // CPU 접근 허용 여부
UINT MiscFlags; // 기타 플래그
UINT StructureByteStride; // buffer가 structuredBuffer일 경우 각 element의 크기
} D3D11_BUFFER_DESC;
// 버퍼 초기 데이터
typedef struct D3D11_SUBRESOURCE_DATA
{
const void *pSysMem; // 초기 데이터 주소
UINT SysMemPitch; // 2D, 3D Texture에서만 사용. 텍스처 한 줄의 크기
UINT SysMemSlicePitch; // 3D Texture에서만 사용. 텍스처 한 층의 크기?
} D3D11_SUBRESOURCE_DATA;
typedef struct D3D11_INPUT_ELEMENT_DESC
{
LPCSTR SemanticName; // 쉐이더 스크립트로 넘어가는 이름
UINT SemanticIndex; // 동일한 Semantic이 있을 경우 사용
DXGI_FORMAT Format; // DXGI_FORMAT 사용
UINT InputSlot; // Input Assembler 번호
UINT AlignedByteOffset; // 하나의 Element에 다수의 정보가 저장되어 있을 시 원하는 데이터의 시작 주소 위치
D3D11_INPUT_CLASSIFICATION InputSlotClass; // 입력 데이터의 종류, input slot마다 지정
UINT InstanceDataStepRate; // 위 데이터가 per_instance 시 설정
} D3D11_INPUT_ELEMENT_DESC;
정점 버퍼에 있는 모든 정점에 대해 한번씩 작업 수행
float4 main(float3 p : POSI1TION ) : SV_POSITION
{
// px,py,pz, 1.0f
return float4(p,1.0f);
}
대소문자 구분 안함
고유 Sementic은 반환 타입이 지정되어 있음
Sementic은 D3D11_INPUT_ELEMENT_DESC에서 지정한 값과 동일해야 함
레이아웃을 생성하기 이전에 쉐이더가 미리 컴파일 되어있어야 함
디버깅하기 위해서는 특별한 유틸리티 필요(Error용 Blob사용 추천)
모든 픽셀에 대해 한번씩 작업 수행
float4 PSMain(float4 p : SV_POSITION, float4 color : COLOR0) : SV_Target
{
return c;
}
입력된 정점들을 어떤 식으로 출력할 것인가에 대한 결정
List형태의 경우 짝이 맞을 경우에만 출력(직선 2개씩, 삼각형 3개씩)
삼각형의 경우 시계방향의 순서로 주어져야지만 정면으로 판단하고 출력