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指令将反射映射调整为折射映射。
如果你还想了解更多
- 关于反射映射和立方体贴图,你应该阅读“反射表面”部分.
- 关于 refract指令,你可以在 “Khronos OpenGL ES API 注册表” 上找到的“OpenGL ES 着色语言 1.0.17 规范”中查找。
除非另有说明,本页面上的所有示例源代码均授予公有领域。