정확히는
를 계산하는 함수인데, 광원 효과에 쓰이는 함수라서 굉장히 빨라야 한다
중요한 건 느리면 60 프레임을 못맞추고, 빨라도 값의 정확하지 않으면 빛이 이상하게 표현된다
나눗셈이랑 제곱근을 쓰는 방법은 정확한 대신 리소스도 많이 필요하고 줜나 느려서 60프레임을 못맞춘다
그래서 퀘이크 3 개발진은 저런 함수를 만들어
를 빠르고 정확하게 계산했다
일단 보면 주석에 왓더뻑이라고 적힌 것처럼 씨1발 이게 뭐야 어캐 하는건데 싶어진다
그래도 하나 하나 뜯어보면 이해가 되긴 된다
우선 맨 앞에 변수의 자료형 두 개가 나온다
long은 숫자를 이진법으로 00000000 00000000 00000000 00000000으로 표시한다
long형에서 특별히 봐야할 건 없으니 넘어가자
float은 소숫점을 포함한 실수를 0 00000000 00000000000000000000000으로 표현한다
첫 자리는 부호를 나타낸다
0이면 양수 또는 0, 1이면 음수를 뜻한다
뒤의 8자리는 지수(2E)를 나타낸다
E = -127를 00000000으로 하고 E = +128을 11111111로 사용한다
마지막 23자리는 가수부(M)를 나타낸다
이진법으로 1.00000000000000000000000부터 1.11111111111111111111111까지 소숫점을 나타내는 데 사용한다
float형을 수식으로 표현하면 이런 꼴이 된다
뜬금없이 나온 뮤(μ)는 log2의 근사값을 구하는 데 쓰인 숫자다
1보다 작은 x에 대해
인데 적당한 수를 더하면(
) 전반적인 정확도를 높일 수 있다
실험적으로 찾아낸 적절한 값은 μ≒0.0430357이다
그런데 float형의 비트값은 E*223 + M 꼴의 형태가 되는 것을 알고 있다
(여기서 음수는 생각하지 않는다)
앞에서 구한 로그값이랑 비교하여 생각해보면 float형의 비트값을 그대로 하나의 정수로 생각하면 이 정수는 원래 값에 log2를 취한 것과 같다고 생각할 수 있다
변수 정의 뒤에 나오는 i = * ( long * ) &y; 가 바로 float형으로 받은 비트값을 그대로 숫자로 받는 줄인 것이다
어찌저찌하여 중간까지는 왔는데 그 다음 줄이 문제다
앞서
였고
를 구해야 하는데, 로그의 특성에 따라
가 된다!
그리고 이진수에서 오른쪽으로 비트를 이동(bit shift)하면 2로 나눈 것과 같은 효과를 얻는다
예를 들어 110(10진법으로 6)을 오른쪽으로 비트 이동시키면 11(10진법으로 3)이 된다
111(10진법으로 7)도 11(10진법으로 3)이 되는 문제가 있지만 어쩔 수 없이 받아들여야 한다
오른쪽으로 비트 이동이 >>니까 -0.5i는 -(i >> 1)이 된다
그러면 저 0x5f3759df(=1597463040)는 대체 뭔 수일까?
실제로 구해야 하는 해
를 감마(Γ)라고 하면 i와 Γ의 관계는 다음과 같다
정리하면,
값을 계산하면, 3/2 * 223 * (127-μ) = 1597488309.57 ≒1597463040 = 0x5f3759df
그렇다, 오차를 보정하는 값이 바로 저 0x5f3759df였던 거다!
값을 다 구했으니 구한 값을 float형으로 되돌리고 → y = * (float *) &i;
f(x) = 0을 정확하게 구할 때 쓰는 뉴턴-랩슨법을 이용해 정확도를 높여주면 → y = y * (threehalfs - (x2 * y * y));
그리하여 나눗셈도, 제곱근 계산도 없이 포인트 참조, 비트 이동, 뺄셈, 그리고 곱하기만 가지고 빠르고 비교적 정확하게
를 구할 수 있었다!














(IP보기클릭)125.179.***.***
(IP보기클릭)116.47.***.***
??? 나 겜 만들거니까 수학 안해도 됨 ㅋㅋ!
(IP보기클릭)183.100.***.***
(IP보기클릭)118.235.***.***
이과도 알아먹게 설명해 주시겠습니까?
(IP보기클릭)61.74.***.***
그래서 프로 글래머들은 어디에 있죠
(IP보기클릭)222.233.***.***
(IP보기클릭)1.1.***.***
바카밧카!! 게시글 내용이 뭐길래 분석을 해달래? 내가 탐정이냐? 좀 더 구체적으로 말해봐! 👀🔍
(IP보기클릭)61.74.***.***
그래서 프로 글래머들은 어디에 있죠
(IP보기클릭)183.100.***.***
(IP보기클릭)110.46.***.***
로마군이 출동했으니 안심하십시오 | 25.02.09 16:47 | | |
(IP보기클릭)222.233.***.***
(IP보기클릭)125.179.***.***
(IP보기클릭)218.149.***.***
그거야 자연은 대화하지 않으니 뭐 ㅋㅋㅋㅋㅋㅋㅋ 우짤수 없지 | 25.02.09 16:49 | | |
(IP보기클릭)175.199.***.***
(IP보기클릭)112.186.***.***
(IP보기클릭)121.157.***.***
컴퓨터 자료형을 이용한 트릭임. 컴퓨터는 어차피 모든 숫자를 2진법으로 근사한다는 점에 착안해서 애초에 2진법으로 표현하느라 이미 계산된 부분은 건너띄어버리고, 나머지 부분은 2진법으로 근사값을 구하게 하고 오류는 적당히 보정하는거. 총쏘는 와중 화면 픽셀단위로 RGB 따져가며 빛 계산이 이상하냐니 이딴 소리 할 플레이어는 없을테니 어차피 보는데 어색하지 않으면 장땡이니까. 물론 원리는 알겠는데 그래서 왜 저런지는 나도 모르겠다. 발상이 진짜 미친거 같아... | 25.02.09 16:59 | | |
(IP보기클릭)112.186.***.***
지금은 하드웨어 성능이 좋아져서 오히려 이 코드 쓰지 마라고 들었던거 같은ㄷㄷ | 25.02.09 17:02 | | |
(IP보기클릭)121.157.***.***
저땐 퍼스널컴 시퓨의 실수형 자료 계산능력이 형편 없어서 표준 수학 라이브러리의 폴리필이 온갖 삽질을 했음. 예를들어 루트 계산해주는 명령어가 없는 시퓨를 위해 실수를 0이 될때까지 무작정 2로 나누어본다. 이딴식으로 구현하지. 그러니 당시에는 저게 대개의 경우 훨씬 빠른 코드였음. 근데 세월이 흐르며 고급 실수 계산 명령어들이 보편화 되면서 저게 오히려 더 느린 코드가 되어버림. 그 외에도 저 당시 게임들은 실수를 정수로 근사시켜서 계산하는 뻘짓을 많이 했음. 당연히 표준 수학라이브러리랑 호환이 안 되기 때문에, 자체 제작 수학 모듈을 따로 만들어야 했음. 심지어 3D 좌표도 그런 마법을 부려야 겨우 퍼스널컴에서 실시간으로 돌릴 수 있는 게임이 나왔지. 예를들어 스타크래프트랑 비슷한 시기에 나온 토탈어나힐레이션이라는 게임이 있는데 내부 물리가 3차원 좌표였고 그래픽도 맵이랑 스프라이트 제외하고 3D였거든? 근데 좌표를 죄다 정수로 근사시켜서 계산함. 예를 들어 각도는 0-2PI를 0~65535 이런식으로... 그래서 오늘날 퍼스널컴에서는 그냥 실수형 써서 대충 만든 게임보다 되려 굉장히 비효율적으로 느린 게임이 되었음. 저것도 마찬가지겠지. | 25.02.09 18:17 | | |
(IP보기클릭)116.47.***.***
??? 나 겜 만들거니까 수학 안해도 됨 ㅋㅋ!
(IP보기클릭)175.202.***.***
...
(IP보기클릭)121.135.***.***
(IP보기클릭)1.1.***.***
니가가라폭포
바카밧카!! 게시글 내용이 뭐길래 분석을 해달래? 내가 탐정이냐? 좀 더 구체적으로 말해봐! 👀🔍 | 25.02.09 16:46 | | |
(IP보기클릭)1.239.***.***
(IP보기클릭)114.199.***.***
(IP보기클릭)118.235.***.***
이과도 알아먹게 설명해 주시겠습니까?
(IP보기클릭)59.29.***.***
최적화 레이트레이싱 함수 | 25.02.09 16:47 | | |
삭제된 댓글입니다.
(IP보기클릭)119.192.***.***
루리웹-4672534900
산셍님 제가 아는 한줄의 의미와 선생님이 아는 한줄의 의미가 조금 차이가 있는 것 같습니다. | 25.02.09 16:49 | | |
(IP보기클릭)58.230.***.***
(IP보기클릭)118.235.***.***
(IP보기클릭)14.36.***.***
저런거 보면 난 영원히 코드싸개로 남을 듯 | 25.02.09 16:56 | | |
(IP보기클릭)36.248.***.***
(IP보기클릭)36.248.***.***
버그걸렸냐 왜 안말해 | 25.02.09 16:49 | | |
(IP보기클릭)1.1.***.***
바카밧카!! 네가 직접 찾아볼래? 하지만 굳이 알려주자면, 기본적인 방향광 코드는 이거야: ```cpp FDirectionalLightComponent* CreateDirectionalLight(AActor* Owner) { FDirectionalLightComponent* LightComponent = Owner->CreateComponent<FDirectionalLightComponent>(); if (LightComponent) { LightComponent->SetLightColor(FLinearColor::White); // 색상 설정 LightComponent->SetIntensity(1.0f); // 밝기 설정 LightComponent->SetCastShadows(true); // 그림자 생성 여부 // 방향 설정 등 추가 속성은 필요에 따라 조정 } return LightComponent; } ``` 점광이나 스포트라이트도 비슷한 방식으로, 타입만 바꿔줘. 네가 직접 좀 더 찾아보는 게 어때? 흥! 🌟💡 | 25.02.09 16:49 | | |
(IP보기클릭)119.192.***.***
(IP보기클릭)121.140.***.***
(IP보기클릭)175.116.***.***
| 25.02.09 16:49 | | |
(IP보기클릭)112.186.***.***
이 짤에서 한심한 것으로 나오던 애는 후에 개조 나오면서 지상 최강의 mg가 된다던ㅎㅎ | 25.02.09 17:04 | | |
(IP보기클릭)110.46.***.***
(IP보기클릭)175.116.***.***
(IP보기클릭)183.105.***.***
(IP보기클릭)183.105.***.***
요즘에 저러라 하면 에이 C8소리나오지 ㅋㅋㅋㅋㅋㅋㅋ | 25.02.09 16:51 | | |
(IP보기클릭)219.250.***.***
그래픽관련 최적화에선 비슷한거 해요 ㅋㅋㅋ | 25.02.09 16:56 | | |
(IP보기클릭)183.105.***.***
아 그건 그런데 처음부터 깡으로 저러진 않을꺼라 뭐 그런말 .. | 25.02.09 16:59 | | |
(IP보기클릭)223.38.***.***
(IP보기클릭)121.175.***.***
(IP보기클릭)121.146.***.***
(IP보기클릭)218.157.***.***
(IP보기클릭)221.149.***.***
(IP보기클릭)114.202.***.***
(IP보기클릭)126.171.***.***
(IP보기클릭)59.11.***.***