OpenGL12-shader(GLSL)着色语言4-广告版的实现


之前介绍了vertex shader的基本原理,现在我们来做一个简单的实践,在游戏中广告版(布告版)

随处可见,而且效率很高,现在我们就使用shader来实现这一过程,首先我们要知道布告版的原理

实际上就是一直对着摄像机,与摄像机的方向上是垂直的。如下图所示:

不管摄像机如何去动,那么广告版也跟随一起动(即旋转),那么在摄像机动的时候,就要重新计算

布告版的位置,为了做到这一点,我么要对摄像机的原理有所了解,看摄像机的几个重要的参数,

观看的方向:dir

向上的方向:up

向右的方向:right

及组成如下的坐标系(就是摄像机的局部坐标系了)

黑色的表示的是世界坐标系,蓝色的是摄像机的坐标系。为了让布告版与摄像机垂直,我们要实时的对布告版的位置

做调整,首先我们要先定义下布告版的位置。然后根据计算的几个方向,就可以计算出来新的布告版的位置。

假设有四个点:如下图所示

以A点为起点,根据摄像机的 up,right,dir,就可以计算出来,B,C,D几个点的新的位置(即不管如何旋转,变化,A点的世界坐标

是不变的,我们才可以根据A计算出来B,C,D三个点的新位置)

下面就是一些数学上的基本知识了。

B点的位置如果要用摄像机垂直,及B点的方向是与摄像机的Up点是一致的。那么我们就可以计算出来它的位置。

B = A + (Width) * right;

C = A + Up* height + Width * right

D = A + Up * height

如下图:

现在我们知道了原理,就可以进行编写代码了:

uniform float size;
uniform vec3 camPos;

void main()
{    
    vec3 vAt = camPos - gl_Vertex.xyz;
    vAt      = normalize( vAt );
    vec3 vRight = cross( vec3( 0.0, 1.0, 0.0 ), vAt );
    vec3 vUp = cross( vAt, vRight );
    vRight   = normalize( vRight );
    vUp = normalize( vUp );


    vec2 s  = gl_MultiTexCoord0.zw * vec2( size/2.0, size );
    vec3 vR = s.xxx * vRight;
    vec3 vU = s.yyy * vUp;

    vec4 dir = vec4( vR + vU, 0.0 );
    gl_Position = gl_ModelViewProjectionMatrix * (gl_Vertex + dir );
    
    gl_TexCoord[0] = gl_MultiTexCoord0;
} 

上面的代码中有些细节给大家介绍下,为了把布告版的宽度信息与高度信息,传递给shader,我通过纹理参数来做这件事情。

我们知道纹理可以有四维(x,y,z,w),z,w就用来保存布告版的宽度与高度信息。这样就可以参与计算(而不需要在二外的

传递更多的信息).

  当然,还有很多种实现方式方法,大家可以用自己的实现方式,实现更加高效的布告版技术。如果是例子系统,其实OpenGL

也已经有一种实现方案,那就是粒子精灵,效率非常的高,大家可以参考。

  代码随后上传