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 規範”中查詢。
除非另有說明,本頁面上的所有示例原始碼均授予公有領域。