• <noscript id="e0iig"><kbd id="e0iig"></kbd></noscript>
  • <td id="e0iig"></td>
  • <option id="e0iig"></option>
  • <noscript id="e0iig"><source id="e0iig"></source></noscript>
  • UnityShader學習——渲染優化技術(優化方法)

    標簽: 計算機圖形學

    CPU

    一、減少draw call數目

    我們最常看到的優化技術大概就是批處理(batching)了。批處理的實現原理就是為了減少每一幀需要的draw call數目。為了把一個對象渲染到屏幕上,CPU需要檢查哪些光源影響了該物體,綁定shader并設置它的參數,再把渲染命令發送給GPU。當場景中包含了大量對象時,這些操作就會非常耗時。一個極端的例子是,如果我們需要渲染一千個三角形,把它們按一千個單獨的網格進行渲染所花費的時間要遠遠大于渲染一個包含了一千個三角形的網格。在這兩種情況下,GPU的性能消耗其實并沒有多大的區別,但CPU的draw call數目就會成為性能瓶頸。因此,批處理的思想很簡單,就是在每次面對draw call時盡可能多地處理多個物體

    使用同一個材質的物體可以一起處理。這是因為,對于使用同一個材質的物體,它們之間的不同僅僅在于頂點數據的差別。我們可以把這些頂點數據合并在一起,再一起發送給GPU,就可以完成一次批處理。Unity中支持兩種批處理方式:

    1.動態批處理
    • 實現原理:每一幀把可以進行批處理的模型網格進行合并,再把合并后模型數據傳遞給GPU,然后使用同一個材質對其渲染。
    • 優點
      • 一切處理都是Unity自動完成的,不需要我們自己做任何操作(場景中有一些模型共享了同一個材質并滿足一些條件,Unity就可以自動把它們進行批處理)。
      • 物體可以移動(處理每幀時Unity都會重新合并一次網格)。
    • 缺點
      • 限制很多,可能一不小心就會破壞了這種機制,導致Unity無法動態批處理一些使用了相同材質的物體。這些條件有:能夠進行動態批處理的網格的頂點屬性規模要小于900(如果shader中需要使用頂點位置、法線和紋理坐標這3個頂點屬性,它的頂點數目不能超過300)。多Pass的shader會中斷批處理等。
    2.靜態批處理
    • 實現原理

      • 靜態批處理的實現非常簡單,只需要把物體面板上的Static復選框勾選上即可(實際上我們只需要勾選Batching Static即可)。在運行時查看每個模型使用的網格,會發現它們都變成了一個名為Combined Mesh (roo:scene)的東西。
      • 只在運行開始階段,把需要進行靜態批處理的模型合并到一個新的網格結構中,這意味著這些模型不可以在運行時刻被移動。但由于它只需要進行一次合并操作,因此,比動態批處理更加高效。
      • 在內部實現上,Unity首先把這些靜態物體變換到世界空間下,然后為它們構建一個更大的頂點和索引緩存。對于使用了同一材質的物體,Unity只需要調用一個draw call就可以繪制全部物體。而對于使用了不同材質的物體,盡管仍然需要調用多個draw call,但可以減少這些draw call之間費時的狀態切換。
      • 如果場景中包含了除了平行光以外的其他光源,并且在shader中定義了額外的Pass來處理它們,這些額外的Pass部分是不會被批處理的。
    • 優點

      • 自由度很高,限制很少(適用于任何大小的幾何模型)。
    • 缺點

      • 可能會占用更多的內存(如果在靜態批處理前一些物體共享了相同的網格,那么在內存中每一個物體都會對應一個該網格的復制品,VBO(Vertex BufferObject,頂點緩沖對象)的數目會變大)。
      • 經過靜態批處理后的所有物體都不可以再移動了(即便在腳本中嘗試改變物體的位置也是無效的)。
    3.關于共享材質

    無論是動態批處理還是靜態批處理,都要求模型之間需要共享同一個材質。但不同的模型之間總會需要有不同的渲染屬性,例如,使用不同的紋理、顏色等。這時,我們需要一些策略來盡可能地合并材質(只要我們調整了參數,就會影響到所有使用這個材質的對象):

    • 材質的紋理不同:我們可以把這些紋理合并到一張更大的紋理中,這張更大的紋理被稱為是一張圖集(atlas)。一旦使用了同一張紋理,我們就可以使用同一個材質,再使用不同的采樣坐標對紋理采樣即可。
    • 顏色不同、某些浮點屬性不同:使用網格的頂點數據(最常見的就是頂點顏色數據)來存儲這些參數。

    如果我們需要在腳本中訪問共享材質,應該使用Renderer.sharedMaterial來保證修改的是和其他物體共享的材質,但這意味著修改會應用到所有使用該材質的物體上。另一個類似的API是Renderer.material,如果使用Renderer.material來修改材質,Unity會創建一個該材質的復制品,從而破壞批處理在該物體上的應用,這可能并不是我們希望看到的。

    4.批處理的注意事項
    • 盡可能選擇靜態批處理,但得時刻小心對內存的消耗,并且記住經過靜態批處理的物體不可以再被移動。
    • 如果無法進行靜態批處理,而要使用動態批處理的話,那么請小心上面提到的各種條件限制。例如,盡可能讓這樣的物體少并且盡可能讓這些物體包含少量的頂點屬性和頂點數目。
    • 對于游戲中的小道具,例如可以撿拾的金幣等,可以使用動態批處理。
    • 對于包含動畫的這類物體,我們無法全部使用靜態批處理,但其中如果有不動的部分,可以把這部分標識成“Static”。
    • 由于批處理需要把多個模型變換到世界空間下再合并它們,因此,如果shader中存在一些基于模型空間下的坐標的運算,那么往往會得到錯誤的結果。一個解決方法是,在shader中使用DisableBatching標簽來強制使用該Shader的材質不會被批處理。
    • 使用半透明材質的物體通常需要使用嚴格的從后往前的繪制順序來保證透明混合的正確性。對于這些物體,Unity會首先保證它們的繪制順序,再嘗試對它們進行批處理。這意味著,當繪制順序無法滿足時,批處理無法在這些物體上被成功應用。


    GPU

    一、減少需要處理的頂點數目

    1.優化幾何體
    • 建模要盡可能減少模型中三角面片的數目。
    • 一些對于模型沒有影響、或是肉眼非常難察覺到區別的頂點都要盡可能去掉。
    • 為了盡可能減少模型中的頂點數目,美工人員往往需要優化網格結構。在很多三維建模軟件中,都有相應的優化選項,可以自動優化網格結構。
    • 移除不必要的硬邊以及紋理銜接,避免邊界平滑和紋理分離。

    在Unity的渲染統計窗口中,我們可以查看到渲染當前幀需要的三角面片數目和頂點數目。Unity中顯示的數目往往要多于建模軟件里顯示的頂點數。這是因為,三維軟件更多地是站在我們人類的角度理解頂點的,即組成幾何體的每一個點就是一個單獨的點。而Unity是站在GPU的角度上去計算頂點數的。在GPU看來,有時需要把一個頂點拆分成兩個或更多的頂點。它們的本質,其實都是因為對于GPU來說,頂點的每一個屬性和頂點之間必須是一對一的關系。這種將頂點一分為多的原因主要有兩個:

    • 為了分離紋理坐標(uv splits)。建模時一個頂點的紋理坐標有多個。例如,對于一個立方體,它的6個面之間雖然使用了一些相同的頂點,但在不同面上,同一個頂點的紋理坐標可能并不相同。對于GPU來說,這是不可理解的,因此,它必須把這個頂點拆分成多個具有不同紋理坐標的頂點。
    • 為了產生平滑的邊界(smoothing splits)。平滑邊界也是類似的,不同的是,此時一個頂點可能會對應多個法線信息或切線信息。這通常是因為我們要決定一個邊是一條硬邊(hard edge)還是一條平滑邊(smooth edge)。
    2.模型的LOD技術

    LOD(Level of Detail)技術的原理是,當一個物體離攝像機很遠時,模型上的很多細節是無法被察覺到的。因此,LOD允許當對象逐漸遠離攝像機時,減少模型上的面片數量,從而提高性能。在Unity中,我們可以:

    • 使用LOD Group組件來為一個物體構建一個LOD。
    • 為同一個對象準備多個包含不同細節程序的模型。
    • 把它們賦給LOD Group組件中的不同等級,Unity就會自動判斷當前位置上需要使用哪個等級的模型。
    3.遮擋剔除

    遮擋剔除(Occlusion culling)技術可以用來消除那些在其他物體后面看不到的物體,這意味著資源不會浪費在計算那些看不到的頂點上,進而提升性能。我們需要把遮擋剔除和攝像機的視錐體剔除(Frustum Culling)區分開來。視錐體剔除只會剔除掉那些不在攝像機的視野范圍內的對象,但不會判斷視野中是否有物體被其他物體擋住。而遮擋剔除會使用一個虛擬的攝像機來遍歷場景,從而構建一個潛在可見的對象集合的層級結構。在運行時刻,每個攝像機將會使用這個數據來識別哪些物體是可見的,而哪些被其他物體擋住不可見。使用遮擋剔除技術,不僅可以減少處理的頂點數目,還可以減少overdraw,提高游戲性能。

    要在Unity中使用遮擋剔除技術,我們需要進行一系列額外的處理工作。具體步驟可以參見Unity手冊的相關內容(http://docs.unity3d.com/Manual/OcclusionCulling.html)。

    模型的LOD技術和遮擋剔除技術可以同時減少CPU和GPU的負荷。CPU可以提交更少的draw call,而GPU需要處理的頂點和片元數目也減少了。


    二 、減少需要處理的片元數目

    這部分優化的重點在于減少overdraw。簡單來說,overdraw指的就是同一個像素被繪制了多次。Unity還提供了查看overdraw的視圖,我們可以在Scene視圖左上方的下拉菜單中選中Overdraw即可。

    在這里插入圖片描述
    實際上,這里的視圖只是提供了查看物體相互遮擋的層數,并不是真正的最終屏幕繪制的overdraw。也就是說,可以理解為它顯示的是,如果沒有使用任何深度測試和其他優化策略時的overdraw。這種視圖是通過把所有對象都渲染成一個透明的輪廓,通過查看透明顏色的累計程度,來判斷物體之間的遮擋。當然,我們可以使用一些措施來防止這種最壞情況的出現。

    1.控制繪制順序
    • 盡可能地把物體的隊列設置為不透明物體的渲染隊列,而盡量避免使用半透明隊列。由于深度測試的存在,如果我們可以保證物體都是從前往后繪制的,那么就可以很大程度上減少overdraw。這是因為,在后面繪制的物體由于無法通過深度測試,因此,就不會再進行后面的渲染處理。在Unity中,那些渲染隊列數目小于2500(如“Background”“Geometry”和“AlphaTest”)的對象都被認為是不透明(opaque)的物體,這些物體總體上是從前往后繪制的,而使用其他的隊列(如“Transparent”“Overlay”等)的物體,則是從后往前繪制的。
    • 充分利用Unity的渲染隊列來控制繪制順序。例如,在第一人稱射擊游戲中,對于游戲中的主要人物角色來說,他們使用的shader往往比較復雜,但是,由于他們通常會擋住屏幕的很大一部分區域,因此我們可以先繪制它們(使用更小的渲染隊列)。而對于一些敵方角色,它們通常會出現在各種掩體后面,因此,我們可以在所有常規的不透明物體后面渲染它們(使用更大的渲染隊列)。而對于天空盒子來說,它幾乎覆蓋了所有的像素,而且我們知道它永遠會出現在所有物體的后面,因此,它的隊列可以設置為“Geometry+1”。這樣,就可以保證不會因為它而造成overdraw。這些排序的思想往往可以節省掉很多渲染時間。(想著:越靠近攝像頭的越先繪制
    2.時刻警惕透明物體

    對于半透明對象來說,由于它們沒有開啟深度寫入,因此,如果要得到正確的渲染效果,就必須從后往前渲染。這意味著,半透明物體幾乎一定會造成overdraw。如果我們不注意這一點,在一些機器上可能會造成嚴重的性能下降。例如,對于GUI對象來說,它們大多被設置成了半透明,如果屏幕中GUI占據的比例太多,而主攝像機又沒有進行調整而是投影整個屏幕,那么GUI就會造成大量overdraw。

    因此,如果場景中包含了大面積的半透明對象,或者有很多層相互覆蓋的半透明對象(即便它們每個的面積可能都不大),或者是透明的粒子效果,在移動設備上也會造成大量的overdraw。這是應該盡量避免的。

    對于上述GUI的這種情況,我們可以:

    • 盡量減少窗口中GUI所占的面積。如果實在無能為力,我們可以把GUI的繪制和三維場景的繪制交給不同的攝像機,而其中負責三維場景的攝像機的視角范圍盡量不要和GUI的相互重疊。當然,這樣會對游戲的美觀度產生一定影響,因此,我們可以在代碼中對機器的性能進行判斷,例如,首先關閉一些耗費性能的功能,如果發現這個機器表現非常良好,再嘗試開啟一些特效功能。
    • 某些時候,使用透明度混合的性能往往比使用透明度測試更好:在移動平臺上,透明度測試也會影響游戲性能。雖然透明度測試沒有關閉深度測試,但由于它的實現使用了discard或clip操作,而這些操作會導致一些硬件的優化策略失效。例如,我們之前講過PowerVR使用的基于瓦片的延遲渲染技術,為了減少overdraw它會在調用片元著色器前就判斷哪些瓦片被真正渲染的。但是,由于透明度測試在片元著色器中使用了discard函數改變了片元是否會被渲染的結果,因此,GPU就無法使用上述的優化策略了。也就是說,只要在執行了所有的片元著色器后,GPU才知道哪些片元會被真正渲染到屏幕上,這樣,原先那些可以減少overdraw的優化就都無效了。這種時候,。
    3.減少實時光照和陰影

    實時光照對于移動平臺是一種非常昂貴的操作。如果場景中包含了過多的點光源,并且使用了多個Pass的Shader,那么很有可能會造成性能下降。例如,一個場景里如果包含了3個逐像素的點光源,而且使用了逐像素的Shader,那么很有可能將draw call數目(CPU的瓶頸)提高3倍,同時也會增加overdraw(GPU的瓶頸)。這是因為,對于逐像素的光源來說,被這些光源照亮的物體需要被再渲染一次。更糟糕的是,無論是靜態批處理還是動態批處理,對于這種額外的處理逐像素光源的Pass都無法進行批處理,也就是說,它們會中斷批處理。

    當然,游戲場景還是需要光照才能得到出色的畫面效果。我們可以:

    • 使用烘焙技術:把光照提前烘焙到一張光照紋理(lightmap)中,然后在運行時刻只需要根據紋理采樣得到光照結果即可。
    • 使用God Ray。 場景中很多小型光源的效果都是靠這種方法模擬的。它們一般并不是真的光源,很多情況是通過透明紋理模擬得到的。
    • 在移動平臺上,一個物體使用的逐像素光源數目應該小于1(不包括平行光)。如果一定要使用更多的實時光,可以選擇用逐頂點光照來代替。
    • 盡量減少實時陰影:例如,使用烘焙把靜態物體的陰影信息存儲到光照紋理中,而只對場景中的動態物體使用適當的實時陰影。

    三、減少計算復雜度

    1.Shader的LOD技術

    Shader的LOD技術可以控制使用的Shader等級。它的原理是,只有Shader的LOD值小于某個設定的值,這個Shader才會被使用,而使用了那些超過設定值的Shader的物體將不會被渲染。我們通常會在SubShader中使用類似下面的語句來指明該shader的LOD值:

    SubShader{
    	Tags{"RenderType"="Opaque"}
    	LOD 200
    }
    

    我們也可以在Unity Shader的導入面板上看到該Shader使用的LOD值。

    在這里插入圖片描述
    在默認情況下,允許的LOD等級是無限大的。這意味著,任何被當前顯卡支持的Shader都可以被使用。但是,在某些情況下我們可能需要去掉一些使用了復雜計算的Shader渲染。這時,我們可以使用Shader.maximumLODShader.globalMaximumLOD來設置允許的最大LOD值。Unity內置的Shader使用了不同的LOD值,例如,Diffuse的LOD為200,而Bumped Specular的LOD為400。

    2.代碼方面的優化
    • 盡可能地把計算放在每個對象或逐頂點上。通常來講,游戲需要計算的對象、頂點和像素的數目排序是對象數 < 頂點數 <像素數。在具體的代碼編寫上,不同的硬件甚至需要不同的處理。因此,一些普遍的規則在某些硬件上可能并不成立。更不幸的是,通常Shader代碼的優化并不那么直觀,尤其是一些平臺上缺少相關的分析器,例如iOS平臺。盡管如此,還是給出一些被認為是普遍成立的優化策略,但如果在某些設備上性能反而有所下降的話,這并不奇怪。
    • 盡可能使用低精度的浮點值進行運算。最高精度的float/highp適用于存儲諸如頂點坐標等變量,但它的計算速度是最慢的,我們應該盡量避免在片元著色器中使用這種精度進行計算。而half/mediump適用于一些標量、紋理坐標等變量,它的計算速度大約是float的兩倍。而fixed/lowp適用于絕大多數顏色變量和歸一化后的方向矢量,在進行一些對精度要求不高的計算時,我們應該盡量使用這種精度的變量。它的計算速度大約是float的4倍,但要避免對這些低精度變量進行頻繁的swizzle操作(如color.xwxw)。還需要注意的是,我們應當盡量避免在不同精度之間的轉換,這有可能會造成一定的性能下降。
    • 把數據從頂點著色器傳遞給下一個階段時使用盡可能少的插值變量。例如,如果需要對兩個紋理坐標進行插值,我們通常會把它們打包在同一個float4類型的變量中,兩個紋理坐標分別對應了xy分量和zw分量。然而,對于PowerVR平臺來說,這種插值變量是非常廉價的,直接把不同的紋理坐標存儲在不同的插值變量中,有時反而性能更好。尤其是,如果在PowerVR上使用類似tex2D(_MainTex, uv.zw)這樣的語句來進行紋理采樣,GPU就無法進行一些紋理的預讀取,因為它會認為這些紋理采樣是需要依賴其他數據的。因此,如果我們特別關心游戲在PowerVR上的性能,就不應該把兩個紋理坐標打包在同一個四維變量中。
    • 盡可能不要使用全屏的屏幕后處理效果。如果美術風格實在是需要使用類似Bloom、熱擾動這樣的屏幕特效,我們應該盡量使用fixed/lowp進行低精度運算(紋理坐標除外,可以使用half/mediump)。那些高精度的運算可以使用查找表(LUT)或者轉移到頂點著色器中進行處理。除此之外,盡量把多個特效合并到一個Shader中。例如,我們可以把顏色校正和添加噪聲等屏幕特效在Bloom特效的最后一個Pass中進行合成。
    • 盡可能不要使用分支語句和循環語句。
    • 盡可能避免使用類似sin、tan、pow、log等較為復雜的數學運算。我們可以使用查找表來作為替代。
    • 盡可能不要使用discard操作,因為這會影響硬件的某些優化。
    3.根據硬件條件進行縮放

    諸如iOS和Android這樣的移動平臺,不同設備之間的性能千差萬別。我們很容易可以找到一臺手機的渲染性能是另一臺手機的10倍。那么,如何確保游戲可以同時流暢地運行在不同性能的移動設備上呢?一個非常簡單且實用的方式是使用所謂的放縮(scaling)思想。我們首先保證游戲最基本的配置可以在所有的平臺上運行良好,而對于一些具有更高表現能力的設備,我們可以開啟一些更“養眼”的效果,比如使用更高的分辨率,開啟屏幕后處理特效,開啟粒子效果等。



    帶寬

    一、節省帶寬

    大量使用未經壓縮的紋理以及使用過大的分辨率都會造成由于帶寬而引發的性能瓶頸。

    1.減少紋理大小
    • 使用紋理圖集。所有紋理的長寬比最好是正方形,而且長寬值最好是2的整數冪。這是因為有很多優化策略只有在這種時候才可以發揮最大效用。在Unity 5中,即便我們導入的紋理長寬值并不是2的整數冪,Unity也會自動把長寬轉換到離它最近的2的整數冪值。但我們仍然應該在制作美術資源時就把這條規則謹記在心,防止由于放縮而造成不好的影響。
    • 盡可能使用多級漸遠紋理技術(mipmapping)。在Unity中,我們可以通過紋理導入面板來查看紋理的各個導入屬性。通過把紋理類型設置為Advanced,就可以自定義許多選項,例如,是否生成多級漸遠紋理(mipmaps),如圖16.12所示。當勾選了Generate Mip Maps選項后,Unity就會為同一張紋理創建出很多不同大小的小紋理,構成一個紋理金字塔。而在游戲運行中就可以根據距離物體的遠近,來動態選擇使用哪一個紋理。這是因為,在距離物體很遠的時候,就算我們使用了非常精細的紋理,但肉眼也是分辨不出來的。這種時候,我們完全可以使用更小、更模糊的紋理來代替,這可以讓GPU使用分辨率更小的紋理,大量節省訪問的像素數目。在某些設備上,關閉多級漸遠紋理往往會造成嚴重的性能問題。因此,除非我們確定該紋理不會發生縮放,例如GUI和2D游戲中使用的紋理等,都應該為紋理生成相應的多級漸遠紋理。
    • 盡可能使用紋理壓縮。然而像Android這樣的平臺,有很多不同架構的GPU,紋理壓縮就變得有點復雜,因為不同的GPU架構有它自己的紋理壓縮格式,例如,PowerVRAM的PVRTC格式、Tegra的DXT格式、Adreno的ATC格式。所幸的是,Unity可以根據不同的設備選擇不同的壓縮格式,而我們只需要把紋理壓縮格式設置為自動壓縮即可。但是,GUI類型的紋理同樣是個例外,一些時候由于對畫質的要求,我們不希望對這些紋理進行壓縮。
    2.利用分辨率縮放

    過高的屏幕分辨率也是造成性能下降的原因之一,尤其是對于很多低端手機,除了分辨率高其他硬件條件并不盡如人意,而這恰恰是游戲性能的兩個瓶頸:過大的屏幕分辨率和糟糕的GPU。

    因此,我們可能需要對于特定機器進行分辨率的放縮。當然,這樣可能會造成游戲效果的下降,但性能和畫面之間永遠是個需要權衡的話題。在Unity中設置屏幕分辨率可以直接調用Screen.SetResolution。實際使用中可能會遇到一些情況,雨松MOMO有一篇文章詳細講解了如何使用這種技術,讀者可參考。

    一個非常好的游戲優化實例是Unity自帶的項目《Angry Bots》,讀者可以直接在Unity資源商店下載到完整的項目源代碼。

    版權聲明:本文為qq_36622009原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
    本文鏈接:https://blog.csdn.net/qq_36622009/article/details/105729041

    智能推薦

    bat腳本判斷服務是否存在windowsXP

    有一個在xp系統下自動判斷snmp服務并安裝的需求。 起因 在網上查了一些判斷服務是否存在的辦法,最常見的是調用sc query |find /i "snmp",但是經過我測試,這個方法只能判斷服務是否開啟,對于存在未開啟的服務無法查詢,因此直接查詢服務是否存在應該使用sc query snmp這個語句。這些內容在下面這篇博客bat判斷window服務是否存在也提到了。 這個辦...

    一個簡單的socket服務端Demo

    博主本人用的是maven管理的spring-mvc。 核心代碼如下: OioServer.java,socket服務端實體類 OioServerTest.java,socket服務端測試類 Demo項目結構如圖: 啟動服務端: 使用終端敲命令行連接服務端: 終端命令為: 客戶端發消息給服務端,服務端收到消息 終端輸入Ctrl+]可以進入telnet的命令模式,之后輸入quit,之后回車就可以關閉t...

    MAHAKIL之最新類不平衡過采樣方法

           最近在幫實驗室一師兄做實驗時,剛好在學習類不平衡的采樣方法,采樣方法大致分為過采樣和欠采樣兩大類,但是目前研究的主要為過采樣方法,因為它主要是往少數類集合中增加樣本點實現與多數類集合的動態平衡,這樣能最大程度的保證樣本的準確性,所以我將會在接下來的幾篇博客里詳細闡述過采樣方法。過采樣方法一般分為ROS(隨機過采樣),SMOTE-Regular,...

    關于靜態/動態類型檢查 和 不可變包裝的筆記

    靜態類型檢查和動態類型檢查 Java是一種靜態類型語言。所有變量的類型在編譯時(在程序運行之前)都是已知的,因此編譯器也可以推導出所有表達式的類型。如果a和b聲明為int,那么編譯器得出結論,a+b也是int。 相比較之下,在像Python這樣的動態類型語言中,這種檢查會被推遲到run-time。 靜態檢查一個bug比動態檢查好,而動態檢查它比根本不沒檢查它好。 靜態檢查的好處就是可在編譯階段發現...

    IntelliJ IDEA中創建xml文件

    IntelliJ IDEA中創建xml文件 1、file—setting,左上角輸入template, 2、在左側欄找到File And Code Templates 3、中間選中Files 4、點擊+號,添加模板 5、輸入模板名字:Name:mybatis-cfg.xml (name可以自定義) 6、后綴名extension:xml 7、在面板中間輸入內容: 8、把enable li...

    猜你喜歡

    CocosCreator內存與性能優化

    CocosCreator內存與性能優化 一、內存優化 因為 iOS小游戲和微信共用同一個進程,而微信在連續兩次收到系統內存警告的時候會關閉小游戲并釋放小游戲占用的內存。如果你的小游戲有外網用戶反饋“閃退”,或者你自己測試的時候頻繁出現“該小程序可能導致微信響應變慢被終止”等提示,那么就應該是時候優化你的小游戲內存了! 1、優化雙份紋理(必做!) 在你...

    TabLayout+ViewPager實現橫向tab導航欄

    效果 實現方案 activity 布局文件 activity_main.xml view_pager_1.xml view_pager_2.xml 完整源代碼 https://gitee.com/cxyzy1/tablayoutDemo...

    springboot進階

    1.配置文件application.yml 1.1基本語法 k:(空格)v:表示一對鍵值對(空格必須有); 以空格的縮進來控制層級關系;只要是左對齊的一列數據,都是同一個層級的 屬性和值也是大小寫敏感; 1.2值的寫法 1)字面量:普通的值(數字,字符串,布爾) k: v:字面直接來寫; 字符串默認不用加上單引號或者雙引號; “”:雙引號;不會轉義字符串里面的特殊字符;特殊...

    OpenCV學習筆記(二)——初始Mat類

    前言:      在計算機內存中,數字圖像以矩陣的形式存儲和運算,比如,在MatLab中,圖像讀取之后對應一個矩陣,在OpenCV中,同樣也是如此。     在早期的OpenCV1.x版本中,圖像的處理是通過IplImage(該名稱源于Intel的另一個開源庫Intel Image Processing Library ,縮寫成...

    ArrayList實現

    API https://docs.oracle.com/javase/8/docs/api/ 實現 MyList MyArrayList MyIterator MyArrayListIterator Test...

    精品国产乱码久久久久久蜜桃不卡