Density Field

Date:     Updated:

카테고리:

태그:

홍정모님의 그래픽스 새싹코스 강의를 듣고 정리한 내용입니다.


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
043603 045932

만약 Geometry Shader를 사용해 Sprite로 렌더하지 않고 Compute Shader에서 바로 렌더링하게 되면 오른쪽 그림과 같이 많은 픽셀들이 깨진 결과가 나타난다. Compute Shader에서는 각 파티클의 위치가 하나의 스레드가 되어 병렬 처리된다. 만약 두 파티클의 위치가 충분히 가깝다면 텍스처의 같은 위치에 접근해 color 지정하기 때문에 race condition이 발생하게 된다. 따라서 compute shader에서 직접 렌더링하는 것은 항상 조심해야 한다.


Result

HongLabGraphicsExample2024-09-2205-00-25-ezgif com-crop


HongLabGraphicsExample2024-09-2506-03-31-ezgif com-crop



맨 위로 이동하기

Graphics 카테고리 내 다른 글 보러가기

댓글 남기기