广告版技术BillBoard 原理与实现

面向世界的广告板demo下载



广告板技术:

无论观察者处于什么位置观察任何图像,广告版都能提供一个朝向观众的面,这个面随着摄像机的改变而改变.BillBoard技术是计算机图形学领域中进行快速绘制的一种方法。在类似游戏这种对实时性要求较高的场景下采取BillBoard技术可以大大加快绘制的速度从而提高画面的流畅性。
把3D的物体用2D来表示,然后让该物体始终朝向镜头。比如场景中的一棵树,对于整个场景来说不是主要物体,因此无需花费大量的时间去计算树的每一部分的细节。通常的做法是首先准备好一张树的照片,然后镜头运动的时候使得树始终正对着镜头,我们看到的始终是树的正面。
我们在渲染树木,灌木丛,云,烟等效果时都会用到.

先看一下图片,这颗树就是广告板技术生成的


原理:

问题的实质就是我们知道结果是物体面对摄像机,然后求物体的世界变换矩阵.



我们 看这张图,其中有两种坐标,一种是Camera,一种是Particle,其中Particle就是我们要讨论的广告板(BillBoard).

// 计算此物体的朝向矩阵,首先计算几个向量
    float3 v3Look  = normalize( + g_vEyePt.xyz - g_vLookAt.xyz );
    float3 v3Right = normalize( cross( float3( 0.0f , 1.0f , 0.0f ) , v3Look ));
    float3 v3Up    = cross( v3Look , v3Right );

这是其中三行确定广告版坐标的代码.
v3Look图中Particle 蓝色箭头的方向,意思是朝向Camera的方向,这个很容易由两个向量相减得到,然后规范化.
v3Right是图中Particle中深绿色的箭头.首先由Particle中的浅绿色箭头(float3( 0.0f , 1.0f , 0.0f )),也就是Camera中间的Y方向向量,然后和v3Look 叉乘,最后规范化,可以得到深绿色的v3Right向量.
v3Up是图中Particle 中是深红色的向量.可以由v3Look和v3Right叉乘得到.




    float4x4 matLookAt ;
    matLookAt[ 0 ] = float4( v3Right.xyz , 0.0 );//将右向量作为矩阵的X变换分量
    matLookAt[ 1 ] = float4( v3Up.xyz , 0.0 ); //将向上向量作为矩阵的Y变换分量
    matLookAt[ 2 ] = float4( v3Look.xyz , 0.0 );//将向前向量作为矩阵的Z变换分量
    matLookAt[ 3 ] = float4( g_vEyePt.xyz , 1.0 );//将观察位置作为矩阵的Z变化平移分量
    float4x4 matLocal = mul( matLookAt , g_matWorld );
    float4x4 matWorldView = mul( matLocal ,g_matView );
    float4x4 matWorldViewProject = mul( matWorldView ,g_matProject );
    Out.Position = mul( In.Position , matWorldViewProject );

这样子就能得到真实世界的坐标了.

广告版的种类:

1.面向世界的广告板,大小随远近调整,也称精灵技术
2.某轴是巨鼎的,大小随远近变化
3.提示信息类,大小与远近距离无关

一.面向世界的广告板,大小随远近调整,也称精灵技术

VS_OUTPUT RenderSceneVS( VS_INPUT In )
  {
    VS_OUTPUT Out = ( VS_OUTPUT )0;
    // 计算此物体的朝向矩阵,首先计算几个向量
    float3 v3Look  = normalize( + g_vEyePt.xyz - g_vLookAt.xyz );
    float3 v3Right = normalize( cross( float3( 0.0f , 1.0f , 0.0f ) , v3Look ));
    float3 v3Up    = cross( v3Look , v3Right );
    // 通过几个向量建立矩阵
    float4x4 matLookAt ;
    matLookAt[ 0 ] = float4( v3Right.xyz , 0.0 );
    matLookAt[ 1 ] = float4( v3Up.xyz , 0.0 );
    matLookAt[ 2 ] = float4( v3Look.xyz , 0.0 );
    matLookAt[ 3 ] = float4( g_vEyePt.xyz , 1.0 );
    float4x4 matLocal = mul( matLookAt , g_matWorld );
    float4x4 matWorldView = mul( matLocal ,g_matView );
    float4x4 matWorldViewProject = mul( matWorldView ,g_matProject );
    Out.Position = mul( In.Position , matWorldViewProject );
    Out.TextureUV = In.TextureUV;
    return Out;
  }

三个变量建立起了matLookAt矩阵,再使用此矩阵与世界矩阵相乘后到世界位置.

二.某轴是巨鼎的,大小随远近变化

比如上面的树木的效果,模型只会随Y轴变化而转动.
要建立起轴向固定的布告栏变化矩阵,需要以下几个变量,观察者的位置,向上方向,和被观察的位置.实际上,观察方向在Y轴上的投影为0,所以Y轴不参与变换,即观察变量v3Look = float3(v3Look.x,0.0,v3Look.z),同时 float3 v3Up    = float3( 0.0f , 1.0f , 0.0f ),即v3Up向量也要变为向Y轴的.

VS_OUTPUT RenderSceneVS( VS_INPUT In )
  {
    VS_OUTPUT Out = ( VS_OUTPUT )0;
    // 计算此物体的朝向矩阵,首先计算几个向量
    float3 v3Look  = normalize( + g_vEyePt.xyz - g_vLookAt.xyz );
    v3Look = float3( v3Look.x , 0.0 , v3Look.z );//重点是这行
    float3 v3Right = normalize( cross( float3( 0.0f , 1.0f , 0.0f ) , v3Look ));
    float3 v3Up    = float3( 0.0f , 1.0f , 0.0f );//cross( v3Look , v3Right );
    // 通过几个向量建立矩阵
    float4x4 matLookAt ;
    matLookAt[ 0 ] = float4( v3Right.xyz , 0.0 );
    matLookAt[ 1 ] = float4( v3Up.xyz , 0.0 );
    matLookAt[ 2 ] = float4( v3Look.xyz , 0.0 );
    matLookAt[ 3 ] = float4( g_vEyePt.xyz , 1.0 );
    float4x4 matLocal = mul( matLookAt , g_matWorld );
    float4x4 matWorldView = mul( matLocal ,g_matView );
    float4x4 matWorldViewProject = mul( matWorldView ,g_matProject );
    Out.Position = mul( In.Position , matWorldViewProject );
    Out.TextureUV = In.TextureUV;
    return Out;
  }


三.提示信息类,大小与远近距离无关

有时候,需要某种提示信息的广告版技术,即广告板随物体运动,但是大小不会随远近而变换.
这里,此广告板有一些特性,提示框与屏幕对齐,用于实现文字或图形信息.\
这说明广告板的坐标的X轴和Y轴是随着物体变化而变化的.所以广告版的X坐标就是物体X坐标,广告板Y坐标就是物体Y坐标.



面向世界的广告板demo下载




  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 可以使用 Cesium 的 `BillboardCollection` 类来实现在 Vue 框架中点击创建 billboard 的功能。 首先,在 Vue 组件的 data 中定义一个变量来存储 billboard 集合: ``` data() { return { billboardCollection: new Cesium.BillboardCollection() } } ``` 然后,在组件的 mounted 钩子函数中,将 billboard 集合添加到场景中: ``` mounted() { this.viewer.scene.primitives.add(this.billboardCollection); } ``` 接着,在组件的 template 中绑定点击事件,在事件处理函数中添加新的 billboard: ``` <template> <div @click="addBillboard">Click to add a billboard</div> </template> <script> export default { methods: { addBillboard() { // 获取鼠标点击的位置 let pickedObject = this.viewer.scene.pick(this.viewer.camera.getPickRay(this.viewer.canvas.clientWidth / 2, this.viewer.canvas.clientHeight / 2)); if (Cesium.defined(pickedObject)) { let position = this.viewer.scene.globe.ellipsoid.cartesianToCartographic(pickedObject.position); // 创建新的 billboard let billboard = this.billboardCollection.add({ position: Cesium.Cartesian3.fromRadians(position.longitude, position.latitude, position.height + 100), image: 'path/to/image.png' }); } } } } </script> ``` 在这个例子中,我们使用了 Cesium 的 `pick` 方法来获取鼠标点击的位置,然后使用 `Cartesian3.fromRadians` 将经纬度坐标转换为笛卡尔坐标,最后使用 `BillboardCollection.add` 方法添加新的 billboard。 希望这些信息能帮助您实现在 Vue 框架中使用 Cesium 创建 billboard 的功能。 ### 回答2: 在Vue框架中实现点击创建billboard功能,可以按照以下步骤进行: 1. 首先,在Vue项目中引入Cesium库,可以通过npm安装或直接引入Cesium.js文件。 2. 在Vue组件中,可以在`mounted`钩子函数中创建Cesium的Viewer对象,并将其初始化为指定DOM元素的父元素,如: ``` mounted() { this.viewer = new Cesium.Viewer(this.$refs.mapContainer); } ``` 其中`$refs.mapContainer`是在模板中定义的一个ref,用于获取地图容器的DOM元素。 3. 在模板中定义一个按钮,并绑定一个点击事件,如: ```vue <template> <div> <button @click="createBillboard">创建Billboard</button> <div class="map-container" ref="mapContainer"></div> </div> </template> ``` 4. 在Vue组件的methods选项中定义`createBillboard`方法,用于创建billboard。在该方法中,可以使用Cesium的`Cesium.Cartesian3`类创建一个位置,然后通过`Cesium.BillboardCollection`类创建一个billboard,并设置其属性,最后将billboard添加到scene中。代码示例如下: ```vue methods: { createBillboard() { // 创建位置 var position = Cesium.Cartesian3.fromDegrees(103, 30); // 创建BillboardCollection并设置属性 var billboard = this.viewer.scene.primitives.add( new Cesium.BillboardCollection() ); billboard.add({ position: position, image: "path/to/billboard-image.png", scale: 1.0, }); }, } ``` 其中,`Cesium.Cartesian3.fromDegrees`根据经纬度创建一个位置,`Cesium.BillboardCollection`用于存储和渲染多个billboard,`image`属性指定billboard的图片路径,`scale`属性用于设置billboard的大小。 5. 最后,通过点击按钮,调用`createBillboard`方法即可在地图上创建一个billboard。 这样,就在Vue框架中实现了点击创建billboard功能。 ### 回答3: 在Vue框架中实现点击创建Billboard功能,可以按照以下步骤实现: 1. 首先,将Cesium集成到Vue项目中。可以通过npm安装Cesium,然后在Vue组件中引入Cesium相关的库文件。 2. 在Vue组件的data选项中添加一个数组billboards,用于存储所有的Billboard对象信息。在初始状态下,该数组为空。 3. 在Vue组件的template中添加一个Cesium的Canvas元素,用于渲染Cesium场景。可以将该Canvas元素的id设为"cesiumContainer"。 4. 在Vue组件的methods选项中添加一个方法handleClick,用于处理点击事件。在该方法内,获取点击事件的坐标,在3D场景中添加一个Billboard对象,并将其位置设为点击坐标。然后,将该Billboard对象的信息添加到billboards数组中保存。 5. 在Vue组件的mounted钩子函数中,通过Cesium的Viewer对象初始化3D场景,并将Canvas元素绑定到该Viewer对象上。同时,监听Canvas元素的点击事件,当点击事件发生时,调用handleClick方法。 6. 在Vue组件的template中,使用v-for指令循环遍历billboards数组,并根据每个Billboard对象的信息,在Canvas中显示对应的Billboard元素。 通过以上步骤,就可以在Vue框架中实现点击创建Billboard功能。当用户在Canvas中点击时,会在点击位置创建一个Billboard,并在屏幕上显示出来。同时,Billboard对象的信息也会保存在billboards数组中,以便后续的操作和管理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值