跳轉到內容

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

來自華夏公益教科書,開放的書籍,為一個開放的世界
水晶球是彎曲、透明表面的例子。

本教程介紹了折射對映及其在立方體貼圖中的實現。

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

折射對映

[編輯 | 編輯原始碼]

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

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

         #ifdef FRAGMENT
 
         void main()
         {
            float refractiveIndex = 1.5;
            vec3 refractedDirection = refract(normalize(viewDirection), 
               normalize(normalDirection), 1.0 / refractiveIndex);
            gl_FragColor = textureCube(_Cube, refractedDirection);
         }
 
         #endif

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

完整著色器程式碼

[編輯 | 編輯原始碼]

使用修改後的片段著色器,完整的著色器程式碼變為

Shader "GLSL shader with refraction mapping" {
   Properties {
      _Cube ("Environment Map", Cube) = "" {}
   }
   SubShader {
      Pass {   
         GLSLPROGRAM

         // User-specified uniforms
         uniform samplerCube _Cube;   

         // The following built-in uniforms  
         // are also defined in "UnityCG.glslinc", 
         // i.e. one could #include "UnityCG.glslinc" 
         uniform vec3 _WorldSpaceCameraPos; 
            // camera position in world space
         uniform mat4 _Object2World; // model matrix
         uniform mat4 _World2Object; // inverse model matrix

         // Varyings         
         varying vec3 normalDirection;
         varying vec3 viewDirection;
         
         #ifdef VERTEX
         
         void main()
         {            
            mat4 modelMatrix = _Object2World;
            mat4 modelMatrixInverse = _World2Object; // unity_Scale.w 
               // is unnecessary because we normalize vectors
            
            normalDirection = normalize(vec3(
               vec4(gl_Normal, 0.0) * modelMatrixInverse));
            viewDirection = vec3(modelMatrix * gl_Vertex 
               - vec4(_WorldSpaceCameraPos, 1.0));
            
            gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
         }
         
         #endif


         #ifdef FRAGMENT
 
         void main()
         {
            float refractiveIndex = 1.5;
            vec3 refractedDirection = refract(normalize(viewDirection), 
               normalize(normalDirection), 1.0 / refractiveIndex);
            gl_FragColor = textureCube(_Cube, refractedDirection);
         }
 
         #endif

         ENDGLSL
      }
   }
}

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

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

進一步閱讀

[編輯 | 編輯原始碼]

如果你還想了解更多


< GLSL 程式設計/Unity

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