2012-10-08 33 views
1

我用DX9使用頂點緩衝區(DrawPrimitive)渲染2D精靈。 一些動畫獲得了不同大小的不同紋理文件。dx紋理不會按時更改?

現在我得到以下問題:在兩個具有不同紋理文件的動畫之間切換的單幀上(例如,當開始走路或完成走路並開始站立時),它將以座標新的紋理,但仍呈現舊紋理。這看起來好像我沒有爲新動畫設置紋理。唯一的問題是 - 我做到了。

我如何理解問題:我在該框架上截取了一個截圖,並注意到它渲染了一個紋理,其座標與其他紋理貼合。

在我的渲染函數中,我首先獲取新紋理並將其發送到DX,而不是計算座標,最後我使用座標和新紋理集渲染我的頂點。我檢查並調試了數百萬次,所有的值都是正確的,但是卻發生了錯誤。

任何想法,爲什麼會發生這種情況?

謝謝!

編輯:當你說 「座標爲新的紋理」,你reffering這個

// Render a quad using the vertex buffer 
void CGraphicsManager::RenderQuadViaVertexBuffer(const SVertex* pVertices) const 
{ 

    // Increase renders count 
    this->m_RenderCount++; 

    // vb_vertices now points to our vertices inside the Vertex buffer, so 
    // to fill in our VB, we copy to vb_vertices. 
    memcpy(this->m_pVertexBufferBuffPtr + this->m_OffsetInVertexBuffer, pVertices, sizeof(SVertex) * (VERTICES_IN_QUAD)); 

    // Render the rectanlge using the vertices we got. 
    this->m_pD3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, this->m_OffsetInVertexBuffer, PRIMITIVES_IN_QUAD); 

    // Increment the offset in the vertex buffer 
    this->m_OffsetInVertexBuffer += VERTICES_IN_QUAD; 

} 
// Render a quad 
void CGraphicsManager::Render(const STexture& p_Texture, SLocation p_RenderLocation, SSize p_RenderSize, const SQuad& p_TextureQuad, SfColor p_RenderColor, ERenderEffects p_RenderEffect) const 
{ 
    // Set render effect 
    this->SetRenderEffect(p_RenderEffect); 

    // Set texture 
    this->SetTexture(p_Texture); 

    // Set the vertex needed for the rendering 
    VerticesForQuadRender[0].Position.x = p_RenderLocation.x; 
    VerticesForQuadRender[0].Position.y = p_RenderLocation.y; 
    VerticesForQuadRender[0].Position.z = 0.0f; 
    VerticesForQuadRender[0].color  = p_RenderColor; 
    VerticesForQuadRender[0].tv   = p_TextureQuad.left; 
    VerticesForQuadRender[0].tu   = p_TextureQuad.top; 

    VerticesForQuadRender[1].Position.x = p_RenderLocation.x + p_RenderSize.x; 
    VerticesForQuadRender[1].Position.y = p_RenderLocation.y; 
    VerticesForQuadRender[1].Position.z = 0.0f; 
    VerticesForQuadRender[1].color  = p_RenderColor; 
    VerticesForQuadRender[1].tv   = p_TextureQuad.right; 
    VerticesForQuadRender[1].tu   = p_TextureQuad.top; 

    VerticesForQuadRender[2].Position.x = p_RenderLocation.x; 
    VerticesForQuadRender[2].Position.y = p_RenderLocation.y + p_RenderSize.y; 
    VerticesForQuadRender[2].Position.z = 0.0f; 
    VerticesForQuadRender[2].color  = p_RenderColor; 
    VerticesForQuadRender[2].tv   = p_TextureQuad.left; 
    VerticesForQuadRender[2].tu   = p_TextureQuad.bottom; 

    VerticesForQuadRender[3].Position.x = p_RenderLocation.x + p_RenderSize.x; 
    VerticesForQuadRender[3].Position.y = p_RenderLocation.y + p_RenderSize.y; 
    VerticesForQuadRender[3].Position.z = 0.0f; 
    VerticesForQuadRender[3].color  = p_RenderColor; 
    VerticesForQuadRender[3].tv   = p_TextureQuad.right; 
    VerticesForQuadRender[3].tu   = p_TextureQuad.bottom; 

    this->RenderQuadViaVertexBuffer(VerticesForQuadRender); 
} 


// Starts a rendering frame 
bool CGraphicsManager::StartFrame() 
{ 
    // Clear texture 
    this->ClearTexture(); 

    // Zero renders count 
    this->m_RenderCount = 0; 

    // Clear screen 
    if (!this->ClearScreen()) 
    { 
     this->ResetDevice(); 
     return false; 
    } 

    // Begin new rendering scene 
    if (FAILED(this->m_pD3dDevice->BeginScene())) 
    { 
     this->ResetDevice(); 
     return false; 
    } 

    // Set render from our vertex buffer 
    this->BeginRenderFromVertexBuffer(); 

    return true; 
} 


// Finish rendering 
bool CGraphicsManager::EndFrame() 
{ 
    // Unlock vertex buffer 
    this->m_pVertexBuffer->Unlock(); 

    // Notify the device that we're finished rendering for this frame 
    if (FAILED(this->m_pD3dDevice->EndScene())) 
    { 
     this->ResetDevice(); 
     return false; 
    } 

    // Present scene 
    if(FAILED(this->m_pD3dDevice->Present(NULL,  //Source rectangle to display, NULL for all of it 
         NULL,      //Destination rectangle, NULL to fill whole display 
         NULL,      //Target window, if NULL uses device window set in CreateDevice 
         NULL)))     //Dirty Region, set it to NULL 
    { 
     this->ResetDevice(); 
     return false; 
    } 

    // Finish rendering 
    return true; 
} 

// This function must be called before rendering textured surfaces 
void CGraphicsManager::BeginRenderFromVertexBuffer() const 
{ 
     // Lock the vertex buffer (unlock on release) and get the pointer to the begining of the buffer 
     HRESULT hr = this->m_pVertexBuffer->Lock 
      (0,          // Offset, we want to start at the beginning 
      0,          //SizeToLock, 0 means lock the whole thing 
      (void**)&this->m_pVertexBufferBuffPtr, //If successful, this will point to the data in the vertex buffer 
      0); 

     ASSERT(SUCCEEDED(hr), "Failed to lock vertex buffer! (err: " << hr << ")"); 

    // Set offset in vertex buffer back to 0 
    this->m_OffsetInVertexBuffer = 0; 
} 
+0

添加SetRenderEffect和SetTexture的代碼。 – Goz

回答

0

嗯,我可以看到你的問題,你正在複製數據到一個鎖定的頂點緩衝區,然後渲染該數據。你不能這樣做。鎖定的頂點緩衝區中的數據實際上尚未生效。一旦你解鎖它,它就會變得有效。這是因爲您要填寫的數據位於主內存中,實際上可能是圖形卡上的內存遮蔽。當你解鎖它時,將數據複製到顯卡上。

因此,如果您爲每個繪製調用鎖定/解鎖,則一切正常,因爲您正在強制複製。

但是,正如你所發現的那樣,這遠非最佳。

你應該做的是在一次通過中計算所有四個頂點位置。然後你需要通過並渲染所有的四邊形(理想情況下,每次調用都不需要交換紋理/着色器等)。

這樣做的一種方法是填充您的頂點緩衝區,然後將繪圖命令存儲在頂點緩衝區中。這需要你存儲紋理,效果等等。然後,你可以遍歷列表並渲染已經填充的頂點緩衝區中的所有內容。

如果通過紋理和着色器常量對事物進行排序(以最大限度地減少狀態變化),您會發現性能要好很多倍。儘管您需要將頂點緩衝區標記爲「動態」,並且在鎖定頂點緩衝區時建議使用D3DLOCK_DISCARD標誌,因爲這會丟棄頂點緩衝區中的當前數據(基本上它會返回一個全新的內存塊填充並不會從卡中複製任何內容),而不是阻止並等待GPU完成使用。

我希望這有些幫助!

+0

解決了我的問題!謝謝 –

1

http://en.wikipedia.org/wiki/UV_mapping添加一些代碼?

如果精靈在更新時會得到舊的紋理,則可能是幾件事情。

1:你的渲染管線的工作方式如何?你爲每個drawcall設置每個紋理嗎? - 即時尋找的是,如果你只是設置紋理一次,而不是perdrawcall(或者如果你按批次排序)

2:你確定你綁定你的新紋理?

你可以在你的繪圖函數上貼一些代碼嗎?

+0

嗨,謝謝你的回覆。 1.是的我指的是UV貼圖 2.我有一個機制來設置紋理只在必要時,但我懷疑這可能是問題的根源,所以我已經禁用它。現在,我在每次渲染調用之前設置紋理。 - 仍然發生。 3.是的,正如我上面提到的解決此錯誤的嘗試,我將代碼更改爲每次渲染之前設置紋理和座標的點,無論如何設置。我也調試了非常有問題的框架,一切似乎都沒問題。 –

+0

如果你強制每個框架和每個drawcall一個新的紋理,它仍然不工作,它可能是與它自己的紋理(你可以有一個敏捷地放在相同的紋理),如果你冷後發佈一些代碼,這將有助於! – Tordin

+0

紋理本身是可以的,否則它在下一幀也不起作用。問題在於替換紋理的單個框架。我只是調試它,我看到我設置了正確的紋理和座標(檢查紋理指針和UV),但是當我走過呈現框架本身的線(pD3dDev-> Present)時,錯誤的紋理!它的行爲好像我從來沒有調用過「SetTexture」函數,但是我只是看到了我做過的事情,並且我仔細檢查了我設置的紋理。這太奇怪了!這就是爲什麼我懷疑自己的邏輯是好的,但是我在DX –