計(jì)算機(jī)圖形學(xué)

<p align="center">計(jì)算機(jī)圖形學(xué)</p>


介紹

計(jì)算機(jī)圖形學(xué)(Computer Graphics,簡(jiǎn)稱CG)是一種使用數(shù)學(xué)算法將二維或三維圖形轉(zhuǎn)化為計(jì)算機(jī)顯示器的柵格形式的科學(xué),==所有計(jì)算機(jī)學(xué)科中正反饋?zhàn)顝?qiáng)的一個(gè),沒(méi)有之一==。

大綱

1. 數(shù)學(xué)

2. 渲染管線

3. 光照模型


<p align="center">數(shù)學(xué)</p>

<p align="center">一切科學(xué)都起源于數(shù)學(xué)</p>



<p align="center">渲染管線</p>


  • 渲染管線,也稱渲染流水線,是顯示芯片內(nèi)部處理圖形信號(hào)相互獨(dú)立的并行處理單元。渲染管線就是要把一系列的頂點(diǎn)數(shù)據(jù),紋理等信息,最終轉(zhuǎn)換成一張人眼可以看到的圖像。這個(gè)過(guò)程由CPU和GPU共同完成。

<p align="center">頂點(diǎn)數(shù)據(jù)為[(1, 1, 1), [1, -1, 1]...]的正方形</p>

<p align="center">↓</p>


1. 準(zhǔn)備階段(Input Assembler)

通過(guò)索引來(lái)定義如何將頂點(diǎn)組成三角形,構(gòu)成面片

<p align="center">
</p>

<p align="center">↓</p>

<p align="center">
</p>


<p align="center">一個(gè)平面是由兩個(gè)三角形組成的</p>

<p align="center">
</p>


2. 頂點(diǎn)著色器(Vertex Shader)

a. 局部坐標(biāo)系(Local)

獲取各個(gè)頂點(diǎn)的位置,并表示為矩陣[(1, 1, 1), [1, -1, 1]...]


b. 世界坐標(biāo)系(World)

將模型通過(guò)平移、旋轉(zhuǎn)、縮放操作,實(shí)質(zhì)是矩陣操作,將模型從局部坐標(biāo)軸統(tǒng)一到世界坐標(biāo)軸。
這些平移旋轉(zhuǎn)縮放矩陣相乘所得矩陣,稱之為世界變換矩陣



c. 觀察坐標(biāo)系(View)

為了讓模型在觀察者的視角顯示出,最后得把所有坐標(biāo)系統(tǒng)一到觀察坐標(biāo)系,所乘矩陣稱之為觀察變換矩陣



d. 投影坐標(biāo)系(Projection)

透視矩陣變換,產(chǎn)生近大遠(yuǎn)小的視覺(jué)效果



3. 曲面細(xì)分(Tessellator)

dx11引入,曲面細(xì)分,或者更準(zhǔn)確的說(shuō)“鑲嵌化處理技術(shù)”,就是在頂點(diǎn)與頂點(diǎn)之間自動(dòng)嵌入新的頂點(diǎn)。在自動(dòng)插入大量新的頂點(diǎn)之后,模型的曲面會(huì)被分得非常細(xì)膩,看上去更加平滑致密


4. 幾何著色器(Geometry Shader)

在頂點(diǎn)和片段著色器之間有一個(gè)可選的著色器,叫做幾何著色器(Geometry Shader)。幾何著色器以一個(gè)或多個(gè)表示為一個(gè)單獨(dú)基本圖形(primitive)的頂點(diǎn)作為輸入,比如可以是一個(gè)點(diǎn)或者三角形。幾何著色器有意思的地方在于它可以把(一個(gè)或多個(gè))頂點(diǎn)轉(zhuǎn)變?yōu)橥耆煌幕緢D形(primitive),從而生成比原來(lái)多得多的頂點(diǎn)。

==Unity2017開(kāi)始支持,適用于發(fā)毛==



5. 裁剪(Clipping)

視域體以外的頂點(diǎn)忽略


6. 光柵化(Rasterization)

a. 視口變換
當(dāng)適配不同設(shè)備屏幕時(shí),不同比例以及不同分辨率的矩陣變換。



b. 背面剔除(Culling)
為了優(yōu)化,刪除看不到的面的頂點(diǎn)數(shù)據(jù),讓計(jì)算機(jī)忽略對(duì)其的處理

  • 剔除前:


  • 剔除后:



c. 頂點(diǎn)屬性插值

<p align="center"> ==有沒(méi)想過(guò)頂點(diǎn)有了,像素(屏幕所見(jiàn)的一切都是像素)怎么來(lái)==?</p>

<p align="center">
</p>


7. 像素著色器(Fragment Shader)

像素著色引擎是以每像素為單位的圖形處理功能。

像素都匯聚到這個(gè)地方了,接下來(lái)就可以為所欲為了
代碼層面上逐像素光照可以涉及的領(lǐng)域,Lambert光照(漫射光)Phong Specular高光等光照模型可以套用的地方。


總結(jié)一下

<p align="center">準(zhǔn)備階段(Input Assembler)

<p align="center">頂點(diǎn)著色器(Vertex Shader)

<p align="center">曲面細(xì)分(Tessellator)

<p align="center">幾何著色器(Geometry Shader)

<p align="center">裁剪(Clipping)

<p align="center">光柵化(Rasterization)

<p align="center">像素著色器(Fragment Shader)


<p align="center">不同工種研究不同的領(lǐng)域,作為技術(shù)美術(shù),應(yīng)該深入研究其中的三個(gè)

<p align="center">==頂點(diǎn)著色器==(Vertex Shader)

<p align="center">==幾何著色器==(Geometry Shader)

<p align="center">==像素著色器==(Fragment Shader)


<p align="center">什么是著色器?


<p align="center">所有復(fù)雜的兩層關(guān)系,可以通過(guò)==中間層==解決,著色器就是程序員告訴計(jì)算機(jī)如何渲染的方式


<p align="center">講得太抽象,結(jié)合實(shí)際代碼走一遍


一個(gè)只顯示白色的材質(zhì)


//定義=告訴計(jì)算機(jī)
Shader "PeroPero/Unlit" //顯示材質(zhì)在Unity面板的位置,如上圖
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {} //定義一個(gè)外部獲取的貼圖
    }
    SubShader
    {
        Tags { "LightMode"="ForwardBase" } //定義光照模式為ForwardBase

        Pass    //定義一個(gè)pass,代表一次渲染,多個(gè)pass代表多次渲染
        {
            CGPROGRAM   //定義用CG語(yǔ)言的語(yǔ)法溝通
            #pragma vertex vert //定義頂點(diǎn)著色器在vert函數(shù)中
            #pragma fragment frag //定義像素著色器在frag函數(shù)中
            
            #include "UnityCG.cginc" //引用外部程序集,用于一些快捷API

            //定義一個(gè)數(shù)據(jù)結(jié)構(gòu)
            struct appdata
            {
                float4 vertex : POSITION; //釋義,告訴計(jì)算機(jī)這個(gè)值用于緩存頂點(diǎn)的本地坐標(biāo)的位置
            };

            struct v2f
            {
                float4 vertex : SV_POSITION; //釋義,告訴計(jì)算機(jī)這個(gè)值用于緩存頂點(diǎn)的最終位置
            };
    
            //頂點(diǎn)著色器
            v2f vert (appdata v)
            {
                v2f o; 
                //頂點(diǎn)坐標(biāo)乘以世界坐標(biāo)系的混合矩陣M,再乘以觀察矩陣V,再乘以投影矩陣P,得到最終的坐標(biāo)
                o.vertex = mul(UNITY_MATRIX_MVP, v.vertex); 
                //返回給計(jì)算機(jī)算出來(lái)的最終頂點(diǎn)坐標(biāo)
                return o;
            }
            
            //像素著色器
            fixed4 frag (v2f i) : SV_Target
            {
                //像素的顏色都是白色
                return fixed4(1, 1, 1, 1);
            }
            ENDCG
        }
    }
}


頂點(diǎn)著色器(Vertex Shader)

image

在這里可以獲得所有頂點(diǎn)的控制權(quán),可以做任何和頂點(diǎn)有關(guān)的效果。如UV動(dòng)畫(huà),頂點(diǎn)動(dòng)畫(huà),逐頂點(diǎn)光照




像素著色器(Fragment Shader)


在這里可以獲得所有像素的控制權(quán),可以做一切渲染相關(guān)的效果,如光照、貼圖映射、凹凸貼圖等。

什么是光照效果?如Lambert(漫射光)、Phong Specular(馮氏高光)、Ramp Texture(漸變貼圖)、BRDF(雙向反射分布函數(shù))、Fresnel Reflection(菲涅爾反射)等

<p align="center">Lambert(漫反射)

<p align="center">
</p>

<p align="center">Phong Specular(馮氏高光)

<p align="center">


<p align="center">BRDF(雙向反射分布函數(shù)))

<p align="center">

<p align="center">Fresnel Reflection(菲涅爾反射)

<p align="center">


<p align="center">把以上所有模擬真實(shí)環(huán)境的Shader都寫到一個(gè)材質(zhì)中

<p align="center">那么這個(gè)材質(zhì)就是大家天天吹牛所說(shuō)的==PBR材質(zhì)(Physically Based Rendering)==,即基于物理的渲染,沒(méi)什么深?yuàn)W的。它就是是基于很多==光照模型==。

<p align="center">所以說(shuō),所有復(fù)雜的東西都是簡(jiǎn)單的東西拼湊起來(lái)的。即積木原理,那大家知道什么叫拼圖原理呢?


<p align="center">光照模型</p>


什么是光照模型呢?

當(dāng)光照射到物體表面時(shí),物體對(duì)光會(huì)發(fā)生反射、透射、吸收、衍射、折射、和干涉,其中被物體吸收的部分轉(zhuǎn)化為熱,反射、透射的光進(jìn)入人的視覺(jué)系統(tǒng),使我們能看見(jiàn)物體。為模擬這一現(xiàn)象,我們建立一些數(shù)學(xué)模型來(lái)替代復(fù)雜的物理模型,這些模型就稱為明暗效應(yīng)模型或者光照明模型

簡(jiǎn)而言之,就是復(fù)雜的數(shù)學(xué)算法


Lambert漫反射

模擬漫反射。

漫反射,是投射在粗糙表面上的光向各個(gè)方向反射的現(xiàn)象。當(dāng)一束平行的入射光線射到粗糙的表面時(shí),表面會(huì)把光線向著四面八方反射,所以入射線雖然互相平行,由于各點(diǎn)的法線方向不一致,造成反射光線向不同的方向無(wú)規(guī)則地反射,這種反射稱之為“漫反射”或“漫射”



漫反射光的強(qiáng)度近似地服從于Lambert定律,即漫反射光的光強(qiáng)僅與入射光的方向和反射點(diǎn)處表面法向夾角的余弦成正比。

Phong Specular高光

模擬高光。

Phong 高光模型是最基礎(chǔ)且表現(xiàn)最友好的高光類型。它會(huì)計(jì)算出光在物體表面的反射方向與觀察者視線方向之間的對(duì)比結(jié)果。它是一種非常常見(jiàn)的高光模型,從游戲到電影都有諸多的應(yīng)用。雖然在鏡面反射的精確建模上它并不是最接近現(xiàn)實(shí)的,但在大多數(shù)情況下它都顯得極為逼真。




BlinnPhong Specular高光

廉價(jià)高效模擬高光。

Blinn 是另一種計(jì)算和估算鏡面高光更有效的方式。它是通過(guò)視線方向和光線方向所形成的半角向量來(lái)完成的。它是由一位名叫吉姆·博林(Jim Blinn)的人帶進(jìn)CG 世界的。他發(fā)現(xiàn)使用半角向量而不是我們自己形成的反射向量來(lái)進(jìn)行計(jì)算顯得更加高效。這樣既減少了代碼量也減少了運(yùn)算時(shí)間。




Anisotropic各向異性高光

模擬頭發(fā)和金屬絲的光照模型

(來(lái)自B站Aniraiden)



首先,經(jīng)Anisotropic Normal Map擾動(dòng)后,表面法線已經(jīng)具備凹槽特性。
float3 anisoDir = normalize(s.Normal + s.AnisoDir);
float aniso = dot(anisoDir, halfVector);
==其次,Sin函數(shù)的目的中為了產(chǎn)生一個(gè)環(huán)。如下圖。如果沒(méi)有sin,則不會(huì)產(chǎn)生光環(huán)。==
最后,_AnisoOffset的作用是控制光環(huán)位置。使得光環(huán)可以水平位移,達(dá)到你想要的任何位置。
aniso = max(0, sin((aniso + _AnisoOffset) * 3.14));
如何成環(huán)呢,忽略_AnisoOffset
算式為 aniso = max(0, sin((aniso) * 3.14));
對(duì)比aniso = max(0, aniso);
則如下圖


<p align="center">僅高光的圖:

<p align="center">

<p align="center">加入Anisotropic各向異性后

<p align="center">

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。