02.03

신승빈·2023년 2월 3일
0

KGCA 수업

목록 보기
102/128

Geometry Shader

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로 분리한다던가, 털, 핀 생성 등 작업 가능

Reference : https://learn.microsoft.com/en-us/windows/win32/direct3d11/geometry-shader-stage
Reference : https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-so-restartstrip
Reference : https://heinleinsgame.tistory.com/34

Texture

mipmap

메모리를 추가로 사용하여 downgrade된 texture를 미리 생성한 것
카메라와의 거리에 따라 적절한 mipmap 선택을 통해 연산량을 줄일 수 있음

Cube Texture(Texture2DArray)

6면체 cube에 사용하기 좋은 texture type
index별로 방향이 지정되어있음

CopyResource

원본 Resource의 전체를 대상 Resource에 복사

CopySubresourceRegion

원본 Resource의 일부 영역을 대상 Resource에 복사

Map, UnMap

	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단위로 이동해야 함(왜?)

Stream Output Stage

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 );	

FXC


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 생성, 사용 가능

XMMatrix

DirectX는 SIMD와 SSE를 지원하는 고유의 자료형인 DirectXMath를 지원
내부는 _m128을 이용하지만 그래픽스 연산을 위한 함수들이 미리 제작되어 사용이 편리
다만 DirectX는 그래픽스를 위한 라이브러리인만큼 Unreal에서 지원하는 FMath쪽이 게임에서는 더 효율적이다는 듯

Plane Shadow(Depth Stencil Buffer)

평행한 평면이라면 단순한 투영 행렬을 이용해서 쉽게 그림자를 만들 수 있음

Point Light에서의 Plane Shadow Matrix

Direct Light에서의 Plane Shadow Matrix


위 Matrix를 적용하여 계산된 좌표를 Stencil buffer에 기록한 후 Stencil buffer에 설정된 pixel에는 rendering을 하지 않는 방식으로 간단하게 그림자 적용 가능
단, 일종의 간략화같은 것이므로 평면이 굴곡져있다거나 Object가 Object를 가리는 등의 상황에서는 그림자가 정확하게 표현되지 않음

위 사진에서의 그림자를 보면 Box들이 서로를 가리는 것으로 보이지만 Box에는 해당 그림자가 표현되지 않음

UML의 composition과 aggregation

UML에서 Pointer를 어떻게 표현하는가에 대한 의문이 들어 조사해보던 중 pointer, composition, aggregation을 잘 표현한 글이 있어 가져왔다

Reference : https://stackoverflow.com/a/21817223/8106257
profile
이상을 길잡이 삼아 로망을 추구합니다.

0개의 댓글