레이블이 개발일지인 게시물을 표시합니다. 모든 게시물 표시
레이블이 개발일지인 게시물을 표시합니다. 모든 게시물 표시

2013년 5월 16일 목요일

난 왜 아직도 직장인인가...?

사실 난 게임개발을 직장인으로 먼저 시작한 놈이 아니다. 물론 내가 시작할때는 누군가를 채용할수 있는 게임제작회사란 존재자체가 거의 없었기에 창업을 꿈꾸는게 당연했다. 그리고 내 성향상 내 스스로 이루는걸 되게 좋아하는 성격이라... 자기 팀/회사를 성공적으로 키워나가는거에 꽤나 만족을 느끼는 스타일이다...

뭐 근데 그일은 어찌저찌 안되었고.... 잠시 법대로 외도한 뒤 캐나다 이민오면서 다시 게임쪽으로 돌아가기로 맘먹은건데... 그때는 일단 정착도 해야하고 해서 당연히 직장에 들어가겠단 생각을 했다. 그렇다면 난 대체 무슨 목표를 가지고 직장인을 시작한건가... 물론 난 이 일이 재밌어서 한다... 하지만 자신만의 것을 이르켜 세우는 것보단 직장인이 재미없는건 사실.. 따라서 직장인이 되는걸 합리화할만한 개인적인 목표가 필요했던 거 같다....

지금 생각해보니 내겐 크게 2가지 목표가 있었던 듯.....

1) 뛰어난 게임개발자로 인정받자 = 연봉 여섯자리 이상
난 남에게 인정받는걸 되게 좋아한다. 하지만 나 스스로를 판단하는 기준이 좀 엄격한 편이여서 "나 정말 실력 좋다." 나서서 말하지 못한 채 몇년을 허비(?)했다. 그러는 동안 수많은 개발자들을 만나보고 일해보면서 나를 다른사람에게 비교한 뒤에야... "아.. 내 실력이 꽤 좋은거구나.."라고 알게 되었다. (솔직히 좀 씁쓸했다) 아직도 내 스스로 날 판단할테는 "그냥 프로그래밍 하는 놈이지.."라고 생각한다. 남하고 비교할때만 자뻑이 되는거지... -_-... 그래도 웃긴건(아니면 다행인건?)...... 입바른 말 잘하기로 유명한 동료들이 그걸 인정한다는 것.. (물론 내자랑..)

하지만 이건 어디까지나 주관적인 판단일거다.. 난 사실 객관적인 지표로 실력을 인정받고 싶었다. 그게 바로 연봉... 난 자본주의 시장에선 몸값 = 실력이라 생각한다. 실력이 좋으면 당연히 돈도 많이 받아야하고.... 실력이 안좋으면 당연히 적게 받는다 생각.....물론 이상한 짓해서 몸값만 올리는 애들도 몇 봤지만 결국 걔네들은 몇년지나면 밑천 보여서 아무데도 못가더라...

내가 '이정도면 충분히 인정받은걸거야....'라고 목표로 정했던 연봉이 여섯자리 숫자, 즉 $100,000 이상이었는데.... 이 목표는 사실 이미 몇년전에 성취했다...... 고로 지금은 그냥 허무하고 밋밋한 느낌....

2) 언젠가 큰일을 벌일 동료들은 만나자.
두번째는 언젠가 기회가 되면 의기투합해서 큰일을 벌일 동료들을 만나는 것이었다. 주변을 둘러보면 최소한 한손에 꼽을만한 사람들은 이제 있는거 같다. 내가 사실 실력 좋다고 인정하는 프로그래머들이 매우 적은데.. 이 친구중에 몇명은 정말 내가 인정하는 사람들.. 그리고 삶을 바라보는 자세도 나와 비슷해서... 뭔가 같이 하면 매우 재밌을거 같다.


그리고 이건 지난 몇년간 계속 하고 있는 생각...
그럼 왜 나는 아직도 직장생활을 하고 있는걸까...? 아쉬운게 하나 있다면 정식으로 리드명함 달고 팀을 리드 못해본 것이다. 명함없이 리드는 해봤다. 리드 밑의 위치였는데.. 사실 사람들이 날 리드로 따른 경우... 그 뒤에 그 동료들이 날 리드로 원해서 거의 될뻔하다가 팀이 접히면서 다들 퇴사한 케이스... 리드는 정말 잘할 자신 있는데 그 뒤로 회사를 한 두번 옮겨다니면서 전혀 stranger들과 일하게 되니 아직도 리드를 하고 싶은지는 모르겠다. 난 내가 아끼는 팀원들을 이 끌때 보람을 느끼지... 빈 껍데기뿐인 리드 타이틀은 달고 싶지 않거든...



2013년 5월 11일 토요일

포워드 렌더링으로 컴백

사실 예전에 '포워드 렌더링을 다시 고려하는 이유'라는 글을 쓰다가 완성을 못한적이 있었다... 뭐 당연히 다들 아는 그런 이야기들인데..

다시 포워드 렌더링으로 돌아왔다.. 돌아오니 디퍼드 렌더링에서 아주 속썩었던 부분들이 해결되서 참 맘에 든다.. 하지만 또 이렇게 오래 포워드쓰다보면 다시 디퍼드가 그리워지겠지...

하지만 뭐든간에 실시간으로 처리할수 있는 그래픽효과는 한계가 있다... 동적으로 변하는것이 많지 않은 게임이라면 오프라인으로 라이트맵으로 베이크 하는게 최고고... 그러면 굳이 디퍼드가 필요없고.. 그럼 포워드 하면서 하드웨어 앤티애일리어싱 써주면 아주 행복 ^_^

하지만 그럼에도 동적그림자가 필요한 부분이 있으니 샤도우맵을 만들어야 하지만.. 현재 만드는 게임 - FIFA - 는 동적 그림자를 드리워야 할 놈들이 딱 정해져 있으므로 보다 generic하게 만들 필요가 없어서 그림자의 품질 유지가 가능함.. (물론 거기에 PCF니 뭐니 해야하지만...)

생각해보니 처음으로 60FPS로 도는 게임을 만드는거 같다..... 여태까진 디퍼드에 포스트 이펙트 팍팍 넣어서 30FPS로 겨우 돌렸음.. 60 FPS는 사실 게임반응속도가 높아 좋은거고... 화면에 그리는 픽셀수가 많을수록 화면 품질은 좋아지는듯.. 특히 최소한 1080p는 뽑아줘야 하지 않나.. 60 FPS에 1080P.. 추릅...


2013년 1월 3일 목요일

쓸모없는 회의

정확히 기억은 안나는데 아마도 애플사의 일 진행법을 소개하는 프리젠테이션이었던거 같다. 거기서 한 말중에 기억에 남는 게...

  • 모든 회의의 끝에는 결정(액션 플랜)을 내릴 것
  • 결정을 내리지 않을 회의는 하지도 말 것
  • 결정을 내릴 권한이 없는 직원은 회의에 포함시키지 말 것

원래부터 쓸모없는 회의에 들어가서 시간낭비하는 걸 싫어했던 나에게 참 괜찮게 들리는 이야기였다. 

그 후, 어떤 회의에 초대되어 들어갔다. 한두시간에 끝나는 회의가 아니라 한 3일간에 걸쳐서 하는 회의였고 참여자만도 20명정도 되었는데  회의의 주제는 '차세대 그래픽'이었다.

정확히 회의가 어떻게 진행는지 아무도 내게 말해준 적이 없어서... 

'대체 무슨 회의지?'

하는 생각에 들어갔는데... 이런 저런 새로운 그래픽 기법들이 있는데 자기 팀에서는 어떤 시도를 해봤는지 그리고 앞으로 어떻게 사용할건지 등을 공유하는 거였다. 뭐 결과적으론 시그래프 등에서 볼 수 있는 내용들을 그냥 반복하는 정도랄까... 차이점이라면 

"우린 이거 시도해봤는데 너무 느려서 실제 게임에선 못쓰겠어요."

라고 (주로) 실패한 경험을 공유하는 정도... 이쯤 이야기하면

"아, 대단히 값진 회의였군요."

라고 말할 사람들이 있을지도 모르겠다. 솔직히 말하면 시간낭비였다. 게임쪽에서 차세대 그래픽이 그리 엄청난 도약을 하지 않을 것이라는 건 이제 누구나 아는 이야기이다. 전세대에서 현세대로 넘어올 때 처럼의 엄청난 도약은 없을거란 말...

근데 회의를 마치는 날에 회의 진행자가 갑자기 말하더라. 이 회의의 끝에는 액션 플랜을 만들어야 한다고... 

'아, 이 사람도 그 프리젠테이션을 봤구나.'

라는 생각이 들었는데 사실 유쾌하기 보다는 좀 실망스러웠다고 할까? 왜냐면 그 프리젠테이션에서 전하고자 하는 의미를 제대로 이해 못한 채, 어설프게 흉내내며 시간만 더 낭비하는 느낌이었다.

우리가 만든 액션플랜은 한 대 여섯개 되었는데 이건 사실 다음과 같이 한 줄로 요약이 가능했다. 

"이런 이런 기법이 있다. 하지만 게임에서 사용하기엔 너무 느림. 도구와 파이프라인의 효율성을 높이는데 더 주력해야 할 것"

이건 회의를 들어가기 전에 회의 세부일정을 보고 이미 생각한 거였다. 나 뿐 아니라 회의 참가자들 모두가 같은 생각을 했을 거라 생각한다. (아니라면 그놈들 실력을 심각히 의심해봐야할 듯...).어차피 뻔히 알고 있는 내용으로 결론을 내릴 것을 20명이나 되는 시니어 그래픽 프로그래머들의 시간을 3일이나 낭비시킬 이유가 있는건지....

위의 프리젠테이션에 다음 내용을 추가해야만 이런 쓸모없는 시간낭비를 막을 수 있을 거 같다.
  • 이미 알고 있는 결정을 내릴 회의는 하지도 말 것

2012년 5월 26일 토요일

OpenCL에서 OUT_OF_RESOURCE 또는 CL_MEM_OBJECT_ALLOCATION_FAILURE 에러가 날 때

현재 개발중인 애플리케이션에서 OpenCL을 써서 속도를 높이고 있는데...

clEnqueueNDRangeKernel() 함수를 호출할때 갑자기 CL_MEM_OBJECT_ALLOCATION_FAILURE 에러가 나지 않나 나중엔 OUT_OF_RESOURCE 에러도 나고... 그래서 니가 삽질/해결한 방법을 잠시 노트로 남김.

1. 우선 실제 allocation을 하는 메모리가 얼마나 되는지 확인
실제 사용하고 있는 cl_mem 버퍼는 다 더해봐야 3MB 이하. OpenCL 최소 global 메모리 지원이 128MB 이니. 아무 문제가 없음.

2. Notification 함수
이리저리 뒤지다보니 에러가 날 때 notification 하는 함수를 안붙여놨음. 이 함수를 구현해서 컨텍스트를 생성할때 함수포인터를 전달. 그러니 clEnqueueWriteBuffer() 를 호출할때도 CL_MEM_OBJECT_ALLOCATION_FAILURE 발생하는걸 확인. 그래도 여전히 문제 해결엔 도움이 안됨.

3. CPU OpenCL 디바이스로 실행
인텔 CPU에서 아무 문제없이 실행됨... NVidia GPU에서 돌릴때만 문제가 생김... 순간 드라이버 문제가 아닌가 싶어 최신 드라이버 설치.. 아무 문제 없음

4. 메모리 stomp 확인
코드를 잘 살펴보니 allocation한 local memory의 범위를 넘어서 쓰기/읽기를 하고 있었음... 이걸 제거하니 아무 문제 없이 실행.. 드디어 고쳤다.. 만세..!




오늘의 교훈: OpenCL에서 CL_MEM_OBJECT_ALLOCATION_FAILURE 따위의 에러가 나온다면 메모리 stomp를 확인해보세요.

2012년 5월 22일 화요일

민근님이 진행하시는 게임개발자 팟캐스트

톡톡한 입담으로 저에게 듬뿍 사랑을 받고 계시는(네.. 여친이 없으세요 -_-) 민근님이 새로 게임개발자 팟캐스트를 시작하셨습니다. 1편(상)을 들어봤는데 역시 재밌네요... 한번 꼭 들어보세요.. 저도 앞으로 종종 듣게 될 거 같습니다... ^^



2012년 3월 16일 금요일

컴파일 경고하나당 3 대씩 맞습니다

컴파일 경고(warning) 얼마나 신경쓰세요? 현재 작업중인 코드베이스를 컴파일하면 경고가 몇개나 나오나요? 하나라도 있다면 반드시 다 고치세요. 구차한 변명따윈 필요없습니다. 하나도 안나오게 다 고치세요. 왜인지는 얼마전에 있던 제 경험담을 통해 아주 짧게 주저리주저리 설명드립니다.

며칠 전에 발견한 컴파일 경고 하나
현재 마무리를 도와주고 있는 콘솔게임을 PS3용으로 컴파일하다(즉 g++을 사용하면) 운좋게(왜 운좋은건지는 나중에 설명) 다음과 같은 컴파일 경고를 봤습니다.

1>..\..\src\monster.cpp(2814): warning : unused variable 'temp'

보통 때 같으면 무시하겠는데(왜 무시하는지도 나중에 설명.. 원래는 절대 무시하면 안됨) 그날 따라 무슨 신내림을 받았던지...

'응? 이놈이 뭐지? 궁금한걸?'

이란 생각이 더블클릭을 해서 소스코드를 봤지요.


bool swapped = false;
if( dist1 > dist2 )
{
  swapped = true;
  float temp = dist1;
  dist1 = dist2;
  dist2 = dist1;
}

어라... 버그가 보이는군요. 무슨 버그일까요.... 잠시 여백을 두어 생각하실 기회를 드리겠습니다... 한 눈 팔지 말고 코드 분석하세요...

한 눈 팔지 말랬잖아요.. 이 이미지를 보시면 이미 한눈 파신 겁니다. (그래도 출처는 http://curiousanimals.net)

자, 문제점을 찾으셨나요? 찾으셨을거라 믿습니다... 아니시라면.... 당신은 프로그래머가 아니야~ 버럭!

그래도 또 설명하는 친절한 포프씨 -_-
위 코드가 하려는 일은 두 거리(dist1, dist2) 중에 dist2가 언제나 dist1보다 크도록 변수값을 교환해주는 거군요. 매우 간단하죠. 근데... 뭔가 이상하죠? temp 변수가 안쓰였다니... 프로그래머가 아니신 분들을 위해 친절하게 예를 들어 한 단계씩 보여드리죠..


1. 일단 대충 변수값을 제맘대로 대입
다음과 같이 변수값을 정해서 이게 왜 버그인제 예를 보여드리겠습니다.

  • dist1 = 20
  • dist2 = 10


2. float temp = dist1;이 라인을 실행하면 변수값이 다음과 같이 됩니다. 별문제는 없죠 아직.

  • temp = 20
  • dist1 = 20
  • dist2 = 10

3. dist1 = dist2; 
이 놈 이후엔 변수값이 이리 됩니다. 역시 괜찮습니다.

  • temp = 20
  • dist1 = 10
  • dist2 = 10

4. dist2 = dist1;  

이게 마지막 라인이군요. 드디어 버그가 보이는군요. 이걸 실행하면 최종 변수값이 이따위가(?) 됩니다.

  • temp = 20
  • dist1 = 10
  • dist2 = 10

temp에 저장해눴던 값을 dist2에 대입하는 대신 dist1을 대입함으로 해서... 버그가 생긴거지요...  그럼, 이 버그로 인해서 생기는 문제는 뭐였을까요?

전.모.릅.니.다.
정말 몰라요....(출처: http://knowyourmeme.com)


대충 코드를 훑어봤는데... 파일 이름은 monster.cpp이고 함수이름은 updateTail() 이었습니다. 사실 정확히 어떤 버그가 생기는지는 제대로 살펴보지 않았습니다. 그냥 대충 생각해보니 몬스터들이 팔을 휘두르거나 그럴 때 자취를 보여주기 위해 띄를 하나 그려 주거든요? 가끔, 그 띄가 뒤로 역류해서 겹쳐보이는 경우가 있었습니다. 그게 바로 이 버그 때문일지도 모릅니다. 하지만... 귀찮아서 더 자세히 보진 않았습니다. 그냥

'이 버그 발견했으니 고쳐주세요.'

라고 이메일만 보냈습니다.

버그는 어느 프로그래머나 만든다.
뭐 이정도 버그야 어느 프로그래머도 만들 수 있는 버그입니다. 그 부분에 대해선 프로그래머를 탓하지 않겠습니다. 저같은 꽃미남 프로그래머도 만드는 버그입니다.

뭐, 위의 예는 약간의 비주얼적인 하자.... 별 큰 문제는 아니었죠... 근데... 이게 뭔가 더 중요한 코드였다면 엄청난 하자가 될수도 있죠. 특히나 이처럼 특정조건에서만 생기는 문제였다면 디버깅도 쉽지 않습니다.

하지만 버그를 안만들기 위해 노력은 해야할거 아닌가?
따라서 제가 탓하고 싶은 건 컴파일 경고가 떡하니

"너 뭔가 잘못하고 있을지도 몰라. temp변수가 안쓰였잖아"

라고 말해주는데 그걸 무시한 만행(?)입니다.

컴파일러 경고를 고치는 것만으로도 상당히 많은 수의 버그를 미리 잡아낼 수 있습니다. 이 코드가 들어가있는 게임... 수백만장 팔립니다... 개발비도 수백만불 됩니다. 이런 프로젝트에서 가장 쉽게 코드품질을 보장할 수 있는 법을 무시하는 프로그래머의 자세 좋지 못하죠. -_-

보통 이따위로 깔끔하지 못하게 프로그래머하시는 분들... 전 타박해 드립니다... 하지만, 이번에는 그러지 못하는 이유가 있었습니다. 그것은....

너도 범인이다.
사실 문제는 이 코드를 작성한 프로그래머에게만 있는 건 아니었습니다. 이 회사의 모든 프로그래머 또는 제대로 된 정책을 만들지 않은 리드급 프로그래머에게도 문제가 있었습니다.

왜냐면..... 이 코드베이스를 컴파일하면 컴파일 경고가 1019개 나오기 때문입니다. -_- 1019개나 되는 경고속에 파묻힌 경고 하나를 찾으라고 하는게 어불성설이지요.....

자네...나보고 어쩌라는 겐가....?

보통 때 같으면 전 이런 경고 다 고쳐버리고,

"앞으로 경고 나오면 경고 하나당 저에게 3대씩 맞습니다."

라고 통보를 해드립니다. 하지만 그럴 수 없었던 이유가 이미 너무 늦었다는거죠.  -_-.... 게임 마무리 단계에서는 아무리 사소한 거라도 안건드립니다. (이건 전에 '게임 출시전 개발자가 갖춰야할 마음가짐'이란 글에서 말씀 드렸었습니다.) 딱히 발견된 버그가 있지 않는한 절대 안고칩니다. 코드를 바꿀 때마다 새로운 버그가 나올 위험이 있거든요. 그래서.... 안고칩니다.... 무조건 안고칩니다.

게임 출시하고 나서 고치죠. 근데 이 프로젝트 이후에 제가 이 팀을 도와줄 일이 없을거 같으니....

아마 평생 안고칠지도.... -_-

컴파일 경고를 방지하는 무대뽀 실용적인 방법
자, 그럼 저희처럼 너무 늦기전에 이런 일이 발생하는 것을 방지합시다. 당장 오늘부터라도 시작합시다.

컴파일러 경고를 오류로 처리한다.
가장 실용적인 방법은 컴파일러 경고가 나는 경우 이걸 아에 오류(error)로 처리해서 실행파일 조차 안만들어지게 하는겁니다. 아주 무대뽀 실용적이지요. 간단히 Visual Studio에서 컴파일 옵션만 켜주면 됩니다.

아주 실용적(?)인 방법

이러면 경고가 날 때마다 아예 실행파일이 안만들어지니 테스트를 못하지요! 그래서 프로그래머는 반드시 이 경고를 고쳐야만 합니다. 그래야 제대로 도는지 테스트라도 하니.... 근데 문제는.... 임시적으로 뭐 테스트하고 지우기 위해 대충 코드짜놨는데 경고가 나면...... 짜증나지요... 프로그래머들의 반란(?)을 부추기는 계기가 됩니다.... -_-

그래서 이 옵션은 release 빌드용으로만 켜주는게 좋습니다. debug 빌드에서는 프로그래머가 뭔짓을 해도 냅두는게 장수의 비결입니다. 문제는 프로그래머가 debug 빌드에서만 테스트하고 경고있는 코드를 그대로 check-in 했을 때인데요.

뭐, 이럴 때는 자동빌드머쉰(automatic build machine)이 release 빌드에 실패한뒤 그 프로그래머에

"당장 경고를 고치지 않으면 구워먹겠다!"

라는 협박 이메일을 보낼 거라고 믿습니다. 자동빌드머쉰이 없다면 만드세요. 이것도 없이 어떻게 게임 개발하지...? -_-;;;

정말 말도 안되는 경고는 꺼준다
가끔 정말 말도 안되는 경고도 있습니다. 별 의미가 없는 경고도 있고요. 이런 건 꺼주시면 됩니다. 단, 자기 맘대로 끄지 마시고 다른 프로그래머들과 상의한 뒤 동의를 얻어 꺼주세요. 자기 맘대로 끄는 것을 허용하면 경고 고치기 싫어서 그냥 꺼버리는 몰상식한 프로그래머들 꼭 나옵니다. 이런 분들 발견하시면 퇴사처리 해버리셔도 됩니다. -_-

끄는 법에는 2가지가 있습니다. 프로젝트 전체로 꺼주는 법도 있고, 각 파일별로 (또는 그보다 작은 단위로) 꺼주는 법도 있습니다. 원하는 대로 골라서 쓰시면 됩니다.

프로젝트 전체에서 경고 꺼주기
아래처럼 프로젝트 속성에서 꺼주면 됩니다. 아래 예는 프로젝트 전체에서 경고 #4507을 다 꺼주는 겁니다.




파일별로 꺼주기
그냥 아래처럼 #pragma warning()을 써주시면 그 뒤부터는 경고가 안나옵니다.

#pragma warning( disable : 4507 )

이걸 나중에 다시 켜줄려면

#pragma warning( default: 4507 )

을 해주면 됩니다.


대충 정리
뭐... 결국 할 말은.... '경고를 반드시 고쳐주세요.'였으나 역시나 너무나 주저리주저리 써서 대충 정리.

  • 컴파일 경고만 살펴봐도 정말 명백한 버그들을 고칠 수 있다.
  • 릴리즈 빌드에서는 컴파일 경고를 컴파일 오류로 처리해서 프로그래머들이 언제나 경고없는 소스코드를 유지할 수 있게 돕는다.
  • 필요없는 경고는 프로젝트 속성에서 전역적으로 꺼주거나 파일별로 #pragma warning()을 이용해서 꺼준다.


p.s. 앞으로도 대충 어이없는 경험을 바탕으로 '제발 이러지 맙시다.'라는 글을 종종 올리겠습니다. 은근 좋아하는 분들이 많으신듯..... -_-


2012년 2월 8일 수요일

거짓말로 버티고 사는 개발자...


최근에 회사를 떠나야 했던 떠난 개발자가 있다. 뭐 짧게 짧게 여러 회사를 옮겨다녀야 하는 인간 중 하나인데.... (뭐, 그래야 하는 이유는 대충 다들 알테고).... 어쩌다 오늘 그 인간의 블로그를 보게 되었는데 본인이 회사를 떠나게 된 이유를 설명하고 있었다. 나를 비롯한 많은 울 회사 직원들이 이 글을 아주 즐겁게 봤는데... 이게 세계 최고의 판타지 소설 '반지의 제왕'을 연상시키기 때문이라지....?

이미지 출처: http://images.wikia.com/lotr/images/9/9e/Smeagol.jpg

뭐, 굳이 그놈이 한 모든 거짓말들을 들추어 낼 생각은 없다. 어차피 이 업계에서 머무르려면 그놈은 그런 거짓말을 해야만 할테니까... 그냥 조만간 이놈이 밴쿠버 밖에서 직장을 찾아야 할 꺼라고만 추측한다. 이미 이 도시에서 꽤 유명하더군.... ㅎㅎ... 그 외에도 괜히 여기 까발려서 명예훼손죄로 고소 받는 것도 좀 귀찮고... 뭐 실제 고소 들어오면 어차피 내가 이길 게 뻔하니 그것도 꽤 재밌을 거 같긴 하다.  내가 하는 말은 모두 사실이거든.... (괜히 법대 나온게 아니라니까? -_-) 그냥 아무것도 모르는 똘아이하고 상대하는 게 골치아프니 귀찮은 것일뿐....  그래도 개인적으로 물어오는 사람이 있다면 당연히 주저하지 않고 말해줄거다. 뭐든간에 난 솔직하고 직설적인 놈이어서.. 절대 거짓말도.. 숨기지도 않으니까...

거짓말 이야기가 나왔으니 말인데... 난 의견/판단 <--> 사실을 구분하는 법을 매우 잘 알고 있다. 법대 괜히 나온게 아니라니까.....? -_- 마찬가지 이유로 내가 그놈을 거짓말쟁이라 부르는 이유도 그놈이 허위사실을 유포하기 때문이지 그놈의 말도안되는 판단이나 의견 때문이 아니다. 그래도 정말 스스로 자기주장이 사실이라 믿고 있다면.... 그놈은 엔지니어가 될 최소한의 자질조차 갖추지 못했다는 증거일 뿐... 아니면 여기가 그놈의 새 전세방이 될지도....





2012년 2월 7일 화요일

그래픽 프로그래밍 팀장이 될 뻔 했었다....

난 매우 직선적인 성격이다.. 특히 회사에서 일할 땐.... 말도 안되는 개소리는 개소리라고 말해주고... 실력이 없는 놈이 정치를 하려고하면 쌍욕도 잘해준다... 사실 주변에서는 이러면 적만 만들다가 회사 짤리니 조심하란 이야길 하는데... 내 자세는 언제나..


'그러던가?'

였다. 실력 하나로 믿고 살아온 인생.... 괜히 누구에게나 착한 척 가식떨며 내 자리 지키고 싶은 마음은 한번도 없었으니까...

이렇게 말하면 내가 누구에게나 개판으로 대하는 인간처럼 보일지도 모르겠지만 사실 그건 아니다. 난 대우 받을 가치가 있다고 생각하는 개발자들에게는 정말 잘해준다. 한마디로 직급/연차 상관없이 실력좋고 책임감있고 인간되었으면(가식이 아닌 진짜 인간) 존경해준다.

사실 얼마 전까지는 이런 성격때문에 난 적이 꽤 많다고 생각해왔다. 그런데 최근 들어 그보다 아군(?)들이 더 많다는 사실을 깨닫게 되는 계기가 있었다. 다음은 그 이야기... (내 잘난 척 할거니... 보기 싫음 닫으삼.... 경고했음..... -_-)



이번에 렐릭에서 pre-production에 들어가는 프로젝트가 하나 있다. 그 팀에서 그래픽 쪽 일이 좀 많아서 그래픽 팀 리드가 필요하단다. 원래 그 일을 맡기려고 채용했던 놈이 하나 있었는데 실력이 너무 형편없고 구라만 까고 정치만 하는 개늠... -_- 그래서 오늘부로 퇴사... 따라서 저번주부터 새로운 그래픽 팀 리드를 찾으려고 했단다. 윗선에서는 새로운 사람을 채용하려고 구인공고를 낸다 했다지... 근데 그 이야기들을 팀원들 중에 4명(내가 아는 것만)이 나를 그자리에 추천했단다. (현재 그 팀 규모는 15명정도? pre-production이니까 아직 팀 크기가 좀 작다) 여기서 더 재밌는 사실은 그 4명이 합심해서 날 추천한게 아니라... 한 명씩 따로 자기 생각에 내가 좋을거 같아서 추천했단다. 다른 사람들이 날 추천하는 것도 모른 채.... 다들 나랑 스페이스마린 팀에서 같이 일했던 동료들이었고... 하는 일들도 테크니컬 아티스트 감독부터 원화 아티스트, 그리고 내가 그래픽 팀 팀장이 되면 내 밑에서 일하게 될 쥬니어 그래픽 프로그래머까지 다양....

이렇게 산발적으로 여러명이 추천을 하니 그제서야 나의 가치(?)를 알아본 윗선들이 급하게 나를 현재 팀(다크사이더 2 팀)에서 빼가서 그 팀의 그래픽 리드로 앉히려고 했지만... (민주주의의 승리....?) 다크사이더 2 게임의 출시가 6월달이라 그쪽에서 날 놔줄수 없다고, 나 빼가면 울 모회사 THQ에게 이르겠다고(?) 해서 어쩔수 없이 못빼간단다... -_- (민주주의는 개뿔...?)

솔직히 팀장이 안된건 좀 아쉽다. 오랜만(한 15년? 아니 학교에서 한거 따지면 7년인가...)에 팀장질을 다시 해보고 싶은 욕심도 있었지만... 더 큰 이유는 나를 팀장으로 모시고(?) 싶어하는 사람들이 눈에 밟힌다고 할까? 특히 내 밑에서 일하게 될 그 쥬니어 그래픽 프로그래머는 실력에 비해 몸값이 저평가된 경우라, 팀장이 되면 곧바로 내 직급 정도까지 승진(3단계 승진해서 선임으로 -_-... 연차는 안되는데 실력은 거의 나랑 삐까하다고 생각.. 나보다 나을지도?)을 시켜주고 싶었거든...

어쨋든 날 추천했던 놈들에게 이런 이런 이유로 그래픽 팀장이 안된다는 사실을 알려주니 말도 안된다며 화내는 놈도 있었고... 그냥 아쉬워 하는 놈도 있었고... '그래서 이번 게임 6월에 끝나면 뭐할건데?'라고 물어보는 놈들도 있었다. '뭐, 딱히 갈 팀이 없으면 짤리지 않겠어?'라고 하니 혹시라도 그런 일 생기면 자기도 그 날 사표낸다는 놈들까지 -_-;

참, 고맙단 생각이 들었다. 나와 같은 가치 -- 실력위주, 정직함 그리고 integrity(한국어로 뭔지 모름 -_-) -- 를 가지고 개발을 하는 사람들이 있다는 게... 그리고 그 사람들이 내 리더쉽을 믿어 준다는게...

나는 언제나 상향식 변화(bottom-up change)를 선호한다.


2012년 2월 1일 수요일

새로운 기법 != 새 장난감

게임데브포에버에 무슨 글을 올릴까 고민을 좀 해봤는데... 그래픽 전문자료들은 이미 다른 필자분들이 열심히 올리고 계셔서 요번에는 그냥 제 경험담을 올리도록 하지요.. (이런 글을 원하시는 분들도 꽤 계실듯...?)


제가 이리도 오래 쉰내나도록(?) 게임 업계에 머무르는 이유 중 하나가 언제나 새로운 것들을 시도해 볼 기회가 충분하기 때문입니다. 특히나 그래픽 프로그래밍 쪽은 하루가 멀다하고 계속 발전하는 분야라서 마약처럼 매우 짜릿하죠. (마약이라고 좀 언급해두면 한국 정부에서 게임개발 셧다운제를 해주지 않을까하는 생각에...그럼 한국 게임개발자 분들도 정시퇴근 하실 수 있습니다. 회사 매출이 높으면 일찍 퇴근!)

근데 가끔은 이런 짜릿함에 눈이 멀어 게임을 망치는 경우도 좀 있습니다. 아직 검증되지 않은 새로운 기법을 동원할 때 그에 부수하는 단점들을 간과하는 경우가 허다하거든요. 심지어는 그런 단점들이 이미 잘 알려져 있더라도 장점보다 단점을 더 크다고 착각하는 경우도 문제입니다. (보통 이미 그 기법을 사용해서 게임을 출시한 개발자들이 하는 이야길 듣는게 검증인데.... 그 개발자들이 컨퍼런스에서 발표를 할 때는 당연히 단점보단 장점을 부각시키는게 일반적이라지요.)

디퍼드 라이팅
제가 요번에 적어드릴 경험담은 디퍼드(deferred) 렌더링에 대해서 입니다. 이미 아시는 분들은 아시겠지만 스페이스마린은 자체 개발한 디퍼드 라이팅(deferred lighting) 엔진을 씁니다. 뭐 찾아보면 좀 더 있겠지만 제가 당장 생각하는 퍼드 라이팅 렌더러의 장단점은 다음과 같습니다. (제가 생각하는 중요도 순서로...)

장점:

  1. 포워드(forward) 렌더링에 비해 사용할 수 있는 광원의 수가 많다. (예, '물체당 광원 3개' 라는 제한이 없어짐)
  2. 대부분의 조명을 동적으로 처리함으로 아티스트들의 작업시간이 빨라진다.
  3. 화면공간에서 행하는 후처리(post-processing) 기법들을 사용하기 쉽다. (예, SSAO, Screen Space Decal 등)

단점:
  1. (반)투명한 물체 처리가 골아프다.
  2. 하드웨어 자체적으로 앤티에일리어싱(anti-aliansing)을 처리하기 힘들다.
  3. 메모리를 좀 더 많이 잡아먹는다. (화면 해상도 크기의 렌더타겟들이 여러 개 필요)

스페이스 마린에서 디퍼드를 사용한 이유

원래 시작은...
스페이스 마린에서 디퍼드 렌더링을 사용한 이유는 사실 역사적인 이유가 강합니다. 스페이스 마린을 만들기 전에 Grand Theft Auto 류의 오픈월드 게임을 제작하고 있었는데 이 때 (2008년 중순) 다음과 같이 디퍼드 라이팅 엔진을 판단했었습니다.
  • 오픈월드 게임이니 광원의 수가 꽤 많겠군? 디퍼드가 좋겠어. (장점 #1)
  • 아무래도 밤낮이 바뀌는 효과가 있어야 하니 동적 조명이 좋겠는걸? (장점 #2)
  • 근데 배경이 도시니까 투명한 물체가 꽤 필요하겠는데? (단점 #1).... 으음... 뭐 투명한 물체는 디퍼드 말고 따로 포워드로 그려줘야겠군.. (어쩔수 없는그럴듯한 해결책)
  • 근데 앤티에일리어싱은 어쩌지? (단점 #2) 아직 1~2년 남았으니 나중에 고민해보지 뭐...(대충 책임 회피 -_-)
근데 이 게임이 한 6개월 만에 취소됩니다. 게임 자체에 문제는 아니었고 THQ가 구조 조정을 하면서 그 당시 스페이스 마린 게임을 개발중이던 THQ 호주 스튜디오를 문을 닫았죠. 워낙 렐릭이 워햄머 40,000 게임을 잘 만드는 회사로 유명했던지라 저희쪽에서 대신 해달라고.... 

그래서 처음부터 다시 스페이스마린을 만들었습니다. -_- (THQ 호주에서 만들어 놨던건 하나도 안썼죠.. 저희가 원하는 방향과 너무나 달라서...)

그리고 다시 결정을 내리기엔...
자, 그럼 이번엔 스페이스마린을 만들기로 했으니 다시 한 번 렌더링 엔진에 대해 고민해볼 차례인데... 이 때 (2009년) 저희의 생각은 이랬습니다.
  • 과연 광원의 수가 많을까? (장점 #1이 시들해짐)
  • 밤낮이 바뀌는 효과도 없는데? (장점 #2도 시들해짐)
  • 그런데... 아티스트들이 이미 디퍼드 라이팅에 맛을 들여서(iteration 시간이 매우 빨라졌어요... 모든게 동적 조명이니) 매우 원함... (장점 #2가 다시 살아남)
  • 또한 디퍼드에 기반해서 구현한 Screen Space Decal을 역시 아티스트들이 너무 좋아함 (장점 #3)
  • 서기 40,000년엔 투명한 유리창 따윈 이미 다 뽀개지고 없으니.. 투명한 물체는 그닥 문제가 안될 거야.. (단점 #1이 좀 완화됨)
  • 근데 앤티에일리어싱은 어쩌지? (단점 #2)요즘들어 이 분야에 대한 좀 발전이 있으니(Kill Zone 2가 SSAA를 대충 사용할 때..) 좀더 기다려보지.. (여전히 책임 회피... -_-)
  • 그럼 딱히 디퍼드를 할 이유가 없지 않아?..... 응... 없지.... 근데 이미 만들어 놓은거 다시 포워드로 돌리는 데 드는 시간과 비용이 과연 값어치가 있을까?......... 없군...... 
그래서 결국 디퍼드로 그냥 가기로 했죠. 최소한 아티스트들이 작업을 빨리할 수 있으니까 비주얼 품질이 높아질거라 생각했거든요. 그리고 그건 현실이 되었죠. 아티스트들이 여러번 손 대니까 확실히 스페이스마린의 비주얼 퀄리티도 상승.



그래서 단점은 어케 극복을?
그리고 시간은 흐르고 흘러서 2011년 9월 스페이스 마린을 출시했죠. 그렇다면 저 단점들은 어떻게 극복 했을까요?

투명한 물체
"서기 4만년엔 모든 유리들이 뽀작나서 더이상 투명한 물체가 없습니다 -_-;" 는 저희가 장난처럼 한 말이었는데... 사실 저희 게임에서 투명한 물체가 거의 없습니다. 종류따라 다음과 같이 처리했어요.
  1. 알파테스트: 반투명 블렌딩을 하기 보다 대부분의 물체는 완전투명 아니면 완전 안투명의 두가지로 처리했습니다. 이러면 디퍼드를 사용할 수 있죠.
  2. Screen Space Decal(SSD): 다른 물체의 표면에 찰싹 붙은 반투명한 물체는 SSD로 처리했습니다. SSD에 대한 자세한 내용은 위에 링크 걸어드린 발표자료를 참조하시길. 역시 깊이버퍼를 업데이트할 필요가 없는 놈들이라 디퍼드에 무난히 사용가능
  3. 특수 쉐이더: 머리카락에만 쓴 쉐이더인데 딱히 깊이 버퍼를 업데이트 하지 않고 머리통에 있는 법선 조명 정보를 대충 가져다가 씁니다. 즉 디퍼드도 포워드도 아닌 이상한 꼼수를 썼죠.
  4. 파티클: 파티클은 여전히 포워드로 했습니다. 워낙 투명하니... 저희 파티클 시스템은 또 워낙 빨라놔서.. (파티클 질을 저렇게 해도 콘솔에서 2.75 ms 밖에 안걸림)
이래서 투명한 물체는 해결... 사실 이걸 해결할 수 있던 가장 큰 원인은 아티스트들의 워크플로우를 뚜렷하게 정했다는 거에요. 뭐는 안되고 뭐는 되고를 확실히 알려줬고.. 안되는게 있으면 그걸 성취할 수 있는 다른 방법을 제시했고요.

앤티에일리어싱
그럼 앤티에일리어싱은 어떻게 해결을 했을까요? 사실 운이 좋았죠... -_-

다행히도 게임을 출시할 때쯤 해서 MLAA(God of War 3, The Saboteur)와 FXAA라는 기법들이 이미 개발되었었고... 저희도 FXAA에서 영감을 받아서 그것보다 한 0.1ms 정도 빠른 자체 기법을 개발했습니다. 한 0.8ms 걸렸죠. FXAA라고 해봐야 화면의 색상(또는 조도)을 대충 분석해서 갑자기 픽셀값이 변하는 부분을 적당히 블렌딩 해주는 기법이거든요.

콘솔에서 사용하는 FXAA 기법은 사실 좀 화면에 흐릿해진다는 단점이 있습니다. (PC버전과 달라요) 그래도 스페이스 마린의 비주얼은 만화스럽기보단 사실적에 좀 더 가까워서... 약간 흐릿해져도 큰 문제가 없었죠. (만화처럼 색이 강렬하고 짜잘한 디테일들이 막 들어가있으면 이렇게 흐릿해지는게 문제가 많아요.) 그래서 운좋게 대충 무사히 해결... 

지금와서 생각하는데 타사의 개발자들이 이런 기법들을 개발해 놓지 않았다면, 거기에서 영감을 받지도 못했을거고... 그러면 스페이스마린은 앨리어싱 때문에 꽤 타격을 받았을 거 같아요. 그렇다고 Gears of Wars 3처럼 아예 앤티 엘리어싱을 꺼버릴수도 없는거고... 운이 좋았죠. 책임회피는 했지만 운이 좋은.... -_-v

그렇다고 다 우리처럼 운이 좋을리는 없지?



그리고 스페이스마린을 출시한 뒤, 다른 회사의 게임을 좀 도와줬습니다. 몇 년전에 출시했던 게임의 후속작인데요. 따라서 그래픽 쪽으로는 특별히 손봐줄게 없겠다고 생각했죠. 어차피 컨텐츠만 좀 바꾸면 되니까. 그래픽 쪽은 좀 빠르게 만들어주거나 눈사탕 몇 개만 슬쩍 추가...?

근데 ... 아.뿔.사... -_- 소스코드를 열어보니... 포워드로 잘돌던 그래픽 엔진을 디퍼드로 바꿔버렸더군요..... 과연 왜 그랬는지 마땅히 말해주는 개발자들이 없어서.. 혼자 장단점을 따져봤습니다.
  • 광원의 수가 전 게임에 비해 늘었니? 아니... 거의 똑같은데... (장점 #1 실패 -_-)
  • 그럼 아티스트들의 작업시간은? 그림자를 오프라인에서 baking 하지 않으니 빨라짐... (장점 #2).... 근데 그림자 품질이 오프라인 처리할 때보다 저하되서 다시 baking을 시작하고 있음.. (결국 장점 #2 실패 -_-)
  • 화면공간에서 하는 후처리 기법은? 저번 게임하고 그닥 달라진게 없음... SSAO 정도 추가했나? (미약한 장점 #3)
  • 반투명한 물체는? 화면의 절반... -_- 여전히 포워드로 처리함... 한 10 ms 걸림... 쿨럭 -_- (심각한 단점 #1)
  • 앤티에일리어싱은? 아직 구현 안했었음...  스페이스마린에서 사용한 AA를 구현해줬으니 게임자체의 색상이 화려한 편이라 흐릿함이 눈에 거슬림.... 이걸 제대로 고치려면 PC버전에서 쓰는 FXAA를 써서 3ms낭비하거나... 아니면 깊이 및 법선 비교까지 해야함. 이러면 2.6 ms 정도 걸림.... (단점 #2)

아무리 생각해도 디퍼드로 갈 이유가 없는 게임이더군요. 아직도 정확한 이유는 모릅니다. 왜 디퍼드로 가기로 결정했는지.... '이론상으로' 포워드보다 낫다고 생각했고... 새로운 기법에 대한 짜릿함 때문에 그렇게 결정해버린 게 아닌지.. 생각만 할뿐..... 처음 게임이 더 비주얼이 좋을 거 같아요......버럭!

대충 정리
글만 주저리주저리 길게 쓰는 놈이라.. 대충 이 일화의 교훈(?)을 정리.
  1. 새로운 기법을 도입하기 전에는 반드시 장/단점을 반드시 따져볼 것. 특히 단점을 위주로...
  2. 그 기법을 이용해서 게임을 출시한 사람들이 발표하는 장/단점은 언제나 장점에 치우쳐 있음. 단점의 심각함을 2배로 곱해서 생각할 것...
  3. 그 기법을 이용해 컨텐츠를 제작할 아티스트 및 디자이너들을 프로토타입 과정에 포함시킬 것. 그 개발자들의 피드백이 좋지 않으면 그 보다 큰 단점이 없음.
  4. measure, measure and measure!: 언제나 실제로 성능을 측정해볼 것....



2012년 1월 25일 수요일

디테일맵과 감마보정에 대한 뻘쭘 경험담


디퓨즈 맵에 디테일 맵을 곱하는 방법은 텍스처 타일링으로 인해 발생하는 반복패턴을 숨길 때 사용할 수 있는 좋은 방법입니다.

스페이스 마린을 제작하는 도중에도 아티스트의 요청에 따라 이런 일을 하는 쉐이더를 만든 적이 있는데요. (스페이스 마린에 들어가는 쉐이더는 거의 전부 제가 작성했음... Shader Guy = Pope 였다는...).  그 때 제가 사용했던 블렌딩(?) 공식은 다음과 같았습니다.


디퓨즈맵 * 디테일맵 * 2

마지막에 2를 곱해준 이유는 디퓨즈 맵보다 밝은 색을 만드는 것이 가능하게 하기 위해서였죠. (이게 없으면 쉐이더에서 구해오는 텍스처맵의 범위는 0 ~ 1(0~100%)이기 때문에 디퓨즈맵을 어둡게 만드는 효과밖에 없습니다.) 따라서 아티스트가 디테일맵을 50%  회색(0.5)으로 칠하면 최종결과는 디퓨즈맵의 색과 같게 됩니다.

이 방법이 한동안 아무 무리 없이 작동했었는데.. 그 후에 렌더링 엔진을 "감마 친화적"으로 만들면서 좀 이상해졌습니다. 텍스처를 읽어올 때 하드웨어 자체에서 sRGB 변환을 켜줬는데, 실수로 디테일맵을 읽어올 때도 자동변환 기능을 켜버린 거죠.... 그리고 한 두달이 지나는 동안 이 새로운 쉐이더를 이용한 몇몇 아트들이 탄생했죠.


이 쯤되서 기술력 위주의 아티스트 한 명이 디테일 텍스처의 값을 0.5로 설정하면 최종결과가 디퓨즈맵의 색보다 어두워진다는걸 발견했습니다.... 아뿔싸.... 그 이유는 하드웨어에서 자동으로 sRGB -> Linear 변환을 사용한 결과 저희 공식이 이따위가 되었기 때문이지요.


{ (디퓨즈맵 ^ 2.2) * (디테일맵 ^ 2.2) * 2 } ^ (1/2.2)

0.5에 2.2 제곱을 하면 이 값이 0.25 보다도 작아지기 때문에 여기에 2를 곱해도 50프로보다도 더 어두워지기 때문.... 고치는 건 간단했습니다. 디테일맵을 읽어올때 자동 sRGB 변환을 꺼줬죠. 이래서 블렌딩 연산이 다음과 같이 되었습니다.

{ (디퓨즈맵 ^ 2.2) * 디테일맵 * 2 } ^ (1/2.2)

훨 낫죠?

이제 쉬운건 끝났고.. 그 다음은 아티스트들에게 지난 한두달 동안 이 쉐이더를 이용해서 만든 아트들을 다시 고쳐달라고 할 차례였죠. 뭐, 그리 무리한 요구는 아니였습니다. 지난 한 두달간 새로 만든 아트가 몇 안되었거든요. 디테일맵을 고치는 방법은 매우 간단했습니다.
  1. 포토샵에서 디테일 맵을 연다.
  2. 메인 메뉴에서 Image > Adjustment > Exposure를 선택한다.
  3. gamma를 0.454545(1 / 2.2와 같음)로 정해준다.
  4. OK를 누른다.
하지만 이번에는 시각위주의 아티스트가 디테일맵 대신 디퓨즈맵을 바꾸고 싶다고 하더군요. 디테일맵의 감마를 고쳐주니까 너무 어둡게 보여서 작업하는데 힘드시다고... 기존에 있던 디퓨즈맵을 새로운 공식에 맞게 고칠 수 있는 방법을 알려달라더군요. 위에서 디테일맵을 간단히 바꿀수 있었듯이... 그래서 곰곰히 생각해봤는데 수학적으로 옳게 변환을 할 수 있는 방법이 딱히 안떠오르더군요. 그래서.... '직접 눈으로 결과를 확인하시면서 변환을 하셔야 할 것 같네요. 죄송합니다~'라고 해드릴 수밖에 없었던 일이 있습니다.

뒤돌아보면 이게 수학적으로 옳은 것이 아티스트의 삶을 좀더 평안하게 만들 수 있었던 흔치않던 경우라고 생각하는데요... 뭐 불행히도 디퓨즈맵을 변환하는 공식을 찾을 수 없었으니... 제가 멍청한 건지도 모르지만 일단 불가능하다고 생각...

혹시 이거 할 수 있는 공식 아시는분은 연락주세요 ^^