유머천국 코하비닷컴
https://cohabe.com/sisa/2415382

게임 개발자가 수학을 잘해야하는 이유


Screenshot_2021-02-24 EARLY GAME MADNESS - CREEPER WORLD 4.png




이것이 뭐냐하면 퀘이크 3 소스코드에 있는 함수다


정확히는 Screenshot_2021-02-25 Desmos 그래핑 계산기.png를 계산하는 함수인데, 광원 효과에 쓰이는 함수라서 굉장히 빨라야 한다

(빛의 반사 계산하는 데 쓰는데, 단위벡터가 어쩌구 반사벡터가 저쩌구 하는 건 생략)

 

중요한 건 느리면 60 프레임을 못맞추고, 빨라도 값의 정확하지 않으면 빛이 이상하게 표현된다



나눗셈이랑 제곱근을 쓰는 방법은 정확한 대신 리소스도 많이 필요하고 줜나 느려서 60프레임을 못맞춘다


그래서 퀘이크 3 개발진은 저런 함수를 만들어 Screenshot_2021-02-25 Desmos 그래핑 계산기.png를 빠르고 정확하게 계산했다



 




일단 보면 주석에 왓더뻑이라고 적힌 것처럼 씨1발 이게 뭐야 어캐 하는건데 싶어진다


그래도 하나 하나 뜯어보면 이해가 되긴 된다



우선 맨 앞에 변수의 자료형 두 개가 나온다



Screenshot_2021-02-25 Fast Inverse Square Root — A Quake III Algorithm.png

 

long은 숫자를 이진법으로 00000000 00000000 00000000 00000000으로 표시한다


long형에서 특별히 봐야할 건 없으니 넘어가자








Screenshot_2021-02-25 Fast Inverse Square Root — A Quake III Algorithm(1).png



float은 소숫점을 포함한 실수를 0 00000000 00000000000000000000000으로 표현한다


첫 자리는 부호를 나타낸다

0이면 양수 또는 0, 1이면 음수를 뜻한다


뒤의 8자리는 지수(2E)를 나타낸다

E = -127를 00000000으로 하고 E = +128을 11111111로 사용한다

 

마지막 23자리는 가수부(M)를 나타낸다

이진법으로 1.00000000000000000000000부터 1.11111111111111111111111까지 소숫점을 나타내는 데 사용한다

 

 

 

 

 

 

Screenshot_2021-02-25 Fast Inverse Square Root — A Quake III Algorithm(2).png

 

float형을 수식으로 표현하면 이런 꼴이 된다

 

저 수식을 2의 로그로 감싸고 정리하면 Screenshot_2021-02-25 Desmos 그래핑 계산기(2).pngScreenshot_2021-02-25 Desmos 그래핑 계산기(1).png가 된다

 

뜬금없이 나온 뮤(μ)는 log2의 근사값을 구하는 데 쓰인 숫자다


1보다 작은 x에 대해 Screenshot_2021-02-25 Desmos 그래핑 계산기(3).png인데 적당한 수를 더하면(Screenshot_2021-02-25 Desmos 그래핑 계산기(3).png) 전반적인 정확도를 높일 수 있다


실험적으로 찾아낸 적절한 값은 μ≒0.0430357이다

참고: https://en.wikipedia.org/wiki/Fast_inverse_square_root#Aliasing_to_an_integer_as_an_approximate_logarithm

 



Screenshot_2021-02-25 Fast Inverse Square Root — A Quake III Algorithm(4).png



그런데 float형의 비트값은 E*223 + M 꼴의 형태가 되는 것을 알고 있다

(여기서 음수는 생각하지 않는다)


앞에서 구한 로그값이랑 비교하여 생각해보면 float형의 비트값을 그대로 하나의 정수로 생각하면 이 정수는 원래 값에 log2를 취한 것과 같다고 생각할 수 있다



변수 정의 뒤에 나오는 i = * ( long * ) &y; 가 바로 float형으로 받은 비트값을 그대로 숫자로 받는 줄인 것이다



Screenshot_2021-02-25 Fast Inverse Square Root — A Quake III Algorithm(5).png


어찌저찌하여 중간까지는 왔는데 그 다음 줄이 문제다


앞서 Screenshot_2021-02-25 Desmos 그래핑 계산기.png였고 Screenshot_2021-02-25 Desmos 그래핑 계산기(1).png를 구해야 하는데, 로그의 특성에 따라 Screenshot_2021-02-25 Desmos 그래핑 계산기(2).png가 된다!

 

 

그리고 이진수에서 오른쪽으로 비트를 이동(bit shift)하면 2로 나눈 것과 같은 효과를 얻는다


예를 들어 110(10진법으로 6)을 오른쪽으로 비트 이동시키면 11(10진법으로 3)이 된다


111(10진법으로 7)도 11(10진법으로 3)이 되는 문제가 있지만 어쩔 수 없이 받아들여야 한다

 


오른쪽으로 비트 이동이 >>니까 -0.5i는 -(i >> 1)이 된다


그러면 저 0x5f3759df(=1597463040)는 대체 뭔 수일까?





Screenshot_2021-02-25 Fast Inverse Square Root — A Quake III Algorithm(1).png

 

실제로 구해야 하는 해 Screenshot_2021-02-25 Desmos 그래핑 계산기(1).png를 감마(Γ)라고 하면 i와 Γ의 관계는 다음과 같다

 

Screenshot_2021-02-25 Desmos 그래핑 계산기(6).png

이걸 좀전에 봤던 Screenshot_2021-02-25 Desmos 그래핑 계산기(5).png꼴로 표현하면,

 


Screenshot_2021-02-25 Desmos 그래핑 계산기(3).png

정리하면,

 

Screenshot_2021-02-25 Desmos 그래핑 계산기(4).png

 



값을 계산하면, 3/2 * 223 * (127-μ) = 1597488309.57 ≒1597463040 = 0x5f3759df

 

그렇다, 오차를 보정하는 값이 바로 저 0x5f3759df였던 거다!

 

 

값을 다 구했으니 구한 값을 float형으로 되돌리고 → y = * (float *) &i;

 

f(x) = 0을 정확하게 구할 때 쓰는 뉴턴-랩슨법을 이용해 정확도를 높여주면 → y = y * (threehalfs - (x2 * y * y));



그리하여 나눗셈도, 제곱근 계산도 없이 포인트 참조, 비트 이동, 뺄셈, 그리고 곱하기만 가지고 빠르고 비교적 정확하게 Screenshot_2021-02-25 Desmos 그래핑 계산기(1).png를 구할 수 있었다!





 




댓글
  • 금어린이 2022/04/05 14:54

    아니 댓글에 달려야 할 짤을
    작성자가 다 해먹으면 우리는 뭘 올려야 합니까.

  • Azathoth 2022/04/05 14:59

    주석의 왓더뻑은 코드를 복붙한 존 카멕이 달아놓은것이다

  • 철학도 릴리 2022/04/05 14:57

    고속 역 제곱근 이라고 불리는 코드인데
    0x5f3759df은 그냥 매직 넘버라고 불리더라 ㅋㅋㅋ
    처음에 c언어 배울때 비트이동 연산자는 어따 쓰는 건지 싶었는데
    이거 보고 감탄함 ㅋㅋㅋ

  • 나일론마스크 2022/04/05 14:56

    물론 적절한 라이브러리를 잘 쓰는것도 실력이다

  • 디바이드로끌려간NCR말년병장 2022/04/05 15:01

    아니 트리비아까지 다해쳐먹네. 너 이거 반독점법 위반이야.

  • 보드카★ 2022/04/05 14:56

    하지만 현대 게임들은 저런거 몰라도 최소사양을 올리면 해결!


  • 금어린이
    2022/04/05 14:54

    아니 댓글에 달려야 할 짤을
    작성자가 다 해먹으면 우리는 뭘 올려야 합니까.

    (dnOJoM)


  • Azathoth
    2022/04/05 14:59

    주석의 왓더뻑은 코드를 복붙한 존 카멕이 달아놓은것이다

    (dnOJoM)


  • 디바이드로끌려간NCR말년병장
    2022/04/05 15:01

    아니 트리비아까지 다해쳐먹네. 너 이거 반독점법 위반이야.

    (dnOJoM)


  • 데드풀!
    2022/04/05 15:03

    아이고 작성자가 다 해먹네 이게 나라냐
    황달은 사퇴해라

    (dnOJoM)


  • 와사미의 여자
    2022/04/05 14:54

    아 그래서 이 라이브러리가 좋다는거죠? ㄱㅅ

    (dnOJoM)


  • 나일론마스크
    2022/04/05 14:56

    물론 적절한 라이브러리를 잘 쓰는것도 실력이다

    (dnOJoM)


  • Azathoth
    2022/04/05 14:58

    지금은 더 좋은게 있어서 저거 안쓴다더라

    (dnOJoM)


  • 코크럴
    2022/04/05 15:02

    그럼 지금 쓰는 것도 알려줘

    (dnOJoM)


  • Azathoth
    2022/04/05 15:05

    https://ko.wikipedia.org/wiki/%EA%B3%A0%EC%86%8D_%EC%97%AD_%EC%A0%9C%EA%B3%B1%EA%B7%BC
    "이 알고리즘은 뉴턴의 방법을 사용하여 비교적 정확한 결과를 만들어 내지만, 소수점의 손실 때문에 부정확하고 1999년부터 도입된 x86 SSE의 rsqrtss에 비해 훨씬 느리다."

    (dnOJoM)


  • 루리웹-5994867479
    2022/04/05 14:55

    아ㅋㅋㅋ 유저들의 컴 사양에 떠넘기면 될걸 애쓰네ㅋㅋㅋㅋㅋ

    (dnOJoM)


  • 보드카★
    2022/04/05 14:56

    하지만 현대 게임들은 저런거 몰라도 최소사양을 올리면 해결!

    (dnOJoM)


  • 안드로스
    2022/04/05 14:57

    거 머신파워로 해결봅시다

    (dnOJoM)


  • 철학도 릴리
    2022/04/05 14:57

    고속 역 제곱근 이라고 불리는 코드인데
    0x5f3759df은 그냥 매직 넘버라고 불리더라 ㅋㅋㅋ
    처음에 c언어 배울때 비트이동 연산자는 어따 쓰는 건지 싶었는데
    이거 보고 감탄함 ㅋㅋㅋ

    (dnOJoM)


  • 쁠랙빤서
    2022/04/05 15:00

    그래서, 개발자인 지금의 삶은 행복하신가요?

    (dnOJoM)


  • 4701778
    2022/04/05 15:01

    호에엥 저게 뭐야 무서워
    언리얼 해줘

    (dnOJoM)


  • 루리웹-2618503929
    2022/04/05 15:02

    요즘 컴퓨터는 충분히 빨라서 저런건 오히려 안하는게 좋음
    저런수준의 최적화를 하면 다음 사람이 건드릴때 비용이 미친듯이 뛰어버림
    코드의 가독성을 버리고 하는 최적화는 양날의 검임

    (dnOJoM)


  • baddude
    2022/04/05 15:02

    에잇, 수학하는 놈들 저리 꺼져라 꺼져

    (dnOJoM)


  • 요리왕 비룡
    2022/04/05 15:02

    뭔소리여

    (dnOJoM)


  • noname72620
    2022/04/05 15:03

    와드

    (dnOJoM)


  • 方外士
    2022/04/05 15:03

    망할 이과 새기들
    고마워요..!!

    (dnOJoM)


  • Mintjoa
    2022/04/05 15:03

    보기만해도 어질어질해진다..

    (dnOJoM)


  • 127.0.0.1
    2022/04/05 15:04

    문제 대부분은 라이브러리 잘 쓰고 하면 해결되는데
    그럼에도 중고등학교때 수학 포기한애들이 프로그래머 하겠다는 생각을 버려야하는 이유는
    실무에 수학이 필요하냐 아니냐를 떠나서 프로그램을 만드는 과정은 논리를 타이핑으로 표현해내는 과정인데 수학 또한 논리의 학문이라는것이다.
    중고등학교 수학문제 수준의 논리에서 뻗으면...

    (dnOJoM)


  • 블랙미노타우르스
    2022/04/05 15:04

    주석이 정확하네

    (dnOJoM)


  • 고구마구이
    2022/04/05 15:04

    엑셀 함수만 써봐도 수학 나름 해야하는데 프로그래머라면 더욱더 그래야지..

    (dnOJoM)


  • 이삭루리아
    2022/04/05 15:05

    간단하게 슈팅게임 만들때도 수학이 이리 ㅈ 같이 많은줄 몰랐지
    그 이후로 게임 만드는것 극혐함...

    (dnOJoM)


  • 격투기궁금하면물어봐
    2022/04/05 15:05

    전체 공격력 = {[(무기 최소 데미지 + 악세사리의 최소피해 or 피해 옵션의 낮은값의 합) + (무기 최대 데미지 + 악세사리의 최대피해 or 피해 옵션의 높은값의 합)] / 2 } x 무기 고유 공속 X (1+아이템 공속증가들의 합) x (1+주 스탯) x (1+극확X극피) X ( 1+ 정예에게 주는 대미지 등등 ) X ( 1+ 아이템으로 증가하는 대미지) X ( 1+ 액티브 스킬로 증가하는 대미지) X ( 1+ 자기 버프로 증가하는 대미지 ) X ( 1 + 다른 사람의 버프로 증가하는 대미지 ) X ( 1+ 패시브 스킬로 증가하는 대미지 ) X ( 기타 증가하는 대미지. 광분 신단 등등등 )
    대충 디아블로 데미지 계산식

    (dnOJoM)


  • 루리웹-8954325234
    2022/04/05 15:05

    구글신과 msdn이 해결해 줄거야!

    (dnOJoM)

(dnOJoM)