24/03/20
1교시
주제 : 구조화 버퍼 개선
작업 내용 : 시스템 메모리와 GPU 버퍼간의 데이터를 양방향으로 이동 가능하게 구현
CStructuredBuffer::Create() :
구조화 버퍼를 생성해주는 함수인 Create() 함수는 아래와 같이 선언되어 있다.
int Create(UINT _ElementSize,
UINT _ElementCount,
SB_TYPE _Type,
bool _bSysMemMove,
void* _InitialData = nullptr);
입력받는 인자중 "_bSysMemMove" 의 값에 따라 추가로 생성되는 버퍼가 생긴다.
참고로 해당 값이 true 이면 시스템 메모리와 GPU 버퍼간에 데이터 이동이 있음을 의미하고 false는 데이터 이동이 발생하지 않음을 의미한다.
SB_TYPE::SRV_ONLY 와 SB_TYPE::SRV_UAV :
"m_Desc"의 타입은 "D3D11_BUFFER_DESC" 이다.
생성하고자 하는 Buffer에 대해 설명하는 객체라고 생각하면 된다.
typedef struct D3D11_BUFFER_DESC {
UINT ByteWidth; // 버퍼의 크기
D3D11_USAGE Usage; // 버퍼를 읽고 쓰는 방법을 식별
UINT BindFlags; // 버퍼가 파이프라인에 바인딩 되는 방법을 식별
UINT CPUAccessFlags; // 리소스에 허용되는 CPU 액세스 유형을 식별, 액세스가 필요하지 않은 경우 '0'
UINT MiscFlags; // 리소스에 대한 옵션을 식별, 사용하지 않는 경우 0
UINT StructureByteStride; // 구조화 버퍼를 나타내는 경우 각 요소의 크기(Byte)
} D3D11_BUFFER_DESC;
// BindFlags 에 사용 가능한 값들
typedef enum D3D11_BIND_FLAG {
D3D11_BIND_VERTEX_BUFFER = 0x1L,
D3D11_BIND_INDEX_BUFFER = 0x2L,
D3D11_BIND_CONSTANT_BUFFER = 0x4L,
D3D11_BIND_SHADER_RESOURCE = 0x8L, // 버퍼 또는 텍스처를 셰이더 단계에 바인딩
D3D11_BIND_STREAM_OUTPUT = 0x10L,
D3D11_BIND_RENDER_TARGET = 0x20L,
D3D11_BIND_DEPTH_STENCIL = 0x40L,
D3D11_BIND_UNORDERED_ACCESS = 0x80L,// 순서가 지정되지 않은 액세스 리소스를 바인딩
D3D11_BIND_DECODER = 0x200L,
D3D11_BIND_VIDEO_ENCODER = 0x400L
} ;
Unordered Access ? :
Read/Write Buffer 생성 :
Read/Write Buffer 생성시 register에 바인딩 하지 않는다고 해서 "BindFlag = 0"으로 설정하면 Buffer 생성 실패한다.
때문에 아무 값이나 하나 줘야하는데 무난한 "D3D11_BIND_SHADER_RESOURCE" 로 설정해줌
Read/Write 테스트 :
값이 제대로 넘어가고 받아지는지 테스트 하기위해 particle 구조체에 정의된 값을 SetData() 함수를 사용해 Write Buffer 를 거쳐 Main Buffer로 넘겨주고, 넘어간 값을 Read Buffer를 거쳐 다시 particle1 구조체에 받아준다.
particle1 구조체에 particle 구조체와 같은 값이 들어간 것이 확인됨으로 정상적으로 SetData(), GetData() 함수가 동작함을 알 수 있다.
StructuredBuffer::GetData() 와 StructuredBuffer::SetDate() :
SetData()는 시스템 메모리의 데이터를 GPU의 Write Buffer로 옮기고, Wrute Buffer로 넘겨진 데이터를 Main Buffer로 복사해준다.
GetData()는 GPU의 Main Buffer에 있는 데이터를 Read Buffer로 복사한 후, 가져온 데이터를 memcpy로 복사하여 저장한다.
참고로 pData의 경우 Unmap시 사라지기에 Unmap 전에 memcpy로 인자로 들어온 _pDest에 memcpy로 복사해준 것
Map() :
HRESULT Map(
[in] ID3D11Resource *pResource,
[in] UINT Subresource,
[in] D3D11_MAP MapType, // ☆
[in] UINT MapFlags,
[out, optional] D3D11_MAPPED_SUBRESOURCE *pMappedResource
);
Map 함수의 인자 중 세번째 인자인 MapType에 정의된 값들은 아래와 같다.
SetData() 함수에선 Map()함수 사용시 "D3D11_MAP_WRITE_DISCARD" 값을 사용했고, GetData() 함수에선 "D3D11_MAP_READ" 값을 사용했다.
2교시
주제 : ParticleSystem 설계 시작
작업 내용 : Particle 입자 초기세팅 후 화면에 렌더링 해보기
Particle 전용 셰이더 생성 :
파티클 객체는 빌보드로 구현할 것이기에 Rasterizer 옵션으로 CULL_NONE,CULL_BACK, CULL_FRONT 중 어떤걸 넣어도 상관없다. (빌보드 : 어디서 보든 카메라에 대해 정면으로 보인다.)
Particle 객체는 깊이 테스트는 진행하되 깊이값을 남기진 않을것이기에 DepthStencil State 를 "NO_WRITE" 로 해준다.
NO_WRITE는 깊이 테스는 하고, 깊이 기록은 하지 않는 설정이다.
Blend State는 ALPHA_BLEND 로 해줬는데 그 이유는, 투명 처리된 alpha 값에 의해 뒷 이미지에 구멍이 뚫리면 안되기 때문이다.
Particle Material 생성 :
생성해준 Particle 전용 Shader를 기반으로 Material 생성
ParticleSystem 클래스 초기화 :
ParticleSystem은 전용 셰이더로 Render 해줄것 이기에 초기화 과정에 Material 을 설정해준다.
또한 Mesh도 RectMesh를 사용할 것이기에 같이 설정해준다.
ParticleSystem::render() 구현 :
m_ParticleBuffer에 들어가 있는 Particle 에 대한 정보를 17번 레지스터에 바인딩해주고,
ViewMatrix, ProjMatrix 때문에 Transform 데이터도 바인딩해준다.
이후, 반복문을 돌며 particle 들을 render 해주는데, 파티클은 여러개인데 셰이더에선 해당 particle이 몇번째 파티클인지 알 수 없다.
때문에 Material의 ScalarParam의 INT_0을 통해서 몇번째 반복문을 도는지 render 전에 바인딩하여 정보를 넘겨준다.
파티클 전용 셰이더파일(particle.fx) :
Vertex Shader에서 들어온 Vertex의 값에 Scale을 곱해줌으로써 Rect의 크기를 Scale 만큼 키워준다.
이후 WorldPos를 더해줘서 위치 이동을 해준다.
Particle Shader에서는 들어온 pixel의 색상을 붉은색으로 변경해준다.
Rendering을 해보면 화면에 10개의 붉은색 사각형 Particle이 성공적으로 출력된다.
Next Note
AR50_ClassNote_2
24/03/21 1교시 주제 : 작업 내용 : 2교시 주제 : 작업 내용 :
coder-qussong.tistory.com
'DirectX11 > AR' 카테고리의 다른 글
AR50_ClassNote_6 (0) | 2024.03.28 |
---|---|
AR50_ClassNote_5 (0) | 2024.03.26 |
AR50_ClassNote_4 (0) | 2024.03.26 |
AR50_ClassNote_3 (0) | 2024.03.23 |
AR50_ClassNote_2 (0) | 2024.03.22 |