跳转到内容

Cg 编程/Unity/广告牌

来自 Wikibooks,开放世界开放书籍
高速公路上的广告牌。请注意广告牌的朝向以获得最佳可见度。

本教程介绍了广告牌

它基于“纹理球体”部分以及“顶点变换”部分中的讨论。

广告牌

[编辑 | 编辑源代码]

在计算机图形学中,广告牌是经过变换的纹理矩形,它们始终平行于视平面显示。因此,它们类似于高速公路上的广告牌,它们被旋转以获得最佳可见度。但是,它们不同于高速公路上的广告牌,因为它们会动态旋转以始终提供最佳可见度。

广告牌的主要用途是用二维图像替换复杂的 3D 模型(例如草、灌木甚至树)。事实上,Unity 也使用广告牌来渲染草。此外,广告牌通常用于渲染 2D 精灵。在这两种应用中,至关重要的是广告牌始终与视平面对齐,以便保持 3D 形状的错觉,尽管只渲染了 2D 图像。

广告牌的顶点变换

[编辑 | 编辑源代码]

“天空盒”部分类似,我们可以使用默认立方体对象来渲染广告牌。(为了使其与默认四边形一起工作,您应该将代码中的减号更改为加号。对于默认平面,您必须使用z坐标而不是y坐标。)基本思想是只将对象空间的原点 使用标准模型视图变换UNITY_MATRIX_MV 转换为视图空间。(在齐次坐标中,所有点的第四个坐标为 1;请参见“顶点变换”部分中的讨论。)视图空间只是世界空间的旋转版本,其中平面平行于视平面,如“顶点变换”部分中所述。因此,这是构造适当旋转的广告牌的正确空间。我们从视图坐标中变换后的原点中减去对象坐标(vertex.xvertex.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" }

< Cg 编程/Unity

除非另有说明,否则本页上的所有示例源代码均归属公共领域。
华夏公益教科书