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 规范”中查找。
除非另有说明,本页面上的所有示例源代码均授予公有领域。