真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

深入U(xiǎn)RP之Shader篇3:UnlitShader分析[下]-創(chuàng)新互聯(lián)

Unlit shader

上篇中我們分析了Unlit shader的Properties在ShaderGUI中的處理,接下來(lái)看Sub Shader。

十年建站經(jīng)驗(yàn), 網(wǎng)站設(shè)計(jì)、成都網(wǎng)站設(shè)計(jì)客戶(hù)的見(jiàn)證與正確選擇。創(chuàng)新互聯(lián)建站提供完善的營(yíng)銷(xiāo)型網(wǎng)頁(yè)建站明細(xì)報(bào)價(jià)表。后期開(kāi)發(fā)更加便捷高效,我們致力于追求更美、更快、更規(guī)范。SubShader

unlit shader以及其他URP shader包含兩個(gè)SubShader,分別是針對(duì)ShaderModel4.5和2.0。由于unlit shader本身很簡(jiǎn)單,這兩個(gè)SubShader幾乎一樣,唯一的差別是ShaderModel 4.5的SubShader會(huì)定義#pragma multi_compile _ DOTS_INSTANCING_ON,這個(gè)可參考dots-instancing-shaders,本文中先忽略它。總之這兒的要點(diǎn)是URP會(huì)針對(duì)比較強(qiáng)大的設(shè)備使用一個(gè)SubShader,而比較弱的設(shè)備使用另一個(gè)。但這并不是說(shuō)URP只是把設(shè)備分成兩類(lèi)這么簡(jiǎn)單,這兒只說(shuō)Shader。由于硬件總是要發(fā)展,我們關(guān)注的重點(diǎn)是ShaderModel4.5,因此就只看這第一個(gè)SubShader了。

Pass

我們看到unlit shader的SubShader中包含了3個(gè)Pass,分別是Unlit,DepthOnlyMeta。我們知道URP是單Pass渲染,這只是說(shuō)URP是在一個(gè)Pass中完成物體的大部分計(jì)算,包含各種光照的計(jì)算等等。而Sub Shader中仍然是會(huì)包含多個(gè)pass,這些Pass是在渲染管線(xiàn)中特定的時(shí)候被執(zhí)行。例如這兒的DepthOnlypass,是在渲染所有不透明物體之前預(yù)先生成一張depth texture的pass;而Metapass則只在烘焙光照貼圖時(shí)使用。而決定這些pass被使用的并不是他們的名字,而是上面說(shuō)過(guò)的LightModetag。但是Unlitpass并沒(méi)有指定這個(gè)tag,所以它使用的就是默認(rèn)的SRPDefaultUnlit。

unlit pass

首先分析unlit pass

  • keyword定義:
#pragma shader_feature_local_fragment _ALPHATEST_ON
            #pragma shader_feature_local_fragment _ALPHAPREMULTIPLY_ON

            // -------------------------------------
            // Unity defined keywords
            #pragma multi_compile_fog
            #pragma multi_compile_instancing
            #pragma multi_compile _ DOTS_INSTANCING_ON

shader feature支持alpha test和 alpha premultiply,muti compile則包含fog, instacing和 dots instancing。這些都是一些宏定義開(kāi)關(guān),shader使用了不同的開(kāi)關(guān),會(huì)編譯成不同的變體,變體才是最終使用的shader。對(duì)于shader feature是可以定義在材質(zhì)上的,上面處理Properties的時(shí)候看到會(huì)根據(jù)不同情況設(shè)置不同的關(guān)鍵字,就是設(shè)置使用這兒的關(guān)鍵字,所以要首先包含這些關(guān)鍵字。而multi compile是指無(wú)論如何都要包含這些關(guān)鍵字(和材質(zhì)是否開(kāi)啟沒(méi)關(guān)系)。

  • uniform定義:
    uniform定義被包含在文件UnlitInput.hlsl中。這個(gè)hlsl文件定義了unlit shader使用的uniform,根據(jù)SRP的規(guī)則,使用的是CBuffer。
CBUFFER_START(UnityPerMaterial)
    float4 _BaseMap_ST;
    half4 _BaseColor;
    half _Cutoff;
    half _Surface;
CBUFFER_END

CBUFFER_STARTCBUFFER_END是定義在SRP Core的Shader Library中的宏,并且根據(jù)不同的API有不同的定義,在GLES2中由于不支持constant uniform buffer,因此這兩個(gè)宏被定義為空。

  • Attributes 和 Varyings
    這兩個(gè)分別是vertex shader的輸入,以及fragment shader的輸入,這是URP的命名習(xí)慣,和內(nèi)置流水線(xiàn)不一樣。
struct Attributes
            {float4 positionOS       : POSITION;
                float2 uv               : TEXCOORD0;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            struct Varyings
            {float2 uv        : TEXCOORD0;
                float fogCoord  : TEXCOORD1;
                float4 vertex : SV_POSITION;

                UNITY_VERTEX_INPUT_INSTANCE_ID
                UNITY_VERTEX_OUTPUT_STEREO
            };

先忽略gpu instancing相關(guān)的宏。vs的輸入只有位置和uv坐標(biāo),而fs的輸入還多了一個(gè)fogCoord。

  • Vertex shader
Varyings vert(Attributes input)
            {Varyings output = (Varyings)0;

                UNITY_SETUP_INSTANCE_ID(input);
                UNITY_TRANSFER_INSTANCE_ID(input, output);
                UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);

                VertexPositionInputs vertexInput = GetVertexPositionInputs(input.positionOS.xyz);
                output.vertex = vertexInput.positionCS;
                output.uv = TRANSFORM_TEX(input.uv, _BaseMap);
                output.fogCoord = ComputeFogFactor(vertexInput.positionCS.z);

                return output;
            }

同樣先忽略instacing。VS就是簡(jiǎn)單的從物體局部坐標(biāo)系變換到clip space,將結(jié)果寫(xiě)入Varying的vertex;變換uv坐標(biāo);以及計(jì)算霧參數(shù)。
這兒要注意的是GetVertexPositionInputs方法。這個(gè)方法位于Packages\com.unity.render-pipelines.universal\ShaderLibrary\ShaderVariablesFunctions.hlsl中:

VertexPositionInputs GetVertexPositionInputs(float3 positionOS)
{VertexPositionInputs input;
    input.positionWS = TransformObjectToWorld(positionOS);
    input.positionVS = TransformWorldToView(input.positionWS);
    input.positionCS = TransformWorldToHClip(input.positionWS);

    float4 ndc = input.positionCS * 0.5f;
    input.positionNDC.xy = float2(ndc.x, ndc.y * _ProjectionParams.x) + ndc.w;
    input.positionNDC.zw = input.positionCS.zw;

    return input;
}

可以看到,這個(gè)方法里面計(jì)算了世界坐標(biāo),view坐標(biāo)和clip space坐標(biāo),以及NDC坐標(biāo)。幾乎所有的URP shader都會(huì)調(diào)用這個(gè)方法。雖然說(shuō)unlit shader里面只需要clip space坐標(biāo),但是為了統(tǒng)一就直接調(diào)用了。由于shader的函數(shù)都是內(nèi)聯(lián)的,不使用的變量和方法應(yīng)該會(huì)被編譯器優(yōu)化掉(錯(cuò)了請(qǐng)告訴我),所以也不用太擔(dān)心性能浪費(fèi)。
關(guān)于uv坐標(biāo)的變換,使用了TRANSFORM_TEX這個(gè)宏,這個(gè)宏的定義位于SRP Core的Shader Library中:
#define TRANSFORM_TEX(tex, name) ((tex.xy) * name##_ST.xy + name##_ST.zw)
就是使用_BaseMap_ST去縮放偏移了一下uv坐標(biāo)。
最后,ComputeFogFactor也位于ShaderVariablesFunctions.hlsl中:

real ComputeFogFactor(float z)
{float clipZ_01 = UNITY_Z_0_FAR_FROM_CLIPSPACE(z);

    #if defined(FOG_LINEAR)
        // factor = (end-z)/(end-start) = z * (-1/(end-start)) + (end/(end-start))
        float fogFactor = saturate(clipZ_01 * unity_FogParams.z + unity_FogParams.w);
        return real(fogFactor);
    #elif defined(FOG_EXP) || defined(FOG_EXP2)
        // factor = exp(-(density*z)^2)
        // -density * z computed at vertex
        return real(unity_FogParams.x * clipZ_01);
    #else
        return 0.0h;
    #endif
}

首先,real是一個(gè)宏定義,位于SRP Core的Common.hlsl中,對(duì)于支持half的平臺(tái),real就是half,否則就是float。
UNITY_Z_0_FAR_FROM_CLIPSPACE是定義在URP的core.hlsl中的一個(gè)宏,會(huì)根據(jù)是否是reverse Z做不同的計(jì)算,關(guān)于z相關(guān)的話(huà)題是很重要也比較復(fù)雜的,將會(huì)單獨(dú)寫(xiě)一篇,這兒就不說(shuō)了。

  • Fragment Shader
half4 frag(Varyings input) : SV_Target
            {UNITY_SETUP_INSTANCE_ID(input);
                UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);

                half2 uv = input.uv;
                half4 texColor = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, uv);
                half3 color = texColor.rgb * _BaseColor.rgb;
                half alpha = texColor.a * _BaseColor.a;
                AlphaDiscard(alpha, _Cutoff);

#ifdef _ALPHAPREMULTIPLY_ON
                color *= alpha;
#endif

                color = MixFog(color, input.fogCoord);

                return half4(color, alpha);
            }

SAMPLE_TEXTURE2D是一個(gè)定義在SRP Core shader library中的一個(gè)跨平臺(tái)的宏,例如:
dx11是
#define SAMPLE_TEXTURE2D(textureName, samplerName, coord2) textureName.Sample(samplerName, coord2)

GLES2是
#define SAMPLE_TEXTURE2D(textureName, samplerName, coord2) tex2D(textureName, coord2)

AlphaDiscard也還是位于ShaderVariablesFunctions.hlsl中:
void AlphaDiscard(real alpha, real cutoff, real offset = 0.0h)
{
#ifdef _ALPHATEST_ON
clip(alpha - cutoff + offset);
#endif
}
很簡(jiǎn)單,根據(jù)是否定義_ALPHATEST_ON關(guān)鍵字,使用cutoff計(jì)算clip。
這兒還會(huì)判斷關(guān)鍵字_ALPHAPREMULTIPLY_ON,如果定義,則會(huì)將alpha值預(yù)先乘到color上,這就是傳統(tǒng)的Alpha預(yù)乘技術(shù)。

Depth only pass

Depth only pass用于生成場(chǎng)景的深度貼圖。這個(gè)pass的代碼在Packages\com.unity.render-pipelines.universal\Shaders\DepthOnlyPass.hlsl中。

本篇小結(jié)

本篇中我們主要分析了Unlit pass的內(nèi)容,可以看到很多宏定義,函數(shù)都來(lái)自于URP和SRP Core的ShaderLibrary中。熟悉這些宏和函數(shù)方便我們寫(xiě)自己的自定義Shader。另外我們要注意CBuffer這個(gè)結(jié)構(gòu),后面會(huì)說(shuō)一下SRP Batcher相關(guān)的內(nèi)容。

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購(gòu),新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧


網(wǎng)站名稱(chēng):深入U(xiǎn)RP之Shader篇3:UnlitShader分析[下]-創(chuàng)新互聯(lián)
標(biāo)題來(lái)源:http://weahome.cn/article/djcpse.html

其他資訊

在線(xiàn)咨詢(xún)

微信咨詢(xún)

電話(huà)咨詢(xún)

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部