亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

Unity3d中Shader的一些常用方法

2019-11-06 09:39:31
字體:
來源:轉載
供稿:網友

float4 tex2D(sampler2D samp, float2 s)

2D紋理采樣,CG內置函數。 內部實現分為以下幾步: 1. 用圖片的寬高度乘以uv數值,得到像素坐標。widthPixel=samp.x*s.x;heightPixel=samp.y*s.y; 2. 因為取到的數值基本上都是帶有小數點的,也就是說不是一個整數,這個時候,需要看圖片的過濾設置了。也就是Unity3d的圖片設置中的Filter Mode。 3. Filter Mode是Point,不過濾,就會取像素點最靠近的整數,也就是四舍五入,得到像素點的坐標,然后出去圖片中,這個坐標的顏色。 4. 雙線性過濾,會取目標像素的附近4個像素,然后進行插值計算,得到平均顏色值,作為最終顏色。適合紋理由小放大過程中,出現的“馬賽克”。 5. 三線性過濾,在雙線性過濾的基礎上考慮到了深度LOD,會進行兩次雙線性過濾,來使不同的LOD等級紋理中,更加平滑的過渡。

TRANSFORM_TEX(tex,name)

這個方法的定義在UnityCG.cginc中,它有兩個參數,tex.xy是頂點的uv值,name##_ST則是在這個shader所在的材質球中,紋理圖片的縮放和偏移,S指Scale,T指Transform,它是一個float4類型,其值分別為(Tiling.x,Tiling.y,Offset.x,Offset.y)。這個方法運算后,得到的是經過偏移和縮放的uv。它的運算公式是TextureCoordinate = tex.xy * name##_ST.xy + name##_ST.zw。如果偏移為0,縮放為默認1,則可以不用經過這個過程。

inline UnpackNormal(fixed4 packednormal)

這個方法是對法線紋理進行采樣。它的定義同樣在UnityCG.cginc里。

inline fixed3 UnpackNormal(fixed4 packednormal){#if defined(UNITY_NO_DXT5nm) return packednormal.xyz * 2 - 1;#else return UnpackNormalDXT5nm(packednormal);#endif}inline fixed3 UnpackNormalDXT5nm (fixed4 packednormal){ fixed3 normal; normal.xy = packednormal.wy * 2 - 1; normal.z = sqrt(1 - saturate(dot(normal.xy, normal.xy))); return normal;}

這里有兩個方法,以UnpackNormal方法來說,它最主要的也就是 packednormal.xyz * 2 - 1; 要解釋這個,就必須講到法線紋理的生成。法線紋理是把模型的法線信息存到圖片中去,每條法線的x,y,z對應的存到每個像素的r,g,b中。每條法線里的每個數值都是一個[-1,1]的閉合區間里,像素的每個數值則都是在[0,255]中,(n + vec3(1.0,1.0,1.0)) * (255.0 / 2.0),每個法線向量,經過加上 vec3(1.0,1.0,1.0)。變成[0,2]的閉合區間里,然后除以2,再乘以255,發現向量,就會轉換成了[0,255]里的數值。這也是上述那條公式的由來。 至于法線紋理如何生成,有興趣的可以詳細了解一下這個算法,各個軟件的生成算法不一樣,最終得到的法線紋理也不一樣。但是紋理里的數據,肯定是符合規范的法線紋理數據,可以在shader中使用。 另外一個方法UnpackNormalDXT5nm ,則是一個壓縮法線紋理后的方法。大家都知道,法線是一個單位向量,也就是它的長度是1,所以只需要知道x,y的數值,是可以計算得到z的數值的,z=1-(x+y)的平方。這樣就可以減少貼圖的大小,減少GPU的數據傳輸量。

inline float3 UnityObjectToWorldNormal( in float3 norm )

從模型空間到世界空間轉換法線。它的定義同樣在UnityCG.cginc

inline float3 UnityObjectToWorldNormal( in float3 norm ){ // Multiply by transposed inverse matrix, actually using transpose() generates badly optimized code return normalize(_World2Object[0].xyz * norm.x + _World2Object[1].xyz * norm.y + _World2Object[2].xyz * norm.z);}

其實也相當于

normalize(mul((float3x3)_World2Object),norm);

_World2Object在上一篇 Unity3d中Shader的一些關于矩陣變換的基本信息中說過它是當前世界矩陣的逆矩陣。

inline float3 UnityObjectToWorldDir( in float3 dir )

inline float3 UnityObjectToWorldDir( in float3 dir ){ return normalize(mul((float3x3)_Object2World, dir));}

光照的計算

拿”Mobile/Bumped Diffuse”這個shader來說,它的代碼很短,是一個中間代碼,需要點擊右方的Show generated code,出現詳細的代碼,其中的頂點函數

v2f_surf vert_surf (appdata_full v) { v2f_surf o; UNITY_INITIALIZE_OUTPUT(v2f_surf,o); o.pos = mul (UNITY_MATRIX_MVP, v.vertex); o.pack0.xy = TRANSFORM_TEX(v.texcoord, _MainTex); //這里是計算頂點的世界坐標 float3 worldPos = mul(_Object2World, v.vertex).xyz; //得到頂點法線轉換到世界空間的法線,得到切線空間的N fixed3 worldNormal = UnityObjectToWorldNormal(v.normal); //得到頂點的切線轉換到世界空間的切線,得到切線空間的T fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz); //計算方向,后面用到 fixed tangentSign = v.tangent.w * unity_WorldTransformParams.w; //通過T和N的向量積,得到垂直這兩個向量的向量,但是它的方向有兩個,所以乘以上面得到的方向參數,得到最終的向量,得到切線空間的B fixed3 worldBinormal = cross(worldNormal, worldTangent) * tangentSign; //所以下面是得到模型的頂點的切線空間到世界空間的矩陣,分行顯示,沒看明白的可以看一下矩陣的基本知識 o.tSpace0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x); o.tSpace1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y); o.tSpace2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z); #ifndef DYNAMICLIGHTMAP_OFF o.lmap.zw = v.texcoord2.xy * unity_DynamicLightmapST.xy + unity_DynamicLightmapST.zw; #endif #ifndef LIGHTMAP_OFF o.lmap.xy = v.texcoord1.xy * unity_LightmapST.xy + unity_LightmapST.zw; #endif // SH/ambient and vertex lights #ifdef LIGHTMAP_OFF #if UNITY_SHOULD_SAMPLE_SH o.sh = 0; // ApPRoximated illumination from non-important point lights #ifdef VERTEXLIGHT_ON o.sh += Shade4PointLights ( unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0, unity_LightColor[0].rgb, unity_LightColor[1].rgb, unity_LightColor[2].rgb, unity_LightColor[3].rgb, unity_4LightAtten0, worldPos, worldNormal); #endif o.sh = ShadeSHPerVertex (worldNormal, o.sh); #endif #endif // LIGHTMAP_OFF TRANSFER_SHADOW(o); // pass shadow coordinates to pixel shader UNITY_TRANSFER_FOG(o,o.pos); // pass fog coordinates to pixel shader return o;}

像素片段函數

// fragment shaderfixed4 frag_surf (v2f_surf IN) : SV_Target { // prepare and unpack data Input surfIN; UNITY_INITIALIZE_OUTPUT(Input,surfIN); surfIN.uv_MainTex.x = 1.0; surfIN.uv_MainTex = IN.pack0.xy; //把頂點函數取得的世界頂點坐標取出來< float3 worldPos = float3(IN.tSpace0.w, IN.tSpace1.w, IN.tSpace2.w); #ifndef USING_DIRECTIONAL_LIGHT //如果用的是直線光,就把頂點的位置轉換成向量,成為光照向量 fixed3 lightDir = normalize(UnityWorldSpaceLightDir(worldPos)); #else //否者直接用世界光照的方向 fixed3 lightDir = _WorldSpaceLightPos0.xyz; #endif #ifdef UNITY_COMPILER_HLSL SurfaceOutput o = (SurfaceOutput)0; #else SurfaceOutput o; #endif o.Albedo = 0.0; o.Emission = 0.0; o.Specular = 0.0; o.Alpha = 0.0; o.Gloss = 0.0; fixed3 normalWorldVertex = fixed3(0,0,1); // call surface function surf (surfIN, o); // compute lighting & shadowing factor UNITY_LIGHT_ATTENUATION(atten, IN, worldPos) fixed4 c = 0; fixed3 worldN; /*通過向量計算,得到世界法線的方向,這里Surf方法里o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_MainTex)); 得到的是該頂點的切空間的法線方向,實際上,下面這個方法也等于 worldN= normalize(mul( float3x3(IN.tSpace0.xyz, IN.tSpace1.xyz, IN.tSpace2.xyz),o.Normal)); */ worldN.x = dot(IN.tSpace0.xyz, o.Normal); worldN.y = dot(IN.tSpace1.xyz, o.Normal); worldN.z = dot(IN.tSpace2.xyz, o.Normal); o.Normal = worldN; // Setup lighting environment UnityGI gi; UNITY_INITIALIZE_OUTPUT(UnityGI, gi); gi.indirect.diffuse = 0; gi.indirect.specular = 0; #if !defined(LIGHTMAP_ON) gi.light.color = _LightColor0.rgb; gi.light.dir = lightDir; //進行光照計算,獲得夾角 gi.light.ndotl = LambertTerm (o.Normal, gi.light.dir); #endif // Call GI (lightmaps/SH/reflections) lighting function UnityGIInput giInput; UNITY_INITIALIZE_OUTPUT(UnityGIInput, giInput); giInput.light = gi.light; giInput.worldPos = worldPos; giInput.atten = atten; #if defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON) giInput.lightmapUV = IN.lmap; #else giInput.lightmapUV = 0.0; #endif #if UNITY_SHOULD_SAMPLE_SH giInput.ambient = IN.sh; #else giInput.ambient.rgb = 0.0; #endif giInput.probeHDR[0] = unity_SpecCube0_HDR; giInput.probeHDR[1] = unity_SpecCube1_HDR; #if UNITY_SPECCUBE_BLENDING || UNITY_SPECCUBE_BOX_PROJECTION giInput.boxMin[0] = unity_SpecCube0_BoxMin; // .w holds lerp value for blending #endif #if UNITY_SPECCUBE_BOX_PROJECTION giInput.boxMax[0] = unity_SpecCube0_BoxMax; giInput.probePosition[0] = unity_SpecCube0_ProbePosition; giInput.boxMax[1] = unity_SpecCube1_BoxMax; giInput.boxMin[1] = unity_SpecCube1_BoxMin; giInput.probePosition[1] = unity_SpecCube1_ProbePosition; #endif LightingLambert_GI(o, giInput, gi); // realtime lighting: call lighting function c += LightingLambert (o, gi); UNITY_APPLY_FOG(IN.fogCoord, c); // apply fog UNITY_OPAQUE_ALPHA(c.a); return c;}

以上就是主要的光照和法線貼圖的使用。其實還可以把光照轉換到切空間中進行計算,得到計算結果后,再轉換回世界空間,都是可行的。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品色视频| 91老司机在线| 日韩欧美中文字幕在线播放| 欧美日韩性生活视频| 日韩欧美在线第一页| 久久视频在线播放| 尤物yw午夜国产精品视频明星| 伊人伊成久久人综合网站| 视频直播国产精品| 2018日韩中文字幕| 国产亚洲精品美女久久久久| 久久久噜噜噜久久中文字免| 91久久精品久久国产性色也91| 久久夜精品va视频免费观看| 午夜伦理精品一区| 亚洲美女www午夜| 久久精品国产久精国产思思| 69久久夜色精品国产69乱青草| 91麻豆国产精品| 97国产suv精品一区二区62| 国产在线观看精品一区二区三区| 国产精自产拍久久久久久| 成人黄色生活片| 亚洲精品一区中文字幕乱码| 国产一区二区黑人欧美xxxx| 岛国av午夜精品| 欧美乱大交xxxxx另类电影| 97在线视频免费| 91精品在线看| 亚洲精品www久久久久久广东| 深夜精品寂寞黄网站在线观看| 成人午夜高潮视频| 国产亚洲一区精品| 日韩精品免费在线视频观看| 日韩免费在线电影| 成人a在线观看| 日韩av电影中文字幕| 精品久久久在线观看| 欧美大片在线免费观看| 555www成人网| 98精品国产高清在线xxxx天堂| 久久久国产视频91| 欧美午夜精品伦理| 精品久久久久久中文字幕| 色偷偷888欧美精品久久久| 欧美高跟鞋交xxxxxhd| 亚洲精品mp4| 亚洲最大福利视频| 在线观看欧美视频| 色综合老司机第九色激情| 超碰91人人草人人干| 久久精品一本久久99精品| 欧美电影在线播放| 92版电视剧仙鹤神针在线观看| 亚洲第一区中文99精品| 国产精品一区二区三区久久久| 亚洲美女av电影| 不卡av在线播放| 日韩精品中文字幕有码专区| 久久成人av网站| 亚洲视频在线观看免费| 日韩av电影免费观看高清| 国产成人拍精品视频午夜网站| 日本亚洲欧洲色α| 久久亚洲精品一区| 亚洲人永久免费| 国产精品欧美一区二区| 欧美成人sm免费视频| 日韩免费观看视频| 国产在线a不卡| 国内揄拍国内精品少妇国语| 国产丝袜高跟一区| 久久久亚洲欧洲日产国码aⅴ| 亚洲视频网站在线观看| 色妞久久福利网| 国产精品久久久久久中文字| 色婷婷综合久久久久| 777777777亚洲妇女| 国产一区二区三区视频在线观看| 在线视频亚洲欧美| 国产精品久久久久久久久免费看| 亚洲欧洲视频在线| 97人人爽人人喊人人模波多| 亚洲电影免费观看高清完整版在线观看| 国产精品美女在线观看| 欧美性猛交xxxx富婆弯腰| 亚洲成人av在线播放| 在线免费观看羞羞视频一区二区| 亲爱的老师9免费观看全集电视剧| 日本精品久久久久影院| 国产一区二区三区在线视频| 欧美极品少妇与黑人| 国产精品丝袜久久久久久高清| 久久免费在线观看| 隔壁老王国产在线精品| 欧美激情成人在线视频| 日韩高清不卡av| 亚洲日本中文字幕| 亚洲精品国精品久久99热一| 国产精品久久91| 精品在线观看国产| 欧美巨乳美女视频| 亚洲精品一区二区三区婷婷月| 久久久久久国产精品三级玉女聊斋| 欧美日韩在线视频一区二区| 亚洲国产精品网站| 高清日韩电视剧大全免费播放在线观看| 成人精品网站在线观看| 亚洲人成自拍网站| 午夜精品久久久久久99热| 国模gogo一区二区大胆私拍| 国产91精品网站| 日韩国产激情在线| 欧美电影电视剧在线观看| 国产性色av一区二区| 怡红院精品视频| 另类少妇人与禽zozz0性伦| 欧美日韩国产中文精品字幕自在自线| 欧美小视频在线| 九九热精品视频在线播放| 国产精品精品一区二区三区午夜版| 欧美一级电影在线| 国产精品96久久久久久又黄又硬| 中文字幕精品www乱入免费视频| 亚洲影视九九影院在线观看| 亚洲精美色品网站| 欧美理论片在线观看| 久久久久久久久中文字幕| 亚洲激情在线观看视频免费| 亚洲精品视频在线观看视频| 国产成人一区二| 91九色视频导航| 日韩美女主播视频| 国产精品久久久久久av下载红粉| 538国产精品视频一区二区| 色在人av网站天堂精品| 91精品视频在线| 欧美成人在线免费视频| 一本大道香蕉久在线播放29| 欧美电影第一页| 91在线无精精品一区二区| 欧洲亚洲免费在线| 91国内揄拍国内精品对白| 日韩精品视频免费专区在线播放| 欧美性xxxx极品hd满灌| 97在线精品视频| 亚洲变态欧美另类捆绑| 精品久久中文字幕久久av| 久久在线视频在线| 在线播放国产一区中文字幕剧情欧美| 亚洲午夜女主播在线直播| 国产色视频一区| 国产精品一区二区三| 欧美午夜性色大片在线观看| 日韩欧美一区二区三区久久| 秋霞av国产精品一区| 久久天天躁狠狠躁夜夜躁| 日韩精品小视频| 色视频www在线播放国产成人| 亚洲女在线观看| 中文字幕亚洲一区二区三区| 久久精品国产99国产精品澳门| 国内精品久久久久久| 亚洲变态欧美另类捆绑|