Shader學習筆記

来源:http://www.cnblogs.com/susufufu/archive/2017/05/27/6912333.html
-Advertisement-
Play Games

Shader學習筆記 例子: Mesh Filter : 存儲一個Mesh(網格,模型的網格,就是模型的由哪些三角面組成,組成一個什麼樣子的模型,三角面的一些頂點信息) Mesh Renderer:用來渲染一個模型的外觀,就是樣子, 按照 mesh給它皮膚,給它顏色 通過Material(材質)控制 ...


Shader學習筆記
例子:

Shader "SrfShader1"{
    //定義顯示在Inspector中的變數,並從Inspector中獲取值
    Properties{
        _Color("Color",Color)=(1,1,1,1) //用來融合漫反射或2d紋理的顏色
        _MainTex("MainTex (RGB)",2D)="white"{} //主2d紋理圖片色
        _Gloss("Gloss",Range(1,100)) = 10
    }
    //可以多個SubShader塊(渲染方案),從第一個開始匹配,直到可用,否則匹配FallBack方案
    SubShader{
        Pass{
            Tags{"LightMode"="ForwardBase"}//標簽
            CGPROGRAM
            //引入unity內置的文件,取得第一個直射光源(這樣可以訪問它的屬性:顏色_LightColor0,法線_World2Object,位置_WorldSpaceLightPos0)
            #include "Lighting.cginc" 
            //聲明兩個函數,頂點函數和片元函數(系統自動調用這兩個函數)
            #pragma vertex vert
            #pragma fragment frag
            //定義變數,從Properties中獲得的材質球的顏色
            fixed4 _Color; 
            sampler2D _MainTex; //2d紋理
            float4 _MainTex_ST;  //該2d紋理的縮放和偏移
            half _Gloss;
            //定義結構體(定義了一個頂點的3個屬性:頂點坐標、法線方向、紋理貼圖中的坐標)
            struct a2v{
                float4 vertex:POSITION; //告訴Unity把模型空間下的頂點坐標填充給該變數vertex
                float3 normal:NORMAL; //告訴Unity把模型空間下的法線方向填充給normal
                float4 texcoord:TEXCOORD0; //告訴Unity把第一套紋理坐標UV填充給texcoord
            };
        
            struct v2f{
                float4 position:SV_POSITION; //填充為剪裁空間的坐標
                float3 worldNormal:COLOR0;
                float3 worldVertex:COLOR1;
                float2 uv:TEXCOORD1; 
            };
            //定義頂點函數(對模型的每個頂點調用,把結構a2v中的值賦值給f,把返回值應用到每個頂點,根據頂點之間的插值來填充非頂點位置)
            //把邏輯寫在這裡,表示使用逐頂點計算的光照色
            v2f vert(a2v v){
                v2f f;
                //把把模型空間下的頂點坐標轉換為剪裁空間的頂點坐標
                f.position = mul(UNITY_MATRIX_MVP,v.vertex);
                f.worldNormal = mul(v.normal,(float3x3)_World2Object);
                //f.worldNormal = UnityObjectToWorldNormal(v.normal);//也可以使用UnityCG.cginc中一些常用的函數
                f.worldVertex = mul(v.vertex,_World2Object).xyz;
                f.uv = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw; //取到貼圖的UV坐標的縮放倍數+偏移
                return f;
            }
            //定義片元函數(對剪裁空間下的模型上的每個像素點調用,把返回值顏色應用到每個對應的像素點)
            //把邏輯寫在這裡,表示使用逐像素計算的光照色
            fixed4 frag(v2f f):SV_Target{
                //把把模型空間下的法線方向轉換為模型空間的法線方向,並取得該法線的單位向量
                fixed3 normalDir = normalize(f.worldNormal);
                //取得光的位置(這裡是平行光)的單位向量
                fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
                //取得紋理貼圖當前像素點的顏色,並和指定顏色融合
                fixed3 texture2dColor = tex2D(_MainTex,f.uv.xy)*_Color.rgb;
                //1.取得漫反射的顏色(使用半蘭伯特光照模型),融合貼圖顏色
                fixed3 diffuse = _LightColor0.rgb * (dot(normalDir,lightDir)*0.5+0.5) * texture2dColor;
                //取得反射光的方向,利用reflect()方法,根據入射光和法線來取
                //fixed3 reflectDir = normalize(reflect(-lightDir,normalDir));
                //取得視野方向,_WorldSpaceCameraPos表示視野位置
                fixed3 viewDir = normalize( _WorldSpaceCameraPos.xyz - f.worldVertex );
                //取得平行光和視野方向的平分線方向單位向量(兩個向量相加除2就等於平分線向量)
                fixed3 halfDir = normalize(lightDir+viewDir);
                //2-1.取得反射光顏色(Blinn光照模型)
                //fixed3 specular = _LightColor0.rgb * pow(max(dot(reflectDir,viewDir),0),_Gloss);
                //2-2.取得反射光顏色(Blinn-Phong光照模型)
                fixed3 specular = _LightColor0.rgb * pow(max(dot(normalDir,halfDir),0),_Gloss);
                //3.各種影響的顏色疊加:漫反射 + 高光反射 + Unity內置環境光顏色與貼圖色融合(融合後效果更好,不會只是變亮或變暗)
                fixed3 tempColor = diffuse + specular + UNITY_LIGHTMODEL_AMBIENT.rgb*texture2dColor;
                return fixed4(tempColor,1);
            }
            ENDCG
        }
    }
    FallBack "Diffuse"
}

Mesh Filter : 存儲一個Mesh(網格,模型的網格,就是模型的由哪些三角面組成,組成一個什麼樣子的模型,三角面的一些頂點信息)
Mesh Renderer:用來渲染一個模型的外觀,就是樣子, 按照 mesh給它皮膚,給它顏色
通過Material(材質)控制模型渲染的樣子
Material貼圖(可以沒有,可以是一個單純的顏色)

書籍
unity shader 入門精要(樂樂程式猿)
unity 3d shaderlab開發實戰詳解(第二版)
unity 5.x shaders and effects cookbook(中文版 unity著色器和屏幕特效開發秘籍)

CG語言教程官網
http://http.developer.nvidia.com/CgTutorial/cg_tutorial_frontmatter.html

一些網站
www.shadertoy.com
http://blog.csdn.net/poem_qianmo?viewmode=contents

數學函數線上演示
http://zh.numberempire.com/graphingcalculator.php

UnityCG.cginc中一些常用的函數,這個文件預設會自動引入

//攝像機方向(視角方向)
float3 WorldSpaceViewDir(float4 v)      根據模型空間中的頂點坐標 得到 (世界空間)從這個點到攝像機的觀察方向
float3 UnityWorldSpaceViewDir(float4 v) 世界空間中的頂點坐標==》世界空間從這個點到攝像機的觀察方向
float3 ObjSpaceViewDir(float4 v)         模型空間中的頂點坐標==》模型空間從這個點到攝像機的觀察方向
//光源方向
float3 WorldSpaceLightDir(float4 v)     模型空間中的頂點坐標==》世界空間中從這個點到光源的方向
float3 UnityWorldSpaceLightDir(float4 v)     世界空間中的頂點坐標==》世界空間中從這個點到光源的方向
float3 ObjSpaceLightDir(float4 v)     模型空間中的頂點坐標==》模型空間中從這個點到光源的方向
//方向轉換
float3 UnityObjectToWorldNormal(float3 norm) 把法線方向 模型空間==》世界空間
float3 UnityObjectToWorldDir(float3 dir) 把方向 模型空間=》世界空間
float3 UnityWorldToObjectDir(float3 dir) 把方向 世界空間=》模型空間

什麼是OpenGL、DirectX
shader可以認為是一種渲染命令 ,由opengl 或者dx進行解析,來控制渲染豐富多彩的圖形

OpenGL 使用GLSL 編寫shader
DirectX 使用HSSL 編寫shader
英偉達 CG 編寫shader(跨平臺)

Unity Shader的分類
使用的是ShaderLab編寫Unity中的Shader
1,錶面著色器 Surface Shader
2,頂點/片元著色器 Vertex/Fragment Shader
3,固定函數著色器 Fixed Function Shader

Unityshader中屬性的類型有哪些
_Color("Color",Color)=(1,1,1,1)
_Vector("Vector",Vector)=(1,2,3,4)
_Int("Int",Int)= 34234
_Float("Float",Float) = 4.5
_Range("Range",Range(1,11))=6
_2D("Texture",2D) = "red"{}
_Cube("Cube",Cube) = "white"{}
_3D("Texure",3D) = "black"{}
傳遞步驟:1-3
1.從應用程式傳遞到頂點函數的語義有哪些a2v
POSITION 頂點坐標(模型空間下的)
NORMAL 法線( 模型空間下)
TANGENT 切線(模型空間)
TEXCOORD0~n 紋理坐標(0-1的值)
COLOR 頂點顏色

2.從頂點函數傳遞給片元函數的時候可以使用的語義
SV_POSITION 剪裁空間中的頂點坐標(一般是系統直接使用)
COLOR0 可以傳遞一組值 4個
COLOR1 可以傳遞一組值 4個
TEXCOORD0~7 傳遞紋理坐標

3.片元函數傳遞給系統
SV_Target 顏色值,顯示到屏幕上的顏色

聲明兩個函數,頂點函數和片元函數(系統自動調用這兩個函數)
#pragma vertex vert
#pragma fragment frag
逐頂點計算光照,效果較差,頂點之間的過度跡象明顯,但渲染速度較快
v2f vert(a2v v){.....}
逐像素計算光照,效果較好,平滑過渡,但渲染速度較慢
fixed4 frag(v2f f):SV_Target{...}

什麼是光照模型
光照模型就是一個公式,使用這個公式來計算在某個點的光照效果(模擬現實中的效果)

標準光照模型
在標準光照模型裡面,我們把進入攝像機的光分為下麵四個部分
1.自發光
2.高光反射(根據法線直接反射,類似鏡子)
3.漫反射 Diffuse = 直射光顏色 * max(0,cos夾角(光和法線的夾角) ) cosθ = 光方向· 法線方向
4.環境光

Tags{ "LightMode"="ForwardBase" }
只有定義了正確的LightMode才能得到一些Unity的內置光照變數
#include "Lighting.cginc"
引入unity的內置的文件,取得第一個直射光源(這樣可以訪問它的屬性)

normalize() 用來把一個向量,單位化(原來方向保持不變,長度變為1),單位向量
max() 用來取得函數中最大的一個
dot 用來取得兩個向量的點積
_WorldSpaceLightPos0 取得平行光的位置
_LightColor0取得平行光的顏色
UNITY_MATRIX_MVP 這個矩陣用來把一個坐標從模型空間轉換到剪裁空間
_World2Object 這個矩陣用來把一個方向從世界空間轉換到模型空間
UNITY_LIGHTMODEL_AMBIENT 用來獲取環境光,可在Window>>Linghting菜單裡面的Ambient Source設置

融合:兩個顏色相乘,融合後混合了兩種顏色,但亮度可能變暗
疊加:兩個顏色相加,相加後亮度一般會增強

漫反射:
蘭伯特光照模型:背光部分是純黑的
Diffuse = 直射光顏色 * max(0, cosθ) ,其中cosθ = dot(光方向,法線方向),即:點積
半蘭伯特光照模型:背光部分不會全黑
Diffuse = 直射光顏色 (cosθ0.5 +0.5)

高光反射:
Blinn光照模型
Specular= 直射光 * pow(max(cosθ,0),10) θ:是反射光方向和視野方向的夾角
Blinn-Phong光照模型
Specular=直射光 * pow(max(cosθ,0),10) θ:是法線和x的夾角 x 是平行光和視野方向的平分線

shader中的各種空間坐標
http://blog.csdn.net/lyh916/article/details/50906272
什麼是切線空間(法線貼圖使用切線空間,就可以通用於不同模型)
http://blog.csdn.net/bonchoix/article/details/8619624

法線貼圖:顯示為藍色的圖片,使用切線空間
法線坐標處理為像素值:
pixel = (normal+1)/2
像素值處理為法線坐標:
normal = pixel*2 - 1

法線貼圖的使用(凹凸調節+透明度)

Shader "Rock Alpha"{
    Properties{
        //_Diffuse("Diffuse Color",Color) = (1,1,1,1)
        _Color("Color",Color) = (1,1,1,1)
        _MainTex("Main Tex",2D) = "white"{}
        _NormalMap("Normal Map",2D) = "bump"{} //法線貼圖
        _BumpScale("Bump Scale",Float)=1 //用來調節凹凸
        _AlphaScale("Alpha Scale",Float)=1 //調節透明度
    }
    SubShader{
        //用於透明度渲染
        Tags{ "Queue"="Transparent" "IngnoreProjector"="True" "RenderType"="Transparent" }
        Pass{
            Tags{ "LightMode" = "ForwardBase" }
            //以下兩個用於透明度渲染
            ZWrite Off
            Blend SrcAlpha OneMinusSrcAlpha
            CGPROGRAM
            #include "Lighting.cginc"
            #pragma vertex vert
            #pragma fragment frag
            //fixed4 _Diffuse;
            fixed4 _Color;
            sampler2D _MainTex;
            float4 _MainTex_ST;
            sampler2D _NormalMap;
            float4 _NormalMap_ST;
            float _BumpScale;
            float _AlphaScale;
            struct a2v {
                float4 vertex:POSITION;
                float3 normal:NORMAL;
                float4 tangent:TANGENT;//tangent.w是用來確定切線空間中坐標軸的方向的 
                float4 texcoord:TEXCOORD0;
            };
            struct v2f {
                float4 svPos:SV_POSITION;
                //float3 worldNormal:TEXCOORD0;
                //float4 worldVertex:TEXCOORD1;
                float3 lightDir : TEXCOORD0;
                float4 uv:TEXCOORD1; //貼圖坐標存在xy,法線貼圖存在zw
            };
            v2f vert(a2v v) {
                v2f f;
                f.svPos = mul(UNITY_MATRIX_MVP, v.vertex);
                //f.worldNormal = UnityObjectToWorldNormal(v.normal);
                //f.worldVertex = mul(v.vertex, _World2Object);
                f.uv.xy = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
                f.uv.zw = v.texcoord.xy * _NormalMap_ST.xy + _NormalMap_ST.zw;
                TANGENT_SPACE_ROTATION;//調用這個巨集之後,會得到一個矩陣 rotation 這個矩陣用來把模型空間下的方向轉換成切線空間下
                //ObjSpaceLightDir(v.vertex)//得到模型空間下的平行光方向 
                f.lightDir = mul(rotation, ObjSpaceLightDir(v.vertex)); //得到切線空間下的平行光方向 
                return f; 
            }
            fixed4 frag(v2f f) :SV_Target{
                //fixed3 normalDir = normalize(f.worldNormal);
                fixed4 normalColor = tex2D(_NormalMap,f.uv.zw);
                fixed3 tangentNormal = UnpackNormal(normalColor);//UnpackNormal()轉換為切線空間下的法線
                tangentNormal.xy = tangentNormal.xy*_BumpScale;//調節凹凸
                tangentNormal = normalize(tangentNormal);
                fixed3 lightDir = normalize(f.lightDir);
                fixed4 texColor = tex2D(_MainTex, f.uv.xy)*_Color;
                fixed3 diffuse = _LightColor0.rgb * texColor.rgb * max(dot(tangentNormal, lightDir), 0);
                fixed3 tempColor = diffuse + UNITY_LIGHTMODEL_AMBIENT.rgb*texColor;
                return fixed4(tempColor,_AlphaScale*texColor.a );//透明度混合了_AlphaScale和texColor.a 
            }
            ENDCG
        }
    }
    Fallback "Specular"
}

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 用vue-cli搭建一個前端開發環境確實是極其方便,在寫前端代碼肯定也是少不了需要調用後臺提供的業務介面進行前後端交互,特別在敏捷開發中,前後端都要提前確定業務介面併進行打樁,在開發過程中基本是沒有現成的後臺可以調用,基本上都是自己寫mock進行模擬。 在vue-cli搭建的項目中,框架上用的是ex ...
  • css基礎 1、 Css新建格式 Css語法: 選擇符{屬性名稱:屬性值;} 1、內部樣式表(嵌套到頁面中) 語法: <style type="text/css"> css語句 </style> 註:使用style標記創建樣式時,最好將該標記寫在<head></head>; 2、內聯樣式(行間樣式, ...
  • 一、寫在前面的話   Node.js是一個開放源代碼、跨平臺的JavaScript語言運行環境,採用Google開發的V8運行代碼,使用事件驅動、非阻塞和非同步輸入輸出模型等技術來提高性能,可優化應用程式的傳輸量和規模。這些技術通常用於數據密集的事實應用程式。—— "來自維基百科" ...
  • 課程2B的內容主要包括:使用變數來更新欲顯示在屏幕上的內容,為按鈕添加事件響應(聯繫XML屬性與Java方法)邏輯等。 ...
  • android-support-v4.jar 是谷歌提供給我們的一個相容低版本安卓設備的軟體包,裡面包囊了只有在 Android 3.0 以上可用的API。而 ViewPager 就是其中之一。利用它,我們可以做很多事情,從最簡單的導航,到頁面菜單等等。 準備 在使用ViewPager之前,需要在 ...
  • Big Nerd Ranch是美國一家專業的移動開發技術培訓機構。本書主要以其Android訓練營教學課程為基礎,融合了幾位作者多年的心得體會,是一本完全面向實戰的Android編程指南。全書共34章,詳細介紹了8個Android 應用。通過這些精心設計的應用,讀者可掌握很多重要的理論知識和開發技巧 ...
  • 最近在做iOS系統通訊錄備份到伺服器,並且可以從伺服器中下載備份文件恢復到手機的功能,部分實現細節記錄如下。 將iphone系統通訊錄生成.vcf文件 運行後系統沙盒Document目錄下會生成contacts.vcf文件,上傳至伺服器即可。 通訊錄恢復: 從伺服器下載contents.vcf文件, ...
  • 用as開發過程中遇見問題app閃退 log如下圖: 解決: File—Settings: 點擊Apply—OK重新運行即可 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...