2015-12-10 8 views
0

Я отрисовываю сплайн в DirectX 11, но у меня проблема, когда он застрял на экране, и я не могу убедить его быть в мировом пространстве ,Рендеринг мировой космической линии в DirectX 11

Stubborn spline

В шлицевой первоначально определен как std::vector<DirectX::XMFLOAT3> контрольных точек, которые расширяют до вектора одного и того же фактических точек на сплайн под названием linePoints. Тогда вершина, индекс и постоянные буферы создаются в этой функции:

void Spline::createBuffers(ID3D11Device* device) 
{ 
    Vertex vertices[100]; 
    for (int i = 0; i < 100; i++) 
    { 
     Vertex v; 
     v.position = linePoints.at(i); 
     v.colour = XMFLOAT4(0, 0, 0, 1.0); 
     vertices[i] = v; 
    } 

    D3D11_BUFFER_DESC bd; 
    ZeroMemory(&bd, sizeof(D3D11_BUFFER_DESC)); 
    bd.Usage = D3D11_USAGE_DEFAULT; 
    bd.ByteWidth = sizeof(Vertex) * linePoints.size(); 
    bd.BindFlags = D3D11_BIND_VERTEX_BUFFER; 
    bd.CPUAccessFlags = 0; 

    D3D11_SUBRESOURCE_DATA InitData; 
    ZeroMemory(&InitData, sizeof(InitData)); 
    InitData.pSysMem = vertices; 

    device->CreateBuffer(&bd, &InitData, &vertexBuffer); 

    ZeroMemory(&bd, sizeof(D3D11_BUFFER_DESC)); 
    bd.Usage = D3D11_USAGE_DEFAULT; 
    bd.CPUAccessFlags = 0; 
    bd.ByteWidth = sizeof(WORD) * linePoints.size(); 
    bd.BindFlags = D3D11_BIND_INDEX_BUFFER; 

    WORD indices[200]; 
    int count = 0; 
    for (WORD i = 0; i < 100; i++) 
    { 
     indices[count] = i; 
     indices[count + 1] = i + 1; 
     count += 2; 
    } 

    ZeroMemory(&InitData, sizeof(InitData)); 
    InitData.pSysMem = indices; 
    device->CreateBuffer(&bd, &InitData, &indexBuffer); 

    ZeroMemory(&bd, sizeof(bd)); 
    bd.Usage = D3D11_USAGE_DEFAULT; 
    bd.ByteWidth = sizeof(LineCBuffer); 
    bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER; 
    bd.CPUAccessFlags = 0; 
    device->CreateBuffer(&bd, nullptr, &constBuffer); 
} 

Функция ничья:

void Spline::Draw(ID3D11PixelShader* pShader, ID3D11VertexShader* vShader, Camera& cam) 
{ 
    context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP); 

    context->VSSetShader(vShader, nullptr, 0); 
    context->PSSetShader(pShader, nullptr, 0); 

    LineCBuffer lCB; 
    lCB.world = XMMatrixIdentity(); 
    lCB.view = XMMatrixTranspose(cam.getView()); 
    lCB.projection = XMMatrixTranspose(cam.getProjection()); 

    context->UpdateSubresource(constBuffer, 0, nullptr, &lCB, 0, 0); 

    context->VSSetConstantBuffers(0, 1, &constBuffer); 

    UINT stride = sizeof(Vertex); 
    UINT offset = 0; 

    context->IASetVertexBuffers(0, 1, &vertexBuffer, &stride, &offset); 
    context->IASetIndexBuffer(indexBuffer, DXGI_FORMAT_R16_UINT, 0); 

    context->DrawIndexed(100, 0, 0); 

    context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); 
} 

И весь файл шейдера:

cbuffer lineCBuffer : register(b0) 
{ 
    matrix World; 
    matrix View; 
    matrix Projection; 
}; 

struct VS_IN 
{ 
    float3 position : POSITION; 
    float4 colour : COLOUR; 
}; 

struct VS_OUT 
{ 
    float4 pos : SV_POSITION; 
    float4 colour : COLOUR; 
}; 

VS_OUT lineVertexShader(float3 position : POSITION, float4 colour : COLOUR) 
{ 
    VS_OUT output = (VS_OUT)0; 
    output.pos = mul(position, World); 
    output.pos = mul(output.pos, View); 
    output.pos = mul(output.pos, Projection); 
    output.pos.w = 1.0f; 
    output.colour = colour; 

    return output; 
} 

float4 linePixelShader(VS_OUT input) : SV_TARGET 
{ 
    return input.colour; 
} 

Этот вопрос что начало строки (особенно когда оно установлено (0,0,0)) привязано к окну просмотра. Когда старт, если линия находится на (0,0,0), она не покинет центр экрана, даже если она должна быть вне экрана.

+0

Упростить вещи, вплоть до простейшей возможной сцены, а именно тот, который содержит только ваши мозаичные сегменты сплайна линии. На вашем снимке экрана есть куча других вещей, показанных на сцене. После того, как вы будете изолировать линию, сделайте программную смену камеры, чтобы вращаться вокруг линии и убедитесь, что она правильно перемещается в мировом пространстве. – legalize

ответ

1

Я думаю, что вы делаете что-то не так с вашим умножением.

VS_OUT lineVertexShader(float3 position : POSITION, float4 colour : COLOUR) 
{ 
    VS_OUT output = (VS_OUT)0; 
    output.pos = mul(position, World); 
    output.pos = mul(output.pos, View); 
    output.pos = mul(output.pos, Projection); 
    output.pos.w = 1.0f; 
    output.colour = colour; 
    return output; 
} 

Вы используете float3 как позиционный вход. Позиция является точкой, поэтому вы должны использовать

float4(position,1.0f) 

как точка в 3D пространстве. Если float3 будет вектором, вы создаете

float4(position,0.0f) 

Таким образом, ваш Vertex Shader должен выглядеть следующим образом:

VS_OUT lineVertexShader(float3 position : POSITION, float4 colour : COLOUR) 
{ 
    VS_OUT output; 
    output.pos = mul(float4(position,1.0), mul(mul(World,View),Projection)); 
    output.colour = colour; 
    return output; 
} 

еще одна вещь. Не устанавливайте pos.w в 1! Rasterrizer автоматически преобразует перспективу в значение SV_POSITION. Затем однородное значение передается в пиксельный шейдер. Иногда вы действительно хотите установить z и w на 1, возможно, для вашего куба-карты, отображаемой на максимальном расстоянии или тому подобного. Но я думаю, что здесь другая ошибка.

Когда вам не нужно использовать мир, просмотр и проецирование в дополнительных умножениях, почему бы не прекомпретировать его на процессоре, а затем просто подтолкнуть финальную матрицу worldViewProj к вашим шейдерам?

Good Look