꽃미남 프로그래머 김포프가 창립한 탑 프로그래머 양성 교육 기관 POCU 아카데미 오픈!
절찬리에 수강생 모집 중!
프로그래밍 언어 입문서가 아닌 프로그래밍 기초 개념 입문서
문과생, 비전공자를 위한 프로그래밍 입문책입니다.
jobGuid 꽃미남 프로그래머 "Pope Kim"님의 이론이나 수학에 치우치지 않고 실무에 곧바로 쓸 수 있는 실용적인 셰이더 프로그래밍 입문서 #겁나친절 jobGuid "1판의내용"에 "새로바뀐북미게임업계분위기"와 "비자관련정보", "1판을 기반으로 북미취업에 성공하신 분들의 생생한 경험담"을 담았습니다.
Posted by 알 수 없는 사용자

이번에 간단히 끄적여 볼 포스팅은 여기저기서 많이 논의되고 있기에 다루기 좀 무서운(?!) 게임의 스토리에 대한 이야기이다. 사실 게임 UX 기획 연재할 때부터 생각하고 있던 아이템이라 원래 좀더 길고 장황하게 쓰고 있다가, 그림도 없이 텍스트로만 정리되다보니 지루하고 안읽히는 것 같아 그냥 짧게 줄인 글로 정리해 보았다.

 

 

A. 서사/서술보다는 상황을 통한 스토리 전달

 

 플레이어는 게임을 진행하면서 끊임없이 목표를 부여 받아 해결해 나간다. 이 목표는 단기적인 목표 뿐만 아니라, 전체를 관통하는 장기적인 목표까지 포괄한다. 리니지의 경우는 원작 만화의 반왕 켄라우헬과 데포로쥬 왕자의 갈등 구조를 참조해 쫓겨난 왕자가 동료를 모아 ‘공성전’을 통해 영지를 차지하고 지배해 나간다라는 장기 목표 아래, 성장과 도전의 모든 상황을 사용자경험의 흐름으로 연결시켰고, 블레이드앤소울의 경우는 끊임없는 대사 전달과 적재적소의 연출씬을 통한 몰입을 통해 ‘복수’라는 큰 테마 속에 스토리 위주로 사용자경험의 흐름을 연결시켰다.

 

 두 게임 모두 기본적인 전제는 '영지 탈환'이나 '스승의 복수' 같은 스토리 테마 속에 녹아있다. 하지만 게임 컨텐츠의 구성에서는 차이를 보이는데, 리니지가 대사 전달이나 연계 퀘스트의 스토리텔링보다는 공성전을 위해 진행하는 과정 중의 갈등 구조(PK, 사냥터 점령 등)를 통해 창발적 경험을 이끌어내는데 반해, 블레이드앤소울은 (아직까지 보여지는 바로는) 유저의 창발성에 의존하기 보다는 철저히 계획된 대사 전달과 연계 퀘스트를 통한 스토리텔링을 통한 진행을 주요 경험으로 깔고 있는 듯 보인다. 물론 어느 것이 더 좋다 나쁘다를 이야기 하는 것이 아니다.

 

 전자의 방법은 기획된 의도에 맞게 플레이 하는 유저의 참여가 쉽지 않다는 점, 후자의 방법은 의도를 전달하기엔 좋지만 반복적인 플레이에서는 매우 쉽게 지루해질 수 있다는 점에서 각각의 장단점이 있다. 온라인 게임이 되고 싶어한 패키지 게임 디아블로3의 사례에서 볼 수 있듯, 성장과 반복이 주요 순환 컨텐츠로 쓰여지는 온라인 게임에서 스토리 위주의 흐름으로만 게임 디자인을 하는 것은 지속적인 업데이트와 물량적 푸쉬가 뒤따르지 않는다면 그만큼 빨리 사용자가 이탈하게 될 위험성을 안고 있다.

 

 이러한 상황에서 컨텐츠를 디자인할 때 어떻게 고민해 볼 수 있을까? 게임 UX 디자인이라는 측면에서 보자면, 스토리가 양날의 검이 될 수 있는 이러한 위험성을 최소화 하기 위해서는 서사적인 이야기를 자잘하게 모두 만들어나가는 것 보다는 ‘왜 그러한 목표를 갖는지 그 당위성과 그 목표 하에서 어떻게 행동해야 하는지, 그 행동에 있어 얼만큼 다양한 선택지를 갖는지, 그 선택지가 창발적 경험으로 이어져 반복하더라도 지속적으로 플레이 할 동기를 부여할 수 있는지’의 측면에서 접근해 갈 필요가 있다.

 

 즉, 플레이어가 처해질 상황을 제시하고, 그 상황 속에서 샌드박스처럼 대응할 수 있는 다양한 요소를 제공함으로써 서사적 스토리 진행이 아니더라도 내러티브의 흐름을 중심으로 해 플레이를 끌어갈 수 있게 만드는 것이다. 컨텐츠 디자인 작업에 앞서 이러한 형태로 전반적인 사용자 경험을 설정해볼 수 있다면, 그로 하여금 연속성을 갖는 내러티브를 제시하고 그 하위에 속할 플레이 컨텐츠를 설계해 좀더 당위성 있으면서도 서사적이 아님에도 일관되게 흘러가는 스토리를 제공할 수 있을 것이다.

 

 예를 들어, 좀비가 가득한 세상 속에서 '생존'이라는 테마 하에 게임을 만든다고 가정해 보자. 생존을 위해서는 물과 식량, 자신을 보호할 칼이나 총, 잠을 잘 수 있는 안전한 공간이 필요하다. 내러티브의 연속성 하에 이를 구성해 보자면, '위험지역으로부터의 탈출 → 안전한 지역을 찾아가는 이동 → 주변 탐색을 통한 자원 확보 → 추가적인 생존자의 구출 → 자신이 속한 안전지대를 강화하고 세력을 형성 → 한정된 물자를 놓고 다른 세력과의 갈등' 같이 게임적으로 정리해 볼 수 있다. 이러한 각각의 내러티브가 에픽 퀘스트를 설정하고 각 구역 간의 레벨을 디자인하는데 테마로써 쓰여진다면, '이동과 자원 확보' 같은 플레이를 '이목을 끌지 않고 회피하며 환경 진행' or '전면적으로 대항해나가며 전리품 수집' 같은 식으로 선택지를 나눌 수 있게 될 것이고, 이러한 선택지 내에서 '정찰 → 전술수립 → 대응' 같은 식으로 퀘스트를 짜 넣을 수 있을 것이다.

 

 

B. 당위성을 갖고 연계되는 행동을 통한 스토리 전달

 

 게임에서는 다양한 상황 속에서 그때그때에 맞춰 유연하게 동작하는 행동들이 많이 등장한다. 이는 플레이어블한 부분이 아니더라도 방향 전환할 때 벽을 딪는다던가, 환경 위에서 손발의 상황에 맞게 IK가 적용된다든가, 못올라갈 것 같은 지역을 벽을 타고 올라간다든가, 성장에 따라 행동의 범주가 늘어남으로써 못가던 지역을 진입하게 된다든가 하는 식으로 적용되고 있다. 하지만 온라인 게임에서는 콘솔 게임에 비해 이러한 부분이 야박(?)하게 적용되고 있었다.

 

 온라인 게임에서는 일반적으로 잘 쓰이지 않았던 무브먼트 요소 중 하나인 '벽 타기'를 놓고 생각해보자. 블레이드앤소울의 공개 이후, 경공이라든지 벽을 타는 플레이가 기본적으로 탑재되는 게임들이 많이 등장한 것 같다. (개인적인 생각이다.) 여기서 플레이어가 ‘벽을 탄다’는 기능적 행동은 개발기획 시 시스템적으로 의미가 있을지 몰라도, 사용자의 재미 경험에 있어서는 그 자체만으로는 의미가 없다. 왜 그러한 행동을 해야 했는지, 그 행동에 있어 유저가 어떤 선택을 하게 될 것이고 그를 통해 결과를 얻게 된다는 측면에서 행동 시스템을 접근할 필요가 있다.


 작년 지스타에서 공개된 리니지이터널의 경우, 어떻게 될지 알 수 없는 위기의 전쟁상황 속에서 아군의 공성을 위해 위험을 무릅쓰고 벽을 타고 올라 문을 연다는 상황적 행동을 통해 벽타기 자체가 '위기를 전환시킬 수 있는 행동'으로써의 가치를 부여 받았다. 공성 단계에서 상대의 허를 찌르기 위해 몰래 벽을 타 올라간다든지, 공격 받을 것을 뻔히 알면서도 사다리를 성벽에 대고 오리는 행동은 모두 아군에게 ‘문을 열어 기회를 주기 위한’이라는 상황적 전제가 깔려있다. 마찬가지로, 수성 단계에서 전황을 살펴보기 위해 높이 올라가 주변상황을 살필 필요가 있다는 전제를 깔고 나면 망루에 오르기 위해 공격 받아 무너진 계단을 복구한다든가, 아예 성벽을 타고 올라가야 한다 같은 행동이 창발적인 재미로 전달된다면, 플레이어 개개인에게 창발적인 ‘스토리’를 만들어 낼 수 있는 방법으로써 사용될 수 있다. 이는 리니지의 바츠 해방전쟁처럼, 사소하지만 큰 영웅적 행동이 스토리가 되어 회자될 수도 있을 것이다.

 

C. 정리

 

 온라인 게임에서 '스토리'의 가치에 대해서는 예전부터 개발자건 사용자건 왈가왈부가 많았다. 하지만 그러한 논쟁에 있어 스토리는 '서사적' 혹은 '읽히는 대사'로써 전달력만을 두고 회자되었지, 그 배경에 깔린 당위성에 대한 전달의 측면에서 이야기 된 부분은 적은 것 같다.

 

 위에서 다룬 것처럼, 게임에 있어 '상황을 통한 내러티브 텔링'이라든지, '샌드박스형 환경 속에서 행동을 통한 창발적 스토리의 형성' 같은 측면에서도 게임 내 스토리텔링의 가치와 그 방법들에 대한 논의가 되어, 게임의 스토리가 무작정 찍어내는 소모성 컨텐츠를 위한 설정이 아닌, 소설이나 만화처럼 주제를 갖는 '문화적 가치'를 지닐 수 있도록 확장되기를 기대해 보고 싶다.

 

 

반응형

'기획' 카테고리의 다른 글

밸런싱, 숫자의 함정  (18) 2013.01.25
1 depth, 1 play, 1 rank  (2) 2012.12.11
게임 UX 기획 - 04. prototyping 下  (4) 2012.06.15
게임 스토리와 연출  (8) 2012.06.10
FDB 작성 및 적용 사례 - Config  (8) 2012.04.20
,
Posted by 친절한티스

최근 꿈속에서 계시를 받아 "iOS로 간단한 2D 게임 한번 만들어볼까?" 하는 생각이 들어 유니티를 만지작 거리고 있었습니다. 그런데 cocos2d 2.0이 새로 나왔다는 소식을 듣고, "2D 게임엔 cocos2d가 최고라며?" 하길래 cocos2d를 설치 해보았습니다.


원래 cocos2d의 경우 iOS용으로 제작된 만큼 object-c로 작성되어 맥에서 개발할수 있게 되어있습니다. 하지만 고맙게도 cocos2d-x라고 해서 안드로이드와 윈도우에서 개발이 가능하도록 포팅(?) 된 버전이 존재하더군요.


저 같은 경우도 맥이나 맥북이 없어서 개발을 윈도우에서 해야 했기에 cocos2d-x를 이용하기로 했습니다( 줏어 들은 이야기로는 윈도우에서 개발한 cocos2d-x 프로젝트도 맥에서 몇 가지 설정만 바꿔주면 빌드가 잘 된다고 합니다. ).


먼저 cocos2d-x 사이트에 들어가 최신 안정화 버전을 받습니다. 


다운 받은 파일을 압축 풀면 아래와 같이 나올겁니다.



Visual Studio 2008/2010 솔루션 파일이 있어서 이를 이용해 곧 바로 Visual Studio에서 빌드가 가능합니다. build-win32.bat 파일을 이용해 Visual Studio 없이도 빌드가 가능하죠. 일단, 빌드를 해줍니다. 빌드를 하면 Debug.win32/Release.win32 폴더에 파일들이 생성됩니다.



여기까지 기본적인 준비는 끝났습니다. 이제 자신만의 프로젝트를 만들어야겠죠. cocos2d 위키를 보면 기존 cocos2d-x 솔루션에 프로젝트를 추가 하는 형식으로 알려 주는데, 이 방식대로 하면 cocos2d-x 소스를 보면서 작업을 할수 있어 좋은 점도 있겠지만, 자신의 프로젝트 버전 관리를 할거라면 cocos2d-x의 소스들 때문에 애로사항이 꽃 필수가 있습니다. 


그렇기 때문에 딱! 필요한 헤더들과 라이브러리 파일들만 빼서 자신 만의 프로젝트에 추가하는 식으로 하는 편이 나중을 위해서라도 좋을 것 같습니다.


cocos2d-x 프로젝트를 만들기 위해서 cocos2d-x 폴더에 있는데 install-templates-msvc.bat 파일을 실행 해줍니다. 그러면 visual studio 2010의 새 프로젝트 템플릿에 cocos2d-x 프로젝트 템플릿이 생성됩니다. 



그리고 이 템플릿으로 새 프로젝트를 하나 만듭니다. 생성된 프로젝트를 빌드 하려고 시도 하면, cocos2d 헤더 파일을 못 찾는다는 에러가 뿜어져 나올겁니다. 당연히 없으니까요...


새로 생성한 프로젝트의 폴더에 새로운 폴더를 하나 만듭니다. 이 폴더에 cocos2d 관련 헤더와 라이브러리 파일들을 넣기로 하죠. include 폴더와 lib 폴더를 만들어 각각 파일들을 넣기로 하겠습니다. 저 같은 경우는 밑의 스샷 처럼 구성을 했습니다.



Include 폴더에는 각 라이브러리 별로 불필요한 파일들을 제외하고, 헤더 파일 .h 들을 집어넣습니다. 그리고 Lib 폴더에는 아까 빌드한 cocos2d의 라이브러리 .lib 파일들을 넣어둡니다. 이제 새 프로젝트의 경로 설정을 해줍니다.




이제 프로젝트를 빌드하면 OK. 






반응형

'프로그래밍' 카테고리의 다른 글

D3D11에서 Lock ??  (6) 2012.09.02
C# WPF TreeView에서 상위 TreeViewItem 얻어오기  (8) 2012.08.10
Fast sine approximation  (11) 2012.07.12
PC에서 3D 입체 영상 게임 개발하기 #4  (1) 2012.07.09
C++에서도 coroutine & yield  (3) 2012.07.02
,
Posted by 알 수 없는 사용자

Fast sine function approximation 

근래에 세이더를 짜는동안 vertex shader 에서 sine function 많이 쓰는 경우가 생겼는데, 요놈이 아무래도 모바일 쪽에서는 당연히 빨리 돌아가지 않을 같다는 생각에 여러 가지로 궁리를 하고  찾아 보던 Devmaster 에서 좋은 정보를 찾아서 공유하고자 합니다~

사실 많이 알려져 있을 수 도 있는 방법인데 아직 GDF 에는 안 올라 와 있는것 같아서요.

 

 

~ 그럼 두말 필요 없이 cg 소스 공개~

 

float sine(float x)

{

const float pi = 3.14159265358979323846264338327950288f;

const float pi_2 = 6.28318530717958647692528676655900577f;

const float b = 1.2732395447351626861510701069801f ;

const float c = -0.40528473456935108577551785283891f;

//const float p = 0.225f;

// x 값을 -pi ~ +pi 로 리 맵핑해주기

float k = fmod( abs(x), pi_2 ) - pi;


   //sine 값 계산 

   float y = (b  + c * abs(k)) * k;


    // 더 정확한 계산이 필요 하다면 이부분 이용

// float y = p * ( y *abs(y) -y ) + y;


// x 값이 0 보다 클땐 결과물을 반전 해줘야 함.

   y  *= (step(x,0)*2 - 1);


return y;

}

 

일단 저도 Devmaster 올라온 글을 100% 숙지 하지 않아서 어찌하여 이렇게 짜야 하는지는 이해하지 못했습니다. 오리지널 포스팅은 여기 있습니다.

 

http://devmaster.net/forums/topic/4648-fast-and-accurate-sinecosine/

 

~ 이제 보시면 Devmaster Nick 라는 천재의 approximation 정말 훌륭하다고 있는데요. 가지의 곱하기와 더하기로 아주 훌륭한 sine function 구현 한걸 알수 있죠. 여기서 한가지 주의 해야 하실 거는 Nick sine approximation input 값을 -pi 에서 +pi 하고 있습니다. 그럼 이슈는 어떻게 하면 외에 숫자도 여기에 들어 갈수 있게 멥핑 해주느냐 인데요.

 

위에 보시면 Nick 오리지널 포스팅 에는 없는 부분이 있습니다.

 

바로  요거하고

float k = fmod(abs(x), pi_2) - pi;

 

이것 입니다.

y  *= (step(x,0)*2 - 1);

 

float k = fmod(abs(x), pi_2) - pi;

이것은 x 절대값을 2pi 모둘라 해주고 거기에서 pi 값을 빼주는 작업인데요. 이렇게 하면 일단 x 값이 -pi 에서 pi 값으로 들어옵니다. 여기서 -pi 를 빼주는 이유로 x 0  보다 클때는 sine 결과물 반대가 되야 하기 때문에 나중에 결과물에 -1 곱해줘야 하더군요. (이건 간단하게 sine 그래프만 그려보시면 이유를 아실수 있을꺼라 생각 됩니다.)   이렇게 맵핑 하는 게 최적화를 생각 했을때 잘한 일인지는 모르겠지만 일단 저는 이렇게 해결을 봤습니다. ( 왠지 x 리 맵핑 작업이 sine 값을 계산하는 부분보다 부하가 더 걸릴것 같다는 생각이... -,.- 이 부분은 더 좋은 방법이 있을듯 한데 ...)

 

// for precision boost

// y = p * (y *abs(y) -y) + y;

 

부분은 쓰게 되면 정확도가 많이 올라가는데요. 필요에 따라 수도 있고 수도 있습니다. 경우에는 굳이 정확도가 그리 중요하지가 않아서 쓰지 않았습니다.

 

테스트 해본 결과 제가 필요로 하는 정확도를 만족 시켰고요. 아무래도 cg 에서 제공하는 sine 보다는 훨씬 빠르지 않을까 싶네요. Vertex shader 에서 필요로 했기에 lookup 같은 것을 하고 싶지도 않았는데 아주 좋았습니다. 유니티를 안드로이드 모발에서 테스트 해봤는데 돌아 가더군요. 아무래도 모발이 이런 수학적인 함수가 부담이 많이 갈수 밖에 없기 때문에 모발에서 쓰기에 더욱더 적절하지 않을까 싶네요. ( mobile 에서는 필요에 따라 float 대신에 half 를 써도 무난할 듯 합니다.. )

 

참고로 세이더 뿐만아니라 그냥 다른 분야에도 쓸수 있는 데요, Unity c# 에서 기본으로 제공 하는것 보다 얼마나 더 빠른지는 비교해 보지는 못했습니다. ( 귀찮아서.. -,.- )

 

시간 있으면 원본을 정독해서 완전히 이해해 봤으면 하네요. 언제 시간이 좀 나겠죠.~


혹시 이런 방법보다 더 효율적 인게 있으면 같이 공유 합시다~

 

.. 그럼 오늘은 이만.

 

꾸벅.

이세훈

 

 

반응형
,
Posted by ozlael

지난 번 글에서 이어지는 글입니다.

이전 글 : PC에서 3D 입체 영상 게임 개발하기 #3


들어가며

지난 시간에는 미들웨어의 지원을 받아서 따로 알아서 입체 영상이 생성 되는 것을 알아보았습니다. 이번 시간부터는 조금 귀챦은 내용을 다뤄보도록 하겠습니다 :-)

 

Virtual Screen과 UI

 전통적인 3D공간에서 모니터 스크린의 위치는 근(near)평면과 일치합니다. 전통적인 프러스텀공간을 생각시에는 당연한 이야기입니다만은 입체 영상에서는 추가적인 새로운 개념이 나타납니다. 근(near)평면과 원(far)평면 사이에 버쳘스크린(virtual screen)이존재하는 것입니다. 이 버쳘 스크린은 앞서 2화에서 말씀드렸던 컨버젼스 포인트(convergence point, 수렴 혹은 폭주)에 위치합니다. 즉 좌우 주시선이 교차하는 위치이고, 좌우 프러스텀이 겹치는 공간이고, 패럴렉스가 0인 위치인 것입니다. 사용자는 이를 모니터의 깊이로 받아들이게 되고 때문에 일반적으로 UI 및 HUD등은 이 깊이에 그립니다

이 virtual screen에 어떻게 UI가 입체화되지 않고 그려지는 것일까요? 앞서서 말씀드렸다시피 좌우 두개로 분리되어있는 랜더타겟에 드로우 시 입체화 되서 그려집니다. 이 UI를 그릴때도 역시 마찬가지로 두번 그려지긴합니다. 다만 패럴랙스가 일어나지 않는 같은 좌표에 그려지기 때문에 convergence point가 되어 virtual screen에 그려지는 것이지요. 이는 뷰트랜스폼을 다 처리 한 후 그릴시 이러한 현상이 일어납니다. 일반적으로 UI를 그릴 시 FVF를 D3DFVF_XYZRHW 로 설정하고 W를 1로 설정하여 그리지요. 이러한 경우는 트랜스폼음 모두 거친 것으로 처리되어 그대로 찍게 되는것입니다. 그렇기 때문에 패럴렉스가 일어나지 않고 좌우 같은 위치에 그려집니다.

하지만 여기서부터 신경 써 줘야 할 것들이 생깁니다. 모든 UI가 virtual screen 위치에 그려져야 하는 것은 아닙니다. 오히려 convergence point에 위치해 있으면 안되는 UI가 존재합니다. 3D 공간상의 포인터 역할을 하는 것 들, 즉 크로스헤어나 마우스커서나 케릭터명 등은 가리키는 오브젝트에 맞는 적절한 깊이에 그려져야 합니다. 그렇지 않고 스크린 깊이에만 그려진다면 뇌가 매우 힘들어하게되지요. 특히 FPS의 크로스헤어가 virtual screen 깊이에만 그려지는 경우는 치명적입니다. 그런 경우는 크로스헤어에 집중하면 케릭터의 상이 깨지고 케릭터에 집중하면 크로스헤어의 상이 깨지는 혼란을 가져다주게 됩니다. 눈과 뇌는 이러한 경우에 매우 취약해서 금새 안정피로 증상을 보일 수 있으므로 매우 조심해야 합니다. 그렇지 않으려면 크로스 헤어 역시 가리키는 케릭터의 깊이에 맞게 그려서 패럴렉스가 존재해야 합니다. 

하지만 그럴만한 여력이 되지 않는다면 크로스헤어를 끄는 옵션을 두는 것도 방법중 하나입니다. 다행히 세 미들웨어 모두 크로스헤어 기능을 제공하고 있기 때문에 유저가 게임에서 그려주는 크로스헤어를 끄고 미들웨어가 제공해주는 크로스헤어를 켜주면 미들웨어가 알아서 적절한 깊이에  크로스헤어를 그려줍니다.



특수 효과

하지만 문제는 UI뿐만이 아닙니다. 특수 랜더링 피쳐들이 사용 될 수록 문제점들이 보이기 시작 할 것입니다. 특히 픽셀 셰이더 레벨에서 스크린 스페이스로 투영하여 텍스쳐를 사용하여야 하는 효과들이 주로 그러합니다. 소프트 파티클이라던가 왜곡 효과 등 랜더 타켓에 그려진 씬의 장면을 스크린 스페이스에서 재차 샘플링 하여야 하는 것 들이지요. 보통 물에는 굴절 왜곡 효과를 넣는데 기존의 효과들을 미들웨어를 통해 드려보면 다음과 같이 어긋나 보일 것입니다.

왜 이러한 현상이 일어나는 것일까요? 일반적으로 이런 랜더링 피쳐들은 버텍스 셰이더에서 윌드 공간을 스크린 좌표로 변환하는 행렬을 반영하여 그 좌표를 픽셀셰이더로 넘겨주게 됩니다. 픽셀 셰이더에서는 그렇게 념겨 받은 좌표대로 장면 및 깊이 텍스쳐를 샘플링하여 특수 효과를 처리하게 되지요. 다음 코드는 DX9 shadowmap 샘플에서 발췌한 것인데 보통 저런 식으로 진행이 되겠지요.

VS :

VPosScreen = mul( vPos, g_mWorldToScreen );

PS :

float2 ScreenTexC = vPosScreen.xy / vPosScreen.w;

float4 d = tex2D( samShdow, ShadowTexC ) + ...

어느 부분이 문제인지 보이시나요? (물론 굵게 칠했으니 보이시겠지요 ㅋ) 버텍스 셰이더에서 곱해주는 g_mWorldToScreen 매트릭스는 mono eye 기준 값입니다. 드로우 콜을 날려주는 C++ 코드 상에서는 좌안 우안 신경쓰지 않고 모노 카메라 기준으로만 식들을 처리하기 때문에 셰이더 상수로 넘겨주는 매트릭스 값도 당연히 모노 카메라 기준 값이지요. 하지만 픽셀 셰이더ㅇ에 진입 시는 이미 스테레오화 되서 그려지게 되므로 모노와 스테레오간의 불일치가 일어나게 되는 것입니다.

하지만 셰이더 모델 3.0에서는 픽셀 셰이더에서 VPOS 시멘틱을 사용하면 간단하게 해결이 가능합니다. VPOS 를 사용하면 버텍스에서 픽셀로 좌표 관련 값을 넘겨 받을 필요가 없어지고 자연스레 모노 카메라 기준 매트릭스 값을 사용할 일이 사라져서 모노와 스테레오의 불일치 걱정이 가라지게 되지요. 좌안용 우안용 픽셀 세이더에서는 VPOS를 사용하여 각각에 맞는 샘플링 포인트를 얻을 수 있을 것입니다.



마치며

하지만 전통적인 랜더링 방식이 아닌 디퍼드 랜더링 방식에서는 일이 커지게 됩니다. 다음 시간에는 지옥의 맛을 다루기 시작하겠습니다. 감사합니다. 꾸벅


 


반응형
,
Posted by 알 수 없는 사용자

비쥬얼드 블리츠 모드를 최근에 재미있게 하고 있어서 해당 모드의 Testcase 설계를 진행해보고 있습니다.

아쉽게도 제가 코드를 볼줄을 모르며 구조 기반의 테스트 기법은 더더욱 문외한에 가깝습니다.
그래서 해당 테스트케이스는 블랙박스 테스팅을 해야하는 상황을 전제로 합니다.

근래에 게임 테스팅 시 Testcase 를 설계하는 방법에 대해 정리가 필요하다는 생각이 계속 들어서 진행을 해 봅니다.
Testcase를 만드는 많은 방법들이 각자 있겠습니다만 이것도 한 방법이라 생각해 주시고 봐주셨으면 합니다.

해당 방법은 마인드맵을 이용하고 있습니다.



당연히 저에게 비쥬얼드2의 기획서 혹은 명세서는 없기 때문에 우선 마인드맵으로 역기획을 합니다.

아직 완성 버전은 아닙니다.

대전제의 작성 기준은 기획적으로 정리가 필요한 내용 혹은 테스트 케이스 작성 시 분류가 될 듯한 부분을 작성했습니다.

하위 토픽으로 본격적으로 테스팅해야하는 항목들을 분류로 나누기 시작했습니다. 이쪽은 대전제가 있으니 나누기 좀더 쉬워집니다.

3번째 토픽부터 상위 토픽을 테스팅하는 항목들을 정리 시작했습니다.

현재 정리 진행중입니다. 퍼즐게임이라 금방 끝나겠거니 생각했는데 생각보다 시간이 많이 걸리네요.

다음에는 항목들을 좀 더 정리하고 테스팅 사항들을 어떻게 테스트케이스로 옮겨 볼지 정리해 보도록 하겠습니다.



P.S 글 안올린지 너무 오래되고 있어 2년전에 썼던 글을 다시 부활! 시켜서 작성중입니다. 잘 마무리를 해보겠습니다. -___-;

반응형
,
Posted by 대마왕J

간만입니다. 그동안 각종 여행에, 발표에, 글 써야 할 일에, 업계에 다사다난한 사건에 -_-;;;
개인적인 환절기 몸살 등등 때문에 제대로 시간을 잡을 수가 없었네요.

그래서 뭐 ... 이번 시간에는 드디어 실습을 해 보도록 하겠습니다.
역시 이론만 쓰니까 리플이 안달리고 막 이래 제길

이론이고 나발이고 그래서 뭐가 어떻게 되는 건데!!! 라고 하시는 분들이 계신 것 같네요.
하긴 저도 그런 속성이긴 합니다만 후후후

그래서 이번 시간에는 드디어 조명을 실습해 보도록 하겠습니다.
여태까지는 조명? 그냥 불 켜주면 밝아지는 것 아냐? 라고 생각하셨을지도 모르겠지만...
이 수업을 들으시면 조명이 그냥 불켜주면 자연히 생기지는 않을거라는걸 감 잡으실 수 있으셨겠지요.
하물며 텍스쳐 하나 입히는데도 샘플러다 UV다 신경써야 하는데, 조명이라고 별 수 있겠습니까?

게다가 솔직히 조명은 제대로 하면 엄청 복잡하단 말이죠.
그래서 이번에도 이론따윗 엿바꿔먹어! 라는 생각으로 일단 실습부터 무작정 해보도록 하겠습니다.
하고 나서 필요할 때 이론 설명하는게 낫지요 여러분???

 

그쵸오? 때릴꺼야?

 

1. 그래도 조금 더 알아야 하는 지식 - 노말벡터

죄송합니다. 그래도 이론 조금 더 해야 하네요..
Normal 이라고 하는 녀석이 있습니다.

그래픽 하시는 분들은 노말맵이라는 이름으로 익숙할텐데요. 그렇다고 Normal이 뭐예요? 라고 갑자기 대놓고 물어본다면
에 ? 하시는 분들이 많지용.

 뭐 여기까지는 그냥 반짝반짝. 그냥 좀 에또... 그게... 라는 느낌. 알긴 아는데 뭐라 설명하지? 라는 그런 느낌 말예요.

에? 그, 그거 .. 그냥 노말맵이라고 울퉁불퉁하게 하는 거 말하는 건데요...

 그런데 거기다가 공돌이들이 쓰는 용어같은 '벡터' 라는 용어를 붙여서 , '노말벡터가 뭐예요?' 라고 물어본다면

"으, 으으으악 저리 치워!! 저리가!!" 라고 하시는 분들도 생깁니다.

공돌이다! 공돌이가 나타났다!!!  

뭐 이해합니다. 어떤 그래픽 책에서도 노말벡터를 "제대로" 노말벡터라는 이름으로 설명하지 않았으니까요.
하지만 지금 우리처럼 조명을 만지려면, 프로그래머만큼 알지는 못하더라도 개념은 대충 알고 있어야 합니다.

 

3D max를 좀 다뤄보신 분들은, 솔직히 다 알고 계세요. 그걸 노말벡터라고 부르지 않았을 뿐.
그럼 어디 한 번 볼까요.

3D max를 켜 봅시다. 공을 하나 만들까요.  

보기 편하게 하려고 폴리곤은 좀 적게 만들었어요.

이 공을 선택하고 모디파이어에서 Edit Normals 를 선택해 보시면 Normal을 보실 수 있으십니다. [각주:1]

 

흐, 흥! 못찾을까봐 사진 올려준거 아니라능!!!

그리고 이걸 선택하면, 옛날 유명한 공포영화인 헬레이져의 한 장면처럼 돋아난 가시를 보실 수 있게 되실 겁니다.

 

이게 누군지 알면 당신은 30 중반

 

저거예요 저거! 저게 노말이예요! 저게 그리고 바깥으로 향한 화살표 모양이면 그게 노말벡터라고요!!![각주:2]

저거는 그냥 노말을 보여주는 거고... 저게 노말벡터라고 불리려면 방향이 있어야 합니다.
그래서 화살표 모양이라고 한 거구요.

노말이라고 하는건, 그냥 이론 따지지 말고 대충 말하자면, 면이나 점의 수직방향, 즉 로컬의 Z 축이라고요.
평평한 책상의 노말벡터는 위로 솟아있겠죠 똑바로. 그렇게 수직되는 방향을 말하는 겁니다.

 

그리고, 심지어는 여러분도 모델링할때 많이 써 와서 이미 개념까지 알고 계세요. 다 아시는 겁니다. 

 

위의 그림 많이 익숙하시죠? Extrude 명령 줄 때 옵션에 심지어 Local Normal 방향이라는 옵션도 있잖아요?
이것 말고도 Normal 이란 용어는 심심치 않게 3D max 안에서도 사용되고 있습니다.

프로그래머들이 '그래픽 아티스트들은 노말이 뭔지 몰라' 라고 하는 것도 사실 틀린 말이라는 거지요.
그래픽 아티스트들은 이미 '몸으로 알고' 있었습니다. 그걸 말로 표현 못했을 뿐

뭐...  그러면 그동안 알고 계시고 심지어 잘 쓰시고 계시던 명령에 Normal이 흔하게 쓰이고 있었다는 것도 알게 되었습니다. 그러면 할 얘기는 더 많지만, 복잡하게 설명하지 말고 간편하게 그냥 한 가지만 더 얘기하죠.
아까 normal은 버텍스에 하나씩 존재했었습니다.

그쵸? 버텍스에 하나씩 있어요. 이걸 보통 버텍스 노말(vertex normal) 이라고 부르는데요.

그렇다면 픽셀노말 (pixel normal) 이라는건 뭔지 짐작 가능하신지요?

 

넹, 한 픽셀 픽셀마다 노말벡터를 하나씩 가지고 있다는 뜻일겁니다 짐작하신대로.

픽셀 노말은 max에서 볼 수 있는 방법은 없습니다. 상상해야 해요.
뭐 상상하면 뻔하겠죠. '털난 공' 같을 겁니다. 그쵸? 한 픽셀마다 저 선이 하나씩 나와있다고 생각해보면.. .으으..

 굳이 비슷하게 보자면 이런 느낌..?[각주:3]

이거... 보다도 몇 십배 더 빽빽하겠죠. 으으으 징그러워...

대충 이 정도까지 이해하시면 그래픽 아티스트로서는 무리없습니다.

이걸 네이버 백과사전 뒤져보면 이렇게 나오니 알아먹을 수가 있어야지...

http://www.scienceall.com/dictionary/dictionary.sca?todo=scienceTermsView&classid=&articleid=251322&bbsid=619&popissue=


 나한테 왜이러는 건데

 

이렇게 노말은 버텍스 노말과 픽셀노말이 있습니다. 그리고 이 노말벡터들은 조명을 계산할때 매우 중요하게 사용되지요.
버텍스 노말로 계산된 조명은 버텍스 라이트 (Vertex light) 라 불리고,

픽셀 노말로 계산된 조명은 픽셀라이트 (Pixel light) 라고 불리거든요. [각주:4]

 

왼쪽이 버텍스로 계산된 specular, 오른쪽이 pixel로 계산된 specular입니다. 확실히 다르죠. [각주:5]

꼬치꼬치 재미없는 얘기 또 해서 죄송합니다. 그럼 진짜로 조명계산을 한 번 해 볼께요.

 

2. 조명 계산하기 준비

일단 맥스를 켜셔야죠. 그리고 준비해야 할 것이 있습니다.

조명과 오브젝트죠.

아주 만만한 주전자를 하나 만들어 두고, 조명은 Standard light 에서 Target Directional Light를 하나 만들었습니다. [각주:6] [각주:7]

 준비가 끝났으면 shader FX를 열어야죠.
shader FX가 실행되면 기본으로 나오는 메터리얼이 있습니다. 선택하고 과감히 삭제합시다. 이번엔 이거 안써요.

삭제해주세요

 그리고 shader FX 의 빈 화면에서 오른쪽 클릭하고, Material / Advanced를 선택합니다.

 그러면 뿅 ... 하고

Advanced material이 나타납니다.

 

자.. 봅시다. 아래쪽 메뉴를요.  좀 더 자세히 말이죠.

 

일단 나머지는 신경 쓸 필요 없고, 이것만 보면 됩니다.

Ambient Pass (nolight)는 말그대로 라이트가 없는 결과물을 float3로 (녹색이니까요) 받습니다.

One Pass per Light는 한 개의 라이트당 한 패스[각주:8] 를 쓴다는 말입니다. 이건 다른 말로  포워드 렌더링 (Forward Rendering ) 이라고 해서, 가장 흔하게 쓰이는 전통적인 렌더링 방법입니다. [각주:9]

Alpha 는 float 이네요. 이건 말 그대로 알파 채널을 받는 것으로 보입니다. 따로 받네요? 싱기해라.

All Light in one Pass 는 아마도 모든 라이트를 모아서 맨 나중에 한번에 그린다는 것으로 보입니다. 이것은 최신 (지금은 좀 아니지만 그래도 상대적으로) 방식인 디퍼드 렌더링 (Deferred Rendering) 으로 보입니다만... [각주:10]

지금 우리가 쓸 방법은 뭘까요?
프로그래머들이 shader를 배울 때에도 맨 처음에 시작하는 방식인, One Pass per Light (Forward Rendering) 입니다.
그러므로 최종 출력된 결과물은 float3로 만들어서 거기다가 넣어주시면 되겠지요?

 

3. 조명 계산을 시작해 봅시다.

자 그럼 일단, 늘 하던 짓을 먼저 합시다.
메터리얼과 오브젝트를 같이 선택하고, Tools / Assign Material to Selection 을 해줘서, 메터리얼을 주전자에 입혀줍시다. 늘 그렇듯 하얗게 변합니다. 아무것도 없어서요.  

예전 메터리얼 같았으면 어땠을까요?
여기서 예전 메터리얼이었으면, Diffuse에다가 칼라 하나만 연결해 주면 알아서 빛이 계산되어 나왔었지요?

 

그치만 지금은, 칼라를 연결했는데도 그냥 단색 칼라만 나옵니다. 아아아아아아아....

네, 이게 다른 겁니다. 예전에 쓰던 메터리얼은 라이트 계산 같은건 알아서 해주던 녀석이었습니다. 자동차로 비유하자면 '오토' 기어 차량이랄까. D에다가만 넣으면 알아서 가는... 

그렇지만 지금 만든 Advanced한 메터리얼은 '메뉴얼' 기어 차량 같은 느낌이어서 , 일일히 값을 넣어주지 않으면 안움직이는 녀석입니다. 귀찮은 대신에 어떨까요? 뭔가뭔가뭔가 성능이 좋겠지요? [각주:11]

자....... 여기서 그동안 배웠던 이론이 나옵니다.

일단 알고 있는게 이거였었죠

빛이랑 직각이 되는 부분이 가장 밝다.[각주:12]

빛이랑 직각이 되는 부분이라... 그러니까 이런 부분이죠.

 

이런 면이 가장 밝을 겁니다. 평면이 기울어지면 밝기가 떨어질거구요.

조명은 Direct Light이므로, 위치와 넓이는 상관없지요.
DIrect Light는 이런 조명이니까요

시작도 없고 끝도 없으시며 그 넓이도 존재하지 않으시고,
오직 한 방향만 존재하실 뿐이어다.

지저스돋네

뭐, 좋아요. 이제 이걸 벡터를 이용해서 표현해 봅시다. 가장 밝을 때는 벡터가 어떻게 될 때라고요?

 

여기서 평면의 벡터는 바로 노말 벡터.

오호라.....  

이것 봐라?

 

이제 대충 눈치 채시는 분들이 나올 것 같은데요... 그래요, 조명의 방향을 나타내는 조명 벡터 (일명 라이트 벡터 Ligjt Vector) 와 평면의 방향을 나타내는 노말벡터 [각주:13] 가 서로 마주보고 있으면 가장 밝게 되는 겁니다.
그리고 이것을 뭐라고 말하냐면,

밝기가 1.0이다

라고 말합니다. [각주:14] 우리는 이제 이렇게 생각하기로 했지요? 모든걸 0에서 1사이의 숫자로 말입니다.
즉 빛 밝기도 숫자로 보여야 한다는 말씀. 중요해요. 자 다시 한 번 집중해 봅시다.

 

그럼 좋아요. 그래픽 아티스트 여러분, 생각해 봅시다. 
아래 경우는 밝기가 어떠겠습니까? 벡터가 서로 45도 기울어졌을때 말입니다. 밝기가 얼마일까요?  

 넹 밝기는 0.5 일겁니다. 
45도면 반쯤 어두워지는 거지요.   * 틀립니다. [각주:15]

그럼 아래와 같이 90도가 되면 밝기가 얼마일까요?

그렇죠! 밝기는 0 입니다. 까맣게 되는 거예요.
빛이 있어도 안밝아요. 그냥 막 생각해 봐도 그럴 것 같잖아요.  

이걸 계산하면 되는 거지요.
다시 한 번 정리해 볼께요.

보통 이 계산은, 계산의 편의를 위해 조명 벡터를 뒤집습니다.
그래서 조명의 벡터가 조명에서 평면으로 가는 화살표가 아니고, 평면에서 조명으로 가는 화살표로 표시되지요.

그렇게 해서 한 방에 정리해 보면 이렇습니다.

평면벡터는 어딘지 이제 다 아실테니 조명 벡터만 보자면,

 

이런 느낌이 되겠지요. 슬슬 이해 가시지요? 이제 다르게, 풀 버전으로 한 번 볼까요?

짜잔~

네 그렇습니다. 노말 벡터와 조명 벡터를 뭔가로 계산해서, 서로 각도 차이가 0일때는 1이 나오고, 45도 차이일때는 0.5가 나오고, 90도 차이일때는 0이 나오게 하면 될겁니다. 

* 다시 한 번 말하지만 틀립니다. 45도일때 엄밀하게 0.5는 아녜요. 0.7 정도입니다. 자세한건 다음 시간에

그리고 소개하겠습니다 그 공식을.

사실 제대로 설명하려면 sin 그래프부터 보여드려야겠지만, 할 수 있다면 내적이 왜 sin 그래프 모양인지 증명까지 해야 겠지만, 그건 필요하면 나중에 할께요. 지금은 급해요 급해 ㅎㅎ
그냥 공식 이름부터 말하고 말께요. 더 설명했다간 맞아죽을것 같아

그 공식이란 벡터의 곱셈인 dot 공식입니다.[각주:16]

('닷' 이라고 부르죠. 좀 더 유식하게 '닷 프로덕트(dot product)' 라고 프로그래머에게 말하시면
프로그래머가 놀라면서 존경의 눈빛을 보내게 될 것입니다 후후후)

그럼 무작정 계산해 보도록 하겠습니다. 이미 이론이 너무 많이 나와서 325분이 쓰러지셨어요. 아아 죄송합니다. 반성하겠습니다.

 

닥치고 실습하겠습니다. 죄송합니다.

 

 자 주둥이가 찢어지기 전에 시작해 보죠.
아래 화면에서부터 시작입니다.

 벡터 두 개가 필요하죠. 조명벡터부터 갑니다.

 조명벡터는 들어오는 거니까 Input에 있겠죠. 우리가 만든거 아니잖아요? 받아오는거지.
보니까 있네요. 선택합시다.

 부왘ㅋㅋㅋ 나 정말 Shder FX 아이콘 디자인 정말 좋아요. 누가 한거야 이거 ㅋㅋㅋ
근데 화살표 방향은 거꾸로 된게 아닐까 합니다 .조명에서 평면 방향이 아니라 평면에서 조명 방향이 아닐까요. 계산하면 그렇게 나오는데, 아이콘 그림은 저렇게 되어 있어서 조금 의문입니다 .어쨌건 신경쓰지 말고 갑시다.

이번엔 평면벡터, 즉 노말벡터를 받아와야죠. 역시 Input을 보니까 Surface Vector가 있습니다. 부담없이 가져다 쓰지요. [각주:17]

 가지고 왔습니다 . 역시 아이콘은 직관적입니다. 그림만 보면 뭔지 다 알거 같다능

 그럼 이제, 두 벡터를 연산하는 Dot 이란걸 불러봅시다.
math에 보니까, DotCrossProduct 라는게 있네요!!! Dot과 Cross라고 하는 (내적, 외적) 벡터의 연산을 처리하는 함수 같은 녀석입니다! [각주:18]

 부왘ㅋㅋㅋ 아이콘 봐 ㅋㅋㅋㅋㅋ

자 이제 필요한 것들이 다 모인 것 같습니다. 연결해 보죠. 두 벡터를 dot 시켜 줍니다.

 

응? 그런데 dot에 있는 출력부인 Result가 파랑색입니다. float 인거죠. float3가 아닙니다.
그렇죠, 위에서 봤던대로 dot 공식을 적용하면 0.0~1.0 까지의 한 자리의 숫자만 나오는 겁니다. 밝기를 나타내는 float이 나오는 거지요. [각주:19]

뭔가 더 필요합니다. float 이 float3로 변할 수 있는 무엇이...
그럴땐 만만한게 Color지요!

그래요, 생각해보니 빼먹은게 있었네요.
빈 화면에서 오른쪽 클릭을 하고 Input 에서 LightColor를 선택합니다. 조명 색상이 빠졌잖아요!!!

부르는건 좋았습니다만... 이걸 더해야 할까요 곱해야 할까요? 이거 숙제입니다. 3분 드릴테니 생각해 보세요.

 

 

 

 

 

 

 

 

 

 

 

 

 

자 정답은?

곱하기 였습니다.

당연하잖아요? 더해 버리면 어두운 면이 아예 안나오고 하얗게 질려버릴 겁니다.

 

 자, 그럼 최종 결과를 보겠습니다.

잘 나왔습니다! 빛의 밝고 어두움을 표현하는데 성공했어요!!! 크흑

이걸 램버트(Lambert : 람베르트) 공식이라고 합니다.
조명 색상을 바꿔 보시고, 각도도 바꿔 보시지요. 잘 동작해야 정상입니다.

이렇게 당연하다고 생각하는 것을 직접 만들어 보니까... 마치 우리가 아무런 생각없이 방에 불을 켜지만, 우리가 직접 전구를 만든다면? 이라는 생각이 들지 않습니까?
그러므로 오늘의 교훈은 전기절약

 

자, 다음 시간에는 조금 더 발전된 조명을 배워보지요. 그러면서 이론을 살짝, 아주 살짝 더 배워보도록 하겠습니다.

 

그러니까 , 여러분 다음 달 3일까지 안녕~

 

* 최근 필자 사정으로 연재주기를 1달로 늘였습니다. 건강문제와 집안/회사일/외부일 때문이죠 뭐.
안정되면 갑자기 연재주기를 줄일 수도 있습니다. 내맘임.

  1. 역시나 3D 그래픽 아티스트들에게는 매우 쉬운 메뉴라서 자세히 설명 안했습니다. [본문으로]
  2. 벡터이면서 길이가 1인 것들이 주로 사용되는데요, 이것을 '단위벡터' 라고 하며, 노말라이즈(Normalize) 했다라고도 합니다. 각종 계산에서 편리해지기 때문에 거의 모든 벡터 계산은 이걸 기본으로 합니다. [본문으로]
  3. 이건 사실 세그먼트를 200까지 올려서 만든 이미지입니다. 여러분들의 이해에 도움이 되게 하기 위해서 말이죠. 그러므로 실제로 픽셀 노말은 더 빽빽합니다. 그냥 공으로 보일 정도로... [본문으로]
  4. 우리는 일단 Pixel light를 배웁니다. 요샌 vertex light 쓸 일도 거의 없어지는 것 같아요... [본문으로]
  5. 사실 normal에 대한 이론은 더 말할게 많이 있습니다만 여기서는 넘어갈께요. 빨리 해보고 싶어서 근질대시잖아요? [본문으로]
  6. free Directional light를 쓰셔도 상관 없습니다. 단, spot이나 omni light는 사용하지 마세요. [본문으로]
  7. 저는 평소에 프로그래머들 책을 볼 때, '이런 기본적인 것은 알겠지' 라고 쓴 글에 많이 좌절했던 사람입니다. 그래서 그 복수로 3D max 를 이 정도는 알겠지 라고 옹졸하게 글을 쓰고 있습니다. 이히힛 [본문으로]
  8. pass 란, 한 '사이클' 정도로 생각하시면 됩니다. '한 패스를 돈다' = '한 사이클을 돈다' = '한 과정을 돈다' = '한 번 첨부터 끝까지 그린다" [본문으로]
  9. 한 조명당 한 번 그리므로, 조명이 많아지면 많아질 수록 여러 번 그리는 방법입니다. 당연히 조명이 많으면 기하급수적으로 느려집니다. [본문으로]
  10. 어쨌건 최신 게임에서는 이 렌더링 방식으로 조명연산을 가볍게 만들기도 합니다. [본문으로]
  11. 성능이 좋은건 나중에 봅시다. 지금은 일단 1단에 넣고 앞으로 가기나 해야죠. [본문으로]
  12. 물리적으로 따지고 들어가면야 여러 가지 얘기가 나옵니다만, 우리 그래픽 아티스트들이 원하는건 정확한 물리기반의 광자이론이 아닙니다. 그저 '우리 그림을 이쁘게 하기 위한 정도의 지식' 이지요. [본문으로]
  13. 3d에서 엄밀히 얘기하면 버텍스 벡터라고 해야 할 거 같은데 일단 이렇게 설명을 해버리지만 나중에 어떻게 꼬일지 나도 모르게... [본문으로]
  14. 간만에 보는 0과1입니다. 늘 얘기했지만 shader는 0과 1이 사이에서 끝나요 [본문으로]
  15. 사실은 cos 45도 라서, 약 0.7의 값이 됩니다. 중간이라고 생각하셔도 대충 개념은 맞지만 사실은 60도가 되어야 0.5 입니다! [본문으로]
  16. 벡터의 곱셈은 두 가지가 있습니다 하나는 dot (내적) 이고 하나는 cross(외적) , 이지요. 제 수업때 cross를 쓸 일은 ..... 없겠군요. 후후후 [본문으로]
  17. 보시면 알겠지만, 여러 가지 용어가 혼용되어 사용되고 있습니다. 노말벡터, 평면벡터, 표면(Surface)벡터, 픽셀벡터... [본문으로]
  18. 프로그래머들 세계에서는 띄어쓰기를 잘못하면 문제가 되는 경우가 꽤 있습니다. 그래서 띄어쓰기를 안하고 대문자로 띄어쓰기를 대신하고는 합니다. 즉 Dot Cross Product 라고 씌여진 거지요. [본문으로]
  19. 어지러울까봐 미리 말씀 안드렸습니다만, 사실 dot을 적용하면 -1.0~ 1.0 까지 나옵니다. 지금은 음수가 무시되는 옵션이 켜져 있어서 0~1까지만 나오는 겁니다. [본문으로]
반응형
,