아래에서 퍼옴
http://eppengine.com/zbxe/programmig/3075

1. max sdk 를 설치하면 max sdk 폴더가 생성된다.

2. 생성된 max sdk 폴더에는 howto 라는 폴더가 존재한다.

3. 그 폴더 안쪽에는 다시 3dsmaxPluginWizard 라는 폴더가 존재한다.

4. 3dsmaxPluginWizard 폴더 안쪽에 있는 3dsmaxPluginWizard.vsz 폴더를 텍스트 문서 편집기로 연다.

5. 3dsmaxPluginWizard.vsz 에서 수정해야할 부분은 한군데가 있는데

   Param="ABSOLUTE_PATH = [Absolute Path Location of 3dsmaxPluginWizard Root Directory]"

요 부분이다.

6. 윗 부분을 wizard 가있는 절대경로를 입력한다. 예를들어

 예> Param = "G:\Program Files\Autodesk\3ds Max 2010 SDK\maxsdk\howto\3dsmaxPluginWizard"

요렇게..

7. 주의 사항은 위 폴더명 기록시 젤 뒤에 slash 를 붙여서는 안된다.

 예> Param = "G:\Program Files\Autodesk\3ds Max 2010 SDK\maxsdk\howto\3dsmaxPluginWizard \"

8. 그리고는 현재 visual stuido 폴더로 들어가서 vc 라는 폴더 아래에 있는 vcprojects 라는 폴더를 연다.

예> G:\Program Files\Microsoft Visual Studio 8\VC\vcprojects

9. 그 폴더 안쪽에 wizard 폴더에 있는 파일 3개를 복사한다.

  3dsmaxPluginWizard.ico
  3dsmaxPluginWizard.vsdir
  3dsmaxPluginWizard.vsz ( 위에서 수정한 파일이다. )

10. visual studio 를 새로 실행하면  max wizard 가 추가되어 있음.

Posted by 노을삼킨별
,

은, 는, 이, 가 알아내기

유니코드에서 한글은 십진수로 44032 에서 55203 까지 ..

유니코드에서 한글 패턴을 분석해보면,



1. 초성 19자 : ㄱ ㄲ ㄴ ㄷ  ㄸ ... 순서

2. 중성 21자 : ㅏ ㅐ ㅑ ㅒ ... 순서

3. 종성 28자 : (없음) ㄱ ㄲ ㄳ ㄴ ㄵ ... 순서


따라서 19 x 21 x 28 = 11172 = 55203 - 44032 + 1 자의 한글 구성.

이들 한글 초 / 중 / 종성 으로 코드를 구성할 때.

초성 - 중성 - 종성 순으로 코드를 구성.


즉 코드 44032 는 ' 가 ' 이고 44033 은 ' 각 '  44034 는 ' 갂 '

'가' 에 종성 붙이는게 끝이나면.. 개 -> 객 -> .... 이런식

따라서 어떤 글자의 코드에서 44032 빼고 21 x 28로 나누면

0 ~~ 18 사이 숫자를 얻게되고, 이는 초성의 순서와 같음.

마찬가지로 44032 빼고 21 x 28로 나누고 그 나머지를 다시 28로 나눈 몫은 0 ~ 20 으로 이는 중성

마지막으로 44032 빼고 21 x 28로 나누고 그 나머지를 다시 28로 나눈 나머지는 0 ~ 27 이고 이는 종성


따라서... 종성을 알고 싶다면,

int end = ( ( szText - 44032 )  %  ( 21 x 28 ) ) % 28;

가바로 end 는 종성 순서... 0 이면 종성 없음.


종성 순서에 따라 배열로 만들어두고 '은' '는' '이' '가' 를 결정하면 끝..

뭐 쉽죠? ^^


'게임 개발' 카테고리의 다른 글

FreeType2 개요 번역  (0) 2010.03.17
Scaleform GFx 분석  (0) 2010.03.17
Winen - Memory Dump Tool  (0) 2010.01.27
Adobe Flash 관련 정보  (0) 2009.07.18
PEDasm 의 신버전 v0.3.3  (0) 2009.07.12
Posted by 노을삼킨별
,

아래에서 퍼옴
http://eppengine.com/zbxe/2179

; 어두운 곳에서 spot light 와 같은 형태의 light source 가 있을때 우리는 shafts of light 를 볼 수 있다.

무대뒤의 조명과 같은 표현을  light shaft 라고 하며, 이러한 표현법에는 여러가지 방법이 있다.

대표적으로 많이 사용하는 방법중 2가지만 소개하겠다.

1. 빌보드 입자를 활용한 방법.

- 빌보드 입자를 활용한 방법은 라이트 위치에서부터 라이트 방향으로 수개의 빌보드 입자를 렌더링 하는 방법으로,

  라이트 위치에서의 깊이값을 활용하여 빛의 그림자 표현을 한다.

  라이트 위치에서부터의 깊이값을 렌더링 하고 안하고에 의해서 빛의 그림자를 만들수도 그렇지 않을수도 있으며
 
  렌더링된 깊이값을 활용하여, 스팟라이트 조명에의한 자연스런 그림자 연출이 가능하다.
 
  단점으로는 성능적인 부분과 빌보드 입자를 적게 사용했을경우 생기는 어색한 비쥬얼적인 부분.


2. 화면공간에서의 처리방법

- 화면공간에서 라이트의 위치를 기준으로 라이트 방향으로의 샘플링을 통해 처리하는 방법.

 장점은 특별한 소스코드의 변경없이 light shafts 처리를 할 수 있으며, 특히 그럴듯한 연출에도 불구하고
 
 퍼포먼스상의 저하를 많이 줄일 수 있다. ( screen 의 1/4 만큼의 텍스쳐를 활용하는 방법등을 활용)

 물론 적절한 선처리( 밝은부분검출과 검출된 부분을 활용한 빛의 늘여짐처리 )는 필수.

 

Posted by 노을삼킨별
,

아래에서 퍼옴
http://eppengine.com/zbxe/programmig/2982


SSAO (Screen Space Ambient Occlusion) 처리 기법(소스포함)

SSAO 는 최근에 많이 이슈가 되고 있는 GI 기법중 하나이다.
GI 라고 하면 단순히 모든 오브젝트가 빛을 발산하는 주체가 된다고만 생각하는데, (빛 반사를 통해.. )
빛으로인해 생겨지는 그림자 역시 GI중 하나이다.
SSAO 는 많은 사람들이 알고 있듯이 환경광 차폐를 화면공간에서 처리하는 기법으로
크게 깊이를 이용한 기법, 깊이와 상방벡터를 이용하는 기법 두가지가 있다.
환경광 차폐가 일어나는 경우에 대해서는 KGC2009 강연자료중 Lighting In Screen Space 의 ppt 자료를 참고.
여하튼.. 위에서 이야기한 두가지 기법 모두 장단이 있기에 적절한 방식을 선택해서 사용하면 되겠다.

uniform sampler2D som;  // Depth texture 

uniform sampler2D rand; // Random texture
uniform vec2 camerarange = vec2(1.0, 1024.0);
     
   float pw = 1.0/800.0*0.5;
   float ph = 1.0/600.0*0.5

   float readDepth(in vec2 coord) 
   { 
     if (coord.x<0||coord.y<0) return 1.0;
      float nearZ = camerarange.x; 
      float farZ =camerarange.y; 
      float posZ = texture2D(som, coord).x;  
      return (2.0 * nearZ) / (nearZ + farZ - posZ * (farZ - nearZ)); 
   }  

   float compareDepths(in float depth1, in float depth2,inout int far) 
   { 

     float diff = (depth1 - depth2)*100; //depth difference (0-100)
     float gdisplace = 0.2; //gauss bell center
     float garea = 2.0; //gauss bell width 2

     //reduce left bell width to avoid self-shadowing
     if (diff<gdisplace){
        garea = 0.1;
     }else{
        far = 1;
     }
     float gauss = pow(2.7182,-2*(diff-gdisplace)*(diff-gdisplace)/(garea*garea));

     return gauss;
   } 

   float calAO(float depth,float dw, float dh) 
   { 
     float temp = 0;
     float temp2 = 0;
     float coordw = gl_TexCoord[0].x + dw/depth;
     float coordh = gl_TexCoord[0].y + dh/depth;
     float coordw2 = gl_TexCoord[0].x - dw/depth;
     float coordh2 = gl_TexCoord[0].y - dh/depth;

     if (coordw  < 1.0 && coordw  > 0.0 && coordh < 1.0 && coordh  > 0.0){
     vec2 coord = vec2(coordw , coordh);
        vec2 coord2 = vec2(coordw2, coordh2);
        int far = 0;
     temp = compareDepths(depth, readDepth(coord),far);

        //DEPTH EXTRAPOLATION:
        if (far > 0){
          temp2 = compareDepths(readDepth(coord2),depth,far);
          temp += (1.0-temp)*temp2;
        }
     }

     return temp; 
   }  
    
   void main(void
   { 
     //randomization texture:
     vec2 fres = vec2(20,20);
     vec3 random = texture2D(rand, gl_TexCoord[0].st*fres.xy);
     random = random*2.0-vec3(1.0);

     //initialize stuff:
     float depth = readDepth(gl_TexCoord[0]); 
     float ao = 0.0;

     for(int i=0; i<4; ++i)
     { 
       //calculate color bleeding and ao:
       ao+=calAO(depth,  pw, ph); 
       ao+=calAO(depth,  pw, -ph); 
       ao+=calAO(depth,  -pw, ph); 
       ao+=calAO(depth,  -pw, -ph);

       ao+=calAO(depth,  pw*1.2, 0); 
       ao+=calAO(depth,  -pw*1.2, 0); 
       ao+=calAO(depth,  0, ph*1.2); 
       ao+=calAO(depth,  0, -ph*1.2);
    
       //sample jittering:
       pw += random.x*0.0007;
       ph += random.y*0.0007;

       //increase sampling area:
       pw *= 1.7
       ph *= 1.7;   
     }        

     //final values, some adjusting:
     vec3 finalAO = vec3(1.0-(ao/32.0));


     gl_FragColor = vec4(0.3+finalAO*0.7,1.0); 
   } 

장점 : 따로 blur pass 를 실행할 필요가 없다. ( 랜덤맵 텍스쳐를 활용하기에 가능한 부분)
         시각적 품질이 나쁘지 않다.
         노멀 버퍼없이도 깔끔하다.

단점 : 전통적 ssao 보다는 좀 느리다.
         역시 노멀 버퍼를 사용하지 않는 것 으로 인한 약간의 시각적 어색함이 존재.. 약간...


'게임 개발 > 3D 게임 플밍' 카테고리의 다른 글

3d max plugin wizard 생성하기  (0) 2010.03.17
Light Shaft  (0) 2010.03.17
SSGI 관련 정리 (소스 포함)  (0) 2010.03.17
언리얼 엔진 3 ( Unreal Engine 3 )  (0) 2009.12.03
BSP를 이용한 3D Game Programming  (0) 2005.11.16
Posted by 노을삼킨별
,

아래에서 퍼옴
http://eppengine.com/zbxe/2985#2



SSGI 는 GI 를 화면공간에서 처리하는 기법으로 화면상에 나타나 있는 모든 오브젝트들은 빛을 반사하여 발광하는 주체가 된다는 개념으로 예를들어, 붉은색 대리석 바닦에 놓여 있는 오브젝트의 경우 아래쪽은 ( 대리석과 맞닿아 있는 부분) 붉은색 빛이 표현 되어져야 한다 는 개념. 물론 SSGI 는 태생적으로 화면공간에서의 처리기법 이므로 화면밖의 오브젝트에대해서는 GI 개념을 적용하기가 애매한 부분이 있다. 전 처리를 통해 물론 해결은 가능하지만, 일반적인 기법에서는 화면밖의 붉은색 오브젝트는 화면안쪽에 있는 어떠한 오브젝트에도 영향을 주지 못한다.
그럼에도 SSGI 를 사용하지 않는 경우보다 훨씬 사실적이고 자연스러운 표현이 가능하다.
SSGI 는 크게 3가지 방식으로 사용되는데 전처리를 통해 마스킹 해 놓는 방식, 깊이만을 활용한 방식, 깊이와 노멀을 둘다 활용하는 방식이 있다. 아래는 깊이만을 활용한 방식이다.

uniform sampler2D som;  // Depth texture 
uniform sampler2D rand; // Random texture
uniform sampler2D color; // Color texture


uniform vec2 camerarange = vec2(1.0, 1024.0);
     
   float pw = 1.0/800.0*0.5;
   float ph = 1.0/600.0*0.5

   float readDepth(in vec2 coord) 
   { 
     if (coord.x<0||coord.y<0) return 1.0;
      float nearZ = camerarange.x; 
      float farZ =camerarange.y; 
      float posZ = texture2D(som, coord).x;  
      return (2.0 * nearZ) / (nearZ + farZ - posZ * (farZ - nearZ)); 
   }  

   vec3 readColor(in vec2 coord) 
   { 
     return texture2D(color, coord).xyz; 
   }

   float compareDepths(in float depth1, in float depth2) 
   { 
     float gauss = 0.0;
     float diff = (depth1 - depth2)*100.0; //depth difference (0-100)
     float gdisplace = 0.2; //gauss bell center
     float garea = 3.0; //gauss bell width

     //reduce left bell width to avoid self-shadowing
     if (diff<gdisplace) garea = 0.2;

     gauss = pow(2.7182,-2*(diff-gdisplace)*(diff-gdisplace)/(garea*garea));

     return max(0.2,gauss); 
   } 

   vec3 calAO(float depth,float dw, float dh, inout float ao) 
   { 
     float temp = 0;
     vec3 bleed = vec3(0.0,0.0,0.0);
     float coordw = gl_TexCoord[0].x + dw/depth;
     float coordh = gl_TexCoord[0].y + dh/depth;

     if (coordw  < 1.0 && coordw  > 0.0 && coordh < 1.0 && coordh  > 0.0){

     vec2 coord = vec2(coordw , coordh);
     temp = compareDepths(depth, readDepth(coord));
        bleed = readColor(coord);

     }
     ao += temp;
     return temp*bleed; 
   }  
    
   void main(void
   { 
     //randomization texture:
     vec2 fres = vec2(20,20);
     vec3 random = texture2D(rand, gl_TexCoord[0].st*fres.xy);
     random = random*2.0-vec3(1.0);

     //initialize stuff:
     float depth = readDepth(gl_TexCoord[0]);
     vec3 gi = vec3(0.0,0.0,0.0); 
     float ao = 0.0;

     for(int i=0; i<8; ++i)
     { 
       //calculate color bleeding and ao:
       gi += calAO(depth,  pw, ph,ao); 
       gi += calAO(depth,  pw, -ph,ao); 
       gi += calAO(depth,  -pw, ph,ao); 
       gi += calAO(depth,  -pw, -ph,ao);
    
       //sample jittering:
       pw += random.x*0.0005;
       ph += random.y*0.0005;

       //increase sampling area:
       pw *= 1.4
       ph *= 1.4;   
     }        

     //final values, some adjusting:
     vec3 finalAO = vec3(1.0-(ao/32.0));
     vec3 finalGI = (gi/32)*0.6;

     gl_FragColor = vec4(readColor(gl_TexCoord[0])*finalAO+finalGI,1.0); 
   } 


장점, 단점은 ssao 랑 비슷

'게임 개발 > 3D 게임 플밍' 카테고리의 다른 글

Light Shaft  (0) 2010.03.17
SSAO (Screen Space Ambient Occlusion) 처리 기법(소스포함)  (0) 2010.03.17
언리얼 엔진 3 ( Unreal Engine 3 )  (0) 2009.12.03
BSP를 이용한 3D Game Programming  (0) 2005.11.16
GLUT 시작  (0) 2005.11.11
Posted by 노을삼킨별
,

아래에서 퍼옴

http://forensic-proof.com/19

Winen - Memory Dump Tool


메모리 분석을 위해서 먼저 선행되어야 할 것이 메모리 덤프이다. 현재 사용 중(활성화)인 메모리의 내용을 특정 순간에 스냅샷으로 파일로 저장하게 된다. 메모리 덤프를 하는 이유는 쉽게 말해 메모리를 더 자세히 보기 위해서이다. 왜냐하면, 루트킷이나 악성코드의 경우 메모리 내의 EPROCESS 구조체 등을 변경시켜 은폐하고 있기 때문이다.

윈도우 기능(작업관리자, API 등)을 이용하여 확인하게 되면 이러한 부분이 보이지 않기 때문에 부득이하게 메모리를 덤프하게 된다. 메모리를 덤프한 후 EPROCESS 구조체를 알고 있다면 덤프한 메모리 파일에서 프로세스의 정보를 뽑아낼 수 있을 것이다. 덤프한 메모리의 프로세스 정보와 운영체제를 통해 확인한 정보에 차이가 있다면 해당 프로세스는 의심 가능성이 농후하다.

물론 이러한 이유 외에도 디지털포렌식 관점에서 활성화된 정보를 얻기 위해 물리메모리를 덤프해야 하는 경우가 있다. 특정 조사자의 컴퓨터를 영장을 통해 조사하러 갔는데 해당 시스템에 활성화 상태라면 컴퓨터의 전원을 분리하기 전에 활성화된 정보를 최대한 수집해야 할 것이다. 활성화 정보는 전원이 차단된 후에 사라지는 정보로 휘발성 기억장치인 RAM 에 저장되는 정보를 의미한다.

물리메모리를 덤프하더라도 분석에 한계가 있기 때문에 활성 시스템에서 쉽게 수집할 수 있는 정보는 바로 수집하는 것이 효율적이다(예, 네트워크 상태정보 등). 활성화 정보의 가장 큰 약점은 법정에서 무결성을 어떡해 입증할 수 있냐는 것이다. 물론 이와 관련해서 국내에서 현장에서 제 3자에 감시와 당사자의 서명이 들어가는 경우가 있지만 아직까지 완벽한 방법이라고 하긴 어렵다.

물리메모리덤프도 무결성에 제약이 있을 수 있겠지만 경우에 따라서는 활성 상태에서 수집한 정보를 입증할 수 있는 자료로 사용될 수도 있을 것이다. 아직까지 국내 수사환경에서 보면 일진회 사건에서 처음 디지털데이터가 증거로 채택되기는 했지만 정책적인 면에서는 걸음마 수준이다. 실제 공판을 담당하는 검사와 변호사 측 모두 디지털포렌식이라는 개념이 부족하기 때문이다.

최근들어 검사와 변호사측 모두 디지털포렌식에 관심을 기울이고 있지만 실제 무결성에 입각한 사건처리가 이루어지기에는 아직 정책적인 면에서 부족한 것이 사실이다. 서론이 주저리주저리 쓰다보니 너무 길어졌다. 본론으로 들어가서 물리메모리를 덤프하기 위해서는 무료로 제공하는 유명한 도구인 win32dd, MDD 등의 도구들과 WinDBG와 같은 디버깅 도구를 이용하여 덤프하는 등의 방법이 있다.

물론 상업적인 도구들도 있다. 이러한 방법들에 대해서는 논외가 되므로 여기서는 winen.exe 를 이용한 덤프만 고려하겠다. winen.exe는 EnCase를 개발한 Guidance Software에서 제공하는 도구로 EnCase와 함께 제공된다. 정확하게 언제부터 지원하는지는 모르겠지만 현재 v4.x 과 v6.13을 쓰고 있는데 v6.13을 설치한 후 발견한 파일이다. v5.x에서 있었는지는 정확히 모르겠지만 최근들어 지원한 것으로 알고 있다.
 

위의 그림에서 보면 winen.exe와 함께 winen64.exe도 함께 존재하는 것을 확인 할 수 있다. 직관적으로 알 수 있듯이 winen64.exe는 64비트 시스템에서 사용할 수 있는 도구이다. 이와 함께 winen.txt 파일이 보이는데 이것은 수집하기 이전에 수집과 관련된 정보를 미리 기입할 수 있는 구성파일이다.
 

구성파일에서 제공하는 내용은 위와 같다. 구성파일을 미리 작성했다면 "-f" 옵션을 이용해 해당 구성파일을 입력받을 수 있다. 입력받지 않게 되면 해당 옵션의 기본적인 내용(경로, 증거이름, 사건번호, 조사자이름 등)은 덤프하기 전에 콘솔로 입력받을 수 있게 해준다.
 

덤프를 실제 수행하면 간단한 프로그레스 형식의 "|" 문자를 통해 덤프되고 있음을 알려준다. 압축 형식을 지정할 수 있는데 지정할 수 있는 압축형식은 다음과 같다. (0=NONE, 1=fast, 2=best) 압축하지 않으면 실제 물리메모리 크기의 파일이 생성되며 압축을 하게 되면 해당 정보가 압축되어 저장된다.

저장되는 형식은 EnCase 증거 이미지인 ".Ex" 형태로 저장된다. 압축 방식도 EnCase 증거이미지의 압축 방식에 따른다. 이는 winen.exe 를 사용해 덤프한 내용은 포맷이 EnCase 증거이미지 형식이므로 EnCase를 통해 분석할 수 있다는 것을 의미한다. 물론 EnCase 포맷을 지원하지 않는 도구에서는 분석이 불가능하다.

결과적으로, EnCase와 함께 제공되는 winen.exe를 이용한 메모리 수집은 다른 기존의 메모리 수집도구와 비교해봐야 겠지만 EnCase를 통해 분석이 가능하다는 점이 강점일 수 있겠다. EnCase를 통해 EnScript, String Search 와 같은 기능을 이용할 수 있을테니 말이다. 메모리카빙이 되는 EnScript를 구현해 놓으면 쉽게 물리메모리를 덤프한 후에 분석이 가능할 것이다. 전체 EPROCESS를 카빙할 수 있는 EnScript를 구현하는 것은 힘들겠지만 간단히 유효한 정보를 보여주는 것은 그리 어렵지 않을 것이다. 자.. 그럼 고고~~

'게임 개발' 카테고리의 다른 글

Scaleform GFx 분석  (0) 2010.03.17
은, 는, 이, 가 알아내기 44032  (0) 2010.03.17
Adobe Flash 관련 정보  (0) 2009.07.18
PEDasm 의 신버전 v0.3.3  (0) 2009.07.12
윈도우 프로그래밍 팁  (0) 2008.06.10
Posted by 노을삼킨별
,


아래 사이트에 2009-12-07 현재 77회까지 있음.

3Dグラフィックス・マニアックス
西川善司

http://journal.mycom.co.jp/column/graphics/index.html

Posted by 노을삼킨별
,


아래에서 퍼옴

http://allosha.tistory.com/category/니시카와%20젠지/PRT





3D모델 변형가능 동적PRT - 동적 PRT 기술의 대두


2009-07-18 01:00:00
3Dモデルの変形に対応した動的PRT技術の台頭 PSF技法ベースのPRTは、自身の遮蔽、他者への遮蔽を考えることにより、シーンに存在する3Dモデルの移動や回転を許容する動的PRTが可能になった。これは、ビリアードのよ ...... >> Read more

(C) Mainichi Communications Inc. All rights reserved


3D모델의 변형에 대응한 동적 PRT기술의 대두

PSF기법 기반의 PRT는, 자신의 차폐와 타 오브젝트에의 차폐를 생각함으로써, 씬에 존재하는 3D모델의 이동이나 회전을 허용하는 동적 PRT가 가능하게 되었다. 이것은, 당구와 같은 테이블 게임이나, 블럭퍼즐 게임과 같은 3D게임 그래픽스에는 응용할 수 있을 것이다.

하지만, 3D모델의 형상(형태)을 변경, 변형할 수 없다는 제약은, 실질적으로 부위가 접히거나 구부러지거나 하는 인간이나 동물과 같은 생물을 취급할 수 없다는 것과 같다. 이것은, 실시간 3D게임 그래픽스에의 응용을 생각하면 큰 제약이라고 할 수 있다.

그런 가운데, 2006년의 SIGGRAPH에서, Zhong Ren씨등이, 「Real-time Soft Shadows in Dynamic Scenes using Spherical Harmonic Exponentiation」이라는 논문을 발표해, PSF기법의 동적 PRT를 기반으로 하면서 자신의 변형까지 지원하는 기술을 발표했다.

그것이 「SH Exponentiation」(SHEXP)이라는 솔루션이다.

지금까지 형상 변형을 실현할 수 없었던 것은, 씬에 등장하는 각각의 3D모델을 「하나의 강체」로 간주해 왔기 때문이다.

SHEXP기법에서는 발상을 전환해, 등장하는 3D오브젝트를, 여러가지 크기로 된 구체(球體)들의 집합체로서 파악한다는 것이다. 즉, 3D모델의 그 형태는 복수의 여러 크기의 구체들이 모여 구성되어 있는 것……으로서 해석하고 처리를 진행시키는 것이다.

이러면, 그 3D모델이 어떻게 변형했다고 해도 「그 3D모델을 구성하고 있는 구체(球體)가 이동했을 뿐」이라고 간주할 수 있다.

3D모델을 복수의 구의 집합체로 생각하면, 3D모델의 변형은 구의 이동으로 생각할 수 있다. 즉, 강체가 이동하는 것에 대응한 PSF기법에 의한 동적 PRT를 응용할 수 있게 된다

SHEXP기법의 실현에 따른 장해

이 아이디어는 훌륭하지만, 몇가지 넘지 않으면 안 되는 문제들이 부상한다.

첫번째로, 3D모델을 어떻게 구체에 근사하는가 하는 실현 방법에 대해서. 이상적인 것은 자동적으로 실행하는 것이지만, 그 3D모델에 어떠한 변형을 허용하는가라는 부분이 복잡하게 관계되기 때문에, 현실적으로는 구(球) 근사화 authoring tool등을 제작해서, 아티스트에게서 구체화(球體化) 처리를 수작업으로 하도록 하는 것이 가장 상책이라고 할 수 있을지도 모른다.

이 구체(球體) 근사에 대해서는 2개의 논문이 참고가 될 것이다.

하나는, Riu Wang씨가 2006년의 PacificGraphic에서 발표한 「Variational Sphere Set Approximation for Solid Objects」라는 논문이다. 2번째는 Gareth Bradshaw씨가 2004년의 SIGGRAPH에서 발표한 「Adaptive Medial-Axis Approximation for Sphere-Tree Construction」이라는 논문이다. 피라미드사의 구현에서는 후자의 논문의 방법을 구현했다고 한다.

드래곤의 3D모델을 다른 레벨로 구상근사(球狀近似)한 모습

두번째로, 구(球)로 3D모델을 근사해 버리면, 세세한 요철이나 가시와 같이 예리한 디테일이 없어져 버린다는 문제가 있다. 이것은 디테일부분의 구체 근사에는 직경이 작은 구를 이용하는 것으로 그나름 대응은 할 수 있다. 단, 그 경우에는 구의 수가 많아져, PRT 처리 때의 부하가 커진다. 즉, 세번째 문제와도 관련이 깊지만, 그 타겟 시스템의 처리 속도에 맞쳐, 어느 정도의 품질로 구체 근사를 해 줄지를 결정하게 될 것이다.

세번째는 처리 속도의 문제. 3D모델이 구체로 근사되었다고 가정하고, 그 모든 구들에 대해서 서로 PSF기법의 동적 PRT를 실시하게 된다. 즉, 처리 부하가 높은 SH Triple Product의 횟수는 급증해, 연산 부하가 매우 높아져 버린다.

첫번째와 두번째 문제는 어떻게든 대응할 수 있지만, 이 세번째 문제는 근본적인 해결책이 필요하다.

거기서 Zhon Ren씨등의 연구그룹은, 이 SH Triple Product 연산 비용을 감소 시키기 위해서 「SH Log」와「SH Exp」라는 2개의 새로운 연산 메소드를 개발했다.(계속)

오리지널 3D모델

구체 근사한 3D모델

형상이 변형 되어도 지면에의 그림자 뿐만 아니라, 신체의 각 부위간의 상호 차폐등도 고려된다. 구체(球體) 근사에 의해서 실현된 기술. 마루의 그림자나 셀프 그림자는 구체 근사에 의해, 상당히 희미해져 있지만, 현실 세계의 그림자도 이처럼 뿌옇게 된다는 것을 생각하면, 충분한 품질이라 할 수 있다




3D모델 변형가능 동적PRT - SH Log와 SH Exp란 ?

SH Log와 SH Exp란?

SH Log의 Log는 로그(對數)를 나타내고 있다. 그리고 SH Exp의 Exp는 지수를 나타낸다.

고등학교 수학에서 배우는 공식에 복수의 곱셈은 그 수의 Log의 총합(덧셈)을 Exp한 값과 같다고 하는 것이 있다.

예를 들어, 25×46 = 1150. Exp(Ln25 + Ln46) 또는 10^(Log25 + Log46)을 윈도우즈의 계산기나 함수 계산기로 계산해 보자. 제대로1150이 될 것이다

이 지수와 로그(대수)의 법칙을 SH Triple Product에 응용한 것이 SH Log와 SH Exp 계산이다.

즉, 차폐계수 벡터끼리의 SH Triple Product 연산 부하를 절감 시키기 위해서, 우선 로그(Log)의 합을 계산해, 그 값에 대해서 지수(Exp)를 취하면 SH Triple Product를 계산한 것이 되지 않을까……라는 것이다. 이것이 성립되면 부하가 높은 SH Triple Product의 반복을 단순한 덧셈으로 떨어뜨릴 수 있게 된다. 이 증명은 매우 복잡해서 여기에서는 생략 하지만, 이것은 성립되는 것이므로, 사용해도 된다.

SHEXP기법에서의 사전 계산

SHEXP기법의 동적PRT에서는, 등장하는 3D모델을 모두 구체(球體)로 해 버리는 관계로, 자기 차폐나 Shadow Fields의 사전 계산을 단일의 구(球), 1개로 한정할 수 있다. 여기에서 이후의 연산을 하기 쉽게하기 위한 방법을 보여준다.

PSF기법에서는 구면조화함수의 스케일링 계수들로 된  계수벡터를 보관하고 있었지만, SHEXP기법에서는, SH Log와 SH Exp의 조합을 활용하기 위해서, 이 계수에 대해서 미리 SH Log 연산을 실시해, SH Log 공간의 값으로 보관 한다.

이 방법에 의해, 차폐 구조의 합성(통합)처리의 중간 계산을 부하가 높은 SH Triple Product가 아니라, 덧셈만으로 처리할 수 있게 된다. 마지막에 SH Exp 연산을 실시해 원래의 공간으로 되돌려서, 음영 처리(휘도 계산)을 실행하도록 한다.

무거운 처리의 일부를 실시간으로 하지 않고, 사전에 미리 해 둔다는 이미지이다. 이것에 의해서 PSF기법에서는 매우 고부하였던 SH Rotation이나 SH Triple Product 연산의 부하가 작아짐으로써, 구(球)가 다수 등장하는 구 근사를 이용하는 SH Exp기법에서도 어느정도의 퍼포먼스를 예상할 수 있게 된다.(계속)

PSF기법과 같이 Shadow Fields를 산출하는 것도, 그 결과를 구면조화함수의 계수벡터 상태 그대로가 아니라, SH Log 연산을 해둔다

SHEXP 기법의 개념도. 고부하인 계산을 SH Log 공간에서의 덧셈으로 떨어뜨리고, 그것을 다시 SH Exp 연산으로 원래 공간으로 되돌린다는 발상이 포인트가 된다


<그림 설명>
상:
(제목) 렌더링 개요(계산 전)
구의 Shadow Filed의 계수 벡터를 SH Log 공간에서 보존한다!!
SH Log 연산
하:
(제목) SHEXP 개념도
계산전,
통상공간, SH Log공간,
물체의 구 근사,
구의 Shadow fields 계산,
SH Log 연산,
SH Log공간의 구의 Shadow fields 계산
계산시
물체 위치, 형상 변신,
차폐 통합,
고속 처리가 가능!!
SH Exp 연산
휘도계산





3D모델 변형가능 동적PRT - 대역조화함수(Zonal Harmonics) 도입

대역조화함수(Zonal Harmonics)의 도입

SHEXP기법에서는, 구(球)의 Shadow Fields를 다루는 부분에 대해 새로운 최적화를 추진한다.

구(球)의 모양은 어디에서 보든 똑같은 "원"이다.

구 전체의 Shadow Fields를 모두 저장하면 실행 측면에서 확실히 유리하지만, 메모리의 소비량이 커져 버린다. 어쨌든, 어디에서 보든 똑같이 원으로 밖에 보이지 않는다면, 어느 한축 방향의 일정거리의 각지점의 Shadow Fields를 산출해 두고, 이것을 리얼타임 렌더링시에 SH Rotation으로 변이 시키는 처리를 구현해 주면 메모리 소비량을 상당히 줄일 수 있다. 그러나, SH Rotation 계산은 자체가 부하가 높기 때문에 실제로는 퍼포먼스 면에서 불리해 진다.

구(球)의 Shadow Fields 취급에 대한 3가지 구현안

<그림 설명>
구의 Shadow field에는 3가지 선택이 존재
표:
                              메모리 소비           실행 속도
전부 보존                        X                      O
SH Rotation                     O                      X
Zonal Harmonics               O                      O
(박스) 전부 보존,
SH Rotation

거기서, 높은 처리 속도와 메모리 소비량이 괜찮은 Zonal Harmonics(대역 조화 함수)라는 개념을 도입한다.

Zonal Harmonics에서는, 앞에서 이야기한 SH Rotation으로 변이 시키는 구현안 처럼, 한방향 만의 Zonal Harmonics 계수를 보관하므로 메모리의 소비량은 작고, 거기다가 계산 부하는 그다지 크지 않다.

Zonal Harmonics는 회전대칭인 정보 밖에는 적용할 수 없다는 제약이 있지만, 다루는 대상이 어디에서 보나 똑같은 모양인 구(球)의 차폐구조 데이터이므로 문제는 없다.

Zonal Harmonics의 요점

대상이 어디에서 보든지 동일한 모양인 구(球)의 차폐구조 데이터이므로 Zonal Harmonics를 적용할 수 있다.

<그림 설명>
상:
1. 특수한 한방향에서, Zonal Hamonics 계수를 계산
-> 한방향만의 계수를 저장하므로, 메모리 소비량은 적다.
2. 다른 방향은 Zonal Hamonics 계수를 이용해서 계산
SH Rotation: 벡터와 행렬의 곱셈 5회
Zonal Harmonics: 벡터와 벡터의 곱셈 1회
-> 상당히 고속
다만 Zonal Harmonics는 "회전 대칭"인 정보만 적용 가능
하:
Zonal Harmonics
제약: 회전대칭인 정보만 적용 가능
구의 Shadow fields 계산
제약을 클리어
구는 어디에서 봐도 회전 대칭


Zonal Harmonics에서 보관할 한 방향을 결정하는 방법에는 요령이 있다. 어떤 조건(그림 참조)을 만족하는 방향을 결정해, 차폐구조를 산출해서 구면조화함수로 근사 시켜 차폐계수벡터를 구하면, m=0 이외의 계수는 모두 0이 되어 버린다. 이 특성에 주목하면, m=0 일 때의 차폐계수벡터만 저장해 두면 되는 것이다.

이 특성은, 그 특수조건을 만족하는 방향을 선택했을 경우의 효과이다. 그리고, 이 m=0 때의 차폐 계수 벡터에 Zonal Harmonics의 보정 계수를 곱해 산출된 값이 Zornal Harmonics계수(ZH계수)가 된다.

바꾸어 말하면, ZH계수는, 특수 조건하에서의 m=0일 때의 구면조화함수의 차폐계수벡터를 조금 세공(=Zonal Harmonics)해준 버전이라 할 수 있다.


Zornal Harmonics 이용을 위한 특수조건

Zonal Harmonics계수의 계산 흐름. l=3 까지의 구면조화함수의 차폐계수벡터는 본래는 16개를 저장해야 하지만, 특수조건하의 혜택으로 m=0 이외의 계수는 전부 제로가 되어 버리므로 그것들이 필요없어진다(4개만 저장). 여기가 포인트

<그림  설명>
상:
(제목) Zonal Harmonics(특수한 한방향을 결정)
물체의 중심과 샘플점의 거리는 일정하다고 가정
특수한 한방향이란?
회전대칭축샘플좌표계의 +z축이 일치하는 특수한 방향
(박스) 회전대칭축과 샘플좌표계의 +z축이 일치하는 점은 한점만 존재
중:
Zonal Harmonics 계수 계산
차폐정보를 취득
 

결국, 원하는 것은 임의의 방향의 차폐계수벡터이다. 이것은, 그 임의의 각도의 구면조화함수와 방금전의 기준축으로 구한 ZH계수의 곱셈(積算)으로 구할 수 있다. 이 부분의 수학적인 이론과 증명은 생략하지만, 이 기법을 이용하는 쪽은 그런 것이다라고 그냥 사용할 수 있다. 포인트가 되는 것은, SH Rotation에서는 벡터와 행렬의 곱셈(積算)이 5회나 필요한데 반해, ZH를 이용하면 벡터끼리의 곱셈(積算) 1회로 임의의 방향의 차폐계수벡터가 구해진다는 점이다.

Zonal Harmonics의 도입으로 임의의 방향의 차폐계수벡터가 비교적 저부하로 계산이 가능해졌다

<그림 설명>
임의의 방향의 차폐계수 벡터 계산
회전 중심축과 샘플 좌표계의 +Z축과의 각도는 θ로 가정
곱셈

실제의 구현에서는 구의 중심으로부터 일정 간격 마다의 ZH계수를 구해, 이것을 테이블화해 보관하게 된다. 이 "일정 거리"라는 것은「구의 중심으로부터의 일정 거리」가 아니고, 구의 중심을 향한 직선과 구의 면에 대한 접선이 구성하는 각도의 변화(구에 대해서 가장 멀다= 0도 ~ 구에 대해서 가장 가깝다=90도)단위로 준다. 이것은 뒤에서 서술할 차폐계수벡터의 통합 계산을 효율적으로 하기 위한 테크닉이다.(계속)

ZH계수 테이블의 개념

ZH계수를 구하는 포인트는 거리가 아니라 각도를 키로 해서 작성하는 것이 나중에 편리하다

구의 Shadow Fields 요약정리. ZH계수를 이용함으로써 적은 메모리 사용과 고속 실행이 가능해 진다

<그림 설명>
상:
Zonal Harmonics 계수 계산,
ZH 계수 테이블,
차폐정보를 취득
하:
1. 특수한 1방향에서, Zonal Harmonics계수를 계산
ZH계수계산,
ZH계수 테이블을 미리 계산,
데이터량은, 수 KB정도
2. 다른 방향은, Zonal Harmonics계수를 이용해서 계산
1.현재의 거리에 대응하는 ZH계수를 테이블로 부터 취득
2. ZH계수 벡터와 구면조화함수 벡터를 곱셈



3D모델 변형가능 동적PRT - SH Log 연산과 SH Log 차원의 차폐 통합

SH Log 연산과 SH Log 공간에서의 차폐 통합

SHEXP기법의 근간이 되는 테크닉인 SH Log연산과 SH Exp연산에 대해서, 지금 한번 집중해서 보기로 한다.

수학적인 유도는 생략 하지만, 이미지적으로는 SH Log와 SH Exp은 구면조화함수 공간에서의 로그, 지수 계산이 된다.

행렬의 로그나 지수의 계산값은, 먼저, 그 행렬을, 쌍(pair)이 되는 직교 행렬과 대각행렬로 분해해서, 그 대각행렬의 각 성분들에 로그나 지수의 계산을 해준 값과 같다라는 성질이 있다. 구면조화함수 공간에서의 로그나 지수 계산도 이 성질을 응용해서 한다.

SH Log를 구하는 방법

행렬의 로그나 지수 계산값은, 우선, 그 행렬을, 쌍(pair)이 되는 직교 행렬들과 대각행렬로 분해해서, 그 대각행렬의 각 성분들에 로그나 지수 계산을 실시한 값과 같다라는 성질이 있다

차폐계수 벡터의 로그는 이와 같이 된다


그런데, 앞에서도 이야기했지만, 구하고 싶은 것은 임의의 방향의 Log공간에서의 차폐계수벡터이다.

실제 구현에서는, 사전에 미리 계산한 ZH계수 테이블에 Log값들을 구해 저장해 둔다(Log ZH 계수 테이블). 이렇게 함으로써, 임의의 방향의 Log공간 차폐계수벡터는, 그 방향의 구면조화함수값에, Log ZH계수 테이블 값을 곱해 주기만 하면 구해진다.

임의의 방향의 Log공간에서의 차폐계수벡터를 구하는 방법은, 이론이나 유도는 몇회 분량이지만 실제 구현은 그렇게까지 어려운 것은 아니다

SH Log 공간에서의 차폐계수벡터가 구해지면, 이번에는 그 차폐를 통합하는 단계로 넘어간다.

정점 단위의 처리가 되는 것은 지금까지의 PRT와 똑같다. 어떤 정점에서의 SH Log공간의 차폐계수벡터는, 아래와 같은 흐름이 된다.

우선, 그 정점에서 대상으로 하는 구의 중심으로 그은 선분과 그 정점로부터 대상 구에 접하는 접선이 이루는 각도를 키로 해, Log ZH계수 테이블을 참조한다(그림). 앞에서 말했던 「일정 거리가 아니라 각도를 키로 하는 테이블 작성」은 여기서 편리함을 준다. 이 Log ZH계수에 그 각도의 구면조화함수를 곱해 주면, 그 정점에서의 SH Log공간의 차폐계수벡터가 구해진다.

그리고, 이 SH Log공간의 차폐계수벡터들의 통합은, 앞에서 이야기한 것처럼 Log공간에서의 메리트를 살려서 덧셉(합산) 만으로 구할 수 있다.

최종적인 총합이 구해지면, 통상 공간으로 되돌리기 위해서, 로그(Log)의 역함수인 지수(Exp) 연산을 실시할  필요가 있다. 그렇다, SH Exp 연산이다.(계속)

SH Log공간에서의 차폐 계수 벡터의 통합 처리. 이 처리를 모든 구에 대해서 실시한다. 각도를 키로 하는 테이블 작성은 여기서 효과적이다.




3D모델 변형가능 동적PRT - SH Exp 연산의 대담한 근사에 의한 고속화

SH Exp연산의 대담한 근사에 의한 고속화

SH Exp연산에 대해서는 정의 그대로의 정직한 연산을 실시하는 것도 하나의 방법이지만, 리얼타임의 퍼포먼스 향상을 위해, 여기서는 근사 방법을 도입한다.

어떤 값의 지수는 급수전개를 하면 아래의 그림처럼 나타낼 수 있다. 이 계산은 제곱승이나 나눗셈이 포함되어 있어서 계산 부하가 높다. 거기서 SHEXP기법의 개발 연구그룹에서는 최초의 2개의 항만으로 근사한다는 대담한 방법을 채택했다. 그러나, 그대로 하면 오차가 너무 크기 때문에, 가중치를 넣은 선형결합으로 근사 한다.

SHEXP 연산을 최초의 2개항만으로 근사를 하는 대담한 방법을 도입해서 퍼포먼스를 올린다.

<그림 설명>
(제목) SH Exp연산
exp(F) = 1 + F + F^2/2! + F^3/3! + F^4/4!+ ...
SH Exp연산은 실행시에 이용 -> 고속으로 계산하고 싶다
부하의 원인: F^2, F^3, F^4,...의 계산이 무겁다
(박스) 최초의 2개항(선형항)만으로 어떻게 근사할 수 없을까?
exp(F) ~ a1 + bF          단, 1=(√4π, 0, 0, ...)
두항에 가중치(a, b)를 곱해서 선형 결합함으로 근사


2개의 선형항들에 곱해지는 2개의 가중치 계수는, 사전 계산으로 테이블화 해둔다. 그렇다면, 이 가중치 계수가 중요해진다.

SHEXP기법의 연구 개발그룹에서는, 이 2개의 가중치 계수의 계산에는 일반적인 수치계산으로 이용되는 최소 이승법(最小二乘法)을 사용했다.

어떤 차폐 정보로부터, 그 차폐계수벡터 g를 구하고, 이것을 SH Log 연산해서 SH Log공간으로 변환해 그것을 f라고 했을 때, f의 값으로부터 최소이승법으로, 그 2개의 가중치 계수 a, b가 구해지므로, 사전 계산해서 작성하는 테이블은 f를 키로 해서 a, b를 구하는 방법을 생각할 수 있다.

그러나, 이것은 실현이 어렵다. 그것은, 아무리 등장하는 3D모델이 구(球)뿐이라고는 해도, 구의 중복 상태나 그 조합은 무수히 많기 때문에, 이것에 대응하는 자기 차폐 상태 g도 무수히 많아지고, 결국은 f도 무수히 존재하게  된다. f를 키로 한 테이블의 사이즈가 방대해져 버려, 현실성이 없는 것이다.

SH Exp 연산의 개념도. 퍼포먼스 향상을 위해서 맨앞의 선형항 2개와 가중치 계수를 이용한 계산으로 근사한다. 그 가중치 계수는 테이블을 사용한다

<그림 설명>
상:
고속판,
근사계산,
a,b의 테이블화,
기본개념 -> 근사 정밀도 개선 ->a, b 테이블 작성
테이블 바깥에의 처리,
고속 처리가 가능!!
하:
기본판,
SH Log공간,
직접계산 or 대각화,
계산부하가 높다,
통상공간,
a, b 테이블


모든 차폐 정보에 대해서의 SH Log공간에서의 f를 구해, 그 f로부터 대응하는 2개의 가중치 계수 a, b를 얻는다는 것이 기본 발상. 그러나, 차폐의 조합이 너무 방대하다

<그림 설명>
(제목) a, b 테이블의 작성 (개념)
요점1: 차폐정보를 몇개정도 직접 작성해, SH Log변환
요점2: 최적의 근사를 해주는 a, b를 계산해서 테이블화
(박스 좌~ 우)
자신이 직접 적당히 만든 차폐정보
SH Log 연산
최적의 a, b를 계산
a,b 테이블

거기서, 한층 더 타협 조건을 부여한다. 그것은 f가 아니라 f의 절대값를 키로 한다는 조건. 나아가, 그 절대값의 상한과 하한을 결정해 버린다는 간략화의 타협도 추가한다. 이렇게 해서, 뭔가 현실적인 테이블화가 보이는 것 같다.

테이블화 실현을 위해서 좀더 타협안을 도입한다

<그림 설명>
(제목) a, b 테이블 작성의 개량
(박스) 차폐정보의 조함은 무수히 존재
→  f 마다 a, b를 테이블화하는 것은 비현실적
타협점:
√  f가 아니라 │f│로 테이블화
   → f가 달라도 │f│가 같으면 같은 a, b를 이용
   → 조합 시킬 수를 감소
√  테이블의 상한, 하한을 설정
(박스) a,b 테이블


타협안으로서는 너무 대담하므로, 이대로는 근사 정밀도가 그다지 좋지 않다. 거기서 정밀도 향상을 위한 방법을 생각해 해준다.

SH Log 공간으로 변환된 차폐계수 벡터의 요소 중에서, 절대값이 큰 것은 최초의 항 뿐이므로, 이 최초의 항만은 원래대로 SH Exp계산을 해주는 것이다. 절대값이 큰 최초의 항이 정밀도가 올라가면, (전체) 정밀도가 올라간다……이것을 노리는 것이다.

구체적으로는, SH Log공간의 차폐 계수 벡터의 최초의 항과 두번째항 이후를 분해해 최초의 항에 대해서는 SH Exp계산을 해주고, 그 이후에 대해서는, 그 대담한 2개의 가중치 계수 테이블을 사용한 간략 계산을 실시하도록 한다.

정밀도에 큰 영향을 주는 절대값이 큰 최초의 항과 두번째항 이후에 대한 계산 방법을 다르게 한다.

<그림 설명>
(제목) a, b 테이블의 근사 정보를 개선
→ DC Isolation (직류성분의 분리)



이 논리를 이용하기 위해서는, 2개의 가중치 계수를 얻기 위한 테이블을, SH Log 공간의 차폐계수벡터의 최초의 항을 제외한 나머지에 대해 작성할 필요가 있다

2개의 가중치 계수를 얻기 위한 테이블 작성의 두번째안. 앞에서 나온 그림과 개념적으로는 같지만, SH Log공간의 차폐 계수 벡터의 최초의 항을 제외한 것들에 대응하는 것으로 한다.

덧붙여, 이 테이블에서는, 키로 하는 f 값에 절대값의 하한과 상한을 설정한다고 하는 타협안을 적용했지만, 그럼, 그 조건을 만족할 수 없는(범위 밖의) f에 대해서는 어떻게 하면 좋을까?

f의 절대값이 하한,또는 상한을 넘는 경우, 하한, 상한 범위에 들어갈 때까지, 그 값을1/2(으) 해 간다. 그리고, 하한 상한 범위에 들어가면 테이블에서 구한 계수 a,b(을)를 꺼내, 그 값으로부터 SH Exp의 근사를 구하는데, 구한 값에 대해서, 방금전의1/2 한 횟수만큼,Triple Product계산을 하면 된다고 한다. 이 논리에 대한 수학적인 증명도 여기서는 생략 한다.

테이블 범위를 벗어난 경우에 대한 대처의 구체적인 예

차폐계수 벡터의 통합을 SH Log공간에서 실시하고, SH Exp연산으로 통상공간으로 되돌릴 수 있으면, 나머지는 음영 처리(휘도 계산) 뿐이다. 이것에 대한 처리계는 PSF기법과 논리는 완전히 똑같아서, 이 이후의 처리에 대해서는 해설을 생략 한다.

자기변형 할수있는 3D모델에 대해서도 동적 PRT를 적용할 수 있게 됨으로써 PRT의 응용범위는 극적으로 넓어졌다.

휘도 계산시의 반사 모델을 변경하면 당연히 금속과 같은 질감 표현도 가능하다

동적PRT의 가능성

2002년에 등장했을 때, PRT는 3D게임 그래픽스와는 관계없는 기술이라고 생각되어져 왔지만, GPU의 진화와, PRT기술 그 자체의 진화에 의해서, 3D게임 그래픽스에의 응용에 대한 기대가 높아져 왔다고 말할 수 있다.

특히 3D모델이 변형해도 적용할 수 있는 SHEXP기법의 동적PRT은, 본스키닝(Bone Skinning)된 3D캐릭터에도 대응 가능한 것이고, 인간이나 동물이라는 동적인 3D캐릭터 표현에도 문제 없게 대응할 수 있는 것이다. 이것이 넓게 활용되게 되면, 3D게임 그래픽스의 리얼리티는 향상되고, 표현의 폭도 한층 더 확장될 것이다.

본 연재에서 다룬 PRT는 차폐(그림자)로 한정한 테마였지만, PRT는 본래 「빛의 전달」(RADIANCE TRANSFER)를 「사전 계산」(PRECOMPUTE)하는 일반형이기 때문에, 사전계산하는 요소를 다르게 하거나 혹은 늘려 감으로써, 복잡하고 특수한 재질의 표현도 가능하다. 예를 들면, 피부와 같은 반투명 재질의 표현이나, 2차 반사광 이후의 복잡한 상호 반사의 음영 처리등도 가능하다.

현재의 SHEXP기법의 동적PRT에서도, 기본적으로 정점 단위의 음영 처리를 하고, 게다가 PRT의 단위가 구체 근사화 된 형상단위가 되므로, 세세한 디테일까지 고려한 복잡한 빛의 전달을 재현할 수 있는 것은 아니지만, 일반적인 반사 모델을 이용한 픽셀 단위의 음영처리와 조합하면, 그러한 결점도 보완할 수 있을 것이다.

가능성은 보였다고 해도, 3D게임 그래픽스에 응용하려면 , 아직도, 처리 속도나 비디오메모리 용량의 관점에서는 넘어야 할 과제가 많은 것 같다. 하지만, 이것은 하드웨어의 진보로 어떻게든 해결될 문제이다.

그런 의미에서는, 현재 세대 이후의 PC게임등의 앞선 엔진등에서는, 동적 PRT의 구현이 시작될 가능성은 높다.

PRT의 대상 요소 예.점 P에 대해서 PRT 할 수 있는 요소는 많이 있다. 다만, 다루는 요소가 많아지면 많아질 수록 계산 부하는 커져, 비디오메모리 사용량은 증가한다. 그러나, 이것은, 역으로 말하면, GPU 진화로 해결할 수 있는 문제라고도 말할 수 있다


 

Posted by 노을삼킨별
,


아래에서 퍼옴

http://allosha.tistory.com/category/니시카와%20젠지/PRT




한정 조건부 동적 PRT - PSF(Precomputed Shadow Fields)란?


2009-07-03 14:51:11
動的PRT第一段階PSF技法とは? 静的PRTが発表された後、世界のリアルタイム3Dグラフィックスの研究者が積極的に研究開発に乗り出したのが「シーン上のオブジェクトを動かせない」という制約の撤廃だ。 2005年のSIGGRA ...... >> Read more

(C) Mainichi Communications Inc. All rights reserved.


동적 PRT 첫번째 단계 Precomputed Shadow Fields(PSF) 기법이란?

정적 PRT가 발표된 이후, 세계의 실시간 3D그래픽스 연구자들이 적극적으로 연구 개발에 나선 것이 「씬 상의 오브젝트를 움직일 수 없다」는 제약의 철폐이다.

2005년의 SIGGRAPH 2005에서 Kun Zhou씨등이 발표한「Precomputed Shadow Fields for Dynamic Scenes」논문에서 제창된 「Precomputed Shadow Fields」(PSF) 라는 개념이 이 제약의 철폐를 향한 큰 발판이 된다.

이것은, 개개의 오브젝트는, 형상(형태) 변형은 허용되지 않지만, 각각의 위치를 바꾸거나 기울기를 바꾸거나 하는 것은 가능한 동적 PRT이다. 석상이나 동상, 연필이나 펜, 병이나 식기 등, 그 자신이 변형되지 않는 강체 모델이라면, 씬에 움직임을 추가한다 해도 활용할 수 있는 PRT이고, 3D게임에의 응용 가능성을 확 끌어 당긴 기술이라고 할 수 있다.

그런데, 정적 PRT에서 , 씬의 움직임에 대응할 수 없었던 것에는 근본적인 이유가 있다. 그것은 「씬 전체를 "1개"의 오브젝트로 취급한다」는 대전제가 있었기 때문이다. 거기서, 씬을 「복수의 오브젝트로 이루어진다」고 분해해서 생각하면 어떨까? 라는 발상이 생겨나게 되었다. 즉, 정적 PRT에서의 차폐구조에 대한 생각을, 「자기 자신의 부위가 자신을 차폐하는 "자기차폐"」와, 「다른 오브젝트에 의한 차폐」로 나누어 생각하려는 것이다.

토끼의 「자기차폐」란, 예를 들면 토끼의 귀가 몸체를 가리는 것. 「다른 오브젝트에 의한 차폐」란 불상의 그림자가 차주전자(teapot)에 걸리는 것 같은 그런 상황

<그림 설명>
자기 자신에 의한 차폐: 자기차폐
타오브젝트에 의한 차폐


자신이 변형하지 않는 강체의 경우, 당연하겠지만 자기차폐 구조는 변하지 않는다. 즉, 이것은 사전계산이 가능하다고 할 수 있는 것이다.

형상이 변하지 않는다고 전제하면, 자기 차폐는 사전에 계산해 둘 수 있다

<그림 설명>
각 물체를 강체라고 가정하면, 자기 자신에 의한 차폐는 불변
-> 각 물체는 이동, 회전할 수 있지만, 형상(형태)은 변형될 수 없다.

정적 PRT에는 없었지만 동적 PRT에서는 요소가 되는 것이「다른 오브젝트에의 차폐」이다.

다른 오브젝트에의 차폐는, 자신을 중심으로 어느 일정 거리에 떨어진 곳에 있는 동심구(同心球, 중심은 동일하고 반경이 다른 구)상의 점에 대한 차폐 구조로 생각한다.

즉, 아래의 그림으로 해설하면, 그림속의 토끼의 주변에, 눈에는 안보이는 가상적인 구를 생각해, 그 구의 내면에 무수한 카메라를 설치해서, 각 점으로부터 토끼의 실루엣이 어떻게 보일까를 모두 기록해 둔다라는 이미지이다.

토끼의 주변에, 눈에는 보이지 않는 가상적인 구를 생각해, 그 구의 내면에 무수한 카메라를 설치해서, 각 점으로부터 토끼의 실루엣이 어떻게 보일까를 모두 기록해 둔다


오브젝트 자신이 변형되지 않으면, 그 구 내의 각 점에 설치된 카메라에서 보이는 모습도 변하지 않는다. 즉, 각각의 방향에서의 다른 오브젝트에의 차폐 구조는 변하지 않는다고 생각할 수 있다. 이 다른 오브젝트에의 차폐 구조를 「Shadow Fields」라고 부르고, 이것을 사전 계산해서 구하기 때문에 "Precomputed" "Shadow Fields", PSF가 된다.

Shadow Fields의 사전 계산

이 PSF기법의 구조는 어떠한가? 조금, 보고 가기로 하자.

자기차폐의 차폐구조의 사전 계산은, 정적 PRT 때와 거의 같다. 각 3D모델상의 모든 정점으로부터 자기 차폐  구조를 조사/추출해서, 이것을 최종적으로는 구면조화함수로 근사 해서 그 스케일링 계수를 얻어, 이것을 차폐 계수 벡터로서 보존하는 것이다.

약간 개념의 전환이 필요한 것은, 다른 오브젝트에의 투사를 구하는 Shadow Fields의 계산이다. 자기 차폐의 산출에서는, 그 3D오브젝트를 구성하는 정점에서 본 차폐 구조를 구했지만, 이것에 반해, Shadow Fields의 산출은, 그 동심구 상의 각 점에서 본 차폐 구조를 구하는 것이 된다.

즉, 차폐 구조를 구하는 위치가 3D오브젝트의 외곽측에서 행해진다는 것 이외에는 자기 차폐의 계산과 같은 것이다. 각 동심구 상의 모든 정점으로부터 차폐 구조를 구해, 이것을 구면조화 함수로 근사해서 그 스케일링 계수를 구해, 저장(보존)하는 것이다.

이 때의 반경 r은, 물체의 경계구(Bounding Sphere. 그 물체 전체를 포괄 할 수 있는 구)를 기본으로 0.2r ~ 8.0r까지, 적당한 스텝으로 결정하고 있다고 한다. 피라미드사의 구현에서는 0.2r ~ 8.0r까지의 각각을 32등분 해서 구현했다고 한다.

「다른 오브젝트에의 차폐 구조」의 사전 계산은, 동심구 상의 각 점에서 3D모델 방향으로의 차폐 구조를 구한다. 구한 차폐 구조 정보는 구면조화 함수로 근사해 그 스케일링 계수를 구해서 보존한다. 이 흐름은 정적PRT와 똑같다

이 자기 차폐나 Shadow Fields의 산출은, 그 씬에 등장하는 3D오브젝트의 개수만큼 실시하게 된다. 예를 들면4종류의 3D오브젝트가 등장한다면 그 4종류에 대해 각각 자기 차폐와 Shdaow Fields를 산출할 필요가 있다.

주목되는 것은 형상(형태)이므로, 다른 색의 동일 형상 오브젝트를 등장시키는 3D게임에서의 활용의 경우에서는, 한 번 산출한 자기 차폐나 Shdaow Fields는 유용(流用)이 가능하게 된다. 또, 동일 형상(형태)이고 크기가 다른 것(확대 축소한 것)도, 동일하게 취급할 수 있다.(계속)





한정 조건부 동적 PRT - PSF기법에서의 라이팅


PSF기법에서의 라이팅

정점 단위의 음영 처리가 되는 것은 앞에서의 정적 PRT와 같다. 즉, 실제 렌더링 시, 3D모델의 각 정점들에 대해 라이팅을 해주게 된다. 구체적으로는, 그 라이팅을 실시하는 정점에 자기 차폐 정보를 고려하고, 나아가 그 정점에 영향을 미치는 다른 오브젝트의 Shadow Fields를 고려한다, 라는 흐름이 된다. 그리고 다른 오브젝트의 동심구 상에 나열된 복수의 Shadow Fields로부터 어떤 것을 선택할까이인데, 이것은 그 라이팅 대상인  정점으로부터 가장 가까운 8개의 후보를 선택해 가중치를 붙여서 선형 보간을 해서, 그 결과를 채택한다.

PSF기법에서의 라이팅

<그림 설명>
(버블) 이 정점의 라이팅은, 이 정점의 자기차폐를 고려하고, 이 정점을 포함하는 가까운 Shadow Fields를 참조 & 선형보간해서 「다른 오브젝트에의 차폐」(이 경우는 토끼에서 차주전자로의)도 고려한 형태로 한다. (이 그림은 2D로 표현되어 있어서 4개의 Shadow Fields를 참조하고 있지만 실제 3D렌더링에서는 8개)

물론, 자신과 다른 오브젝트에서 기준으로 하는 좌표계가 서로 다르기 때문에, 다른 오브젝트의 Shadow Fields 정보를 글로벌 좌표계로 변환하는 처리를 하지 않으면, 이쪽으로부터 다른 오브젝트의 Shdaow Fields를 사용할 수 없다.

알기 쉽게 앞의 그림을 인용해서 말하면, 차주전자와 토끼가 회전하고 있어서 다른 방향이 되어 있을 때, 차주전자에서 본 토끼는 상대적으로 다른 방향을 향하고 있기 때문에, 토끼의 「다른 오브젝트에의 차폐 정보 = Shadow Fields」를 이쪽에 반영 시키려면 그 Shadow Fields의 방향(좌표계)까지 변환하지 않으면 않된다라는 것이다.

이 Shdow Fields의 방향 변환 처리(좌표계 변환 처리)가 SH Rotation이라는 처리이다. SH은 Spherical Harmonics(구면 조화 함수)의 약자이다. 간단히 말하면, 구면 조화 함수로 근사 해서 만든 차폐 구조 데이터를, 그 스케일링 계수만을 사용해 좌표축 회전을 해 버리는 것이 SH Rotation이다.

구면 조화 함수의 스케일링 계수들로 된 계수 벡터만으로 좌표계의 회전을 실시하는 처리가 「SH Rotation」이다.

<그림 설명>
SH Rotation이란??
정보(화상)의 기준축 회전을 계수벡터 공간에서 직접 실행하는 연산

그리고 이어서 좌표계를 변환한 다른 오브젝트의 Shdow Fields들을 이쪽의 자기 차폐에 통합(반영)시키는 처리를 실시하는 것인데, 이것에는 SH Triple Product(고도의 복수회에 걸친 내적 연산)라는 연산을 한다.

SH Rotation과 SH Triple Product의 실제 논리나 처리계에 대해서는, 복잡하고, 지면 문제 상 여기서는 생략 한다. 양쪽 다 계수 벡터 차원에서 실시하는 계산이고, 또한 고속화를 고려한 방법이며, 구면조화 함수등과 같이 「현존하는」툴로서 활용해도 된다고 여겨지고 있다. 다만, 계산 부하는 그 나름대로는 크다.

SH Rotation과 SH Triple Product의 이론이나 구현에 대해서는 「Spherical Harmonic Lighting: The Gritty Details」(SH Rotation의 구현 방법), 「Code Generation and Factoring for Fast Evaluation of Low-order Spherical Harmonic Products and Squares」(SH Triple Product의 구현 방법)라는 논문이나, 피라미드사가 제공하는 자료를 참고하기 바란다.

처리하고 있는 정점에의 타 오브젝트로부터의 영향 유무에 대한 조사는, 그 씬에 등장하는 모든 타 오브젝트에 대해 실시한다. 영향이 있는지 없는지의 판단은, 앞에서의 바운딩스피어의 8.0r의 거리를 기준으로 실시하면 된다. 8.0r의 거리 이상 떨어진 다른 오브젝트에 대해서는 영향이 없다고 무시하고, 반대로 8.0r의 거리 이하의 다른 오브젝트에 대해서는 영향이 있다고 판단한다. 영향이 있다면 그 Shadow Fields를 통합해 나간다(계산에 포함한다).

모든 정점에 대해 차폐 구조를 산출 했으면, 이후의 음영 연산(휘도 계산)은 정적 PRT와 같다. 재차 말할 필요는 없겠지만, 그 차폐 계수 벡터와 광원 계수 벡터의 내적을 구할 뿐이다.(계속)

PSF기법에 의한 동적 PRT는 개개의 3D오브젝트의 변형은 허용 되지 않지만 위치 이동이나 회전은 허용 된다

피라미드사에 의한 PSF의 구현예. 마치 레이트레이싱에 의한 오프라인 렌더링 된 것 같은 부드러운 음영의 오브젝트들이 움직인다. 여기까지 움직일 수 있게 되면, 특정 타입의 게임이라면 실용화가 가능할지도 모른다



 

Posted by 노을삼킨별
,


아래에서 퍼옴

http://allosha.tistory.com/category/니시카와%20젠지/PRT



Precomputed Radiance Transfer(PRT)란?


2009-06-04 01:15:11
現在、次世代の3Dゲームグラフィックス技術として実用化が進められているものにPRT(Precomputed Radiance Transfer)がある。 PRTは日本語訳では「事前計算・放射輝度・伝搬」ということになり、なにをするものか難解 ...... >> Read more

(C) Mainichi Communications Inc. All rights reserved.


오늘날, 차세대 3D게임 그래픽스 기술로서 실용화가 진행되고 있는 것으로 PRT(Precomputed Radiance Transfer)가 있다.

PRT는 일본어 번역에서는 「사전계산 방사휘도 전달」이라 하고, 무엇을 하는 것일까 난해한 키워드들로 되어 있지만, 현재, 근대 GPU의 활용 테마로서는 가장 유행하는 것들 중 하나이며, 근대의 실시간 3D그래픽스를 말할 때 아무래도 피할 수 없는 것이 되고 있다.

이번회 부터는, 이 PRT 기술에 대한 기본사항과 최첨단 PRT기술의 최신 동향까지를 소개한다.

PRT는 실시간 글로벌 일루미네이션(Global Illumination)

오늘날의 실시간 3D그래픽스에서는, 광원을 설정하면 기본적으로는 그 광원의 빛을 직접 받는 음영계산 밖에 하지 않는 약식처리가 대전제로 되어 있다.

현실 세계에서는, 광원으로부터의 빛이 제삼자에 의해 차폐된다거나, 또는 빛이 어떤 물체에 닿아서 반사한 그 빛도, 다시 광원이 될 수 있다(2차 광원). 그러나, 현재의 실시간 3D그래픽스에서는 이러한 처리는 생략되거나 유사방법(Fake)으로 대신하는 경우가 많다. Fake라고 해도 그 나름대로 이치에 맞는 것처럼 보이면 상관없는 것이지만, 무언가 위화감이 남아 버리는 국면도 적지는 않다.

이러한 차폐나 상호반사등을 다뤄, 복잡한 조명을 재현하려고 하는 것이「 대국적인 조명 기술」(Global Illumination : 글로벌 일루미네이션)이라는 기술/개념이다.

하지만, GI는 복잡하고 계산량도 많기 때문에, 정식으로 구현된 것은, 실시간에 작동 시키기가 매우 어렵다.

거기서, 이 GI를, 복잡한 빛의 이동에 대해서는 오프라인으로 시간을 들여 미리 계산해 버리고, 실시간 렌더링시에는 그 사전 계산 결과를 이용해서 실현하려는 아이디어가 등장한다.

그 하나가 이「PRT」라는 것이다.

이 PRT가 각광을 받기 시작한 것은, 2002년 SIGGRAPH 2002에서 「Precomputed Radiance Transfer for Real-Time Rendering in Dynamic, Low-Frequency Lighting Environments.」(Peter-Pike Sloan)라는 논문이 발표되고 부터이다.

이 원조적인 아이디어에서는, 어느 씬에 대해 PRT를 실시할 때 , 광원은 움직일 수 있지만「그 씬에 등장하고 있는 캐릭터나 오브젝트는 일절 움직일 수 없다」라는, 실시간 3D그래픽스에 있어서는 치명적인 제약이 있었다. 거기서 「움직이지 않는 배경에만 PRT를 사용한다」라는 한정 조건부로 3D게임 그래픽스에 응용하는 예도 제창되었지만, 메모리 사용량이나 얻을 수 있는 효과의 밸런스를 생각하면 실용성은 낮다고 하지 않을 수 없었다.

그러나, 이 논문이 기폭제가 되어, 각방면에서 연구 개발이 이루어지게 되었다. 그 보람이 있어, 최근 몇년 사이에, 씬을 실시간으로 움직여도 적용할 수 있는 PRT 기법, 말하자면「동적인 PRT」까지도 발표가 되었다.

본연재에서는, 이 동적 PRT의 기초 이론까지를 소개하겠지만, 갑자기 동적 PRT로 넘어가도 의미가 없기 때문에, 가장 기본적인 PRT인 「정적 PRT」……즉 「그 씬에 등장하고 있는 캐릭터나 오브젝트는 일절 움직이지 않는」, 고정적인 씬에 있어서의 정적PRT 부터 차례대로 보고 가기로 하자.(계속)

                                                          PRT의 기본 개념

< 그림 설명>
좌:
현재의 실시간 3D그래픽스
광원, , 벌레
(버블) 이 픽셀의 음영처리는 광원의 차폐나 반사광의 영향을 무시하고 있다.
우:
광원, 반사, 차폐
(버블 상) 하나의 픽셀에 오는 모든 빛이나 차폐를 실시간으로 고려하는 것은 어렵다.
(박스) 이 픽셀에 어떤 빛이 오는지를 사전에 가능한 계산해 두려는 것이 PRT의 기본방침
(버블 하) ?을 사전에 계산 실시간 렌더링 때에는 사전에 구한 "?"의 부분을 사용한다.


CEDEC2006_kor01.zip


Precomputed Radiance Transfer(PRT)의 기본. 정적 PRT


PRT의 기본 ~ 정적 PRT란?

PRT는, 무엇을 미리 계산하는가에 따라 복잡도가 달라진다.

본연재에서 다루는 PRT는, 2006년에 개최된 게임 개발자 회의 CEDEC 2006에서 피라미드사가 발표한 내용을 바탕으로 하며, 「환경맵을 통째로 광원이라 생각하고, 복잡한 차폐를 고려해 실시간으로 렌더링한다」라는 테마로 한정하고 있다.

씬 내의 오브젝트가 움직이지 않는다고 전제하는 PRT가 「정적 PRT」이다. 2002년에 발표된 PRT의 원조격인 논문은 이 정적 PRT였다. 원안 발표자인 Sloan씨는 이전에 마이크로소프트사에서, Direct3D 개발에 깊게 종사한 인물이다.


그 씬을 둘러싸는 정경을 큐브 환경맵으로 만들어, 이것을 광원으로 보고 실시하는 라이팅을 특히 「Image Based Lighting」(IBL)이라 부른다. 본연재에서 해설하는 PRT 라이팅은 이 IBL를 전제로 한다.

IBL : Image Based Lighting의 기본 개념

<그림 설명>
좌:
이런 씬이 있다고 하면...
(버블) 배경을 텍스처에 렌더링해서 환경맵이라 한다.(실제로는 전방위 6면체 환경맵인 큐브맵을 생성한다.)
우:
(박스) 그 환경맵으로 라이팅을 하는 것이 IBL의 기본개념


픽셀 단위의 라이팅을 할 때, 그 픽셀의 방향(법선벡터)에 근거해 큐브 환경맵을 참조하고, 그 텍셀을 광원으로 보고 음영연산을 실시하는 간이기법도 IBL로 불리지만, 여기서 말하는 IBL은 차폐나 그 외의 복잡한 빛의  움직임(음영 뿐만이 아니라, 경우에 따라서는 빛의 침투나 굴절, 반사 등)을 고려한 것을 가리킨다.

IBL에서는 이와 같이 6면체 구조의 전방위 환경맵을 광원으로서 이용하는 경우가 많다

<그림 설명>
좌:
환경광원
무한원(無限遠, 무한히 먼 곳)에 존재
중:
구(球)에 투영
우:
전개(展開)


그러한 고도의 IBL을 온전히 구현하려면 , 우선, 그 씬의 각 정점으로부터 전방위를 둘러 보았을 때의 차폐정보와 법선벡터 정보(실제로는 코사인값. 뒤에서 서술)를 텍스처에 기록해 둔다. 이것이 「사전 계산」부분이다.

그리고 렌더링시에는, 각 픽셀내지는 각 정점에서, 사전 계산으로 작성한 그 텍스처로부터 광전달 함수를 복원해, 그 때의 시선 방향(시선 벡터)을 고려해서, 큐브 환경맵 광원을 참조해 라이팅을 실시한다. 이것이 IBL기반
 PRT의 기본적인 흐름이다.

사전 계산 부분에서, 「전방위의 차폐 구조를 조사」하는데, 전방위라고는 해도, 실제로는 텍스처 리소스는 유한하기 때문에 8방향, 또는 16방향이라든지 적당한 수의 방향으로의 조사를 된다. 또,  그 차폐 구조 조사는 ray tracing적인 기법으로 행해진다(GPU 가속을 사용한 방법도 있음).

「코사인값」이란, 그 적당한 전방위 방향벡터들과 법선벡터와 내적한 값. 예를 들면 32방향에 대해 차폐 구조를 조사해 그것을 큐브맵에 기록한다면, 그 32방향에 대한 코사인값도 함께 계산해 큐브맵에 저장한다.

이 차폐와 코사인의 2개의 큐브맵을 곱한 것을 IBL적분항이라 부르고, 실제로는 이것을 사전에 계산해서 보관해 둔다.  4만개 정점의 씬이라면, 이 IBL적분항도 4만개 만들지 않으면 안되는 것으로, 이것을 리얼타임에 계산하는 것은 우선 무리라는 것은 상상할 수 있을 것이다. 게다가, 4만개의 큐브맵을 관리한다는 것도, 비디오메모리 용량의 관점에서 보면 비현실적이라고 하지 않을 수 없다.(계속)


IBL베이스의 PRT 개념. 씬을 구 모양의 정경이 둘러싸고 있다라는 이미지. 녹색 화살표는 그 정점의 법선, 오렌지색들은 전방위를 모식적으로 나타낸 것.

그 구 형태의 정경을 큐브 환경맵(6면체의 환경맵)으로서 근사 한다

그 씬의 모든 정점에 대한, 전방위로의 차폐구조(왼쪽)와 법선벡터 정보(코사인값, 오른쪽)를 텍스처에 기록. 이것도 역시 큐브 환경맵으로서 기록

실제로는 차폐 구조와 법선벡터 정보(코사인값)를 하나로 모아 IBL적분항으로서 관리. 논리상, 예를 들면 4만 정점의 씬에서는 이 IBL적분항의 텍스처가 4만개 필요하게 된다. 이것은 비현실적.



 

정적 PRT를 실시간으로 구현하기 위한 타협과 고안

이것을 실시간으로 구현하기 위해서는, 몇개의 타협과 간략화가 필요하게 된다. 1번째의 타협점은,「씬 상태의 고정화」다. 즉, 씬에 등장하는 오브젝트가 전혀 움직이지 않는다라는것. 이것은 「정적」PRT의 「정적」을 붙힌 이유이기도 하다.

PRT에서는, 모든 정점으로부터 전방향으로의 차폐 정보를 사전에 계산해서 취득, 보관했다가 활용한다는 방침을 기본으로 취했다. 따라서, 씬에 등장하는 오브젝트가 움직이면 차폐구조를 다시 한번 계산하지 않으면 안되기 때문에, 실시간에는 씬을 고정화 할 수 밖에 없다

2번째의 타협점은 조명계산(음영 처리)을 정점 단위로 하는 간략화다. 음영 처리를 픽셀 단위로 하는 것이 고품위 영상을 얻을 수 있는 것은 당연하지만, 이것을 정점 단위로 삭감함으로써 처리시간을 벌 수 있다. 실제의 처리계에서는 세정점의 계산 결과로부터, 그 폴리곤을 구성하는 픽셀 컬러를 선형보간해서 구하는 Gouraud Shading적인 접근방법을 취한다.

단, 정점 단위의 라이팅에서 주의하지 않으면 안 되는 것은, 렌더링 대상 3D모델의 정점수(폴리곤수)이다.

비록 아무것도 없는 평면의 지면이라도, 여기에 제3자의 그림자나 그 외의 복잡한 음영이 투사될 것이라고 상정하기 때문에, 1개의 폴리곤이 아니라 다수의 폴리곤으로 분할해 표현할 필요가 있다. 그렇지 않고 대강의 폴리곤 개수라면 음영의 결과가 반영되지 않고 부자연스럽게 되어 버린다.

퍼포먼스를 벌기 위해서 음영 연산을 정점 단위로 실시한다

비록 아무것도 없는 평탄한 마루일지라도, 그곳이 차폐되어서 그림자가 지는 경우, 그 부근의 정점들이 그림자색이 되는 것을 생각할 수 있다. 이것을 상정해, 어느 정도의 폴리곤수로 분할할 필요가 있다

다수의 폴리곤으로 분할하면 할수록 정점 단위의 음영 처리의 결과는 고퀄리티가 되지만, 그 만큼, 지오메트리 부하는 증가한다

3번째는, 모든 정점에 대해서 사전에 계산한 방대한 용량의 데이터를 압축하자는 방책이다.

예를 들면, 4만 정점의 씬으로, 큐브맵화한 IBL적분항이 32×32 텍셀의 작은 큐브맵이었다 해도, 1 정점 당32×32×6면×4바이트(αRGB각 8비트 칼라) = 24kB. 이것이 4만 정점 만큼 있으면 총 938MB의 비디오메모리가 차폐 정보의 저장만으로 사용되어져 버린다.

이것을 압축하는 기술로서 이용되는 것이, 요즘 3D그래픽스의 세계에서 볼 기회가 많아진「구면 조화 함수」(SH : Spherical Harmonics)이다. 이 구면조화함수는「양자 역학」 교과서에나 실려 있을 것 같은 것으로, 그러한 특수 수학을 3D그래픽스의 세계에 응용했다는 점이 PRT의 독특하고 획기적인 점이라 할 수 있다.

그런데, 모든 정점의 차폐 구조를 사전에 계산하고 있다고 해도, 실제로, IBL적분항으로부터 각 정점에 대해서 전방향의 음영 연산을 하는 건 처리가 무겁다. 그러나, 이 구면조화 함수를 사용하면 마침 그 문제도 해결 가능하게 된다.(계속)



 

구면조화(Spherical Hamonics) 함수란 무엇인가?

「구면조화 함수」는 말부터 어렵게 들리므로, 우선은 이미지로부터 파악해 보자.

구면조화 함수란, 극단적으로 간략하게 설명하면, 구(球) 같은 물체로부터 임의의 길이의 가시들이 뚫고 나와있는 「타원형의 찌그러진 성게」같은 물체의 형태를 수학적인 함수로 나타내기 위한 것……이라고 할 수 있다(성게의 가시들이 반대로  오목하게 패여 있는 경우도 있다).

이것이 어째서 큐브맵의 압축에 사용할 수 있는지 이미지가 쉽게 떠오르지 않을 지도 모르겠다.

차례차례 설명해 나가자.

모든 방향의 정경을 나타낸 큐브 환경맵을 구(球)로 보고 그 큐브 환경맵의 텍셀(화소)의 값을 "높이" 로 본다. 그러면 「찌그러진 성게」같은 입체가 완성된다. 그리고, 이 찌그러진 성게를 정확하게 기록하는 것은 포기하고, 「대략적인 형태」만을 기록하기로 한다. 그 수단으로서 구면조화 함수를 이용하는 것이다.

앞에서, 32×32 텍셀의 6면체의 큐브 환경맵을 예로 들었는데, 비압축 시에는 하나의 정점 당 24kB의 데이터량이 필요했다. 저장하는 구면조화 함수의 계수들의 개수에 따라 데이터량이 변하지만, 실용 레벨로는 16개 정도의 계수로도 충분하다고 한다. 만일, 16개의 32비트 부동소수점이면 불과 64바이트. (즉) 24kB의 1/400로 작아진다. 방금전의 4만 정점의 예라면, 2.4MB로 끝나므로, 938MB와 비교하면 상당히 현실적인 데이터량으로 압축할 수 있음을 알 수 있다.

구면조화함수는 「찌그러진 성게」형태의 근사적인 표현방법으로 사용된다.

<그림 설명>
(제목) 구면조화함수의 요점
상:
(박스) 구면조화함수를 사용한 근사 ≒ 본래의 휘도 분포  <-  각방향의 휘도를 높이로 변환
<- 구에 투영
구면조화 함수는, 대강의 특징을 극도의 효율로 근사할 수 있다
하:
(박스 좌) 데이터량
16개~36개의 float: 64byte(16개의 경우)
(박스 우) 데이터량
큐브맵의 데이터량: float * (32*32*6) 필셀: 24,576byte
데이터량을 1/400로 압축!!

구면조화함수는, 어떤 형상을 표현하기 위해 복수의 함수군들로 구성된다. 그 함수의 수가 많을 수록 형상 표현이 정확하게 된다. 자세한 수학적인 정의는 여기서는 생략 하지만, 아래 그림은, 어떤 파라미터가 주어진 구면조화함수를 나타내고 있다. 그림에서 위에서 부터 1차(first order, 또는 1레벨) 까지 구면조화함수를 사용하면 1개, 2차(secode order)까지 사용한다면 합계 4개, 3차까지는 합계 9개, 4차까지는 합계 16개……라는 상태로 함수의 개수가 증가한다.

l = 0,1,2,3…, m = -l ~ +l에서의 구면조화함수의 수식(上)과 3차원으로 가시화한
그림(下). 만일, 예를 들어 l=3의 4 레벨까지 사용한다고 하면 총16개의 구면조화함수를 사용하게 된다


그림을 한번 더 보고 싶다.

l 값이 작을 수록 형상이 단순하고, 반대로 l 값이 커지면(아래에 가면 갈수록) 뾰족뾰족한 형상이 복잡하게 되어 지는 것을 알 수 있다. 방금「찌그러진 성게」의 형상을 근사하는 것에, 많은 구면조화함수를 사용하면 고품질로 근사 할 수 있다고 말했다. 이것은 결국, 이 그림의 아래쪽의 복잡한 형상들을 사용하면 할수록, 그「찌그러진 성게」를 보다 정확하게 표현할 수 있다는 것이다.

표현하고 싶은 「찌그러진 성게」는, 큐브 환경맵이고, 그 값은 큐브 환경맵 마다 고유하다. 그 말은, 각각 그 가시의 길이나 그 구처럼 생긴 형태의 크기가 다 다르다는 것이다. 어느 가시가 길면 그 가시가 길어지도록 구면조화함수의 크기를 바꾸어 줄 필요가 있다.「찌그러진 성게」형상의 근사에는, 복수의 구면조화함수에 대해서 가장 적당한 스케일링 계수(크기를 결정 짓는 에누리)를 줄 필요가 있다. 이 계수를 구하는 계산은 여기서는 생략 하지만, 간단하게 말해 어떤 정해진 방정식을 풀어서 구할 수 있다.

예를 들면, l = 3까지의 16개의 구면조화함수를 이용해 근사 할 때는 16개의 스케일링 계수를 구할 필요가 있다.

「찌그러진 성게」형상의 근사에는, 사용한 구면조화함수 1개마다 가장 적합한  스케일링 계수를 도출해 조합해 줄 필요가 있다

<그림 설명>
(제목) 구면 조화 함수에 의한 근사
좌:
(박스) 대략적인 특징을 근사 가능
(박스) 근사한 결과
우:
(박스 좌) 압축하고 싶은 정보 S
(박스 우) 최적의 계수 계산식
(박스 중) 구면조화함수 -> 스케일링 계수
(박스 우) 1:1 대응
(박스 우) 최적의 계수를 수치적으로 계산 가능
(박스 하) 구면조화함수

스케일링 계수를 도출하면, 이것만으로 근사를 한 「찌그러진 성게」의 형상을 복원할 수 있다. 덧붙여 경험적으로, 실시간 3D그래픽스에서의 PRT용의 경우,  대개 16개(l=3)~36개(l=5)의 구면조화함수면 충분한 것으로 알려져 있다.

<그림 설명>
(제목) 구면조화 함수의 요약
근사한 정보 = 구면조화함수  ≒ 근사전의 원래 정보
계수벡터를 보존하면, 큐브맵을 보존하는 것과 같다
각 정보 사이에서 변화하는 것은 계수 뿐 -> 계수만 정보단위로 보존
계수 벡터라고 호칭
0.0 - 검은색, 1.0 - 흰색의 그레이스케일로 가시화


구면조화함수 그 자체는 이미 존재하는 것이며, 산술적으로 산출할 수 있다. 그렇다면, 어떤 「찌그러진 성게」형상을 기록&재현하려고 했을 때(근사되어 버리지만), 그 구한 계수만을 기록해 두면 복원이 가능하게 된다.

예를 들면 앞의 한개 정점 당 24kB의 데이터량이 필요했던 그 형상 데이터를, 16개의 구면조화함수로 표현한다면, 불과 16개의 계수를 보존해 두면 복원 할 수 있다. 구면조화함수로 1/400로 압축할 수 있는 트릭이 여기에 있다.

보다 감각적인 예를 든다면, 구면조화함수란, MPEG나 JPEG의 압축에 이용되는 이산 코사인 변환의 「구체(球體) 버젼」이라고 할 수 있을지도 모른다.(계속)




 

렌더링 시의 음영 처리는?

여기까지를 근거로 정적 PRT의 흐름과 개념을 정리한 것이 아래 그림이다.

정적 PRT(Static PRT)의 개념도.「구면조화함수」는 데이터 압축 메서드로 활용된다

< 그림 설명>
(제목) Static PRT의 개념도
상:
사전 계산
차폐계수 벡터
차폐정보를 취득 -> 데이터 압축 -> 휘도계산
하:
실행시
구면조화함수
광원정보 입력 -> 데이터 압축 -> 휘도계산
광원계수 벡터


차폐구조의 구면조화함수는 흑백이므로 1채널 분량만 다루면 되지만, 주변 정경의 큐브 환경맵의 압축은 RGB 3채널 분량을 같은 형태의 구면조화함수로 압축해야 한다.

그런데, 이 정적 PRT에서는 각 정점 단위로 음영계산(휘도계산, 조명연산)을 한다고 앞에서 말했다.

그러나, 각 정점에서 차폐구조 큐브맵도, 광원으로 취급하는 전체 정경을 그린 큐브 환경맵도, 모두 구면조화 함수의 계수가 되기 때문에, 그 음영계산 방식이 쉽게 이해되지 않는다. 실은, 이 계산은, 이 구면조화함수의 스케일링 계수열들을 벡터로 가져와서 내적 계산하는 것이다.

수학적인 증명은 여기에서는 생략 하지만, 이번회의 예로 보면, 차폐구조압축에서 구한 구면조화 함수의 스케일링 계수열로 된 「차폐계수벡터」와, 광원용 큐브 환경맵 압축에서 구한 구면조화함수의 스케일링 계수들로 된「광원계수벡터」의 내적을 구하면 음영계산을 한 것이 된다.

구면조화함수를 이용해 정보를 압축할 수 있었을 뿐만 아니라, 부차적으로 음영 계산의 간략화도 동시에 가능한 것이다.(계속)

차폐구조 압축에서 구해진 구면조화 함수의 스케일링 계수열로 된 「차폐계수벡터」와, 광원용 큐브 환경맵 압축에서 구해진 구면조화 함수의 스케일링 계수로 된 「광원계수벡터」의 내적을 구하면 음영연산(휘도 계산)을 해 준 것이 된다

<그림 설명>
제목: 휘도계산
계산정점,
Double Product(내적)


Posted by 노을삼킨별
,