GLSL Programming/Unity/Billboards

From testwiki
Revision as of 07:50, 16 April 2020 by imported>DannyS712 (Update syntaxhighlight tags - remove use of deprecated <source> tags)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Template:TOC right

Billboards along a highway. Note the orientation of the billboards for best visibility.

This tutorial introduces billboards.

It is based on Template:GLSL Programming Unity SectionRef and the discussion in Template:GLSL Programming Unity SectionRef.

Billboards

In computer graphics, billboards are textured rectangles that are transformed such that they always appear parallel to the view plane. Thus, they are similar to billboards along highways in that they are rotated for best visibility. However, they are different from highway billboards since they are dynamically rotated to always offer best visibility.

The main use of billboards is to replace complex three-dimensional models (e.g. grass, bushes, or even trees) by two-dimensional images. In fact, Unity also uses billboards to render grass. Moreover, billboards are often used to render two-dimensional sprites. In both applications, it is crucial that the billboard is always aligned parallel to the view plane in order to keep up the illusion of a three-dimensional shape although only a two-dimensional image is rendered.

Vertex Transformation for Billboards

Similarly to Template:GLSL Programming Unity SectionRef, we are going to use the default cube object to render a billboard. The basic idea is to transform only the origin (0,0,0,1) of the object space to view space with the standard transformation gl_ModelViewMatrix. (In homogeneous coordinates all points have a 1 as fourth coordinate; see the discussion in Template:GLSL Programming Unity SectionRef.) View space is just a rotated version of world space with the xy plane parallel to the view plane as discussed in Template:GLSL Programming Unity SectionRef. Thus, this is the correct space to construct an appropriately rotated billboard. We add the x and y object coordinates (gl_Vertex.x and gl_Vertex.y) to the transformed origin in view coordinates and then transform the result with the projection matrix 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));

Apart from this, we only have to compute texture coordinates, which is done the same way as in Template:GLSL Programming Unity SectionRef:

textureCoords = vec4(gl_Vertex.x + 0.5, gl_Vertex.y + 0.5, 0.0, 0.0);

Then the fragment shader just looks up the color at the interpolated texture coordinates.

Complete Shader Code

The complete shader code for the standard cube object is now:

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
      }
   }
}

Note that we never apply the model matrix to the object coordinates because we don't want to rotate them. However, this means that we also cannot scale them. Nonetheless, if you specify scale factors for the cube in Unity, you will notice that the billboard is actually scaled. The reason is that Unity performs the scaling on the object coordinates before they are sent to the vertex shader (unless all three scale factors are positive and equal, then the scaling is specified by 1.0 / unity_Scale.w). Thus, in order to scale the billboard you can either use the scaling by Unity (with different scale factors for x and y) or you can introduce additional shader properties for scaling the object coordinates in the vertex shader.

Summary

Congratulations, you made it to the end of this tutorial. We have seen:

  • How to transform and texture a cube in order to render a view-aligned billboard.

Further Reading

If you still want to learn more


Template:GLSL Programming BottomNav