반응형

기존에 제작한 은면제거 방식은 벡터의 내적이라는 수학 공식을 활용하여 카메라와 대치되는 각을 계산하여 면을 제거하는 방식이었습니다.

하지만 이 방식은 몇가지 단점이 존재합니다.


1. 각도를 계산해서 하다보니 카메라에 안잡히는 면도 각도조건만 맞으면 남아있게 된다.

2. 면이 깔끔하게 지워지지 않는다. 가령 면은 지워졌는데, 버텍스가 남는다던지..

 

등등.. 여러번 시뮬레이션을 돌려보면 금방 알 수 있는 단점들이 존재합니다.

하지만, 이번에 제작한 Hidden Surface 방식은 렌더링 된 G-Buffer의 값을 얻어와 지오메트리의 렌더링된 면을 메모리에 기억하여 삭제하는 방식이라 더 깔끔하게 면들을 정리해줍니다.

단, 계산시간이 오래 걸릴수 있다는 단점이 있습니다. 이 부분도 차후에 개선할수있도록 해보겠습니다.


이 스크립트의 구동방식을 간단히 살펴보면

1. 먼저 대상이 될 오브젝트의 면들을 전부 디테치 한 후 메모리에 저장한후 각 면마다 오브젝트를 생성해 줍니다.

-여기서 먼저 대상이 될 원본 오브젝트를 하이드 시켜 줍니다.(G-Buffer값 구할때 방해되는 요소)


 



2. 디테치된 면들의 렌더링 된 채널값에서 G-Buffer(지오메트리버퍼) 값을 구해온다.

G-Buffer의 개념 - http://en.wikipedia.org/wiki/Deferred_shading


3. 렌더링 버퍼의 값을 구해서 원본 모델링에 저장이 됐으면 이제 각 면들은 필요없어 졌으니 전부 지워버린다.


4. 원본 면의 페이스 정보들을 비트어레이에 담고 G-Buffer에 담긴 값들만 False로 선언해준다.

5. 이제 원본 오브젝트의 비트어레이에 담긴 면들을 삭제하라는 명령을 실행하면 false로 제외된 값들을 빼고 삭제를 하게 된다.



벡터의 내적 방식과 Hidden Surface 방식의 비교 샷


백페이스 방식- 면이 지저분하게 정리된다.  


 

 히든 서페이스 방식 - 면이 깔끔하게 정리된다.

 

 

이번 과제를 통해 알게 된 내용

1. G-Buffer의 개념과 렌더링에 대한 기초

2. 원본에 있는 면을 뜯어내서 메모리에 저장시킬 수 있는 기능

3. finditem을 이용하여 비트어레이의 값을 조절할수 있는 기능

반응형
반응형

이 스크립트는 최적화를 위한 툴로서 카메라에 보이지 않는 면들을 제거하여 카메라렌더링에 대한 연산을 최소화

시키지 위한 툴입니다.

 

이번 과제를 해결하기 위해서는 삼각함수의 기본 원리와 벡터의 내적을 구하는 공식에 대한
이해가 필요했습니다.

카메라와 오브젝트간 벡터의 내적이 0보다 큰 수의 면만 선택하여 삭제하는 공식을 이해하는데

많은 시간이 필요했습니다.

카메라가 A이고 오브젝트의 한 단면이 B 이고 살리고 싶은 면이 C일때

C = a b cos@를 이용한 벡터의 내적을 이용하여 cos@가 0보다 큰면은 카메라가 바라보는 방향과

같은 방향을 바라보기 때문에 카메라가 잡히지 않는 구간입니다.

따라서 0보다 작은 마이너스 구간을 살리고 0보다 큰 플러스 구간은 삭제하면 됩니다.

 

이 공식을 이용하여 스크립트를 짜게 되면 영상과 같은 결과가 출력됩니다.


 


스크립트

Global backFaceDeleter


--======================================================================================
-- DestroyDialog
--======================================================================================
try (DestroyDialog backFaceDeleter) catch()

--==========================================================================================================

-- rollout backFaceDeleter

--==========================================================================================================
rollout backFaceDeleter "백페이스 방식 삭제"
(
 local mainCamera  -- 메인 카메라 선언
 
 --======================================================================================
 -- struct
 --====================================================================================== 
 struct strt_objinfo   --max 스크립트는 변수 선언에 형식의 제한이 없다. 모든 값을 넣을 수 있음(오브젝트형식)
 (
  obj,     -- 오브젝트 정보
  faces = #(),    -- 전체 페이스 정보
  faceobjs = #()   --  참인 값의 페이스 정보
 )
 ------------------------------------------------------------------------
 -- CameraFilter
 ------------------------------------------------------------------------
 fn FilterCam cam =   --카메라 아니면 선택되지 않게 설정
 (
  if iskindof cam camera then
   return true
  else
   return false
 )
 --======================================================================================
 -- UI
 --======================================================================================
 pickbutton ptn_camera "Pick" filter:FilterCam
 button btn_BackFace "BackFace"
  
  
 --======================================================================================
 -- Fn
 --======================================================================================

 ------------------------------------------------------------------------
 -- FindBackface
 ------------------------------------------------------------------------ 
 fn BackFaceinfo obj camLookPos =     ---- 백페이스 정보와 오브젝트와 카메라의 바라보는 뷰를 변수 선언
 (
  local backFaces = #{}      ----백페이스 관련 좌표와 벡터값을 얻어내기 위해 비트 어레이 변수 선언
                                     
  faceNum = getNumFaces obj        --- 페이스 넘버는 곧 오브젝트의 페이스 넘버다
  for i = 1 to faceNum do                           ----- 1번부터 전체 페이스 넘버를 돌면서 아래를 실행
  (
   facePos = meshop.getFaceCenter obj i        ---- 한 페이스의 중앙 점 좌표를 camLookPos이라는 변수에 대입
   lookV = facePos - camLookPos                            ---- 위에서 구한 중앙 좌표에서 카메라의 위치값을 빼서 lookV에 넣는다. 그래야 벡터의 내적을 구하니까
   
   faceNormal = getFaceNormal obj i        --- 한 페이스가 바라보는 벡터값을 faceNormal 이라는 변수값에 대입
   if dot lookV faceNormal > 0 then       --- 그래서 페이스에서 카메라위치값을 뺀 벡터와 한 페이스의 벡터값을 뺀것의 내적이  0보다 클경우 참.  참인면을 최종적으로 지울것   바라보는 각을 지우고 반대쪽을 바라보는 각을 살리기 위해
    backfaces[i] = true                   --- 비트어레이 backfaces의 페이스 넘버의 참과 거짓을 가림
  )
  
  return backFaces     --- 백페이스 정보 리턴
 )
 
 --======================================================================================
 -- UI Control
 --======================================================================================
 ------------------------------------------------------------------------
 -- ptn_camera
 ------------------------------------------------------------------------ 
 on ptn_camera picked cam do    --- 카메라를 클릭했을때 이름 보여줌
 (
  ptn_camera.text = cam.name
  mainCamera = cam
 )
 
 ------------------------------------------------------------------------
 -- btn_DeleteBackface
 ------------------------------------------------------------------------
 on btn_BackFace pressed do
 (
  local meshObj = $
  local cams = mainCamera

  convertToMesh meshObj  ---메시 형태가 아니면 폴리 넘버를 알수 없다.
  backfaces = BackFaceinfo meshObj cams.pos  ---bacakfaces에 오브젝트와 카메라의 포지션을 넣는다.
  objinfo = strt_objinfo meshObj backfaces   --struct함수로 선언한 세 변수에 각각 값을 집어넣는다. obj에 선택한 오브젝트, face에 backfaces(참인 면)

  --obj : 선택한 오브젝트      faces : 참인 면들의 배열(비트어레이)
  
  print objinfo
  print  objinfo.faces
  
  if objinfo.faces.numberset < getNumFaces meshObj then   -- numberset은 비트어레이 배열안에 몇개의 수가 있는지 알려줌, struct안에 배열의 수가 선택한 메시 수보다 작을경우 선택한 메시의 struct 변수에 넣은
    meshop.deleteFaces meshObj objinfo.faces             ---참인면들을 지워라!
   
  deselect $
  select meshObj
 )
)

CreateDialog backFaceDeleter width:100 height:50

 

 

이번 과제는 저에게 큰 벽이었습니다. 중 고딩때 수학공부를 게을리한 내 자신이 이렇게 미울수가 없었네요..ㅠ

지난 한주간 용인 사는 누나댁을 오가며 열심히 원리를 깨우쳤습니다. 수학과 나온 누님이 저에게 도움 되는 날이

올줄 몰랐어요..ㅎㅎ   어렵지만, 이해하고 나니 정말 극 쾌감이 몰려오네요~^^ 

근데 백페이스 방식은 여러가지 단점이 있어 HIdden 방식을 써야 하는 경우가 생깁니다.

그 방식에 대해서는 다음에 다뤄보겠습니다.


참고 사이트 황군 - http://hwanggoon.tistory.com/118

반응형

+ Recent posts