VS(Direct11이후로는 Tessellation)이후에 수행되는 작업
primitive 단위로 작업 수행
// append 될 최대 vertex의 개수
[maxvertexcount(9)]
// in primitive type, outprimitive type
void GS( triangle VS_OUTPUT input[3], inout TriangleStream<VS_OUTPUT> TriStream )
{
// triangle primitive를 중점을 기준으로 쪼개는 함수
VS_OUTPUT output;
float3 centerPos = (input[0].p.xyz + input[1].p.xyz + input[2].p.xyz)/3.0;
for( int i=0; i<3; i++ )
{
output.p = input[i].p;
TriStream.Append( output ); // stream에 vertex 추가
int iNext = (i+1)%3;
output.p = input[iNext].p;
TriStream.Append( output );
output.p = float4(centerPos,1);
TriStream.Append( output );
//TriStream.RestartStrip();
}
TriStream.RestartStrip(); // 입력으로 들어온 strip 대신 새 strip 생성
}
object를 particle로 분리한다던가, 털, 핀 생성 등 작업 가능
메모리를 추가로 사용하여 downgrade된 texture를 미리 생성한 것
카메라와의 거리에 따라 적절한 mipmap 선택을 통해 연산량을 줄일 수 있음
6면체 cube에 사용하기 좋은 texture type
index별로 방향이 지정되어있음
원본 Resource의 전체를 대상 Resource에 복사
원본 Resource의 일부 영역을 대상 Resource에 복사
d3d_image_load_info.Usage = D3D11_USAGE_STAGING;
d3d_image_load_info.CpuAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
Buffer 생성 시 Staging, CPU_RW를 설정해야 접근 가능
map된 resource는 row 이동 시 rowpitch단위로 이동해야 함(왜?)
GS까지 수행된 Graphics pipeline은 Stream Output Stage에서 CPU로 반환할 수 있음
// Rendering과정에서 사용될 GS와 Stream Output Stage에서 사용될 GS는 생성 방식이 다름
GetDevice()->CreateGeometryShader((DWORD*)pGSBuf->GetBufferPointer(), pGSBuf->GetBufferSize(), NULL,&m_pGS );
GetDevice()->CreateGeometryShaderWithStreamOutput((void* )pGSBuf->GetBufferPointer(), pGSBuf->GetBufferSize(), pDecl, elems, &stride, 1, 0, NULL, &m_pSO );
// Stream buffer의 크기는 정적으로 지정되야 함
// 산출된 vertex의 개수가 buffer를 넘을 경우 무시
int m_nBufferSize = 100000;
D3D11_BUFFER_DESC bufferDesc =
{
m_nBufferSize,
D3D11_USAGE_DEFAULT,
D3D11_BIND_VERTEX_BUFFER | D3D11_BIND_STREAM_OUTPUT,
0,
0
};
V_RETURN( GetDevice()->CreateBuffer( &bufferDesc, NULL, &m_pStreamTo ) );
V_RETURN( GetDevice()->CreateBuffer( &bufferDesc, NULL, &m_pDrawFrom ) );
m_pImmediateContext->VSSetShader( m_pVS, NULL, 0 );
m_pImmediateContext->GSSetShader( m_pSO, NULL, 0 );
m_pImmediateContext->IASetInputLayout( m_pVertexLayout );
UINT stride = sizeof( P3VERTEX );
UINT Offsets[1] = {0};
ID3D11Buffer* pVB[1] = {pBuffer};
// Stream Output으로 나올 buffer 지정
m_pImmediateContext->SOSetTargets( 1, &m_pStreamTo, Offsets );
m_pImmediateContext->IASetVertexBuffers( 0, 1, pVB, &stride, Offsets );
m_pImmediateContext->IASetIndexBuffer( m_pIndexBuffer, DXGI_FORMAT_R32_UINT, 0 );
D3D11_QUERY_DATA_PIPELINE_STATISTICS stats;
// Stream Output으로 나온 stream의 정보를 query하는 방법
// vertex의 개수, face의 개수 등을 알 수 있음
ID3D11Query* pQuery;
D3D11_QUERY_DESC queryDesc;
queryDesc.Query = D3D11_QUERY_SO_STATISTICS;
queryDesc.MiscFlags = 0;
GetDevice()->CreateQuery( &queryDesc, &pQuery );
m_pImmediateContext->Begin(pQuery);
// streamout에 의해 산출된 buffer의 정확한 vertex의 개수를 모를 때 사용
// Draw call하여 Graphics pipeline 가동
// 실제로 rendering이 되지는 않음
m_pImmediateContext->DrawAuto();
m_pImmediateContext->End(pQuery);
D3D11_QUERY_DATA_PIPELINE_STATISTICS stats;
while (S_OK != m_pImmediateContext->GetData(pQuery, &stats, pQuery->GetDataSize(), 0));
SAFE_RELEASE(pQuery);
pVB[0] == NULL;
// Stream output의 출력 buffer 해제
m_pImmediateContext->SOSetTargets( 0, pVB, Offsets );
shader file을 빌드에서 제외하지 않는다면 위 형식으로 컴파일된 파일이 생성됨
이렇게 생성된 파일은 일반적인 file RW를 통해 접근할 수 있음
HANDLE hFile = CreateFile(L"HLSL.cso", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (INVALID_HANDLE_VALUE == hFile)
return E_FAIL;
LARGE_INTEGER FileSize;
GetFileSizeEx(hFile, &FileSize);
BYTE* pFileData = new BYTE[FileSize.LowPart];
if (!pFileData)
return E_OUTOFMEMORY;
DWORD BytesRead;
if (!ReadFile(hFile, pFileData, FileSize.LowPart, &BytesRead, NULL))
return E_FAIL;
CloseHandle(hFile);
Microsoft::WRL::ComPtr<ID3DBlob> VSBlobCSO;
D3DCreateBlob(FileSize.LowPart, VSBlobCSO.GetAddressOf());
memcpy(VSBlobCSO->GetBufferPointer(), pFileData, FileSize.LowPart);
m_dxobj.g_pVertexShader.Attach(LoadVertexShaderFile(GetDevice(), NULL, VSBlobCSO.GetAddressOf(), 0, true));
RW를 통해 접근한 file data는 D3DCreateBlob()을 통해 Blob을 생성 가능
이후는 compile과 동일한 절차로 shader 생성, 사용 가능
DirectX는 SIMD와 SSE를 지원하는 고유의 자료형인 DirectXMath를 지원
내부는 _m128을 이용하지만 그래픽스 연산을 위한 함수들이 미리 제작되어 사용이 편리
다만 DirectX는 그래픽스를 위한 라이브러리인만큼 Unreal에서 지원하는 FMath쪽이 게임에서는 더 효율적이다는 듯
평행한 평면이라면 단순한 투영 행렬을 이용해서 쉽게 그림자를 만들 수 있음
위 Matrix를 적용하여 계산된 좌표를 Stencil buffer에 기록한 후 Stencil buffer에 설정된 pixel에는 rendering을 하지 않는 방식으로 간단하게 그림자 적용 가능
단, 일종의 간략화같은 것이므로 평면이 굴곡져있다거나 Object가 Object를 가리는 등의 상황에서는 그림자가 정확하게 표현되지 않음
위 사진에서의 그림자를 보면 Box들이 서로를 가리는 것으로 보이지만 Box에는 해당 그림자가 표현되지 않음
UML에서 Pointer를 어떻게 표현하는가에 대한 의문이 들어 조사해보던 중 pointer, composition, aggregation을 잘 표현한 글이 있어 가져왔다