Density Field
카테고리: Graphics
태그: DirectX
홍정모님의 그래픽스 새싹코스 강의를 듣고 정리한 내용입니다.
Density Field
이번 강의에서는 Density Field 개념을 이용해 Particle System을 구현할 것이다. Particle이 지나간 자리들의 Density를 조금씩 감소시켜 trail 효과를 나타나게 할 수 있다. 이때 Particle을 어떻게 그릴 것인지 고민해보자. 가장 단순한 방법으로는 Compute Shader 내부에서 particle의 렌더링까지 처리할 수 있다. 아래 정리하겠지만 이 방법은 문제가 발생하기 때문에 particle은 Geometry Shader와 Pixel Shader를 이용해 렌더링 해야 한다.
std::vector<Vector3> rainbow = {
{1.0f, 0.0f, 0.0f}, // Red
{1.0f, 0.65f, 0.0f}, // Orange
{1.0f, 1.0f, 0.0f}, // Yellow
{0.0f, 1.0f, 0.0f}, // Green
{0.0f, 0.0f, 1.0f}, // Blue
{0.3f, 0.0f, 0.5f}, // Indigo
{0.5f, 0.0f, 1.0f} // Violet/Purple
};
std::mt19937 gen(0);
for (auto &p : m_particles) {
p.color = rainbow[dc(gen)];
}
// ...
m_particles.Initialize(m_device);
- 이번 예제의 뽀인트 : 알록달록 무지개 파티클
Render Function
void Render() {
AdvectParticles(); // CS
DrawSprites(); // GS, PS
DissipateDensity(); // CS
ComPtr<ID3D11Texture2D> backBuffer;
ThrowIfFailed(
m_swapChain->GetBuffer(0, IID_PPV_ARGS(backBuffer.GetAddressOf())));
m_context->CopyResource(backBuffer.Get(), m_densityTex.GetTexture());
}
// DissipationCS.hlsl
const float dissipation = 0.1f;
float3 color = densityField[dtID.xy].rgb - dissipation;
color = max(0, color);
AdvectParticles
: 파티클 위치, 속도 계산DrawSprites
: 파티클 위치를 중심으로 bill-board 생성 & 렌더링DissipateDensity
: 파티클의 이전 위치들 density 감소- Pixel Shader 이후 Compute Shader 과정이 필요하기 때문에 PS에서 backbuffer에 바로 그릴 수 없음
- 별도의 텍스처(m_densityTex)에 렌더링 하고 backbuffer로 복사
Explain | Result |
---|---|
만약 Geometry Shader를 사용해 Sprite로 렌더하지 않고 Compute Shader에서 바로 렌더링하게 되면 오른쪽 그림과 같이 많은 픽셀들이 깨진 결과가 나타난다. Compute Shader에서는 각 파티클의 위치가 하나의 스레드가 되어 병렬 처리된다. 만약 두 파티클의 위치가 충분히 가깝다면 텍스처의 같은 위치에 접근해 color 지정하기 때문에 race condition이 발생하게 된다. 따라서 compute shader에서 직접 렌더링하는 것은 항상 조심해야 한다.
Result
댓글 남기기