亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

淺談Unity中的Shader

 更新時(shí)間:2021年06月26日 14:34:15   作者:我聽到你了  
Shader,中文名為著色器,對(duì)很多開發(fā)者來說它是一個(gè)神秘的存在。Shader其實(shí)就是專門用來渲染圖形的一種技術(shù),通過shader,我們可以自定義顯卡渲染畫面的算法,使畫面達(dá)到我們想要的效果

一、Shader基礎(chǔ)知識(shí)

1.1、什么是Shader

在講什么是Shader之前我們先看看下面兩段代碼 

這里寫圖片描述

這兩段代碼實(shí)現(xiàn)的功能都是提取 2D 圖像上每個(gè)像素點(diǎn)的顏色值,第一段代碼是用c++寫的,在cup上面運(yùn)行,它需要循環(huán)遍歷每個(gè)像素點(diǎn),第二段代碼是CG代碼,在GPU上面運(yùn)行,它只需要一行代碼就能實(shí)現(xiàn)同樣的功能。GPU是專門用來進(jìn)行圖形處理的,而Shader,就是GPU執(zhí)行的一段針對(duì)3D對(duì)象進(jìn)行操作的程序。

維基百科上對(duì)shader的解釋是這樣

Shader(著色器)應(yīng)用于計(jì)算機(jī)圖形學(xué)領(lǐng)域,指一組供計(jì)算機(jī)圖形資源在執(zhí)行渲染任務(wù)時(shí)使用的指令,用于計(jì)算圖像的顏色或明暗。但近來,它也能用于處理一些特殊效果,或者視頻后處理。通俗地說,著色器告訴電腦如何用特有的一種方法去繪制物體。

程序員將著色器應(yīng)用于圖形處理器(GPU)的可編程流水線,來實(shí)現(xiàn)三維應(yīng)用程序。這樣的圖形處理器有別于傳統(tǒng)的固定流水線處理器,為GPU編程帶來更高的靈活性和適應(yīng)性。以前固有的流水線只能進(jìn)行一些幾何變換和像素灰度計(jì)算?,F(xiàn)在可編程流水線還能處理所有像素、頂點(diǎn)、紋理的位置、色調(diào)、飽和度、明度、對(duì)比度并實(shí)時(shí)地繪制圖像。著色器還能產(chǎn)生如模糊、高光、有體積光源、失焦、卡通渲染、色調(diào)分離、畸變、凹凸貼圖、邊緣檢測(cè)、運(yùn)動(dòng)檢測(cè)等效果。

1.2、OpenGL的渲染流程

知道了什么是shader,我們?cè)賮砹私庖幌聅hader的種類,首先我先介紹一下OpenGL的渲染流程

這里寫圖片描述

上圖便是OpenGL的渲染流程,將這個(gè)流程簡(jiǎn)化之后是這樣的 

頂點(diǎn)變換 → 圖元裝配和光柵化 → 片元紋理映射和著色 → 寫入幀緩存

在頂點(diǎn)變換和片元著色這兩步時(shí),我們就可以對(duì)其編程,進(jìn)行各種操作,其他的部分我們是沒法進(jìn)行編程的。我們的shader就是作用于頂點(diǎn)變換和片元著色這兩個(gè)部分的。

1.3、shader的種類

知道了shader起作用的地點(diǎn),我們現(xiàn)在可以了解一下shader的種類了。

shader按管線分類一般分為固定渲染管線與可編程渲染管線。固定渲染管線就是功能固定的管線,比如物體表面光的折射,反射的算法是固定無法修改的,我們只能對(duì)這些功能進(jìn)行配置,比如開啟或關(guān)閉反射效果,霧化效果等。因?yàn)檫@種管線功能固定,無法在程序上對(duì)物體細(xì)節(jié)的表現(xiàn)給予更多更自由的控制,無法達(dá)到更多我們想要的畫面效果。所以現(xiàn)在的顯卡都是可編程渲染管線,也就是曾經(jīng)那些我們固定無法修改的部門現(xiàn)在可以編程去修改,自由度高了之后,我們也就能實(shí)現(xiàn)更多自己想要的特效了。

1.4、shader的開發(fā)語(yǔ)言

知道了shader的種類,我在來說說shader的開發(fā)語(yǔ)言

HLSL: 主要用于Direct3D。平臺(tái):windows。

GLSL: 主要用于OpenGL。 平臺(tái):移動(dòng)平臺(tái)(iOS,安卓),mac(only use when you target Mac OS X or OpenGL ES 2.0)

CG:與DirectX 9.0以上以及OpenGL 完全兼容。運(yùn)行時(shí)或事先編譯成GPU匯編代碼。CG比HLSL、GLSL支持更多的平臺(tái),Unity Shader采用CG/HLSL作為開發(fā)語(yǔ)言。

二、Unity中Shader知識(shí)介紹

2.1、shader在GPU的渲染流程

這里寫圖片描述

進(jìn)入GPU運(yùn)算首先進(jìn)行的是Vertex Processor頂點(diǎn)處理器,這個(gè)部分就需要我們使用Vertex Shader頂點(diǎn)著色器,頂點(diǎn)著色器運(yùn)算的結(jié)果會(huì)交給Pixel Processor像素處理器,也就是片段處理器,在這個(gè)部分我需要為像素處理編寫Pixel Shader像素著色器程序,這部分計(jì)算完后就輸出了最終我們可以用于在屏幕上的顏色信息,我們把它叫做Frame Buffer幀緩沖。幀緩沖存儲(chǔ)的是計(jì)算機(jī)依次顯示所要的數(shù)據(jù)。

2.2、Unity中shader的類型

①Fixed function shader :屬于固定渲染管線 Shader, 基本用于高級(jí)Shader在老顯卡無法顯示時(shí)的回滾。使用的是ShaderLab語(yǔ)言,語(yǔ)法與微軟的FX files 或者NVIDIA的 CgFX類似。

②Vertex and Fragment Shader:最強(qiáng)大的Shader類型,屬于可編程渲染管線. 使用的是CG/HLSL語(yǔ)法。

③Surface Shader:Unity3d推崇的Shader類型,使用Unity預(yù)制的光照模型來進(jìn)行光照運(yùn)算。使用的也是CG/HLSL語(yǔ)法。

我們先了解一下這三種shader的異同點(diǎn)。

相同點(diǎn): 

①都必須從唯一一個(gè)根Shader開始 
②Properties參數(shù)部分,作用及語(yǔ)法完全相同 
③具體功能都在SubShader里(Subshader會(huì)自上而下運(yùn)行第一個(gè)硬件能支持的) 
④SubShader都可以打標(biāo)簽 
⑤都可以回滾 
⑥都可以處理基本的功能,例如光照漫反射(Diffuse)以及鏡面反射(Specular)。但是Vertex and Fragment和Surface都能實(shí)現(xiàn)Fixed function實(shí)現(xiàn)不了的高級(jí)功能,例如基于uv計(jì)算的效果等等。

不同點(diǎn) 

①Fixed function shader以及Vertex and Fragment Shader在subshader下面還有pass{}結(jié)構(gòu),但是Surface Shader,已經(jīng)將具體內(nèi)容打包在光照模型了,不能加pass{} 
②Fixed function shader每句代碼之后沒有分號(hào)“;”, 但是V&F shader以及Surface shader每句代碼之后都必須加分號(hào)“;” 
③核心結(jié)構(gòu)不同 

Fixed function shader的SunShader中的結(jié)構(gòu)為

Material{} 
……
SetTexture[_MainTex]{
    ……
}

Vertex and Fragment Shader的核心結(jié)構(gòu)為

CGPROGRAM
#pragma vertex vert
#pragma fragment frag   
……       
#include "UnityCG.cginc"
ENDCG

Surface Shader的核心結(jié)構(gòu)是

CGPROGRAM
#pragma surface surf Lambert
……
ENDCG

可以看到這三種shader的Subshader內(nèi)的編碼實(shí)現(xiàn)是不一樣的,這三種shader的結(jié)構(gòu)如下圖,他們的不同點(diǎn)都在SubShader里面 

這里寫圖片描述

因?yàn)閁nity推薦Surface Shader,所以文章直接分析Surface Shader的用法,其他兩種shader就不做過多介紹了。

三、Surface Shader語(yǔ)法

在Unity的項(xiàng)目面板中直接創(chuàng)建一個(gè)Stander surface shader,默認(rèn)生成的代碼如下

Shader "Custom/DiffuseShader" {
    Properties {
        _Color ("Color", Color) = (1,1,1,1)       //設(shè)置一個(gè)默認(rèn)的顏色值
        _MainTex ("Albedo (RGB)", 2D) = "white" {}  //默認(rèn)的白色紋理
        _Glossiness ("Smoothness", Range(0,1)) = 0.5  //默認(rèn)的光澤度
        _Metallic ("Metallic", Range(0,1)) = 0.0    //金屬光澤度
    }
    SubShader {
        Tags { "RenderType"="Opaque"}
        LOD 200
 
        CGPROGRAM
        // Physically based Standard lighting model, and enable shadows on all light types
        #pragma surface surf Standard fullforwardshadows
 
        // Use shader model 3.0 target, to get nicer looking lighting
        #pragma target 3.0
 
 
        fixed4 _Color;
        sampler2D _MainTex;
        half _Glossiness;
        half _Metallic;
 
 
        struct Input {
            float2 uv_MainTex;
        };
 
 
 
        void surf (Input IN, inout SurfaceOutputStandard o) {
            // Albedo comes from a texture tinted by color
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
            o.Albedo = c.rgb;
            // Metallic and smoothness come from slider variables
            o.Metallic = _Metallic;
            o.Smoothness = _Glossiness;
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

接下來我來介紹一下這段代碼

Properties {}

Properties{}是定義著色器屬性的,在這里定義的屬性將被作為輸入提供給所有的子著色器。屬性定義的格式如下

_Name(“Display Name”, type) = defaultValue[{options}]

_Name代表的是屬性名,如Color,MainTex,Glossiness ,Metallic 等

”Display Name”則是在Inspector中顯示的名字

type代表屬性:

Color - 一種顏色,由RGBA(紅綠藍(lán)和透明度)四個(gè)量來定義;

2D - 一張2的階數(shù)大小(256,512之類)的貼圖。這張貼圖將在采樣后被轉(zhuǎn)為對(duì)應(yīng)基于模型UV的每個(gè)像素的顏色,最終被顯示出來;

Rect - 一個(gè)非2階數(shù)大小的貼圖;

Cube - 即Cube map texture(立方體紋理),簡(jiǎn)單說就是6張有聯(lián)系的2D貼圖的組合,主要用來做反射效果(比如天空盒和動(dòng)態(tài)反射),也會(huì)被轉(zhuǎn)換為對(duì)應(yīng)點(diǎn)的采樣;

Range(min, max) - 一個(gè)介于最小值和最大值之間的浮點(diǎn)數(shù),一般用來當(dāng)作調(diào)整Shader某些特性的參數(shù)(比如透明度渲染的截止值可以是從0至1的值等);

Float - 任意一個(gè)浮點(diǎn)數(shù);

Vector - 一個(gè)四維數(shù);

這段默認(rèn)Properties在Inspector中的顯示效果如下 

這里寫圖片描述

SubShader{}

Tags :tags標(biāo)簽是三種類型的shader都具有的標(biāo)簽,它決定了硬件什么調(diào)用該子著色器

Tags標(biāo)簽里面默認(rèn)的“RenderType”=”O(jiān)paque”,是告訴系統(tǒng)應(yīng)該在渲染非透明物體時(shí)調(diào)用這個(gè)SubShader

“RenderType”=”Transparent”表示在渲染含有透明效果的物體時(shí)調(diào)用該Sunshader,

Tags里面還有許多其他的我們可選的標(biāo)簽

①.”Queue”:定義渲染順序。預(yù)制的值有這些 

    ”Background”。值為1000。比如用于天空盒。

    ”Geometry”。值為2000。大部分物體在這個(gè)隊(duì)列。不透明的物體也在這里。

    ”AlphaTest”。值為2450。已進(jìn)行AlphaTest的物體在這個(gè)隊(duì)列。 

    ”Transparent”。值為3000。透明物體。 

    ”O(jiān)verlay”。值為4000。比如鏡頭光暈。 

    用戶可以定義任意值,比如”Queue”=”Geometry+10”

②“RenderType”:定義渲染類型。預(yù)制的值有這些

    ”O(jiān)paque”:絕大部分不透明的物體都使用這個(gè); 

    ”Transparent”:絕大部分透明的物體、包括粒子特效都使用這個(gè); 

    ”Background”:天空盒都使用這個(gè); 

    ”O(jiān)verlay”:GUI、鏡頭光暈都使用這個(gè); 

③”ForceNoShadowCasting”:定義物體是否有陰影效果

    “true”。表示有陰影

    “false”。表示沒有陰影

LOD:Level of Detail的縮寫,它表示著色器的細(xì)節(jié)層次效果。在某些硬件比較差的系統(tǒng)上,我們可以設(shè)置一個(gè)低一點(diǎn)的值,減少細(xì)節(jié)的顯示。Unity內(nèi)置shader的LOD值如下

  • VertexLit kind of shaders = 100
  • Decal, Reflective VertexLit = 150
  • Diffuse = 200
  • Diffuse Detail, Reflective Bumped Unlit, Reflective Bumped VertexLit = 250
  • Bumped, Specular = 300
  • Bumped Specular = 400
  • Parallax = 500
  • Parallax Specular = 600

從CGPROGRAM 到ENDCG這一部分就這這個(gè)shader的核心內(nèi)容了

#pragma surface surf Standard fullforwardshadows

這段編譯指令聲明了我們要寫一個(gè)Surface Shader,并指定了光照模型。它的寫法是這樣的

#pragma surface surfaceFunction lightModel [optionalparams]

surface - 聲明的是一個(gè)表面著色器surfaceFunction - 著色器代碼的方法的名字lightModel - 使用的光照模型。

這段代碼默認(rèn)的surfaceFunction為surf,我們可以在源碼的底部看到在這兒聲明了的surf函數(shù)。默認(rèn)的lightModel為Standard。

下面我先介紹一下lightModel光照模型

  • Lambert:該光照模型能很好的表示粗糙表面的光照,但不能表現(xiàn)出鏡面反射高光
  • Toon:最近在游戲中常用的風(fēng)格之一即是Toon shading(又稱 cel shading).這是一種非逼真渲染風(fēng)格,通過改變了光在一個(gè)模型上反射實(shí)際情況來給人以手繪的感覺
  • BlinnPhong:仿真鏡面反射材料
  • Standard:Unity5中默認(rèn)的光照模式是Standard, 其引入了 物理渲染 (PBR), 但是與其它光照模型沒有什么不同。相比于朗伯反射, PBR提供了一個(gè)更加逼真的光線物體作用模型,PBR考慮了材料的物理屬性, 比如能量守恒以及光的散射

接下來的這段代碼

fixed4 _Color;
sampler2D _MainTex;
half _Glossiness;
half _Metallic;

我們可以發(fā)現(xiàn) _Color,_MainTex,_Glossiness,_Metallic都shader屬性的聲明,在上面的Properties 中已經(jīng)聲明過了這些屬性,但是在這段CG程序,要想訪問在Properties中所定義的變量的話,必須使用和之前變量相同的名字再次進(jìn)行聲明,其實(shí)就是鏈接在上面properties中聲明的屬性。

我再來介紹一下shader中常用的數(shù)據(jù)類型

3種基本數(shù)值類型:float、half和fixed。 
這3種基本數(shù)值類型可以再組成vector和matrix,比如half3是由3個(gè)half組成、float4x4是由16個(gè)float組成。

float:32位高精度浮點(diǎn)數(shù)。 
half:16位中精度浮點(diǎn)數(shù)。范圍是[-6萬, +6萬],能精確到十進(jìn)制的小數(shù)點(diǎn)后3.3位。 
fixed:11位低精度浮點(diǎn)數(shù)。范圍是[-2, 2],精度是1/256。 
Sampler2D:2D紋理屬性

接下來就是Input結(jié)構(gòu)體

struct Input {
    float2 uv_MainTex;
};

這個(gè)結(jié)構(gòu)體和surf函數(shù)中的另一個(gè)參數(shù)inout結(jié)構(gòu)體是相對(duì)的,一個(gè)代表輸入,一個(gè)代表輸出。我們可以這樣理解這兩個(gè)結(jié)構(gòu)體,你定義輸入數(shù)據(jù)結(jié)構(gòu)(Inputs Struct)、編寫自己的Surface函數(shù)處理輸入、最終輸出修改過后的SurfaceOutput。Input其實(shí)是需要我們?nèi)ザx的結(jié)構(gòu),所以我們可以把所需要參與計(jì)算的數(shù)據(jù)都放到這個(gè)Input結(jié)構(gòu)中,傳入surf函數(shù)使用

默認(rèn)的Input結(jié)構(gòu)體中有一個(gè)uv_MainTex參數(shù),代表了紋理的UV值,我們便可以在surf函數(shù)中直接使用這個(gè)參數(shù)了。

知道了Input的結(jié)構(gòu)體,我們?cè)趤砜纯碠utput的結(jié)構(gòu)體

struct SurfaceOutput
{
    fixed3 Albedo;  // diffuse color  漫反射的顏色值。
    fixed3 Normal;  // tangent space normal, if written 法線坐標(biāo)
    fixed3 Emission;  //自發(fā)光顏色
    half Specular;  // specular power in 0..1 range 鏡面反射系數(shù)
    fixed Gloss;    // specular intensity   光澤系數(shù)
    fixed Alpha;    // alpha for transparencies  透明度系數(shù)
};

現(xiàn)在我們?cè)趤砜纯磗urf函數(shù)里面的內(nèi)容,就已經(jīng)能夠看懂了

我們現(xiàn)在在來看看surf函數(shù)里面的代碼,就能知道里面是什么意思了

void surf (Input IN, inout SurfaceOutputStandard o) {
    fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
    o.Albedo = c.rgb;               //將物體顯示的漫反射顏色設(shè)置成在紋理的顏色值
    o.Metallic = _Metallic;         //將物體顯示的金屬光澤設(shè)置成在properties中定義的光澤
    o.Smoothness = _Glossiness;     //設(shè)置物體顯示的光滑度
    o.Alpha = c.a;                  //設(shè)置物體顯示的透明度
}

以上就是淺談Unity中的Shader的詳細(xì)內(nèi)容,更多關(guān)于Unity Shader的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 淺析C# 基礎(chǔ)語(yǔ)法的使用

    淺析C# 基礎(chǔ)語(yǔ)法的使用

    本篇文章對(duì)C#中基礎(chǔ)語(yǔ)法的使用。進(jìn)行了詳細(xì)的分析介紹。需要的朋友參考下
    2013-05-05
  • C#調(diào)用SQL?Server中有參數(shù)的存儲(chǔ)過程

    C#調(diào)用SQL?Server中有參數(shù)的存儲(chǔ)過程

    這篇文章介紹了C#調(diào)用SQL?Server中有參數(shù)存儲(chǔ)過程的方法,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-03-03
  • Unity腳本自動(dòng)添加頭部注釋的全過程

    Unity腳本自動(dòng)添加頭部注釋的全過程

    在一些公司需要代碼嚴(yán)格的管理,有時(shí)候會(huì)需要用到每個(gè)腳本的頭部做一些介紹,所以下面這篇文章主要給大家介紹了關(guān)于Unity腳本自動(dòng)添加頭部注釋的相關(guān)資料,需要的朋友可以參考下
    2022-01-01
  • 如何在datatable中使用groupby進(jìn)行分組統(tǒng)計(jì)

    如何在datatable中使用groupby進(jìn)行分組統(tǒng)計(jì)

    如何在datatable中進(jìn)行分組,并且計(jì)算分組后每組的數(shù)量,考慮了一下,可以使用LINQ來實(shí)現(xiàn)datatable分組,需要的朋友可以參考下
    2015-08-08
  • C#使用NPOI讀取excel轉(zhuǎn)為DataSet

    C#使用NPOI讀取excel轉(zhuǎn)為DataSet

    這篇文章主要為大家詳細(xì)介紹了C#使用NPOI讀取excel轉(zhuǎn)為DataSet,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • C# wpf Brush轉(zhuǎn)Hex字符串的實(shí)例代碼

    C# wpf Brush轉(zhuǎn)Hex字符串的實(shí)例代碼

    這篇文章主要介紹了C# wpf Brush轉(zhuǎn)Hex字符串的實(shí)例代碼,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2021-01-01
  • C#使用RestClient調(diào)用Web API

    C#使用RestClient調(diào)用Web API

    這篇文章介紹了C#使用RestClient調(diào)用Web API的方法,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-05-05
  • C#實(shí)現(xiàn)在窗體上的統(tǒng)計(jì)圖效果

    C#實(shí)現(xiàn)在窗體上的統(tǒng)計(jì)圖效果

    這篇文章主要為大家詳細(xì)介紹了C#實(shí)現(xiàn)在窗體上的統(tǒng)計(jì)圖效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • c#實(shí)現(xiàn)圖片二值化例子(黑白效果)

    c#實(shí)現(xiàn)圖片二值化例子(黑白效果)

    這篇文章主要介紹了c#實(shí)現(xiàn)圖片二值化例子,圖像二值化就是將圖像上的像素點(diǎn)的灰度值設(shè)置為0或255,也就是將整個(gè)圖像呈現(xiàn)出明顯的黑白效果,需要的朋友可以參考下
    2014-08-08
  • C#獲取日期的星期名稱實(shí)例代碼

    C#獲取日期的星期名稱實(shí)例代碼

    本文通過實(shí)例代碼給大家介紹了基于c#獲取日期的星期名稱,代碼簡(jiǎn)單易懂,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2018-08-08

最新評(píng)論