DirectX에서 두께가 다양한 AA로 선을 렌더링하는 가장 빠른 방법


14

그래서 .NET에서 SharpDX를 사용하여 DirectX 개발을 수행하고 있습니다 (그러나 DirectX / C ++ API 솔루션이 적용 가능합니다). DirectX를 사용하여 직교 투영 (예 : 과학 응용 프로그램의 2D 선 그리기 시뮬레이션)에서 선을 렌더링하는 가장 빠른 방법을 찾고 있습니다.

렌더링하려는 플롯 종류의 스크린 샷은 다음과 같습니다. 여기에 이미지 설명을 입력하십시오

이러한 종류의 플롯이 라인 당 앤티 앨리어싱 (또는 전체 화면 AA 켜기 / 끄기)이 있거나없는 수백만 개의 세그먼트, 가변 두께의 라인을 갖는 것은 드문 일이 아닙니다. 선의 꼭짓점을 매우 자주 (예 : 20 회 / 초) 업데이트하고 가능한 한 GPU로 오프로드해야합니다.

지금까지 나는 시도했다 :

  1. 소프트웨어 렌더링, 예를 들어 GDI +는 실제로 성능이 좋지 않지만 CPU에서 분명히 무겁습니다.
  2. Direct2D API-특히 앤티 앨리어싱을 사용하는 경우 GDI보다 느립니다.
  3. 이 방법을 사용하여 Direct3D10 은 CPU 측에서 정점 색상 및 공간 분할을 사용하여 AA를 에뮬레이션 합니다. 또한 느리게 (프로필을 작성했으며 정점 위치를 계산하는 데 80 %의 시간이 소요됨)

세 번째 방법에서는 정점 버퍼를 사용하여 삼각형 스트립을 GPU에 보내고 200ms마다 새로운 정점으로 업데이트합니다. 100,000 개의 선 세그먼트에 대해 약 5FPS의 화면 주사율을 얻고 있습니다. 이상적으로 수백만이 필요합니다!

이제 가장 빠른 방법은 예를 들어 Geometry Shader와 같은 GPU에서 테셀레이션을 수행하는 것입니다. 정점을 라인리스트로 보내거나 텍스처로 묶고 Geometry Shader에서 압축을 풀어 쿼드를 만들 수 있습니다. 또는 픽셀 쉐이더에 원점을 보내고 Bresenham Line drawing을 픽셀 쉐이더로 구현하십시오. 내 HLSL은 2006 년부터 녹슨 쉐이더 모델 2이므로 현대 GPU가 할 수있는 미친 것들에 대해 잘 모릅니다.

그래서 질문은 :-누구든지 전에 이것을 한 적이 있습니까, 시도해 볼 제안이 있습니까? -지오메트리를 빠르게 업데이트하여 성능을 개선 할 수있는 제안이 있습니까 (예 : 20ms마다 새로운 정점 목록)?

1 월 21 일 업데이트

이후 LineStrip 및 Dynamic Vertex Buffers를 사용하여 Geometry 쉐이더를 사용하여 위의 방법 (3)을 구현했습니다. 이제 100k 포인트에서 100FPS를, 1,000,000 포인트에서 10FPS를 얻습니다. 이것은 크게 개선되었지만 이제는 채우기 속도와 계산이 제한되어 있으므로 다른 기술 / 아이디어에 대해 생각했습니다.

  • 라인 세그먼트 형상의 하드웨어 인스 턴싱은 어떻습니까?
  • 스프라이트 배치는 어떻습니까?
  • 다른 (픽셀 셰이더) 지향 방법은 어떻습니까?
  • GPU 또는 CPU를 효율적으로 제거 할 수 있습니까?

귀하의 의견 및 제안에 감사드립니다!


1
Direct3D의 네이티브 AA는 어떻습니까?
API-Beast

5
플롯하고자하는 몇 가지 예제 곡선을 보여줄 수 있습니까? 백만 개의 정점을 언급했지만 화면에 백만 개 이상의 픽셀 이 없을 것 입니다. 수량이 실제로 필요한가요? 모든 데이터 밀도가 어디에서나 필요하지 않은 것 같습니다. LOD를 고려 했습니까?
sam hocevar

1
두 번째로 연결 한 방법이 좋을 것 같습니다. 업데이트하는 동적 정점 버퍼를 사용하고 있습니까, 아니면 매번 새 것을 작성합니까?

1
동적 정점 버퍼를 사용해야합니다 (많은 작업은 아니지만 정점 버퍼를 동적으로 지정하고 버퍼를 매핑하며 데이터를 복사하고 매핑을 해제하십시오).하지만 병목 현상이 처음에 정점 생성이라면 아마도 지금 많은 도움이되지 않습니다. GS를 사용하여 CPU에 부담을 덜어주는 것에 대해 화난 생각은 없다

1
정점 수가 GPU에 비해 ​​너무 큰 경우에도 입력을 다운 샘플링하려고 시도 할 수 있습니다. 화면 너비가 수천 픽셀이 될 때 단일 곡선에 실제로 수억 줄의 세그먼트가 필요하지 않습니다. 많으면.

답변:


16

Y = f(X)그래프 만 렌더링 하려면 다음 방법을 시도해보십시오.

커브 데이터는 텍스처 데이터 로 전달되어 지속성을 유지하고 glTexSubImage2D예를 들어 부분 업데이트 가 가능합니다. 스크롤이 필요한 경우 순환 버퍼를 구현하고 프레임 당 몇 개의 값만 업데이트 할 수 있습니다. 각 곡선은 전체 화면 쿼드 로 렌더링되며 모든 작업은 픽셀 셰이더에 의해 수행됩니다.

단일 구성 요소 텍스처 내용은 다음과 같습니다.

+----+----+----+----+
| 12 | 10 |  5 | .. | values for curve #1
+----+----+----+----+
| 55 | 83 | 87 | .. | values for curve #2
+----+----+----+----+

픽셀 쉐이더의 작업은 다음과 같습니다.

  • 데이터 세트 공간에서 현재 조각의 X 좌표를 찾습니다.
  • 예를 들어. 데이터가있는 가장 가까운 4 개의 데이터 포인트; 예를 들어 X 값 인 경우 41.3는 선택할 것 40, 41, 4243.
  • 4 Y 값에 대한 텍스처 쿼리
  • X,Y쌍을 화면 공간으로 변환
  • 현재 조각에서 세 개의 세그먼트네 개의 점 까지의 거리 계산
  • 거리를 현재 조각의 알파 값으로 사용

잠재적 인 줌 레벨에 따라 4를 더 큰 값으로 대체 할 수 있습니다.

이 기능을 구현 하는 매우 빠르고 더러운 GLSL 쉐이더를 작성했습니다 . 나중에 HLSL 버전을 추가 할 수도 있지만 너무 많은 노력없이 변환 할 수 있어야합니다. 라인 크기와 데이터 밀도가 다른 결과를 아래에서 볼 수 있습니다.

곡선

한 가지 분명한 이점은 전송되는 데이터의 양이 매우 적고 드로우 콜의 수가 단 하나라는 것입니다.


정말 멋진 기술입니다. 텍스처로 데이터를 패킹하는 것은 내가 아는 것이지만 이것에 대해 고려한 것은 아닙니다. 가장 큰 크기 (예 : 업로드 할 수있는 가장 큰 데이터 집합)는 무엇입니까? 마음에 들지 않으면 코드를 다운로드 할 수 있습니다. 성능을보고 싶습니다.
ABT 박사

@ Dr.ABT 데이터 셋 크기는 최대 텍스처 크기에 의해서만 제한됩니다. 적절한 데이터 레이아웃이 주어지면 왜 수백만 점이 작동하지 않는지 알 수 없습니다. 내 코드는 확실히 프로덕션 품질이 아니지만 문제가 있으면 개인적으로 저에게 연락하십시오.
sam hocevar

건배 @SamHocevar-나는 그것을 줄 것이다. OpenGL 예제 마인드를 컴파일 한 지 오래되었습니다! :-)
ABT 박사

텍스처로드를 사용하지 않더라도 답변으로 표시하면 픽셀 셰이더에 선을 그릴 수 있고 올바른 방향으로 놓을 수있는 실제 OpenGL 예제를 제시했습니다. :)
ABT 박사

4

앤티 앨리어싱 라인 렌더링에 대한 GPU Gems 장이 있습니다 : 빠른 사전 필터링 된 라인 . 기본 아이디어는 각 선분을 쿼드로 렌더링하고 각 픽셀에서 선분으로부터 픽셀 중심 거리의 가우스 함수를 계산하는 것입니다.

이것은 그래프의 각 선분을 별도의 쿼드로 그리는 것을 의미하지만 D3D11에서는 기하학 쉐이더 및 / 또는 인스 턴싱을 사용하여 쿼드를 생성하여 GPU로 전송되는 데이터의 양을 데이터 포인트로 줄일 수 있습니다 그들 자신. 아마도 정점 / 기하학 셰이더가 읽을 데이터 포인트를 StructuredBuffer 로 설정 한 다음 그릴 세그먼트 수를 지정하는 그리기 호출을 수행합니다. 실제 정점 버퍼는 없습니다. 정점 셰이더는 SV_VertexID 또는 SV_InstanceID를 사용하여 볼 데이터 포인트를 결정합니다.


고마워-네, 아쉽게도 그 기사를 알고 있습니다. 불행히도 소스 코드가 없습니다 :-( GeoShader + FragShader의 전제는 이러한 유형의 작업에서 승자로 보입니다. GPU에 데이터를 효율적으로 얻는 것은 까다로운 부분
ABT 박사

Hey @NathanReed 이것으로 돌아가서-Geometry Shader 또는 인스턴스를 사용하여 쿼드를 그리는 경우 Point1 / Point2가 쿼드의 정점과 반대 인 경우 Pixel Shader에서 Pt1과 Pt2 사이의 선까지의 거리를 어떻게 계산할 수 있습니까? 픽셀 쉐이더에 입력 지오메트리에 대한 지식이 있습니까?
ABT 박사

@ Dr.ABT 수학적 행의 매개 변수는 보간기를 통해 픽셀 쉐이더로 전송되어야합니다. 픽셀 셰이더는 형상에 직접 액세스 할 수 없습니다.
Nathan Reed

GeometryShader에서 출력을 보내거나 인스턴스화 하여이 작업을 수행 할 수 있습니까? 추가 크레딧 (관심이있는 경우)을 위해 Q를 추가했습니다 : gamedev.stackexchange.com/questions/47831/…
Dr. ABT

@ Dr.ABT 텍스처 좌표, 법선 벡터 및 모든 종류의 물건이 일반적으로 픽셀 쉐이더로 전송되는 것과 정확히 같은 방식으로 보간되고 픽셀 쉐이더에 입력되는 정점 / 형상 쉐이더의 출력을 작성합니다.
Nathan Reed

0

@ Dr.ABT-이것에 대한 사과는 대답이 아니라 질문입니다. 위의 Sam Hocevar의 답변 내에서 요청할 수있는 방법을 찾지 못했습니다.

차트의 선을 최종적으로 구현 한 방법에 대한 자세한 내용을 공유 할 수 있습니까? WPF 앱도 마찬가지입니다. 이것에 대해 공유 할 수있는 세부 사항이나 코드에 대해 미리 감사드립니다.


답변이 아님을 알고 계신 분은 편집하여 의견으로
MephistonX

나는 그것을 시도했지만 원래 게시물에 "댓글 추가"버튼이 없습니다.
ErcGeek

안녕하세요 ErcGeek, 죄송합니다.이 정보는 우리 회사의 재산이므로 최종 솔루션을 공유 할 수 없습니다. 위의 예제와 제안은 우리를 올바른 길로 안내합니다. 모두 제일 좋다!
Dr. ABT

일정 수준의 평판에 도달하기 전에는 의견을 게시 할 수 없습니다. 그리고이 모든 다운 보트는 그러한 기회를 제공하지 않을 것입니다.
Mathias Lykkegaard Lorenzen

그 사람은 최종 결과를 알고 그에게 가능한 유일한 방법으로 요구하기 때문에 처벌받지 않아야합니다. 답을 올렸습니다.
David Ching
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.