3D 공간에서 1 픽셀 너비의 선 그리기


10

카메라에서 얼마나 멀리 떨어져 있든 항상 화면에서 정확히 1 픽셀 너비 인 3D 공간에 선을 그리려고합니다. (단일 포인트에서도 동일).

내가 어떻게 할 수 있는지에 대한 힌트가 있습니까?

답변:


24

렌더링 선-방법 1 (기본)

3D 공간에서 간단한 선의 경우 LineList또는 LineStrip기본을 사용하여 선을 그릴 수 있습니다 . (0,0,0)에서 (0,0, -50)까지 선을 그리려면 빈 XNA 프로젝트에 추가해야하는 최소한의 코드가 있습니다. 카메라의 위치에 상관없이 선의 너비는 거의 같습니다.

// Inside your Game class
private BasicEffect basicEffect;
private Vector3 startPoint = new Vector3(0, 0, 0);
private Vector3 endPoint = new Vector3(0, 0, -50);

// Inside your Game.LoadContent method
basicEffect = new BasicEffect(GraphicsDevice);
basicEffect.View = Matrix.CreateLookAt(new Vector3(50, 50, 50), new Vector3(0, 0, 0), Vector3.Up);
basicEffect.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45f), GraphicsDevice.Viewport.AspectRatio, 1f, 1000f);

// Inside your Game.Draw method
basicEffect.CurrentTechnique.Passes[0].Apply();
var vertices = new[] { new VertexPositionColor(startPoint, Color.White),  new VertexPositionColor(endPoint, Color.White) };
GraphicsDevice.DrawUserPrimitives(PrimitiveType.LineList, vertices, 0, 1);

기본적으로 BasicEffect뷰 및 프로젝션 변환을 유지하기 위해 간단한 것을 만들고 두 정점 (저장 위치 및 색상)을 GraphicsDevice.DrawUserPrimitives메서드로 전달하여로 렌더링했습니다 LineList.

물론 최적화하는 방법에는 여러 가지가 있으며, 대부분의 VertexBuffer모든 정점을 저장하기 위해 a 를 작성 하고 가능한 한 많은 Draw를 단일 Draw 호출로 일괄 처리하지만 질문과 관련이 없습니다.


렌더링 포인트-방법 1 (SpriteBatch)

점을 그리는 데는 점 스프라이트를 사용하는 것이 쉽지만 XNA 4.0에서 제거되었습니다 . 그래도 몇 가지 대안이 있습니다. 가장 쉬운 방법은 1x1 흰색 Texture2D객체 를 만들어 SpriteBatch올바른 화면 위치에서 렌더링 하는 것 입니다. Viewport.Project 메서드를 사용하면 쉽게 찾을 수 있습니다 .

다음 Texture2D과 같이 필요한 오브젝트를 작성할 수 있습니다 .

Texture2D pixel = new Texture2D(GraphicsDevice, 1, 1);
pixel.SetData(new [] { Color.White });

그리고 다음과 같이 (x, y, z) 위치에 렌더링하십시오.

// Find screen equivalent of 3D location in world
Vector3 worldLocation = new Vector3(0, 0, 50);
Vector3 screenLocation = GraphicsDevice.Viewport.Project(worldLocation, projectionMatrix, viewMatrix, Matrix.Identity);

// Draw our pixel texture there
spriteBatch.Begin();
spriteBatch.Draw(pixel, new Vector2(screenLocation.X, screenLocation.Y), Color.White);
spriteBatch.End();

렌더링 선-방법 2 (SpriteBatch)

또는 여기에 설명SpriteBatch기술을 사용하여 선을 그릴 수도 있습니다 . 이 경우 3D 선의 양쪽 끝에 대한 화면 공간 좌표를 찾아 (한 번 더 사용하여 Viewport.Project) 화면 사이의 선을 그리면됩니다.


렌더링 포인트-방법 2 (프리미티브가있는 작은 선)

이 의견에서 eBusiness는 다음과 같은 질문을 제기했습니다.

시작점과 끝 점이 동일한 선은 어떻습니까? 아니면 단순히 보이지 않을까요?

나는 그것을 시도하고 같은 시작점과 끝점을 LineList사용하여 렌더링하면 아무것도 그려지지 않았습니다 . 나는 그 주위에 방법을 찾았으므로 여기에 완전성을 설명 할 것입니다.

트릭은 동일한 시작점과 끝점을 사용하는 것이 아니라 선을 너무 작게 그려서 그릴 때 하나의 픽셀 로만 나타나는 것입니다. 올바른 끝점을 선택하기 위해 먼저 월드 스페이스 포인트를 화면 공간 으로 투영하고 화면 공간에서 한 픽셀 오른쪽으로 이동 한 다음 월드 스페이스로 다시 투영했습니다. 그것이 점처럼 보이게하기 위해 선의 끝점입니다. 이 같은:

Vector3 GetEndPointForDot(Vector3 start)
{
    // Convert start point to screen space
    Vector3 screenPoint = GraphicsDevice.Viewport.Project(start, projection, view, Matrix.Identity);

    // Screen space is defined in pixels so adding (1,0,0) moves it right one pixel
    screenPoint += Vector3.Right;

    // Finally unproject it back into world space
    return GraphicsDevice.Viewport.Unproject(screenPoint, projection, view, Matrix.Identity);
}

일반 선 프리미티브로 렌더링합니다.


데모

다음은 선 목록 프리미티브를 사용하여 3D 공간에 흰색 선을 그리고 1x1 텍스처와 SpriteBatch를 사용하여 선의 양쪽 끝에 빨간색 점을 그리는 것입니다. 사용 된 코드는 위에서 쓴 것과 거의 같습니다. 또한 확대하여 정확히 한 픽셀 너비임을 확인할 수 있습니다.

여기에 이미지 설명을 입력하십시오


시작점과 끝 점이 동일한 선은 어떻습니까? 아니면 단순히 보이지 않을까요?
aaaaaaaaaaaa

@eBusiness 좋은 질문입니다! 방금 시도해 보았지만 실제로 아무것도 렌더링하지 않습니다.
David Gouveia

@eBusiness 방금 방법을 찾았지만 조금 어리석은 것 같습니다. 어쨌든 완성을 위해 추가하겠습니다.
David Gouveia

2

이것은 XNA로 태그가 붙어 있으므로 그것이 당신이 요구하는 것이라고 가정하고 있습니까?

그렇다면이 기사는 다음 행에 도움이됩니다.

http://msdn.microsoft.com/en-us/library/bb196414(v=xnagamestudio.40).aspx

물론 자체 뷰 / 프로젝션 매트릭스를 사용할 수 있습니다. 기본적으로 PrimitiveType.LineList또는 LineStripGPU 수준에서 선을 그리는 방법입니다.

포인트에 대해서는 더 이상 PrimitiveType.PointList를 사용하여 XNA 4.0에서 포인트를 더 이상 그릴 수 없습니다. 대신 매우 작은 삼각형을 만들어야합니다. 이 샘플은 좋은 기준을 제공합니다.

http://create.msdn.com/education/catalog/sample/primitives_3d

이전 버전의 XNA의 경우, 그 중 하나를 사용하는 경우 위에 게시 된 기사의 XNA 3.0 버전에서 Point 부분을 읽을 수 있습니다.

http://msdn.microsoft.com/en-us/library/bb196414(v=xnagamestudio.30).aspx

링크에는 다음이 있습니다.

graphics.GraphicsDevice.RenderState.PointSize = 10;

분명히로 변경하십시오 1.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.