2017-02-28 3 views
0

directx11에 굵은 선을 구현하고 싶습니다.directx에서 인스턴스 렌더링 된 두꺼운 선 렌더링 11

가 가 가

enter image description here

가 가 가 P1과 P2가되지 등거리 광고 verticies을 대표

가로 주어 느릅 나무 : 난 도시 I이 그림처럼 각 라인에 대해 "고품질"형상을 렌더링하기 위해 복제 된 렌더링 기술을 사용할 수 생각 「D3D11_PRIMITIVE_TOPOLOGY_LINELIST」로서 지정합니다. 선 두께는 정수 버퍼에 저장됩니다. 각 선의 두께는 동일합니다. 인스턴스 지오메트리에는 정점을 삼각형에 연결하는 방법에 대한 정보가있는 인덱스 버퍼가 있습니다 (그림에서 vertitude는 I0 - I11 임).

P1 및 P2 위치와 SV_VertexID를 하나의 정점 셰이더 스레드에 놓아야 만 I0 - I11 정점의 각 위치를 계산할 수 있습니다. 그래서 그것은 문제가되지 않습니다.

질문 : 이것을 구현하기 위해 인스턴스 렌더링 기술을 사용할 수 있습니까?

만약 그렇다면 다음과 같이 사용하는 것이 좋은가요? 두꺼운 둥근 선을 구현하는 데 더 많은 성능 방법이 있습니까? 예를 들어 geometryshader를 사용하거나 그 지오메트리가있는 1000 개의 drawcalls을 만들면됩니다.

+0

이 종류의 벡터 그래픽 그리기를 수행하도록 설계된 Direct2D 만 사용해보십시오. –

+0

@ChuckWalbourn 3D로 된 선 또한 Direct2D를 사용할 수 없습니다. Direct3D 11 만 사용할 수 있습니다. – Thomas

+1

지오메트리 셰이더를 사용하여 쿼드 및 빌보드로 포인트를 확장하는 방법에 대해 생각해 보셨습니까? 기본적으로 한 점에 정점 A와 B 위치를 저장하고 확장 할 수 있습니다. 카메라 행렬에서도 카메라의 위쪽 벡터를 도출 할 수 있습니다. 따라서 권리에 따라 교차 제품을 계산하여 4 개 꼭지점을 생성 할 수 있습니다. 그게 문제의 일부일 뿐이지 만 카메라에서 거리에 따라 선 두께를 에뮬레이트하기 위해 정확한 너비를 계산해야합니다. 나는 그것이 단순한 선형 거리 관계라고 생각한다. – ErnieDingo

답변

1

인스턴스 렌더링 아이디어를 사용하기 위해 많은 노력을했지만 지금은 geometryshader로 아이디어를 변경했으며 구현하기가 매우 쉽습니다. 입력으로 선 (2 개의 정점)이되고 출력은 30 삼각형입니다.) 이제 사진,

#include <psiPosition.hlsli> 

//#pragma warning (disable:3206) 
//#pragma warning (disable:3554) 

static const float PI = 3.1415926f; 
static const float fRatio = 2.0f; 
static float fThickness = 0.01f; 

void addHalfCircle(inout TriangleStream<PS_INPUT> triangleStream, int nCountTriangles, float4 linePointToConnect, float fPointWComponent, float fAngle) 
{ 
    PS_INPUT output = (PS_INPUT)0; 
    for (int nI = 0; nI < nCountTriangles; ++nI) 
    { 
     output.Pos.x = cos(fAngle + (PI/nCountTriangles * nI)) * fThickness/fRatio; 
     output.Pos.y = sin(fAngle + (PI/nCountTriangles * nI)) * fThickness; 
     output.Pos.z = 0.0f; 
     output.Pos.w = 0.0f; 
     output.Pos += linePointToConnect; 
     output.Pos *= fPointWComponent; 
     triangleStream.Append(output); 

     output.Pos = linePointToConnect * fPointWComponent; 
     triangleStream.Append(output); 

     output.Pos.x = cos(fAngle + (PI/nCountTriangles * (nI + 1))) * fThickness/fRatio; 
     output.Pos.y = sin(fAngle + (PI/nCountTriangles * (nI + 1))) * fThickness; 
     output.Pos.z = 0.0f; 
     output.Pos.w = 0.0f; 
     output.Pos += linePointToConnect; 
     output.Pos *= fPointWComponent; 
     triangleStream.Append(output); 

     triangleStream.RestartStrip(); 
    } 
} 

[maxvertexcount(42)] 
void main(line PS_INPUT input[2], inout TriangleStream<PS_INPUT> triangleStream) 
{ 
    PS_INPUT output= (PS_INPUT)0; 

    int nCountTriangles =6; 

    float4 positionPoint0Transformed = input[0].Pos; 
    float4 positionPoint1Transformed = input[1].Pos; 

    float fPoint0w = positionPoint0Transformed.w; 
    float fPoint1w = positionPoint1Transformed.w; 

    //calculate out the W parameter, because of usage of perspective rendering 
    positionPoint0Transformed.xyz = positionPoint0Transformed.xyz/positionPoint0Transformed.w; 
    positionPoint0Transformed.w = 1.0f; 
    positionPoint1Transformed.xyz = positionPoint1Transformed.xyz/positionPoint1Transformed.w; 
    positionPoint1Transformed.w = 1.0f; 

    //calculate the angle between the 2 points on the screen 
    float3 positionDifference = positionPoint0Transformed.xyz - positionPoint1Transformed.xyz; 
    float3 coordinateSysten = float3(1.0f, 0.0f, 0.0f); 

    positionDifference.z = 0.0f; 
    coordinateSysten.z = 0.0f; 

    float fAngle = acos(dot(positionDifference.xy, coordinateSysten.xy)/(length(positionDifference.xy) * length(coordinateSysten.xy))); 

    if (cross(positionDifference, coordinateSysten).z < 0.0f) 
    { 
     fAngle = 2.0f * PI - fAngle; 
    } 

    fAngle *= -1.0f; 
    fAngle -= PI *0.5f; 

    //first half circle of the line 
    addHalfCircle(triangleStream, nCountTriangles, positionPoint0Transformed, fPoint0w, fAngle); 
    addHalfCircle(triangleStream, nCountTriangles, positionPoint1Transformed, fPoint1w, fAngle + PI); 

    //connection between the two circles 
    //triangle1 
    output.Pos.x = cos(fAngle) * fThickness/fRatio; 
    output.Pos.y = sin(fAngle) * fThickness; 
    output.Pos.z = 0.0f; 
    output.Pos.w = 0.0f; 
    output.Pos += positionPoint0Transformed; 
    output.Pos *= fPoint0w; //undo calculate out the W parameter, because of usage of perspective rendering 
    triangleStream.Append(output); 

    output.Pos.x = cos(fAngle + (PI/nCountTriangles * (nCountTriangles))) * fThickness/fRatio; 
    output.Pos.y = sin(fAngle + (PI/nCountTriangles * (nCountTriangles))) * fThickness; 
    output.Pos.z = 0.0f; 
    output.Pos.w = 0.0f; 
    output.Pos += positionPoint0Transformed; 
    output.Pos *= fPoint0w; 
    triangleStream.Append(output); 

    output.Pos.x = cos(fAngle + (PI/nCountTriangles * (nCountTriangles))) * fThickness/fRatio; 
    output.Pos.y = sin(fAngle + (PI/nCountTriangles * (nCountTriangles))) * fThickness; 
    output.Pos.z = 0.0f; 
    output.Pos.w = 0.0f; 
    output.Pos += positionPoint1Transformed; 
    output.Pos *= fPoint1w; 
    triangleStream.Append(output); 

    //triangle2 
    output.Pos.x = cos(fAngle) * fThickness/fRatio; 
    output.Pos.y = sin(fAngle) * fThickness; 
    output.Pos.z = 0.0f; 
    output.Pos.w = 0.0f; 
    output.Pos += positionPoint0Transformed; 
    output.Pos *= fPoint0w; 
    triangleStream.Append(output); 

    output.Pos.x = cos(fAngle) * fThickness/fRatio; 
    output.Pos.y = sin(fAngle) * fThickness; 
    output.Pos.z = 0.0f; 
    output.Pos.w = 0.0f; 
    output.Pos += positionPoint1Transformed; 
    output.Pos *= fPoint1w; 
    triangleStream.Append(output); 

    output.Pos.x = cos(fAngle + (PI/nCountTriangles * (nCountTriangles))) * fThickness/fRatio; 
    output.Pos.y = sin(fAngle + (PI/nCountTriangles * (nCountTriangles))) * fThickness; 
    output.Pos.z = 0.0f; 
    output.Pos.w = 0.0f; 
    output.Pos += positionPoint1Transformed; 
    output.Pos *= fPoint1w; 
    triangleStream.Append(output); 
} 

나는 그것이 매우 하드 알지만, 적어도 작동 :

다음
struct PS_INPUT 
{ 
    float4 Pos : SV_POSITION; 
}; 

지오메트리 쉐이더 여기

pixelshader 입력 구조체 두꺼운 선이있는 입방체 (원근 투영에서 첫 번째, 정사영 투영에서 두 번째) perspective projection orthographic projection

나는 이것을 누군가에게 도움이되기를 바랍니다. 두꺼운 선을 구현하는 것이 더 좋은 아이디어라면 의견을 남겨주세요.