主頁 >  其他 > 【UGUI原始碼分析】Unity遮罩之Mask詳細解讀

【UGUI原始碼分析】Unity遮罩之Mask詳細解讀

2021-08-31 20:57:13 其他

遮罩,顧名思義是一種可以掩蓋其它元素的控制元件,常用于修改其它元素的外觀,或限制元素的形狀,比如ScrollView或者圓頭像效果都有用到遮罩功能,本系列文章希望通過閱讀UGUI原始碼的方式,來探究遮罩的實作原理,以及通過Unity不同遮罩之間實作方式的對比,找到每一種遮罩的最佳使用場合,

Unity UGUI主要提供兩種遮罩,分別是MaskRect Mask 2D,在2D游戲開發中,可能還會用到Sprite Mask,雖然不是本文的重點,但后面也會提到,原本是希望將對各個遮罩的分析與對比整合在一篇文章中,但在書寫程序中發現篇幅過長,因此只好拆分為三個部分,本篇文章是第一部分,專門解讀Mask遮罩,后續關于Rect Mask 2D和遮罩間對比分析的文章會在完成后發出,敬請期待~

本文使用的原始碼與內置資源均基于Unity2019.4版本

Mask

查閱Unity的官方檔案,對Mask有如下定義

遮罩不是可見的 UI 控制元件,而是一種修改控制元件子元素外觀的方法,遮罩將子元素限制(即“掩蓋”)為父元素的形狀,因此,如果子項比父項大,則子項僅包含在父項以內的部分才可見,

也有簡單提到Mask的實作原理

使用 GPU 的模板緩沖區來實作遮罩,第一個遮罩元素將 1 寫入模板緩沖區,遮罩下面的所有元素在渲染時進行檢查,僅渲染到模板緩沖區中有 1 的區域, 嵌套的遮罩會將增量位掩碼寫入緩沖區,這意味著可渲染的子項需要具有要渲染的邏輯和模板值,

是不是有些晦澀難懂?沒關系,接下來的分析就是對這個實作原理的展開,每句話都會有對應的解讀

模板緩沖?

要搞懂模板緩沖,先要了解模板測驗,在渲染流水線的逐片元操作階段,會有一個模板測驗,可以作為一種丟棄片元的輔助方法(這里的片元可以簡單理解為對應著一個像素),而要進行模板測驗就要用到模板緩沖,每個像素/片段都可以有一個與之對應的模板值,就存盤在模板緩沖中,

如果開啟了模板測驗,GPU會首先讀取(使用讀取掩碼)模板緩沖區中該片元位置的模板值,然后將該值和讀取到(使用讀取掩碼)的參考值進行比較,這個比較函式可以是由開發者指定的,例如小于時舍棄該片元,或者大于等于時舍棄,如果這個片元沒有通過這個測驗,該片元就會被舍棄,不管一個片元有沒有通過模板測驗,我們都可以根據模板測驗和下面的深度測驗結果來修改模板緩沖區,這個修改操作也是由開發者指定的,開發者可以設定不同結果下的修改操作,例如,在失敗時模板緩沖區保持不變,通過時將模板緩沖區中對應位置的值加1等,

而Mask就是通過在渲染時,將其對應位置像素的模板值都置為特定值(不一定是1),然后當遮罩下的子元素渲染時,逐像素判斷模板值是否為特定值,如果是特定值,就表示在遮罩范圍內,可以顯示,如果不是,則表示不在遮罩范圍內,不顯示,借用一張網上的圖,很形象的描述了這種方式,

綠色矩形是遮罩區域,模板值都被寫入為1,當渲染橫著的紅色矩形時,只有模板值為1的區域才會顯示,非1的會被丟棄不會顯示,從而實作了裁剪效果

原始碼

在了解了Mask的基本實作原理后,再來通過原始碼看看具體的實作方式

UGUI中所有可顯示的圖形都有一個基類,Graphic,比如Image和Text就是間接繼承于Graphic的,Graphic定義了一個materialForRendering屬性,它表示傳遞給CanvasRenderer,實際被用于渲染的材質,從這個屬性的get訪問器可以發現,在獲取最終被用于渲染的材質時,會先依次呼叫這個GameObject上所有實作了IMaterialModifier介面組件的GetModifiedMaterial方法來修改最后回傳的材質,

public virtual Material materialForRendering
{
    get
    {
        var components = ListPool<Component>.Get();
        GetComponents(typeof(IMaterialModifier), components);

        var currentMat = material;
        for (var i = 0; i < components.Count; i++)
            currentMat = (components[i] as IMaterialModifier).GetModifiedMaterial(currentMat);
        ListPool<Component>.Release(components);
        return currentMat;
    }
}

IMaterialModifier定義如下所示,也就是說其它組件可以通過實作IMaterialModifier介面來達到修改最終渲染所使用的材質的目的

public interface IMaterialModifier
{
    /// <summary>
    /// Perform material modification in this function.
    /// </summary>
    /// <param name="baseMaterial">The material that is to be modified</param>
    /// <returns>The modified material.</returns>
    Material GetModifiedMaterial(Material baseMaterial);
}

Mask組件就實作了IMaterialModifier介面,并通過這個介面回傳了一個新材質,并通過這個新材質設定修改模板緩沖值

/// Stencil calculation time!
public virtual Material GetModifiedMaterial(Material baseMaterial)
{
    // ...
    var rootSortCanvas = MaskUtilities.FindRootSortOverrideCanvas(transform);
    var stencilDepth = MaskUtilities.GetStencilDepth(transform, rootSortCanvas);
    if (stencilDepth >= 8)
    {
        Debug.LogWarning("Attempting to use a stencil mask with depth > 8", gameObject);
        return baseMaterial;
    }

    int desiredStencilBit = 1 << stencilDepth;
    
    // 第一部分
    // if we are at the first level...
    // we want to destroy what is there
    if (desiredStencilBit == 1)
    {
        // CompareFunction.Always,始終通過,執行StencilOp.Replace操作,將模板緩沖中的值替換為(1 & 255)= 1
        var maskMaterial = StencilMaterial.Add(baseMaterial, 1, StencilOp.Replace, CompareFunction.Always, m_ShowMaskGraphic ? ColorWriteMask.All : 0);
        StencilMaterial.Remove(m_MaskMaterial);
        m_MaskMaterial = maskMaterial;

        var unmaskMaterial = StencilMaterial.Add(baseMaterial, 1, StencilOp.Zero, CompareFunction.Always, 0);
        StencilMaterial.Remove(m_UnmaskMaterial);
        m_UnmaskMaterial = unmaskMaterial;
        // 設定渲染器可使用的材質數量為1
        graphic.canvasRenderer.popMaterialCount = 1;
        // 設定渲染器使用的材質
        graphic.canvasRenderer.SetPopMaterial(m_UnmaskMaterial, 0);

        return m_MaskMaterial;
    }
    // 第二部分
    // ...
}

GetModifiedMaterial的實作可以分兩部分來看,上面的代碼只列出了第一部分,簡單起見,我們先只看第一部分,主要是if (desiredStencilBit == 1)陳述句塊內代碼,它是用于處理只有自身有Mask的簡單情況的

  • 代碼中的stencilDepth表示自身到Canvas之間Mask的個數,如果每層有多個Mask則只計一個,如果除了自身的Mask,再往上沒有Mask了,則stencilDepth為0,如果再往上找到1個,stencilDepth為1,找到2個,stencilDepth為2,以此類推,
  • desiredStencilBit表示實際要寫入模板緩沖的參考值,desiredStencilBit = 1 << stencilDepth,當stencilDepth >= 8時會列印警告,是因為模板值一般是8位的,desiredStencilBit將超出這個范圍無法寫入
  • 如果只是自身有Mask,再往上沒有了,那stencilDepth就是0,desiredStencilBit就是1,此時通過StencilMaterial.Add獲得一個新材質,并將這個材質回傳,從而達到修改最終渲染使用材質的目的,StencilMaterial.Add方法具體實作如下所示,主要是對材質設定一些傳入的引數,
public static Material Add(Material baseMat, int stencilID, StencilOp operation, CompareFunction compareFunction, ColorWriteMask colorWriteMask, int readMask, int writeMask)
{
    // ...
    var newEnt = new MatEntry();
    newEnt.count = 1;
    newEnt.baseMat = baseMat;
    newEnt.customMat = new Material(baseMat);
    newEnt.customMat.hideFlags = HideFlags.HideAndDontSave;
    newEnt.stencilId = stencilID;
    newEnt.operation = operation;
    newEnt.compareFunction = compareFunction;
    newEnt.readMask = readMask;
    newEnt.writeMask = writeMask;
    newEnt.colorMask = colorWriteMask;
    newEnt.useAlphaClip = operation != StencilOp.Keep && writeMask > 0;

    newEnt.customMat.name = string.Format("Stencil Id:{0}, Op:{1}, Comp:{2}, WriteMask:{3}, ReadMask:{4}, ColorMask:{5} AlphaClip:{6} ({7})", stencilID, operation, compareFunction, writeMask, readMask, colorWriteMask, newEnt.useAlphaClip, baseMat.name);

    newEnt.customMat.SetInt("_Stencil", stencilID);
    newEnt.customMat.SetInt("_StencilOp", (int)operation);
    newEnt.customMat.SetInt("_StencilComp", (int)compareFunction);
    newEnt.customMat.SetInt("_StencilReadMask", readMask);
    newEnt.customMat.SetInt("_StencilWriteMask", writeMask);
    newEnt.customMat.SetInt("_ColorMask", (int)colorWriteMask);
    newEnt.customMat.SetInt("_UseUIAlphaClip", newEnt.useAlphaClip ? 1 : 0);

    if (newEnt.useAlphaClip)
        newEnt.customMat.EnableKeyword("UNITY_UI_ALPHACLIP");
    else
        newEnt.customMat.DisableKeyword("UNITY_UI_ALPHACLIP");

    m_List.Add(newEnt);
    return newEnt.customMat;
}

StencilMaterial本質上只是快取材質的一個工具類,主要作用就是提供一個新的材質,再結合下面這句代碼傳入的引數,這個新材質起到的作用是始終通過模板測驗(CompareFunction.Always),替換模板緩沖中的模板值(StencilOp.Replace)為1

var maskMaterial = StencilMaterial.Add(baseMaterial, 1, StencilOp.Replace, CompareFunction.Always, m_ShowMaskGraphic ? ColorWriteMask.All : 0);

對材質設定的引數,實際上是設定給Shader的,查看UI默認使用的Shader是UI/Default,這是Unity的內置Shader,原始碼可以在Unity官網下載,下載時選擇"Built in shaders"

UI-Default.shader的部分原始碼如下所示,可以看到主要是利用Unity ShaderLab的模板陳述句來實作對模板緩沖區的一些操作,詳細介紹可以點擊這里查看,就不再贅述了

// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)

Shader "UI/Default"
{
    Properties
    {
        [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
        _Color ("Tint", Color) = (1,1,1,1)

        _StencilComp ("Stencil Comparison", Float) = 8
        _Stencil ("Stencil ID", Float) = 0
        _StencilOp ("Stencil Operation", Float) = 0
        _StencilWriteMask ("Stencil Write Mask", Float) = 255
        _StencilReadMask ("Stencil Read Mask", Float) = 255

        _ColorMask ("Color Mask", Float) = 15

        [Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 0
    }

    SubShader
    {
        // ...
        Stencil
        {
            Ref [_Stencil]
            Comp [_StencilComp]
            Pass [_StencilOp]
            ReadMask [_StencilReadMask]
            WriteMask [_StencilWriteMask]
        }
        // ...
    }
}

到這里不難發現,Unity檔案Mask原理描述中的第一句話就是對上面程序的一個概括

使用 GPU 的模板緩沖區來實作遮罩,第一個遮罩元素將 1 寫入模板緩沖區,

接下來我們再來看被遮掩的物件,是怎樣利用模板緩沖實作遮罩效果的

UGUI中所有可被遮掩的圖形都有一個基類,MaskableGraphic,同樣MaskableGraphic是繼承于Graphic的,比如Image和Text就是繼承于MaskableGraphic的,同理,MaskableGraphic也實作了IMaterialModifier介面來修改最終渲染使用的材質

public virtual Material GetModifiedMaterial(Material baseMaterial)
{
    var toUse = baseMaterial;

    if (m_ShouldRecalculateStencil)
    {
        var rootCanvas = MaskUtilities.FindRootSortOverrideCanvas(transform);
        m_StencilValue = https://www.cnblogs.com/iwiniwin/p/maskable ? MaskUtilities.GetStencilDepth(transform, rootCanvas) : 0;
        m_ShouldRecalculateStencil = false;
    }

    // if we have a enabled Mask component then it will
    // generate the mask material. This is an optimization
    // it adds some coupling between components though :(
    if (m_StencilValue > 0 && !isMaskingGraphic)
    {
        var maskMat = StencilMaterial.Add(toUse, (1 << m_StencilValue) - 1, StencilOp.Keep, CompareFunction.Equal, ColorWriteMask.All, (1 << m_StencilValue) - 1, 0);
        StencilMaterial.Remove(m_MaskMaterial);
        m_MaskMaterial = maskMat;
        toUse = m_MaskMaterial;
    }
    return toUse;
}
  • 代碼中的m_StencilValue表示在自身層級之上有多少個Mask,如果只有父節點有Mask組件,則m_StencilValue值為1
  • 可以看到它回傳的新材質主要作用是,比較傳入的參考值((1 << m_StencilValue) - 1)與模板緩沖中的值,如果相等就通過(CompareFunction.Equal),即使通過了模板測驗也仍保留模板緩沖中的值(StencilOp.Keep),
var maskMat = StencilMaterial.Add(toUse, (1 << m_StencilValue) - 1, StencilOp.Keep, CompareFunction.Equal, ColorWriteMask.All, (1 << m_StencilValue) - 1, 0);
  • 當只有父節點有Mask組件時,(1 << m_StencilValue) - 1值即為1,與前面Mask組件提前設定的模板緩沖區的值相同,所以在Mask范圍內的元素將能夠通過模板測驗,最終顯示出來,未通過的將被裁剪無法顯示出來

這里就對應了Unity檔案Mask原理描述中的中間部分

遮罩下面的所有元素在渲染時進行檢查,僅渲染到模板緩沖區中有 1 的區域,

實際上到這里,一個簡單的,只有父節點有Mask的圖形是怎樣實作遮罩效果的,我們已經徹底搞清楚了,接下來,讓我們來看看復雜點的情況

如果大家還沒忘記的話,讓我們回到Mask的GetModifiedMaterial實作(注意是Mask的哦~),查看它的第二部分,即if陳述句塊后面的代碼,他們是被用來處理嵌套Mask的

public virtual Material GetModifiedMaterial(Material baseMaterial)
{
    if (!MaskEnabled())
        return baseMaterial;

    var rootSortCanvas = MaskUtilities.FindRootSortOverrideCanvas(transform);
    var stencilDepth = MaskUtilities.GetStencilDepth(transform, rootSortCanvas);
    if (stencilDepth >= 8)
    {
        Debug.LogWarning("Attempting to use a stencil mask with depth > 8", gameObject);
        return baseMaterial;
    }

    int desiredStencilBit = 1 << stencilDepth;

    // 第一部分
    // ...

    // 第二部分
    //otherwise we need to be a bit smarter and set some read / write masks
    var maskMaterial2 = StencilMaterial.Add(baseMaterial, desiredStencilBit | (desiredStencilBit - 1), StencilOp.Replace, CompareFunction.Equal, m_ShowMaskGraphic ? ColorWriteMask.All : 0, desiredStencilBit - 1, desiredStencilBit | (desiredStencilBit - 1));
    StencilMaterial.Remove(m_MaskMaterial);
    m_MaskMaterial = maskMaterial2;

    graphic.canvasRenderer.hasPopInstruction = true;
    var unmaskMaterial2 = StencilMaterial.Add(baseMaterial, desiredStencilBit - 1, StencilOp.Replace, CompareFunction.Equal, 0, desiredStencilBit - 1, desiredStencilBit | (desiredStencilBit - 1));
    StencilMaterial.Remove(m_UnmaskMaterial);
    m_UnmaskMaterial = unmaskMaterial2;
    graphic.canvasRenderer.popMaterialCount = 1;
    graphic.canvasRenderer.SetPopMaterial(m_UnmaskMaterial, 0);

    return m_MaskMaterial;
}
  • 與第一部分不同的是,StencilMaterial.Add傳入的引數不同,而這些不同就是處理嵌套Mask的關鍵,嵌套Mask是指除了自身Mask,層級再往上還有Mask,針對這種情況,傳入的參考值是desiredStencilBit | (desiredStencilBit - 1),而不再固定是1了,這個值的實際含義是利用每一位是否是1來表示每一層是否有Mask,舉個栗子,如果除了自身,再往上還能找到兩個Mask,則stencilDepth為2,desiredStencilBit為8,二進制形式為100,經過計算傳入的參考值是111,用每個1來分別表示,自身有Mask,第一層有,第二層有,這個參考值被Unity稱之為增量位掩碼
  • 這個增量位掩碼正好可以與MaskableGraphic部分判斷模板值是否相等時用到的(1 << m_StencilValue) - 1對應上
// Mask處理嵌套遮罩所用的新材質
var maskMaterial2 = StencilMaterial.Add(baseMaterial, desiredStencilBit | (desiredStencilBit - 1), StencilOp.Replace, CompareFunction.Equal, m_ShowMaskGraphic ? ColorWriteMask.All : 0, desiredStencilBit - 1, desiredStencilBit | (desiredStencilBit - 1));

// MaskableGraphic判斷是否在遮罩內所用的新材質
var maskMat = StencilMaterial.Add(toUse, (1 << m_StencilValue) - 1, StencilOp.Keep, CompareFunction.Equal, ColorWriteMask.All, (1 << m_StencilValue) - 1, 0);

實際上這部分就對應了Unity檔案Mask原理描述中的后兩句話

嵌套的遮罩會將增量位掩碼寫入緩沖區,這意味著可渲染的子項需要具有要渲染的邏輯和模板值,

補充

最后還有幾處地方覺得值得提一下

  1. StencilMaterial.Add傳入引數的最后兩個分別是readMask讀取掩碼和writeMask寫入掩碼,讀取掩碼不僅是在讀取模板緩沖中的值時會與其相與,對于要比較的參考值也會相與

  2. 細心的同學可能會發現,Mask在獲取新材質的時候,會多獲取一個,這個材質實際是用來清除模板緩沖區的,以避免不要影響后續的渲染

    // 第一部分
    var unmaskMaterial = StencilMaterial.Add(baseMaterial, 1, StencilOp.Zero, CompareFunction.Always, 0);
    
    // 第二部分
    var unmaskMaterial2 = StencilMaterial.Add(baseMaterial, desiredStencilBit - 1, StencilOp.Replace, CompareFunction.Equal, 0, desiredStencilBit - 1, desiredStencilBit | (desiredStencilBit - 1));
    

    利用Unity的幀除錯器也可以看到這個清除程序

  3. 為什么Mask可以實作圓形遮罩效果?

    眾所周知,圓頭像效果可以使用Mask實作,具體方式是使用一張只顯示圓形,非圓形區域是透明像素的切圖實作的,但這張切圖實際上還是矩形的,根據上面的原理解讀,矩形區域對應的模板值都會被Mask設定為特定值,從而使其下的子元素都能通過模板測驗,是無法實作圓形裁剪的

    關鍵代碼還是在UI-Default.shader中,它通過clip指令,將透明度低于0.001的片元都裁剪掉了,因此被裁剪的片元也就不會再設定對應的模板值了,UNITY_UI_ALPHACLIP宏定義是通過Shader引數_UseUIAlphaClip控制的,Mask獲取的新材質會將該引數設定為true

    #ifdef UNITY_UI_ALPHACLIP
    clip (color.a - 0.001);
    #endif
    
  4. 關于SpriteMask

    Sprite Mask不屬于UGUI的范圍,Unity官方并沒有將它開源,不過通過官方論壇我們可以了解到其實作原理也是利用了模版緩沖,
    不像Mask,只實作了Visible Inside Mask功能,SpriteMask不僅實作了Visible Inside Mask功能,也實作了Visible Outside Mask功能,在經過對Mask的原理分析以后,我們知道通過修改模板緩沖的比較函式是可以輕易的實作這種效果的,感興趣的同學趕快動手試一下吧


參考

  • 【詳細決議版】Unity UGUI Mask組件實作原理
  • 原始碼探析Mask、Rect Mask2D與Sprite Mask的異同
作者:iwiniwin 出處:http://www.cnblogs.com/iwiniwin/ 本文為博主原創文章,轉載請附上原文出處鏈接和本宣告,

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/296248.html

標籤:其他

上一篇:Unity周記: 2021.07.19-07.25

下一篇:在游戲中播放cg視頻遇到的問題

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more