이전 볼륨 렌더링 이미지는 나뭇결 무늬가 심했다. 이를 완화시키는 방법을 소개하고 적용해보자.
먼저 interpolation 방법이다. 이산적인 값으로 이루어져 있는 복셀값을 가중치를 이용하여 연속적인 값을 구하는 방법이다.
Volume.cpp
이를 적용해 렌더링 해보면 아래 그림과 같다. 이전보다 나아졌다고 볼 수 없다.
나뭇결 무늬를 보다 효과적으로 제거하기 위해 기존의 1d Pallette 대신 2d Pallette 를 적용해보겠다.
기존에는 하나의 intensity 에 하나의 값을 가진 팔렛이었다면 2d Pallette 는 이전 intensity 와 현재 intensity 를 interpolation 하여
보다 경계를 부드럽게 만든 pallette 라고 볼 수 있다.
TransferFunction.cpp
pallette 를 모두 만들었으니 2D pallette 를 사용하는 함수를 만들어보자.
매개변수로 2개의 intensity 가 들어오고 2개의 값을 interpolation 해서 가중값을 반환한다.
float TransferFunction::GetPalletteC2DValue(int color, float prev_intensity, float intensity)
{
if(intensity +1.f>= MAX_INTENSITY) return -1.f;
if(prev_intensity +1.f >= MAX_INTENSITY) return -1.f;
float coord_00 = m_PalletteC2D[color].get()[MAX_INTENSITY*static_cast<int>(prev_intensity) + static_cast<int>(intensity)];
float coord_10 = m_PalletteC2D[color].get()[MAX_INTENSITY*static_cast<int>(prev_intensity+1) + static_cast<int>(intensity)];
float coord_01 = m_PalletteC2D[color].get()[MAX_INTENSITY*static_cast<int>(prev_intensity) + static_cast<int>(intensity+1)];
float coord_11 = m_PalletteC2D[color].get()[MAX_INTENSITY*static_cast<int>(prev_intensity+1) + static_cast<int>(intensity+1)];
float weight[2] = {prev_intensity - static_cast<int>(prev_intensity),
intensity - static_cast<int>(intensity)};
float inter_0010 = (1.f - weight[0]) * coord_00 + weight[0]*coord_10;
float inter_0111 = (1.f - weight[0]) * coord_01 + weight[0]*coord_11;
float res = (1.f - weight[1]) * inter_0010 + weight[1] * inter_0111;
return res; }
float TransferFunction::GetPalletteA2DValue(float prev_intensity,
float intensity)
{
if(prev_intensity + 1.f >= MAX_INTENSITY) return -1.f;
if(intensity + 1.f >= MAX_INTENSITY) return -1.f;
float coord_00 = m_PalletteA2D.get()[MAX_INTENSITY*static_cast<int>(prev_intensity) + static_cast<int>(intensity)];
float coord_10 = m_PalletteA2D.get()[MAX_INTENSITY*static_cast<int>(prev_intensity+1) + static_cast<int>(intensity)];
float coord_01 = m_PalletteA2D.get()[MAX_INTENSITY*static_cast<int>(prev_intensity) + static_cast<int>(intensity+1)];
float coord_11 = m_PalletteA2D.get()[MAX_INTENSITY*static_cast<int>(prev_intensity+1) + static_cast<int>(intensity+1)];
float weight[2] = {prev_intensity - static_cast<int>(prev_intensity),
intensity - static_cast<int>(intensity)};
float inter0010 = (1.f - weight[0]) * coord_00 + weight[0] * coord_10;
float inter0111 = (1.f - weight[0]) * coord_01 + weight[0] * coord_11;
float res = (1.f - weight[1]) * inter0010 + weight[1]* inter0111;
return res; }
이후 이를 사용하는 부분을 다듬어야 한다.
Renderer.cpp
이를 적용하여 volume rendering 하면 아래와 같이 나온다.