利用几何着色器实现Billboard(广告牌)
广告牌的介绍
引用http://blog.csdn.net/xiaoge132/article/details/51113670
无论观察者处于什么位置观察任何图像,广告版都能提供一个朝向观众的面,这个面随着摄像机的改变而改变.BillBoard技术是计算机图形学领域中进行快速绘制的一种方法。在类似游戏这种对实时性要求较高的场景下采取BillBoard技术可以大大加快绘制的速度从而提高画面的流畅性。
把3D的物体用2D来表示,然后让该物体始终朝向镜头。比如场景中的一棵树,对于整个场景来说不是主要物体,因此无需花费大量的时间去计算树的每一部分的细节。通常的做法是首先准备好一张树的照片,然后镜头运动的时候使得树始终正对着镜头。
几何着色器
利用几何着色器可以创造和销毁顶点的特性,设置如下顶点结构
struct TreePointSprite
{
//广告牌的中心位置
XMFLOAT3 Pos;
//广告牌的宽高
XMFLOAT2 Size;
};
根据广告牌的中心位置和宽高还有视点计算出广告牌的4个顶点位置,生成新顶点,再在Pix Shader中对相应纹理图进行采样,实现广告牌。
//经顶点着色器输出后的顶点格式
struct VertexOut
{
float3 CenterW : POSITION;
float2 SizeW : SIZE;
};
//经几何着色器输出后的顶点格式
struct GeoOut
{
//经过透视后的齐次坐标
float4 PosH : SV_POSITION;
//世界坐标
float3 PosW : POSITION;
//法线,始终朝向视点
float3 NormalW : NORMAL;
//纹理祖彪
float2 Tex : TEXCOORD;
uint PrimID : SV_PrimitiveID;
};
//输出的最大顶点数
[maxvertexcount(4)]
void GS(point VertexOut gin[1],
uint primID : SV_PrimitiveID,
inout TriangleStream<GeoOut> triStream)
{
//上向量
float3 up = float3(0.0f, 1.0f, 0.0f);
//注视向量
float3 look = gEyePosW - gin[0].CenterW;
//垂直于Y轴
look.y = 0.0f;
look = normalize(look);
//右向量
float3 right = cross(up, look);
float halfWidth = 0.5f * gin[0].SizeW.x;
float halfHeight = 0.5f * gin[0].SizeW.y;
//计算广告牌4个顶点
GeoOut geoOut[4];
geoOut[0].PosW = gin[0].CenterW + right * halfWidth - up * halfHeight;
geoOut[1].PosW = gin[0].CenterW + right * halfWidth + up * halfHeight;
geoOut[2].PosW = gin[0].CenterW - right * halfWidth - up * halfHeight;
geoOut[3].PosW = gin[0].CenterW - right * halfWidth + up * halfHeight;
[unroll]
for (int i = 0; i < 4; i++)
{
geoOut[i].PosH = mul(float4(geoOut[i].PosW, 1.0f), gViewProj);
geoOut[i].NormalW = look;
geoOut[i].Tex = gTexC[i];
geoOut[i].PrimID = primID;
triStream.Append(geoOut[i]);
}
}
最终实现树的广告牌(中心点事根据地形高度随机生成的)的效果图
完整代码地址https://github.com/xinhua302/Graphics-Engine