跳转到内容

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

除非另有说明,本页面上的所有示例源代码均授予公有领域。
华夏公益教科书