Cg 编程/Unity/弯曲玻璃
外观
本教程涵盖折射映射及其与立方体贴图的实现。
它是“反射表面”部分的变体,应该先阅读。
在“反射表面”部分中,我们反射了视角射线,然后在反射方向的立方体贴图中执行纹理查找。在这里,我们在弯曲的透明表面上折射视角射线,然后使用折射方向执行查找。该效果将忽略光线再次离开透明物体时的第二次折射;然而,许多人几乎没有注意到差异,因为这种折射通常不是我们日常生活的一部分。
我们没有使用reflect
函数,而是使用refract
函数;因此,片段着色器可能是
float4 frag(vertexOutput input) : COLOR
{
float refractiveIndex = 1.5;
float3 refractedDir = refract(normalize(input.viewDir),
normalize(input.normalDir), 1.0 / refractiveIndex);
return texCUBE(_Cube, refractedDir);
}
请注意,refract
接受第三个参数,即外部介质的折射率(例如,空气的折射率为 1.0)除以物体的折射率(例如,某些类型的玻璃的折射率为 1.5)。还要注意,第一个参数必须是标准化的,而reflect
则不需要。
使用经过调整的片段着色器,完整的着色器代码变为
Shader "Cg shader with refraction mapping" {
Properties {
_Cube("Reflection Map", Cube) = "" {}
}
SubShader {
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
// User-specified uniforms
uniform samplerCUBE _Cube;
struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float3 normalDir : TEXCOORD0;
float3 viewDir : TEXCOORD1;
};
vertexOutput vert(vertexInput input)
{
vertexOutput output;
float4x4 modelMatrix = unity_ObjectToWorld;
float4x4 modelMatrixInverse = unity_WorldToObject;
output.viewDir = mul(modelMatrix, input.vertex).xyz
- _WorldSpaceCameraPos;
output.normalDir = normalize(
mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
output.pos = UnityObjectToClipPos(input.vertex);
return output;
}
float4 frag(vertexOutput input) : COLOR
{
float refractiveIndex = 1.5;
float3 refractedDir = refract(normalize(input.viewDir),
normalize(input.normalDir), 1.0 / refractiveIndex);
return texCUBE(_Cube, refractedDir);
}
ENDCG
}
}
}
恭喜你。这是另一个教程的结尾。我们已经看到了
- 如何使用
refract
指令将反射映射调整为折射映射。
如果你还想了解更多
- 关于反射映射和立方体贴图,请阅读“反射表面”部分。
- 关于
refract
指令,你可以在Nivida 的 Cg 教程附录 E 中查找。
除非另有说明,否则此页面上的所有示例源代码均授予公共领域。