GLSL 编程/Unity/公告板
本教程介绍了**公告板**。
在计算机图形学中,公告板是纹理矩形,它们被变换以始终平行于视平面。因此,它们类似于高速公路旁的公告板,它们被旋转以获得最佳可见度。但是,它们不同于高速公路公告板,因为它们会动态旋转以始终提供最佳可见度。
公告板的主要用途是使用二维图像替换复杂的 3D 模型(例如草、灌木甚至树木)。事实上,Unity 也使用公告板来渲染草。此外,公告板通常用于渲染 2D 精灵。在这两种应用中,至关重要的是公告板始终与视平面平行,以保持 3D 形状的错觉,尽管只渲染了 2D 图像。
类似于“天空盒”部分,我们将使用默认的立方体对象来渲染公告板。基本思路是用标准变换 gl_ModelViewMatrix
将对象空间的原点 变换到视空间。(在齐次坐标中,所有点都具有 1 作为第四个坐标;参见“顶点变换”部分 的讨论。)视空间只是世界空间的旋转版本,其中 平面平行于视平面,如“顶点变换”部分 所述。因此,这是构建适当旋转的公告板的正确空间。我们将 和 对象坐标 (gl_Vertex.x
和 gl_Vertex.y
) 添加到视坐标中的变换原点,然后使用投影矩阵 gl_ProjectionMatrix
变换结果
gl_Position = gl_ProjectionMatrix * (gl_ModelViewMatrix * vec4(0.0, 0.0, 0.0, 1.0) + vec4(gl_Vertex.x, gl_Vertex.y, 0.0, 0.0));
除此之外,我们只需要计算纹理坐标,这与“屏幕叠加”部分 中的做法相同
textureCoords = vec4(gl_Vertex.x + 0.5, gl_Vertex.y + 0.5, 0.0, 0.0);
然后,片段着色器只需在插值的纹理坐标处查找颜色。
现在,标准立方体对象的完整着色器代码为
Shader "GLSL shader for billboards" {
Properties {
_MainTex ("Texture Image", 2D) = "white" {}
}
SubShader {
Pass {
GLSLPROGRAM
// User-specified uniforms
uniform sampler2D _MainTex;
// Varyings
varying vec4 textureCoords;
#ifdef VERTEX
void main()
{
gl_Position = gl_ProjectionMatrix
* (gl_ModelViewMatrix * vec4(0.0, 0.0, 0.0, 1.0)
+ vec4(gl_Vertex.x, gl_Vertex.y, 0.0, 0.0));
textureCoords =
vec4(gl_Vertex.x + 0.5, gl_Vertex.y + 0.5, 0.0, 0.0);
}
#endif
#ifdef FRAGMENT
void main()
{
gl_FragColor = texture2D(_MainTex, vec2(textureCoords));
}
#endif
ENDGLSL
}
}
}
请注意,我们从未将模型矩阵应用于对象坐标,因为我们不想旋转它们。但是,这意味着我们也不能缩放它们。尽管如此,如果您在 Unity 中为立方体指定了缩放因子,您会注意到公告板实际上被缩放了。原因是 Unity 在对象坐标被发送到顶点着色器之前执行了缩放(除非所有三个缩放因子都是正数且相等,然后缩放由 1.0 / unity_Scale.w
指定)。因此,为了缩放公告板,您可以使用 Unity 的缩放功能(使用 和 的不同缩放因子),或者您可以在顶点着色器中引入额外的着色器属性来缩放对象坐标。
恭喜你完成了本教程。我们已经看到了
- 如何变换和纹理化一个立方体以渲染一个与视图对齐的公告板。
如果您还想了解更多