游戲引擎學習第298天:改進排序鍵 - 第1部分

關于向玩家展示多個房間層所需的兩種 Z 值

我們在前一天基本完成了為渲染系統引入分層 Z 值的工作,但還沒有完全完成所有細節。我們開始引入圖形渲染中的分層概念,即在 Z 軸方向上擁有多個獨立圖層,每個圖層內部再使用一個單獨的 Z 值來實現 Y 方向上的位移。這種做法在游戲中非常關鍵,原因在于本項目雖然是二維游戲,但由于其“2.5D”或“2.2D”的設計特性,房間可以垂直疊放,玩家可以通過地板的孔洞等看到上下層的空間。

為了合理地將這種設計呈現給玩家,我們發現需要兩種不同類型的 Z 值:一種是用于圖形縮放的 Z 值,主要用于體現上下樓層之間的視覺深度感;另一種是標準的正交 Z 值,用于在屏幕上沿 Y 軸移動圖像,以表現相對高度關系。之前我們還沒有徹底整理清楚這兩種 Z 值的使用方式,但現在正處于項目開發向游戲內容過渡的階段,這個系統需要被規范化和最終確定。

因此,我們當前的目標就是將這兩種 Z 值的處理邏輯進一步明確并最終實現到渲染系統中,讓它們能夠同時協同工作,既提供視覺上的深度感,也能保證場景中物體的繪制順序正確

回顧內容并為今天的工作定下方向

我們昨天在最后已經完成了將實體劃分為不同圖層的核心代碼,但尚未處理每層圖層內的 Z 值使用方式。當前的顯示結果看起來有些混亂,比如每個房間本應只有一個蛇和一個怪物,但屏幕上卻顯示出了兩條蛇和兩個怪物,還有一個明顯被分裂的樓梯。這是因為我們雖然實現了將圖塊和實體劃分到不同圖層,但還沒有讓渲染系統識別和使用這些圖層信息來區分不同樓層。

當前的情況是,多個圖層的內容全部被“壓扁”到同一個平面上來渲染了,因為我們沒有將圖層層級的 Z 值單獨處理并傳遞給渲染器,而只是統一用了單一的 Z 值,這個值本應該是用來做 Y 軸方向的位移的。現在我們看到的正是第一個樓層和第二個樓層的內容被堆疊渲染到了同一個平面上,才會看到兩個蛇和兩個怪物重疊在一起。

我們還觀察到一個細節:一組蛇和怪物所在的圖塊會被高亮,而另一組則沒有。這是因為底下那一層的蛇和怪物所站立的圖塊也被處理了高亮邏輯,但因為它們在下層,被上層完全遮擋,看不到。這正說明了圖層處理邏輯沒有完全實現,導致所有圖層被當作一個平面處理了。

接下來的任務就是繼續推進這一部分,把每一層的圖層 Z 值和實體內部的 Y 位移 Z 值區分開來,并在渲染路徑中正確使用。我們需要讓渲染系統清晰知道,哪個 Z 是代表圖層層級(用于透視縮放、遠近遮擋等),哪個 Z 是用來模擬上下位移的,這樣才能真正呈現出“上下樓層”的效果。

這部分工作會比想象中復雜,因為它不是一個標準圖形系統里的通用流程,沒有現成的數學模型或圖形標準可以照搬。我們不能單純地參考現成的 3D 渲染邏輯去解決問題,而是需要根據我們的游戲設計需求,自行定義出一個合理的規則體系,將必要的信息盡量完整地傳遞下去,同時又避免保存冗余或不必要的信息。這就需要我們不斷嘗試、打磨流程,直到形成一個既穩定又清晰的渲染機制。
在這里插入圖片描述

查看 game_render_group.cpp 中目前透視變換的實現方式

我們進入 game_render_group 模塊,查看當前 Z 值的處理邏輯。在這個渲染流程中,我們設置了透視或正交變換,并調用了 GetRenderEntityBasisP 函數,這個函數就是目前進行 Z 值處理的地方。

我們可以明顯看出當前的變換流程存在很多問題。在函數內部,X 和 Y 是按照一種特定方式傳遞和處理的,而 Z 的處理方式卻并不一致,顯得很不統一。其中 OffsetP 是從自動變換中提取出來的,用于做位置的偏移,它會以一種方式保留 Z 的值。但整體上,這些數據如何組合,以及最終如何計算得到的渲染位置 P,流程顯得非常凌亂,存在很多特殊邏輯,缺乏統一結構。

我們現在的任務就是盡可能清晰并統一這套流程,明確 Z 值在系統中的作用和流向。我們希望 Z 的處理方式在整個渲染流程中是連貫一致的,但從當前的代碼來看,它不是一個標準的、直通的路徑。比如我們并沒有在某個固定位置將 Z 值手動地應用到 X 或 Y 坐標上,而是依賴透視變換的某些特性來“自動”地引起 X 和 Y 的變化。這種方式缺乏顯式控制,在我們需要細致地手動指定圖層深度和垂直位移時就顯得非常不足。

所以接下來,我們的目標是:提供一種機制,可以明確地把 Z 值作為渲染控制參數,在變換和排序中手動使用它。我們想要的是一個具備 XYZ 控制邏輯的渲染流程,使得圖層 Z 值(用于表示樓層關系或透視深度)和實體自身的 Z 值(用于模擬垂直位移、遮擋關系)都能正確地傳遞并參與計算,而不是依賴模糊的透視規則或者隱式偏移。

我們需要從底層整理渲染流程,確保渲染系統明確知道 Z 的每個用途,并且能在不同階段進行恰當的處理。總之,我們的任務就是把這一套混亂的處理方式梳理清楚,構建一個可靠、可控、符合我們渲染需求的 Z 體系結構。

黑板講解:處理不同樓層之間的“轉換點”問題

我們現在面臨的一個關鍵問題,是關于在渲染中如何處理兩種不同類型的 Z 值之間的轉換,尤其是在“轉換區域”(Changeover Point)這塊最難處理。

設想一下,我們的游戲中有多個樓層或切片,使用的是一種偽 3D 的視角,允許玩家透過樓層看到下面的內容。這樣就會出現一種情況:同一個實體可以處于不同的高度或樓層,然而由于不同樓層的內容會有不同的縮放比例,我們必須解決一個技術難題:當一個實體從一個樓層跳到另一個樓層時,它的圖像大小不能瞬間發生變化,否則視覺上會非常突兀。所以我們必須做出一種視覺上的過渡處理。

這個問題的關鍵點在于:我們不能讓縮放的變化發生得太突然。我們希望實體從上層跳到底層(或者反之)時,不是立刻改變大小,而是有一個漸變的縮放過程,帶來視覺上的平滑過渡。

為了實現這個,我們需要將整個樓層高度(Z 高度)劃分為兩個區域:

  1. 縮放區(Scaling Region):在這個區域中,實體的 Z 值將被用于計算縮放比例,同時位置也會隨著縮放逐漸改變。
  2. 位移區(Displacement Region):在這個區域中,實體的 Z 不再引起縮放,而是僅僅用于向上或向下的 Y 方向位移(模擬浮動或跳躍等效果)。

舉個例子,假設我們當前有兩個樓層,上面是第一層,下面是第二層。我們希望實體從第一層跳落到第二層時,逐漸縮小,而不是瞬間縮小。我們會定義一個樓層高度參數(當前叫 typical floor height,之后可能會重命名為 floor height),用這個高度來劃分縮放區和位移區的位置。

具體的做法是這樣的:

  • 整個樓層高度是一個固定的值,我們在其中劃出一個上部區域,稱為縮放區;
  • 剩下的部分則是位移區;
  • 當一個實體處于縮放區時,我們根據它的 Z 值去計算縮放比例,并平滑地調整它的位置;
  • 當實體進入位移區后,它的 Z 值不再影響縮放,而是僅僅控制其在 Y 軸上的偏移,從而實現視覺上的高度感,但不會改變圖像大小。

這其實相當于我們人為規定了一個“非線性變換區域”,在這個區域中對 Z 值的處理方式發生了變化,從普通的“Z 控制縮放 + 位置”變成了“Z 只控制 Y 位移”。

這個機制必須非常明確地實現,否則視覺結果會很混亂。我們需要決定清楚是由哪個系統(實體系統、渲染系統、還是某個中間層)來負責判斷當前實體的 Z 值屬于哪個區域,以及什么時候開始或停止進行縮放。換句話說,這里不僅是一個技術實現問題,更涉及到系統設計層面的責任劃分。

這個方案并不復雜,但需要小心實現,以確保畫面中實體跳躍或跨層時的視覺效果平滑自然。這是目前我們需要重點解決的難點。

黑板講解:使用“熱點規則”在 Y 和 Z 方向上對實體進行排序

我們需要注意并控制的另一個重要問題,是場景中“塊狀地形”(block)與角色之間在視覺上的遮擋排序問題。雖然目前我們還沒有完全實現這個系統,可能會等到有完整的美術素材包之后再展開,但現在已經可以看出一些潛在的復雜性。

在我們的場景中,地面不是完全平的,而是由多個可跳躍的“塊”構成,這些塊在 Z 軸上可以有偏移。因此即使我們解決了 Z 切片(Z slice)的繪制問題,依然存在一個問題:角色與地面(或障礙物)在屏幕上的遮擋順序并非總是正確的

作為人類觀察者,我們很容易理解遮擋關系,比如一個人在一個柱子后面,那么柱子應該繪制在前面。但計算機并不具備這種直覺,必須通過規則來嚴格排序。

當前我們使用的是基于 Y 值的排序方法,即對象的 Y 坐標越小(越靠上),越晚繪制,從而“在后面”;Y 越大(越靠下),越早繪制,“在前面”。這個方法在多數情況下是有效的,但當角色站在某些塊上,或者和某些立體物體交錯的時候,就會出現排序錯誤。

舉例來說:

  • 如果角色站在一個高臺上,我們希望他被畫在高臺的上方;
  • 如果在他前方有一個柱子,即使該柱子與他高度相同,但因為柱子更靠近觀察者,它應該被畫在角色前面;
  • 如果只是簡單地根據 Y 值排序,這種情況容易出錯,角色可能會錯誤地出現在柱子前面或后面。

這個問題進一步復雜化的原因在于當前我們使用的排序點(sort point)是 tile(瓦片或圖塊)的中心點。如果角色剛好位于這個排序點附近,就會發生錯誤排序。例如:

  • 當角色剛好站在 tile 的 Y 中心點前方一點,就被當作在它“后面”;
  • 當角色稍微移過中心點一點,就被當作在它“前面”;
  • 實際上這兩種情況下視覺遮擋關系是一樣的,但計算上發生了斷裂。

為了解決這個問題,我們提出了一種思路:

  1. 引入獨立的排序點(sort anchor):每個圖塊或對象可以擁有一個獨立設置的排序錨點,而不是固定使用幾何中心。例如可以把排序點放在 tile 的底部后方,這樣不論角色在 tile 前面還是上面,排序結果都更加符合直覺。

  2. 避免排序點與角色重疊:將 tile 的排序錨點設置在角色無法站立的后方區域,這樣可以防止角色與 tile 的排序位置發生交錯重疊,確保遮擋正確。

  3. 進一步調整角色的排序點:有時候我們也需要調整角色的排序錨點,使得其遮擋邏輯更合理,例如放在角色腳下或陰影下方的位置。但這樣做會引入新的問題,比如當角色站在 tile 前面卻排序點落在 tile 后方,就可能會被 tile 遮擋。

因此,這個問題并不是僅靠移動一個點就能徹底解決的。特別是在陰影投射、腳下陰影貼圖等細節處理上,更容易暴露問題。

可能的解決方向還有:

  • 使用真正的 3D 空間數據進行遮擋判斷:我們本質上是在 2D 中模擬 3D 視圖。如果利用已有的 3D 結構信息,在排序時引入視角方向和相對深度信息,可能能解決一部分遮擋問題。

  • 使用 Z-bias 或圖層偏移處理特殊情況:比如我們可以對一些 tile 使用 Z 偏移,讓它們在排序時更靠前或更靠后,從而調整結果。但這可能只是一個權宜之計,不能完全解決所有情況。

這個問題的本質是:我們希望實現一個理想的視覺遮擋邏輯,而不僅僅是通過坐標排序來完成它。但這種“概念上的排序邏輯”不是傳統的 2D 渲染系統能直接支持的,因此必須通過調整排序錨點、引入額外規則、甚至綜合使用偽 3D 信息等多種手段配合實現。

這確實是一個非常棘手的問題,目前我們還沒有完全確定的解決方案,但可以確定的是,這個問題必須在渲染系統中被考慮進去,并且我們需要設計出穩定的機制來應對各種排序場景。最終不論這個邏輯放在渲染器內部還是外部邏輯層,排序的正確性都是必須要解決的核心問題。

黑板講解:考慮各種情況以獲得更多啟發

我們正在思考渲染排序的問題,試圖找出一種更合理的方式來決定場景中物體的繪制順序。場景中存在兩種排序因素:一個是Y軸(屏幕空間中的縱向位置),另一個是Z值(表示深度或高低)。而我們的問題主要來自于這些排序邏輯在一些特殊情況下會互相沖突,導致不符合直覺的渲染結果。

我們首先意識到一個現象:當一個對象的Z值低于另一個對象時,我們希望它被畫在另一個對象的“上方”——這主要影響的是像陰影這樣的貼地元素。當陰影所在的Z層低于角色所在的Z層,我們希望陰影能夠正常繪制在地面上。但如果Z層更高,就不希望陰影覆蓋角色。也就是說,陰影的繪制主要受Z值控制,而不是Y值。

相對的,對于角色和柱子這種“站立”的物體,它們之間的遮擋關系更多依賴Y軸。比如角色站在較后的地面上,柱子在前面,雖然兩者Z值可能相似,但我們希望根據Y坐標判斷前后關系。這說明,對于這類“直立”的位圖,Y軸排序更加重要。

我們又分析了一些具體情況,比如:

  • 角色站在后方平臺上,前方有一個高柱子。這個時候柱子應當遮擋角色,Z值可以幫助我們做出正確排序。
  • 若將柱子下移(Z值變小),它變成了前方的地面,此時我們希望角色能被正確地畫在柱子“上方”,以顯示角色站在地面前方。這就必須依賴Y排序。

通過這些例子我們得出一個結論:Z值排序在處理“同一個平面上的不同高度層次”時是必要的,而Y值排序在處理“不同前后位置的對象遮擋”時是必要的。問題是,如何將這兩種排序方式合理結合。

我們考慮過以下幾種排序方式:

  1. 單獨用Z值排序:在某些情況下能正常工作,比如繪制陰影。但會出現在Y軸前后遮擋關系錯誤的情況。
  2. 單獨用Y值排序:在大多數情況下可行,尤其是處理前后關系遮擋。但無法處理Z值造成的遮擋和陰影層次。
  3. 先按Y排序,再按Z排序:似乎是最可行的方式,在大多數情況下能得到正確的效果。但在陰影或極端交錯層次下可能仍然出錯。

進一步思考后我們發現,陰影這種半透明的特殊對象可能需要區別處理。一個可能的解決方案是:將陰影分離為每個地磚上的獨立貼圖,而不是一個統一的陰影圖層。這樣可以避免陰影與角色或柱子等物體發生錯誤排序。通過針對每塊地磚繪制陰影,就可以更容易地控制其排序層級。

類似地,對于角色和地面之間的關系,我們也可以通過將角色的排序錨點(sort point)設置在角色腳后的位置來控制其在場景中的繪制順序。這樣即使角色部分身體位于地磚前方,只要錨點正確地放在后面,它就能與地磚正確地排序。

最終,我們認識到要實現正確的視覺效果,必須:

  • 區分處理陰影類和實心類對象;
  • 制定統一的排序錨點規范,使每種對象在排序時能產生正確的結果;
  • 或者進一步引入3D視角信息(比如相機視線方向與對象空間信息),借助更完整的幾何結構進行排序判斷,盡管這可能會使系統復雜度上升;
  • 排序方式可能需要在“Y值主導”加上“Z值輔助”的基礎上做特殊情況處理或修正。

我們還需繼續驗證這些排序規則在更復雜場景中的穩定性和通用性,并最終將其納入渲染系統的排序邏輯中。這個問題確實很棘手,是一個不可回避且必須解決的核心問題之一。

黑板講解:根據實體是否直立決定排序點的位置

我們進一步深入分析了如何設置渲染排序點(sort point)的問題,并嘗試提出一種通用且穩定的排序機制。

首先我們考慮到:
對于“平放”的物體,比如地磚、平臺等,我們應該將排序點(sort point)設置在它的后緣,也就是靠近玩家的相機方向一側;
而對于“直立”的物體,比如角色、柱子等,我們應該將排序點設置在物體底部,也就是它與地面的接觸點。

這樣做的好處是:

  • 如果一個物體是直立的,它的排序點在底部,那么它就會與周圍物體在視覺上正確地進行前后遮擋判斷;
  • 如果一個物體是平鋪的,它的排序點在后方邊緣,當角色站在上面時角色的排序點會在更前方(Y值更大),從而角色會被正確地繪制在地面之上;
  • 一旦角色走下地塊,Y值發生變化,也能自然地導致角色繪制在地塊之后,實現正確遮擋。

在去除陰影這一復雜因素后,這種排序機制基本上可以正確應對各種場景。陰影由于其特殊性(通常為半透明),可通過單獨機制處理,因此不納入這一通用排序邏輯中。

我們得出如下的排序規則流程:

  1. 為每個渲染對象定義一個“排序點”(sort point)

    • 這個點與物體的“錨點”或“放置點”是獨立的;
    • 排序點負責決定該物體在整個渲染中的層級位置;
    • 排序點的位置是人為確定的,依據物體是“平躺”還是“直立”來設定。
  2. 排序邏輯

    • 首先按排序點的 Y 值 升序排序(Y 值越小越靠上,越早繪制);
    • 然后按 Z 值 升序排序,作為次要參考,用于處理同一Y值下的高度差;
    • 若還有需要,可以加一個人工的偏移值或“fudge factor”來進一步控制排序細節,例如角色身上堆疊的裝備等。

這種機制的優點是:

  • 排序邏輯清晰、統一,便于維護;
  • 可以避免依賴“物體是否直立”的額外標記,完全靠排序點的設定決定其排序行為;
  • 減少了不必要的復雜分支和判斷;
  • 更加貼合實際的視覺預期,不易出錯。

此外,我們也確認了,這樣的排序邏輯將“排序點”的概念與其他如“物體中心”、“碰撞盒”等概念徹底分離開,使其成為一個獨立的、專門用于渲染排序的概念。這種獨立性有助于在處理復雜場景(例如嵌套對象、復合動畫、特效層疊等)時更加靈活、清晰。

最后我們也思考了一些可能的問題,但目前看起來這種方式是可行的,不會引入新的錯誤邏輯,且簡化了整體架構。我們準備繼續往這個方向推進,在代碼中實際實現這種排序點和排序機制。

查看 game_render_group.cpp 中 PushBitmap 函數的排序邏輯

我們剛才在嘗試解決排序問題時引申出另一個與渲染排序密切相關的技術點,因此我們又轉向了對現有渲染系統中 push_bitmap 調用及其排序關鍵字(sort key)機制的分析與優化。

在當前的渲染流程中,當調用 push_bitmap 函數時,我們實際上是通過渲染基礎結構(render basis)來計算對應的排序關鍵字。也就是說,雖然函數可以傳入一個排序關鍵字,但真正使用的排序關鍵字通常是通過 push_render_element 這一步計算得出。

這意味著,如果我們想根據剛才討論的“排序點”規則來準確地指定每個圖像的排序方式,我們可能需要在 push_bitmap 調用的過程中就自行計算并傳遞排序關鍵字。這就要求我們對排序關鍵字的組成有明確的控制權,而不能完全依賴當前自動生成的方式。

    Result.SoftKey = ObjectTransform.SortBias +4096.0f * (2.0f * P.z + OriginalP.z + 1.0f * (real32)ObjectTransform.Upright) -P.y;

接著我們分析了代碼中的 CAlign 值,這個值主要是用于調試場景中的。它的作用是讓某些特定的圖像在調試時不被其他渲染對象遮擋,屬于一個專門為調試需求添加的臨時機制。在實際運行中它并不影響渲染排序的邏輯,因此并不需要納入我們目前排序系統的調整范圍。

回到排序關鍵字本身,我們注意到 basis_sort_key 的生成邏輯是基于 camera_transform 等信息的,其中最關鍵的是單位換算的 meters_to_pixels 值。我們意識到這可能會對排序精度或一致性造成影響,特別是在不同尺度轉換或透視變化下。然而,如果場景中所有對象都統一乘以相同的換算比例,那么這部分理論上不會影響相對排序,只需保持整體一致性即可。

因此,我們得出如下思路與計劃:

  1. 排序關鍵字需要手動生成并傳入
    為了實現我們前面討論的基于“排序點”的渲染順序控制,我們打算在 push_bitmap 調用中,顯式地生成并傳入排序關鍵字,而不是依賴渲染系統自動生成。排序關鍵字由排序點的 Y 值與 Z 值組合而成。

  2. 保持現有攝像機變換的統一性
    即便 meters_to_pixels 會影響最終值,只要所有物體的換算一致,排序仍是正確的。因此我們不打算修改換算機制,而是在生成排序關鍵字時,確保使用一致的單位處理。

  3. 需要建立統一的排序關鍵字生成函數
    我們需要在渲染接口層抽出一個統一的邏輯函數,用于從“世界坐標下的排序點”生成標準的 sort_key,并封裝到 push 調用中,以統一各處用法,避免每次都重復計算。

  4. 暫時忽略調試相關的 CAlign
    這部分不影響正式渲染流程,我們不計劃在此階段優化它。

總之,我們發現,要將“排序點”機制成功引入現有渲染框架,必須對排序關鍵字的生成過程進行改造,使其可控、透明、與視覺邏輯一致。這是一個關鍵步驟,也是我們正在著手解決的問題。接下來會進入實際編碼階段,嘗試將這些機制嵌入渲染管線。
在這里插入圖片描述

修改 GetRenderEntityBasisP,使其根據 PerspectiveZ、DisplacementZ、PerspectiveSortTerm、YSortTerm 和 ZSortTerm 計算 SortKey

我們在進一步推導渲染排序系統的細節時,確立了一種新的方式來處理排序關鍵字的生成與位圖的排序偏移問題。整個思路是圍繞“排序點”與實際圖像渲染位置之間的差異展開的,目標是實現更靈活、更精準的圖層排序邏輯,特別是在涉及圖像中心與排序基準點不一致時。


引入“排序點”的第二輸入

我們決定在渲染系統中引入一個第二個點用于排序。這個排序點可能是與圖像實際中心不同的位置,目的是允許我們為不同的圖像類型(比如平放和直立)指定不同的排序基準。

我們通過以下方式來處理這個排序點:

  • 將其視為相對于實際渲染位置的一個位移(delta)
  • 在變換完畢之后,再將這個位移值應用到已變換的位置上。
  • 位移值會受到縮放(scale)的影響,因此需要將位移乘以相應的縮放因子。

將排序偏移視為“排序偏差”(Sort Bias)

我們統一將這種相對位移處理為一種“排序偏差”,主要表現為:

  • X 方向上的位移對排序無影響,可以忽略;
  • Y 方向上的位移影響視覺遮擋,排序需考慮;
  • Z 方向上的位移用于微調相對高度(用于疊加邏輯,例如角色頭部、物品堆疊);

這意味著排序關鍵字其實是由三個維度組成:

  1. 層級 Z(Layer Z):用于區分場景層級,比如背景、前景、UI 等;
  2. Y 排序值(Y Sort Term):代表對象在平面中的前后位置;
  3. Z 排序值(Z Sort Term):代表在同一 Y 值下的精細疊加順序;

我們提出的排序公式為:

最終排序值 = Layer Z(最優先) + Y(次優先) + Z(最低優先)

調整向量結構,顯式表達排序維度

為避免混淆,我們打算將傳入渲染系統的坐標向量從原本的 v3 擴展為 v4,具體含義為:

(x, y, displacement_z, layer_z)
  • x, y:用于實際位置變換;
  • displacement_z:微調用于 Z 排序的偏移;
  • layer_z:作為最重要的排序維度,用于強制層次隔離;

我們將 displacement_z 放入 affine(仿射)部分,是因為它代表偏移;而將 layer_z 放入 perspective(透視)部分,是因為它決定整個排序層。


排序關鍵字的生成邏輯清晰劃分

整個排序關鍵字的生成被拆解為三個明確的部分:

  1. 透視排序項(Perspective Sort Term):基于 layer_z 產生,是最優先的排序指標;
  2. Y 排序項:用 y + sort_bias_y 表達,是主排序手段;
  3. Z 排序項:使用縮放后的 displacement_z * scale 得到,是補充層內排序的依據;

這種方式帶來的好處是排序邏輯清晰、結構統一、計算可控,也不會因渲染偏移中心不同而產生視覺錯亂。


排序點的使用策略與接口設計建議

我們目前在接口層的設計中有兩種方式可以選:

  1. 顯式傳入排序偏移(sort bias)
    保留位圖居中機制,由調用者傳入 Y 排序偏移值。

  2. 直接將圖像錨點放在排序點
    所有圖像都在排序點進行放置,bitmap 居中邏輯內置處理。

我們暫時沒有明確傾向于哪種方式,兩種方式都可行,主要依據是否需要靈活控制位圖的排序錨點。如果選擇第二種方式,我們可以省去很多偏移計算,讓排序邏輯更簡單。


小結

當前渲染排序系統的更新主要集中在以下幾個核心改進點上:

  • 引入排序點(與實際渲染點分離);
  • 排序關鍵字三層劃分:Layer Z、Y、Z;
  • 使用 v4 向量明確傳遞排序相關維度;
  • 排序偏差(sort bias)作為獨立概念處理;
  • 接口可以進一步抽象,統一處理縮放與位移邏輯。

接下來我們將逐步修改現有的渲染代碼路徑,確保排序關鍵字的生成與上述邏輯保持一致,確保各種場景下排序行為穩定、正確。

在這里插入圖片描述

考慮位圖中存在兩個重要點時的風險,以及它們對齊的程度

我們目前遇到的問題在于,一個位圖上存在兩個“關鍵點”的概念,而這兩個關鍵點在功能上是不同的:


兩類關鍵點的定義與用途

  1. 對齊關鍵點(Alignment Point)

    • 這是用于確定位圖在空間中旋轉和縮放的參考點。
    • 例如當進行旋轉或縮放操作時,該點保持不動,其余部分圍繞它變化。
    • 類似于“錨點”或“中心點”,影響圖像的視覺變換方式。
  2. 排序關鍵點(Sorting Point)

    • 這是用于在渲染隊列中確定圖像前后關系的點。
    • 一般反映圖像“落在地上的位置”或“遮擋基準”,用于決定繪制順序。
    • 該點對渲染順序敏感,但對幾何變換(如旋轉)沒有直接影響。

二者之間的一致性問題

我們在思考這兩個關鍵點在實際使用中是否一致,即它們是否經常是同一個點。

目前觀察來看:

  • 在某些情況下,這兩個點可以是同一個,例如:頂部對齊的立式人物貼圖,旋轉和排序都以腳底為基準。

  • 但在其他場景中,這兩個點可能不重合

    • 比如一個從頂部對齊縮放的物體,但它的排序是根據底部計算的;
    • 又比如一個橫向漂浮的UI元素,其中心旋轉,但排序參考左下角。

因此,我們不能默認這兩個點相同,否則會導致排序與變換出現沖突或不一致。


接下來的思考方向

我們需要進一步考慮以下問題,以完善系統設計:

  • 是否需要顯式分離對齊點與排序點?

    • 可以在系統中明確兩個參數,一個用于變換,一個用于排序;
    • 可以統一接口格式,但在內部處理邏輯上保持二者獨立。
  • 在實際使用中,對齊點和排序點之間的默認關系是否應保持一致?

    • 如果默認一致,是否提供“解耦”開關供特殊情況使用?
    • 如果默認不同,是否會增加使用負擔?
  • 是否存在第三類關鍵點,例如碰撞檢測點?

    • 如果存在,是否也應當設計為獨立參數處理?

總結

我們目前識別出位圖存在兩個獨立功能的“關鍵點”:

  1. 用于旋轉/縮放的對齊點;
  2. 用于渲染排序的排序點;

它們在部分場景中重合,但不能默認相同。接下來需要在系統中顯式支持這兩個點的獨立性,以避免排序與變換邏輯之間的混淆,從而確保渲染行為在各種使用情境下都能正確工作。

黑板講解:對多段式身體結構的排序問題

我們考慮一個多段式的身體結構,例如一個關節連接的人物角色,這類角色已經存在并且未來會越來越多。這種結構中,每一部分通常是獨立的位圖,比如軀干、手臂、腿等,這些部分通過關節相連,并作為整體進行旋轉或移動。


位圖對齊點的意義

當我們要圍繞某個點進行旋轉時,這個點顯然應當是該位圖的對齊點(alignment point)——通常是關節或連接點:

  • 例如旋轉上臂時,其對齊點應在肩部;
  • 旋轉小臂時,對齊點應在肘部。

這部分邏輯是明確的,也非常合理,當前系統對此支持良好。


位圖排序的問題:組合體作為一個整體排序

但問題在于這些位圖的排序方式:

  • 這些位圖應該作為一個整體進行排序
  • 排序應該基于整個角色的某個公共參考點(例如腳底中心、角色根節點等);
  • 不是每個部位按自己的排序點單獨參與全局排序

換句話說:

  • 排序基準只需要一個;
  • 內部結構的排序僅依據預設的繪制順序或層級,而不依賴各自的空間位置。

例如:

  • 一條腿可能由大腿、小腿、腳三部分組成;
  • 雖然它們在空間中有不同的Y坐標,但它們在渲染時應始終依照一個整體排序規則
  • 是否遮擋別的對象,只看整個腿的“參考點”在哪,而不是單獨考慮腳或大腿的位置。

內部排序由結構定義,而非位置推導

對于這種組合體結構:

  • 各子部分之間的渲染順序,應由固定的結構順序或“藝術家意圖”定義;
  • 而非根據每個位圖的世界坐標Y值或Z偏移自動計算。

這樣可以避免由于肢體的空間變化造成不合理的遮擋錯誤,例如:

  • 肘部比肩膀略低,不應該因此被提前渲染;
  • 腳掌向上踢起,也不應因為Y值更高而被遮擋掉其他身體部分。

總結與結論

我們需要區分以下兩層排序邏輯:

  1. 整體排序

    • 多段組合體整體只使用一個排序關鍵點;
    • 決定其與其他對象的前后關系。
  2. 局部排序

    • 組合體內部的各部分遵循固定繪制順序;
    • 不依賴位置坐標排序;
    • 與位圖的對齊點(用于旋轉)分離。

因此,我們系統應支持:

  • 設定“組合體排序基準點”,所有子元素共享它;
  • 子元素按指定順序繪制,無需單獨參與全局排序;
  • 對齊點獨立用于每個子元素的局部變換(旋轉、縮放等)。

這樣才能在多關節角色中實現既準確的空間遮擋邏輯,又靈活的動畫變換效果。

在 game_render_group.cpp 中引入 ComputeSortKey 以支持正確排序關節式人物

我們目前的結論是:排序點(Sort Point)應該是一個完全獨立于位圖變換流程之外的概念,并不屬于單個位圖或其局部變換參數中的一部分。


排序點的獨立性和來源

我們在做投影、位移 Z(Displacement Z)等操作時,實際參與排序的值,應該來自獨立計算得到的排序鍵(Sort Key)

  • 排序值不應該由每個位圖單獨計算;
  • 而是由上層邏輯(例如角色、組合體、實體等)統一設定;
  • 這個排序鍵在構建角色或組合體時一次性生成,然后被傳遞給所有子部分共享使用。

舉例:

  • 一個多關節人物由多個子位圖組成,如頭、軀干、手臂、腿等;
  • 排序值應在角色創建階段就被確定,例如設定為“角色根部位置 Y”;
  • 所有子位圖在繪制時,都使用這一共同的排序鍵;
  • 子位圖之間僅通過局部繪制順序控制彼此的顯示層級,而不參與全局排序運算。

排序鍵的傳遞與使用

當我們調用渲染邏輯并執行相關變換時:

  • 排序鍵可以作為一種對象變換的一部分被傳遞下來;
  • 或者以顯式參數的形式傳入,獨立于其他空間變換參數;
  • 這個排序鍵由調用者提前準備好,并統一用于組合體內的所有元素。

換句話說:

  • 位圖變換繼續用于控制位圖的旋轉、縮放、位置等;
  • 排序值不再依賴于單個位圖的計算;
  • 排序鍵是更高層抽象所提供的內容,例如角色系統、層級系統等。

組合體內部的排序:相對結構,而非計算推導

組合體內部的排序應依賴于預設的結構性信息,如:

  • 層級定義;
  • 局部順序;
  • 美術數據文件中的繪制順序。

而不應依賴各個組件的實際空間坐標。


總結

我們的渲染排序邏輯應當遵循以下結構:

  1. 排序鍵應由外部系統提前設定
    排序點(Sort Point)在角色或組合體初始化時就確定,并在所有子元素中復用。

  2. 排序鍵從對象變換中解耦
    位圖變換(Transform)專注于變換,排序鍵專注于渲染層級判斷。

  3. 組合體內部排序基于結構性定義
    子元素不再參與全局排序值的計算,而是根據結構或手工設定順序繪制。

這種方式能帶來更清晰、更可控的渲染排序邏輯,尤其在處理復雜的關節角色、UI組件集合、動態組對象等場景時,能有效避免遮擋錯誤與邏輯混亂。

暫時撤銷 GetRenderEntityBasisP 中的修改

目前我們在一天的開發尾聲,對渲染排序邏輯的一些實現細節進行了反思和回退,同時進一步明確了對投影坐標中 Z 值的處理策略。


回退當前修改的原因

我們決定臨時撤銷部分代碼更改,原因在于:

  • 排序邏輯目前仍存在一些不確定性,特別是在縮放因子與排序值之間的關系上;
  • 投影坐標中的 Z 值(即 Perspective Z)是否應當和其他值一起縮放目前尚未完全確定;
  • 為了保持系統穩定性和后續調試清晰性,暫時選擇回退更改,保留已有的處理路徑。

投影 Z 值(Perspective Z)的縮放疑問

我們目前面對的問題是:

  • 是否應該對透視 Z 值應用縮放(scale)操作?
  • 投影后的 Z 值參與排序時,是否應該和 XY 變換中使用的 scale 保持一致?

目前的想法如下:

  • XY 投影值在渲染系統中經過了統一的單位轉換(如米轉像素),Z 值作為排序參與者,是否也應該被一致地轉換,目前不確定;
  • 如果系統中所有值都統一應用了縮放(包括 bitmap 位置、尺寸、偏移等),那么 Z 值也跟著縮放會更一致;
  • 但另一方面,Z 是用于排序的邏輯值,是否需要和屏幕空間保持一致,取決于排序設計本身。

小結

我們現在的決定:

  1. 暫時回退排序處理相關的代碼改動
  2. 保留當前投影 Z 值的處理方式,避免對其縮放,直到理清是否需要一致處理
  3. 后續在統一的排序策略確定后,再決定是否對 Z 值進行縮放處理

這是一個穩妥的做法,既保留了系統現有的穩定性,又為后續更清晰的排序邏輯設計預留了空間。
在這里插入圖片描述

運行游戲并觀察混亂效果

目前我們正在為接下來的開發周期做出規劃,基于當前渲染排序系統的改進方向,決定從下周開始進入“世界模式”的構建階段。在這一階段,我們的重點是將已有的基礎機制整合成更完整、統一的排序和渲染系統。


當前狀態總結

  • 基礎排序機制已初步建立,部分位圖對象的排序和渲染方式已經可用;
  • 位圖組排序的基本邏輯已被清晰描述,接下來需要將其以更系統的方式實現;
  • 部分臨時性調試代碼(如錯誤注入、臨時標記邏輯)已被移除,以保持代碼清潔;
  • 整體系統進入了可以進一步測試和穩定化的階段。

下一階段目標:“世界模式”構建

計劃從下周開始:

  1. 進入“世界模式”工作流
    將當前“位圖片段”和“渲染排序”機制,提升為處理完整“世界對象”集合的框架;

  2. 實現完整的排序組邏輯

    • 構造排序組(sort key group)機制;
    • 允許一個對象的多個組件共享一個主排序鍵;
    • 在構建排序組時指定排序錨點,確保組內排序有統一參考點;
    • 實現“整體對象排序 + 內部固定結構”的組合渲染。
  3. 定義并完善排序流程

    • 明確“開始一個 sort key”的入口;
    • 實現“排序組起始 + 自動傳播 + 排序錨定”的自動化邏輯;
    • 提供必要的接口或宏,將其集成到渲染調度流程中。

小結

我們已為世界對象的統一渲染和排序打下基礎,接下來將:

  • 構建以排序鍵為核心的統一分組系統;
  • 將片段渲染邏輯提升至完整對象渲染邏輯;
  • 明確各個片段之間如何協作排序,以實現正確、穩定的可視輸出。

這將使整個渲染系統從“逐個位圖拼接”提升到“整體世界分層排序”的完整階段。
在這里插入圖片描述

制定在 game_entity.cpp 中處理關節式人物的計劃,留待下周

我們為下周的任務制定了明確的計劃,目標是在幾天內徹底理順當前的渲染與排序機制,重點集中在**支持帶骨架結構的可動角色(articulated figures)**的渲染提交流程上。具體工作內容與目標如下:


渲染提交邏輯的重構目標

  1. 以骨架整體創建排序鍵(sort key)
    在渲染提交流程中,先為整組可動結構創建一個統一的排序鍵;

  2. 分片提交順序保持穩定
    所有從屬于該骨架的子組件(如身體各部位)在被統一插入渲染序列后,仍然能根據它們被提交的先后順序穩定渲染;

  3. 剔除多余機制,簡化接口

    • 當前使用的“排序偏移(sort bias)”和“位移量(displacement)”機制可被移除;
    • 位圖的對齊點(pivot point)已通過正確機制定義,所有定位與旋轉基準可通過對齊點完成,無需額外偏移;
    • 用戶現在可以直接控制排序值,避免在渲染組內部進行復雜調整;

排序鍵生成與傳遞機制優化

  1. 實現排序鍵變換函數(sort key transform)

    • 實現一個可以將實體基礎信息變換為排序鍵的函數;
    • 此函數將在渲染準備階段調用,負責返回最終用于排序的鍵值;
  2. 排序鍵類型調整為 u32 二元組u32 x, u32 y):

    • 將浮點型排序值轉換為整型,便于之后進行高效比較與組織;
    • 利用低位保留原始提交順序(或用于手動設置局部排序權重);
    • 或者使用穩定排序算法(如 stable sort)來自動保留相對順序;

總結

通過上述改動,我們將實現:

  • 可動角色的各個部位以統一的排序錨點進行整體渲染;
  • 渲染順序既受全局排序控制,又能保持本地一致性;
  • 徹底清除冗余的偏移量與排序偏置參數,接口更清晰;
  • 排序鍵結構簡潔高效,適配當前渲染系統架構。

這將極大提高排序系統的靈活性與可控性,為接下來的更復雜角色和分層世界的支持打下基礎。

問答環節

從郵件中沒太明白——你還打算休息一下并做一個編程入門系列嗎?

我們討論過程中明確表示,不打算進行所謂的“利率編程”相關工作,也不記得曾經承諾過要做這件事。這部分內容明確了目前的工作重點不會涉及相關方向,也不會中斷當前的開發任務去處理這些不相關的內容。

在澄清這一點之后,我們繼續推進當前的技術探討,提出了另一個關于 YZ 方向的使用場景值得考慮。這說明盡管我們否定了與利率編程相關的內容,但仍然專注于渲染系統中與空間變換和排序有關的問題,尤其是涉及到 YZ 平面或坐標軸方向的場景處理,可能關系到視角、深度或圖層分離的精度處理需求。我們將繼續圍繞這類問題進行探索和優化。

一個關于 Y/Z 排序的額外用例:“平面”物體疊放在其他“平面”物體上(比如地毯在地板上),如果上面的物體比下面的還大,這種情況該怎么設置 Y 排序位置?

我們探討了一個關于排序的特殊場景:在一個平面物體上方疊放另一個平面物體,比如一張地毯鋪在地板上。在這種情況下,如何設置 ZY 方向的排序位置尤其復雜,特別是當上層物體的尺寸大于下層物體時,會造成覆蓋范圍廣、可能涉及多個底層圖塊的問題。

我們傾向于將這種情況視作與關節式結構類似的情形來處理,即作為一個整體來排序。初步思路是:只要這些物體在“地板塊”層面上是分割好的,那么排序可以通過 Z 值來簡單管理。也就是說,只需要確保上方物體的 Z 值略高于下方物體,就能保證正確的渲染順序。

不過我們也認識到,如果上方的物體尺寸覆蓋較廣,橫跨多個底層圖塊,那這種簡單的 Z 值方式可能并不完美,很難在所有情況下都確保視覺上嚴格正確的排序。這方面缺乏一個絕對可靠的處理方案,目前還不確定如何在所有復雜情境下實現理想的視覺效果。

這個問題提示我們,在設計排序系統時,可能需要引入更復雜的處理機制,比如明確的遮擋優先級、區域劃分、或者特殊規則來處理類似地毯鋪地板的情形。我們會在之后的實現中持續探索更健壯的解決方式。

你最初想比 C 語言入門更深入一些,后來有沒有改變想法?

我們提到了一些未來想要實現的更復雜或更嚴肅的功能或系統,雖然早期曾經有過相關的設想或者討論,但明確指出這些內容不會在當前階段實現。當前的重心仍然是集中在完成現有的核心項目,也就是說,只有在這個主要項目(例如我們正在推進的)完成之后,才會考慮進入這些更深入、系統性更強的方向。

這表明我們目前的開發節奏是階段性的,優先級清晰:先保證當前項目的完整與質量,之后才是探索更加復雜的新領域。此外,這也強調了一個現實的開發策略——并非所有愿景都能立刻實現,而需要根據項目周期和資源安排逐步推進。

因此,盡管我們對某些更高級的系統或實驗仍然感興趣并保持愿景,但這些工作被明確推遲到未來某個較為自由或后續的階段來進行,而不會干擾當前項目的推進。我們保持計劃性,同時也為未來預留了可能性。

你怎么看把實體表示為簡單的 3D 物體,比如用圓柱表示人物,用立方體表示瓷磚和房間?

我們探討了在渲染中使用簡化的三維幾何體(比如用圓柱體代表角色、用立方體表示瓦片和房間)來簡化處理流程的可能性。這種做法的一個主要優點是可以規避使用純二維位圖在排序上容易出現的問題,尤其是在依賴Y軸進行深度排序時,排序的穩定性和可預測性很差。

我們認為,可能使用帶有Z值的“板子”(plates)來承載每一個精靈圖,是一種合理的折中方法。這在現代游戲開發中其實已經比較常見:每個精靈都會映射到一個扁平的3D平面上,而這個平面可以擁有一個Z值,從而借助Z緩沖(Z-buffer)或其他深度測試機制來進行排序。這樣做可以大大減少我們在排序算法上遇到的問題,并提高圖形渲染的一致性與可控性。

不過,我們同時也表達了顧慮。當前項目的初衷是盡量避免引入復雜的三維系統,因為那可能會讓項目開發的門檻變高、學習曲線變陡。而這正是我們希望通過保持“純2D”來規避的風險。因此,現在還不能確定我們是否最終會選擇引入3D“板子”的方式。或許目前的方案已經足夠用了,也可能隨著項目深入,我們不得不引入一定程度的3D支持來解決無法繞開的問題。

整體來看,我們保持開放態度:傾向于先以簡單方案推進,觀察其效果,再決定是否引入更復雜的3D機制。這樣既控制了復雜度,也保留了升級空間。

黑板講解:地毯與地板的排序方式

關于地毯覆蓋在瓷磚上的排序問題,確實存在比較棘手的情況。這個問題的核心在于如果我們只是單純按照Y軸進行排序,會出現矛盾:地毯應該覆蓋在瓷磚之上,所以瓷磚不應該被排序到地毯前面;但如果給地毯設定一個排序點,使其在所有瓷磚之后,那么一個站在地毯上的角色可能會被地毯“遮擋”,排序反而出現了錯誤。

這個排序矛盾的根本難題是排序點的位置無法兼顧這兩種關系:既讓地毯在瓷磚前面,又不讓地毯遮擋站在它上的角色。換句話說,排序點不能簡單地用一個固定的Y值來表示,因為不同元素的空間關系更加復雜。

因此,我們認為要真正解決這個問題,需要從3D空間的角度來重新思考和處理。在3D中,排序會考慮物體的實際深度和空間位置變化,可能需要對排序值進行插值處理。比如,地毯是平面的,深度值在它的范圍內基本不變,而瓷磚的位置深度是連續變化的,這樣才能更準確地反映視覺關系。

然而,即使是這樣,我們也沒有碰到過真正交叉重疊的情況,理應不存在深度值交錯的問題,所以其實不需要處理物體深度“變化”的復雜情況。問題在于如何找到一種合理的表達方式來準確表示這些物體間的層級關系和空間關系。

總的來說,現階段這個排序難題還需要更詳細地在三維空間里做推敲和驗證,只有理解了3D中物體的空間關系和深度排序機制,才能設計出在二維排序中也能合理復現的解決方案。

黑板講解:將其放入 3D 空間中考慮

我們在觀察一個場景時,如果有類似這樣的物體排列,我們可以知道某個物體是在另一個物體的前面,因為從相機視角出發,射線在穿過第一個物體的時間點會比穿過第二個物體的時間點更早。換句話說,當射線從相機發出時,哪個物體先被“遇到”,那個物體就排在前面。

具體來說,這里的關鍵是射線與物體平面的交點以及交點在相機平面上的投影位置。不同的物體平面在相機視角下形成的交點路徑不同,比如一個物體的交點沿著某條線移動,而另一個物體則是沿另一條線移動,這種差異決定了它們在視線上的遮擋關系。

此外,即使兩個物體整體看上去一個在另一個前面,但它們的不同部分可能會有不同的排序關系:物體的一部分可能在前,而另一部分則不在前。這說明排序不能只考慮整體,而要關注具體平面上的具體部分。

目前,我們對這個問題的理解還不夠完整,這涉及到空間中物體的深度關系和它們在相機視角下的表現,排序的復雜性超出了簡單的規則。還有更多細節和原理需要進一步研究,才能找到更準確的排序方法,確保在實際渲染中各個部分能夠正確表現前后關系。總結來說,這個問題需要更深入地分析和探索,我們的理解還有待完善。

或許你需要在 Y 和 Z 方向分別對物體排序,然后在 A 在 Y 排序中排在 B 前而 Z 排序中排在 B 后時解決沖突?

考慮到排序問題時,有一個想法是對物體分別按Y軸和Z軸進行排序,然后再解決兩者排序沖突。具體來說,如果物體A在Y軸排序中排在物體B前面,但在Z軸排序中卻在物體B后面,那么這種沖突需要特別處理。理論上,如果一個物體在X、Y、Z三個維度上都排在另一個物體前面,那么排序應該是無誤的。

不過,這個方法雖然有趣,但仍然存在困難。一個主要問題是,物體并不是只有單一的Y值,它們可能在空間中占據范圍,這使得單純按Y值排序變得復雜,容易出現模糊或矛盾的情況。為了避免這些問題,不應簡單“作弊”地把物體放在不同位置來適應排序。

同時,也有疑問是否過于復雜化問題,或許真正關鍵的只是Z值(深度值)。也就是說,或許Z軸排序才是我們最應該關注和依賴的。

總的來說,這個問題還沒有完全搞明白,需要更多時間和專門的探討,甚至可以專門開一個完整的討論環節來徹底理清這些排序沖突和邏輯。現在還沒有找到最終的解決方案,理解還不夠全面。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/81691.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/81691.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/81691.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

一些C++入門基礎

關鍵字 圖引自 C 關鍵詞 - cppreference.com 命名空間 命名空間解決了C沒辦法解決的各類命名沖突問題 C的標準命名空間:std 命名空間中可以定義變量、函數、類型: namespace CS {//變量char cs408[] "DS,OS,JW,JZ";int cs 408;//函數vo…

學習筆記:黑馬程序員JavaWeb開發教程(2025.4.6)

12.4 登錄校驗-JWT令牌-介紹 JWT(JSON Web Token) 簡潔是指JWT是一個簡單字符串,自包含指的是JWT令牌,看似是一個隨機字符串,但是可以根據需要,自定義存儲內容 Header是JSON數據格式,原始JSO…

香港科技大學物理學理學(科學計算與先進材料物理與技術)碩士招生宣講會——深圳大學

香港科技大學物理學理學(科學計算與先進材料物理與技術)碩士招生宣講會——深圳大學專場 🕙時間:2025年5月23日(星期五)14:30 🏫地點:深圳大學滄海校區致原樓1101 &#x1f9d1…

數據庫優化技巧:MySQL 重復數據查詢與刪除(僅保留一條)的性能優化策略

目錄 一、查詢重復數據 二、刪除重復數據 方法 1:創建臨時表,操作完成后再刪除臨時表(安全可靠,適合大表) 步驟 1:創建臨時表存儲需刪除的 ID 步驟 2:根據臨時表刪除數據 方法 2&#xff1a…

分布式ID生成器:原理、對比與WorkerID實戰

一、為什么需要分布式ID? 在微服務架構下,單機自增ID無法滿足跨服務唯一性需求,且存在: ? 單點瓶頸:數據庫自增ID依賴單表寫入 ? 全局唯一性:跨服務生成可能重復 ? 擴展性差:分庫分表后ID規…

Golang的代碼注釋規范與實踐

# Golang的代碼注釋規范與實踐 一、注釋的重要性 代碼注釋是程序員交流的橋梁 代碼注釋是程序員之間溝通交流的重要形式,良好的注釋能夠幫助其他開發者更快地理解代碼的意圖和實現方式。 代碼維護離不開注釋 在項目維護過程中,良好的注釋能夠幫助開發者回…

Qt讀取Excel文件的技術實現與最佳實踐

目錄 一、成果展示二、核心方法及原理1. QAxObject(基于COM接口)2. 第三方庫QXlsx3. ODBC數據庫驅動三、實現步驟詳解1. QAxObject讀取Excel(需安裝Excel/WPS)2. QXlsx讀取Excel(跨平臺方案)四、技術選型與對比五、應用場景與優化建議1. 高頻數據處理2. 跨平臺工具開發3.…

機器學習第十五講:決策樹全面講解:像玩“20個問題“游戲猜身份[特殊字符]

機器學習第十五講:決策樹全面講解:像玩"20個問題"游戲猜身份🎮 資料取自《零基礎學機器學習》。 查看總目錄:學習大綱 關于DeepSeek本地部署指南可以看下我之前寫的文章:DeepSeek R1本地與線上滿血版部署&…

CCpro工程編程軟件

CXpro?? 是一個軟件應用套件,用以完成 ABB Cylon CB 系列 BACnet 控制器的設計、工程、編程、配置、測試、調試和維護。 主要優勢 CXpro?? 提供改進的導航和頁面命名,使開發人員能夠輕松地圍繞大型策略進行操作。它也允許立即訪問可快速更新的點和…

數據庫(二):ORM技術

什么是 ORM? ORM(Object-Relational Mapping) 是一種用于實現 對象模型(面向對象)與關系模型(數據庫)之間映射的技術,使程序員可以通過操作對象的方式訪問數據庫數據,而無…

系統設計——項目設計經驗總結1

摘要 在系統設計的時候,注意域的區分,功能區分、類的區分、方法區分范圍和定義。在系統設計的時候的,需要思考類、方法在什么情況下會涉及到修改,遵循記住:一個類應該只有一個原因被修改! 當不滿足&#x…

【Java高階面經:微服務篇】3.熔斷機制深度優化:從抖動治理到微服務高可用架構實戰

一、熔斷抖動的本質剖析與核心成因 1.1 熔斷機制的核心價值與抖動危害 熔斷機制作為微服務彈性架構的核心組件,通過模擬電路斷路器邏輯,在服務出現異常時自動阻斷請求鏈,防止故障擴散引發雪崩。但頻繁的“熔斷-恢復-熔斷”抖動會導致: 用戶體驗惡化:請求成功率波動大,響…

深入淺出人工智能:機器學習、深度學習、強化學習原理詳解與對比!

各位朋友,大家好!今天咱們聊聊人工智能領域里最火的“三劍客”:機器學習 (Machine Learning)、深度學習 (Deep Learning) 和 強化學習 (Reinforcement Learning)。 聽起來是不是有點高大上? 別怕,我保證把它們講得明明…

【動手學深度學習】1.1~1.2 機器學習及其關鍵組件

目錄 一、引言1.1. 日常生活中的機器學習1.2. 機器學習中的關鍵組件1)數據2)模型3)目標函數4)優化算法 一、引言 1.1. 日常生活中的機器學習 應用場景: 以智能語音助手(如Siri、Alexa)的喚醒…

Pytorch針對不同電腦配置詳細講解+安裝(CPU)

一、前言 安裝pytorch前,應按照我前邊的博文中,安裝完anaconda和pycharm,并且配置完環境變量以后哈。 Pytorch是什么? 它是一個庫,是一個開源的機器學習框架,專注于深度學習任務,由Facebook的人工智能研…

[python] 輕量級定時任務調度庫schedule使用指北

schedule是一款專為簡化定時任務調度而設計的Python庫,它通過直觀的語法降低了周期性任務的實現門檻。作為進程內調度器,它無需額外守護進程,輕量且無外部依賴,適合快速搭建自動化任務。不過,該庫在功能完整性上有所取…

React的合成事件(SyntheticEventt)

文章目錄 前言 前言 React的合成事件(SyntheticEvent)是React為了統一不同瀏覽器的事件處理行為而封裝的一套跨瀏覽器事件系統。它與原生事件的主要區別如下: 1. 事件綁定方式 ? 合成事件:使用駝峰命名法綁定事件(如…

報表控件stimulsoft教程:如何在報表和儀表板中創建熱圖

Stimulsoft Ultimate (原Stimulsoft Reports.Ultimate)是用于創建報表和儀表板的通用工具集。該產品包括用于WinForms、ASP.NET、.NET Core、JavaScript、WPF、PHP、Java和其他環境的完整工具集。無需比較產品功能,Stimulsoft Ultimate包含了…

[免費]蒼穹微信小程序外賣點餐系統修改版(跑腿點餐系統)(SpringBoot后端+Vue管理端)【論文+源碼+SQL腳本】

大家好,我是java1234_小鋒老師,看到一個不錯的微信小程序醫院預約掛號管理系統(uni-appSpringBoot后端Vue管理端),分享下哈。 項目視頻演示 【免費】蒼穹微信小程序外賣點餐系統修改版(跑腿點餐系統)(SpringBoot后端Vue管理端) Java畢業設計…

Dify 快速上手 MCP!Java 搭建 MCP Server 接入 Dify詳細實戰攻略

近期,MCP協議在AI領域熱度飆升,成為眾多開發者和行業人士熱議的焦點。下文先介紹MCP究竟是什么?再詳細講下 Dify DeepSeek Java開發 MCP server 實戰。 一、MCP的基本概念 MCP,全稱為模型上下文協議(Model Context P…