日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

三言两语说shader(九)钻石

發布時間:2024/3/26 编程问答 49 豆豆
生活随笔 收集整理的這篇文章主要介紹了 三言两语说shader(九)钻石 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

這次的目標是繪制一顆閃閃發光的鉆石,追求效果是越接近真實越好。


先說說為此我這幾天干了些什么。

1.看了stalendp blog里那篇《鉆石效果》后頭的參考文獻

最有價值的就是ATI在2004年GDC上作的演講,題目就叫Drawing a Diamond。但是由于只有ppt,所以很難重現工程深入學習。思路大概是預備了一張折射CubeMap,一張帶模擬色散的反射CubeMap,最后再加上耀斑混合而成。


2.試驗了一些簡單的鏡面反射

非實時的CubeMap反射最簡單沒什么好說的,需要注意的是要做到位置精確的鏡面反射還是很難的,一不小心就會發現當物體離反射面很近時,尺寸位置都會嚴重錯誤。

像下圖這樣,球的鏡像明顯尺寸過大了。



實時獲取環境CubeMap的反射也測試了下,沒記錯的話上圖CubeMap的FaceSize設的是512,在我的一加手機上基本就跑不到正常幀了,FaceSize設成256幀率還可以接受,但畫質就沒法看了,總之實時反射是手機無法承受的。


這里我總結一點思想:

游戲畫面表現本身就帶有很多虛假的成分,因為全按真實的來計算性能根本無法承受,最簡單的拿光照來說,不談多次反射的環境光,單純的一次平行光照實時計算都沒法滿足,都要預烘焙光照貼圖,陰影也一樣,真實的計算太費性能,一般也弄個假的完事。

所以我們會發現游戲畫面和現實照片的差距總是一目了然。所以會出現很多專門掩飾的技巧。

如何抓住主要部分,在效果和性能間做出取舍,而又能盡量達到接近真實的效果,大概就是圖形工程師們大多數時候在思考的事情了。


這個鉆石效果的演示demo,明顯要按固定環境的思路來,不需要考慮實時問題,像前面提到的那種尺寸扭曲的問題,基本也是可以忽略的,因為鉆石形狀類似小球,環境的輕微扭曲是能被輕易掩飾過去的。


3.到AssetStore搜索了下相關資源

發現免費的Gem Shaders就是Unity官方提供的,而且還為5.0專門更新過一次。我跑了下它的示例場景,感覺觀感不是很滿意。

主要是它提供的幾個鉆石模型形狀我也不喜歡,于是自己到網上找了個大概是傳說中“八星八箭”形狀的模型,然后還是用這個shader試了下效果,結果發現還是很屌的。



我原本的想法是盡量用真實的光線折射、反射計算得到最終效果的。但是就算暫不考慮代碼實現,不考慮實現后的性能如何,首先單純就目前憑我有限的光學姿勢能不能建立起真實準確的光學模型都很明顯是成問題的。

所以這次我們還是以學習官方的示例為主,不要整天想自己搞什么大新聞了。


代碼如下:

Shader "FX/Gem" {Properties {_Color ("Color", Color) = (1,1,1,1)_ReflectionStrength ("Reflection Strength", Range(0.0,2.0)) = 1.0_EnvironmentLight ("Environment Light", Range(0.0,2.0)) = 1.0_Emission ("Emission", Range(0.0,2.0)) = 0.0[NoScaleOffset] _RefractTex ("Refraction Texture", Cube) = "" {}}SubShader {Tags {"Queue" = "Transparent"}// First pass - here we render the backfaces of the diamonds. Since those diamonds are more-or-less// convex objects, this is effectively rendering the inside of them.Pass {Cull FrontZWrite OffCGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct v2f {float4 pos : SV_POSITION;float3 uv : TEXCOORD0;};v2f vert (float4 v : POSITION, float3 n : NORMAL){v2f o;o.pos = mul(UNITY_MATRIX_MVP, v);// TexGen CubeReflect:// reflect view direction along the normal, in view space.float3 viewDir = normalize(ObjSpaceViewDir(v));o.uv = -reflect(viewDir, n);o.uv = mul(_Object2World, float4(o.uv,0));return o;}fixed4 _Color;samplerCUBE _RefractTex;half _EnvironmentLight;half _Emission;half4 frag (v2f i) : SV_Target{half3 refraction = texCUBE(_RefractTex, i.uv).rgb * _Color.rgb;half4 reflection = UNITY_SAMPLE_TEXCUBE(unity_SpecCube0, i.uv);reflection.rgb = DecodeHDR (reflection, unity_SpecCube0_HDR);half3 multiplier = reflection.rgb * _EnvironmentLight + _Emission;return half4(refraction.rgb * multiplier.rgb, 1.0f);}ENDCG }// Second pass - here we render the front faces of the diamonds.Pass {ZWrite OnBlend One OneCGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct v2f {float4 pos : SV_POSITION;float3 uv : TEXCOORD0;half fresnel : TEXCOORD1;};v2f vert (float4 v : POSITION, float3 n : NORMAL){v2f o;o.pos = mul(UNITY_MATRIX_MVP, v);// TexGen CubeReflect:// reflect view direction along the normal, in view space.float3 viewDir = normalize(ObjSpaceViewDir(v));o.uv = -reflect(viewDir, n);o.uv = mul(_Object2World, float4(o.uv,0));o.fresnel = 1.0 - saturate(dot(n,viewDir));return o;}fixed4 _Color;samplerCUBE _RefractTex;half _ReflectionStrength;half _EnvironmentLight;half _Emission;half4 frag (v2f i) : SV_Target{half3 refraction = texCUBE(_RefractTex, i.uv).rgb * _Color.rgb;half4 reflection = UNITY_SAMPLE_TEXCUBE(unity_SpecCube0, i.uv);reflection.rgb = DecodeHDR (reflection, unity_SpecCube0_HDR);half3 reflection2 = reflection * _ReflectionStrength * i.fresnel;half3 multiplier = reflection.rgb * _EnvironmentLight + _Emission;return fixed4(reflection2 + refraction.rgb * multiplier, 1.0f);}ENDCG}// Shadow casting & depth texture support -- so that gems can// cast shadowsUsePass "VertexLit/SHADOWCASTER"} }
下面我來分析其中的姿勢點:

個人水平有限很多說法可能是錯的,這里申明下先。

1.折射光的模擬

首先它的折射光并沒有真實計算,而是給了這樣一張CubeMap圖,然后實際上是通過反射在計算。


2.pass設計

大致分兩步,第一個pass是繪制鉆石的背面,第二個當然就是前面了。注意第二個pass里的Blend One One,表示兩個圖層1:1混合。

考慮到鉆石是個透明的物體,這樣設計也是合情合理的。


3.光照模型設計

大致也是折射光、反射光、環境光、自發光各種疊加各種乘啦。反正因為白色是255,黑色是0,這里雖說算的是光,但實際處理的還是顏色,不管是加還是乘,都是越疊越亮,符合光線疊加的基本規律。至于它的計算公式是源自準確的光學原理,還是近似的模擬,我當然也不知道啦。


4.HDR

High Dynamic Range,不負責任的說下,大概就是假如0是黑色,1是白色,那么有些部分的顏色可以超過1,這樣最終畫面結果會呈現出一種亮處高閃耀的效果,具體請參考Unity官方文檔說明。


5.菲涅爾效果

簡單說就是因為光線射向玻璃時,一部分被反射,一部分直接射進去了,導致最終反射光線呈現一個視角越平行于入射面,反射效果越強,越垂直越弱的現象。

第二個pass計算時引入了這個因子。

所以一開始我說自己難以建立準確的模型,比如像這種細微而又真實存在的現象,僅憑一點粗淺的折射反射姿勢而不去深入學習又怎么能考慮到呢?


這個shader里用了好多宏,在CGIncludes文件夾里的那些文件里都可以查到,這些我大致可以理解或者叫猜到怎么回事,但要真正弄清楚肯定得費一番功夫。

這里請允許豬哥偷個懶,隨便說說裝作懂了的樣子,具體的計算細節就不一一展開了。


結語:

至此初階段的shader學習計劃就算完成了,由于我刻意趕了下進度,偷了些懶,比計劃提前了一周。一分耕耘一分收獲,shader這塊水很深,想要有所造詣肯定得花更多的時間。但我出于全盤考慮目前并不想在這塊繼續投放精力。

下一階段目光回到C#語言這塊最基礎的領域,繼續修內力。去年買的《C#本質論》要收尾,一直沒翻的《深入理解C#》也要看完。

談語言難免會牽涉到設計模式,但也盡量避開。

周期定在五周吧。

總結

以上是生活随笔為你收集整理的三言两语说shader(九)钻石的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。