GPU에서 공유 정점 법선 만들기


9

나는 주로 Marching Cubes의 구현을 CPU에서 OpenGL 컴퓨팅 쉐이더로 이식하는 데 성공했지만 아직 법선을 다루지 않았으며 그것에 대해 가장 좋은 방법을 궁금해했습니다.

내 구현은 특히 이진 값 필드를 다루고 있습니다 (아직 거리 추정 기가없는 3D 프랙탈 함수를 모델링하려고합니다). 그라디언트 및 앞으로 차이 방법은 작동하지 않습니다. 나는 정점을 공유하고 있으며 CPU 구현은 여기 에 설명 된 Quilez의 방법을 사용 하여 각 인접 정점에 얼굴 법선을 축적합니다.

이 구현을 다른 셰이더로 이식 할 수는 있지만, 이것으로 볼 수있는 문제는 필요한 수많은 원자입니다. 우리는 스칼라 정수 유형에서만 원자를 사용할 수 있고 3 개의 부호있는 정수를 1로 요약 할 수있는 방법을 생각할 수 없으므로 쉐이더 호출 당 3 개의 축 * 3 개의 정점 = 9 개의 원자가 추가됩니다. 그것들은 물론 메모리 전체에 퍼져서 단일 원자 카운터를 9 번 누르는 것과 같지 않지만 여전히 많은 지옥처럼 보입니다.

다른 대안은 폴리곤마다 쉐이더 호출을 실행하고면 법선 목록을 작성하는 것입니다 (아마도이 ​​방법으로 x10y10z10으로 압축 할 수 있음). 정점 당 쉐이더는 이웃 얼굴의 모든 법선을 축적합니다. 이것은 거대한 메모리 호그 일 것입니다. 얼굴 인덱스의 저장 공간은 최악의 경우를 처리하기 위해 정점 당 12 int가 필요합니다. 또한 특정 정점에 이미 몇 개의면이 쓰여 졌는지 알아 내기 위해 원자에 의지하지 않고이 저장소에 쓰는 방법에 대한 문제도 있습니다.

이 작업을 수행하는 방법에 대한 더 나은 아이디어가 있습니까?

답변:


5

nVidia 전용 솔루션의 경우 NvInterlockedAddFp32와 같은 부동 소수점 원자 추가 내장 함수를 사용할 수 있습니다 . HLSL에서 GPU 내장 잠금 해제 | 엔비디아 개발자

80.000 버텍스 메시에서 이것을 시도했는데 매우 빠릅니다 (정확하게 기억한다면 GTX980M에서 1 또는 2 ms와 같은 것)

내장 기능이 작동하도록 릴리스에서 셰이더를 컴파일하는 것에주의하십시오 (Nvidia 버그 / 제한으로 인해)

또한 정점 분할 (예 : UV 불연속으로 인해)에주의해야합니다 (예 : UV 불연속으로 인해).


질문이 오래 되었기 때문에 대신 물어볼 것입니다 :-) 각 정점에 대한 단순 정보를 갖는 것이 rus에 충분하지 않다는 것을 이해합니다.
— Andreas

이것은 작년 내 논문 프로젝트를위한 것이었고, 나는 바보 같은 방식으로 정수 원자 추가를 사용하고 정밀도를 최대화하기 위해 확장 된 다음 부동 벡터로 정규화했습니다. 최악의 공간을 할당하지 않고 원자 카운터를 사용하여 목록을 작성하지 않고 각 정점 주위의면을 나열하는 방법을 알 수 없었습니다. 그것은 지옥으로 아마 비효율적하지만 난 아직도 내가 :) 그것으로 행복 충분했다 있도록 CPU 버전과 일류 마크에서 크기 속도 향상의 주문 몇있어
— 러스
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.