Cg 编程/Unity/广告牌
本教程介绍了广告牌。
在计算机图形学中,广告牌是经过变换的纹理矩形,它们始终平行于视平面显示。因此,它们类似于高速公路上的广告牌,它们被旋转以获得最佳可见度。但是,它们不同于高速公路上的广告牌,因为它们会动态旋转以始终提供最佳可见度。
广告牌的主要用途是用二维图像替换复杂的 3D 模型(例如草、灌木甚至树)。事实上,Unity 也使用广告牌来渲染草。此外,广告牌通常用于渲染 2D 精灵。在这两种应用中,至关重要的是广告牌始终与视平面对齐,以便保持 3D 形状的错觉,尽管只渲染了 2D 图像。
与“天空盒”部分类似,我们可以使用默认立方体对象来渲染广告牌。(为了使其与默认四边形一起工作,您应该将代码中的减号更改为加号。对于默认平面,您必须使用z
坐标而不是y
坐标。)基本思想是只将对象空间的原点 使用标准模型视图变换UNITY_MATRIX_MV
转换为视图空间。(在齐次坐标中,所有点的第四个坐标为 1;请参见“顶点变换”部分中的讨论。)视图空间只是世界空间的旋转版本,其中平面平行于视平面,如“顶点变换”部分中所述。因此,这是构造适当旋转的广告牌的正确空间。我们从视图坐标中变换后的原点中减去和对象坐标(vertex.x
和 vertex.y
),然后使用投影矩阵UNITY_MATRIX_P
变换结果
output.pos = mul(UNITY_MATRIX_P,
mul(UNITY_MATRIX_MV, float4(0.0, 0.0, 0.0, 1.0))
+ float4(input.vertex.x, input.vertex.y, 0.0, 0.0));
为了拥有不同大小的广告牌,我们添加了着色器属性_ScaleX
和 _ScaleY
来缩放对象坐标;因此,代码变为
output.pos = mul(UNITY_MATRIX_P,
mul(UNITY_MATRIX_MV, float4(0.0, 0.0, 0.0, 1.0))
+ float4(input.vertex.x, input.vertex.y, 0.0, 0.0)
* float4(_ScaleX, _ScaleY, 1.0, 1.0));
除此之外,我们只需要设置纹理坐标
output.tex = input.tex;
然后片段着色器只在插值的纹理坐标处查找颜色。
现在,标准立方体对象的完整着色器代码是
Shader "Cg shader for billboards" {
Properties {
_MainTex ("Texture Image", 2D) = "white" {}
_ScaleX ("Scale X", Float) = 1.0
_ScaleY ("Scale Y", Float) = 1.0
}
SubShader {
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// User-specified uniforms
uniform sampler2D _MainTex;
uniform float _ScaleX;
uniform float _ScaleY;
struct vertexInput {
float4 vertex : POSITION;
float4 tex : TEXCOORD0;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 tex : TEXCOORD0;
};
vertexOutput vert(vertexInput input)
{
vertexOutput output;
output.pos = mul(UNITY_MATRIX_P,
mul(UNITY_MATRIX_MV, float4(0.0, 0.0, 0.0, 1.0))
+ float4(input.vertex.x, input.vertex.y, 0.0, 0.0)
* float4(_ScaleX, _ScaleY, 1.0, 1.0));
output.tex = input.tex;
return output;
}
float4 frag(vertexOutput input) : COLOR
{
return tex2D(_MainTex, float2(input.tex.xy));
}
ENDCG
}
}
}
恭喜你,你完成了本教程。我们已经看到了
- 如何变换和纹理化立方体以渲染与视图对齐的广告牌。
如果你想了解更多
为了避免渲染多个广告牌时出现“闪烁”,我必须在 Subshader 中添加以下标签
Tags { "DisableBatching" = "True" }