跳轉到內容

Cg 程式設計/Unity/彎曲玻璃

來自華夏公益教科書
水晶球是彎曲透明表面的例子。

本教程涵蓋折射對映及其與立方體貼圖的實現。

它是“反射表面”部分的變體,應該先閱讀。

折射對映

[編輯 | 編輯原始碼]

“反射表面”部分中,我們反射了視角射線,然後在反射方向的立方體貼圖中執行紋理查詢。在這裡,我們在彎曲的透明表面上折射視角射線,然後使用折射方向執行查詢。該效果將忽略光線再次離開透明物體時的第二次折射;然而,許多人幾乎沒有注意到差異,因為這種折射通常不是我們日常生活的一部分。

我們沒有使用reflect函式,而是使用refract函式;因此,片段著色器可能是

         float4 frag(vertexOutput input) : COLOR
         {
            float refractiveIndex = 1.5;
            float3 refractedDir = refract(normalize(input.viewDir), 
               normalize(input.normalDir), 1.0 / refractiveIndex);
            return texCUBE(_Cube, refractedDir);
         }

請注意,refract 接受第三個引數,即外部介質的折射率(例如,空氣的折射率為 1.0)除以物體的折射率(例如,某些型別的玻璃的折射率為 1.5)。還要注意,第一個引數必須是標準化的,而reflect則不需要。

完整著色器程式碼

[編輯 | 編輯原始碼]

使用經過調整的片段著色器,完整的著色器程式碼變為

Shader "Cg shader with refraction mapping" {
   Properties {
      _Cube("Reflection Map", Cube) = "" {}
   }
   SubShader {
      Pass {   
         CGPROGRAM
 
         #pragma vertex vert  
         #pragma fragment frag 
 
         #include "UnityCG.cginc"

         // User-specified uniforms
         uniform samplerCUBE _Cube;   
 
         struct vertexInput {
            float4 vertex : POSITION;
            float3 normal : NORMAL;
         };
         struct vertexOutput {
            float4 pos : SV_POSITION;
            float3 normalDir : TEXCOORD0;
            float3 viewDir : TEXCOORD1;
         };
 
         vertexOutput vert(vertexInput input) 
         {
            vertexOutput output;
 
            float4x4 modelMatrix = unity_ObjectToWorld;
            float4x4 modelMatrixInverse = unity_WorldToObject; 
 
            output.viewDir = mul(modelMatrix, input.vertex).xyz 
               - _WorldSpaceCameraPos;
            output.normalDir = normalize(
               mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
            output.pos = UnityObjectToClipPos(input.vertex);
            return output;
         }
 
         float4 frag(vertexOutput input) : COLOR
         {
            float refractiveIndex = 1.5;
            float3 refractedDir = refract(normalize(input.viewDir), 
               normalize(input.normalDir), 1.0 / refractiveIndex);
            return texCUBE(_Cube, refractedDir);
         }
 
         ENDCG
      }
   }
}

恭喜你。這是另一個教程的結尾。我們已經看到了

  • 如何使用refract指令將反射對映調整為折射對映。

進一步閱讀

[編輯 | 編輯原始碼]

如果你還想了解更多

< Cg 程式設計/Unity

除非另有說明,否則此頁面上的所有示例原始碼均授予公共領域。
華夏公益教科書