欢迎光临
我们一直在努力

Cesium高级教程-三维风场粒子-越界处理与消亡重生

Cesium高级教程-三维风场粒子-越界处理与消亡重生

现在我们的风场粒子已经成功动起来了,但是运行一段时间后会发现两个问题,一是部分粒子会跑出数据边界,二是可见的粒子越来越少导致部分区域没有粒子。

越界处理

首先需要对粒子运行的范围进行限定,当粒子超出边界时将其位置重新定义回数据范围,我们可以将其位置定义为初始位置,因为我们的初始位置存储在一张纹理中的,所以可以直接从这张纹理中重新读取初始位置赋予它的下一个位置。

//计算下一个位置
const computePos = new CommandPrimtive({
outputTexture: nextPosTexture,
commandType: CommandType.Compute,
uniformMap: {

particlePosTexture: () => {
return particlePosTexture;
},

},
fragmentShaderSource: new Cesium.ShaderSource({
sources: [`
precision highp float;
uniform sampler2D particlePosTexture;

vec2 dataLonRange=vec2(116.25, 125.75);
vec2 dataLatRange=vec2(20.25, 28.5);
bool particleOutbound(vec2 particle) {
return particle.y < dataLatRange.x || particle.y > dataLatRange.y || particle.x < dataLonRange.x || particle.x > dataLonRange.y;
}
void main() {

if (particleOutbound(nextPos)) {
out_FragColor =texture(particlePosTexture, v_textureCoordinates);
} else {
out_FragColor = vec4(nextPos, 0.0, 0.0);
}
}`]
})
})

在这里插入图片描述

示例效果可到 xt3d 官网 运行查看

因为粒子的初始位置是一个随机位置,所以我们也可以在它超出边界后重新创建一个随机的位置赋予它,这样能够提高区域内粒子分布的均匀性,否则可能会出现一些空白区域。在glsl中生成指定范围数值的方法有很多,可以网上随意复制一个能用就行。

//计算下一个位置
const computePos = new CommandPrimtive({

uniformMap: {

randomCoefficient: () => {
return Math.random();
},
},
fragmentShaderSource: new Cesium.ShaderSource({
sources: [`
precision highp float;
uniform sampler2D currentPosTexture;
uniform sampler2D speedTexture;
in vec2 v_textureCoordinates;
uniform float randomCoefficient;

vec2 dataLonRange=vec2(116.25, 125.75);
vec2 dataLatRange=vec2(20.25, 28.5);
const vec3 randomConstants = vec3(12.9898, 78.233, 4375.85453);
float rand(vec2 seed, vec2 range) {
vec2 randomSeed = randomCoefficient * seed;
float temp = dot(randomConstants.xy, randomSeed);
temp = fract(sin(temp) * (randomConstants.z + temp));
return temp * (range.y – range.x) + range.x;
}

vec2 generateRandomParticle(vec2 seed) {
float randomLon, randomLat;
// 在数据范围内生成粒子
randomLon = rand(seed, dataLonRange);
randomLat = rand(-seed, dataLatRange);
return vec2(randomLon, randomLat);
}

bool particleOutbound(vec2 particle) {
return particle.y < dataLatRange.x || particle.y > dataLatRange.y || particle.x < dataLonRange.x || particle.x > dataLonRange.y;
}

void main() {
// 获取当前粒子的位置
vec2 currentPos = texture(currentPosTexture, v_textureCoordinates).rg;

if (particleOutbound(nextPos)) {
out_FragColor = vec4(randomPos, 0.0, .0);
} else {
out_FragColor = vec4(nextPos, 0.0, 0.0);
}
}
`]
})
})

在这里插入图片描述

示例效果可到 xt3d 官网 运行查看

闪烁问题

现在我们已经解决了粒子移动时超过边界的问题,但是仔细看会发现一个新的问题,那就是会看到一条条的闪烁线条,这是因为粒子的当前位置和新位置距离过大(新位置是一个随机位置),要解决这个问题我们可以通过判断当前粒子是否是重设的新位置,如果是新位置那么当前一帧先不渲染该粒子,下一帧时位置就不再是新位置了,而是通过移动量计算得来的位置。首先我们需要在输出位置时标记是否为新位置


// 将新的位置写入 out_FragColor
if (particleOutbound(nextPos)) {
out_FragColor = vec4(randomPos, 0.0, 1.0);
} else {
out_FragColor = vec4(nextPos, 0.0, 0.0);
}

然后在绘制指令的着色器中判断标识,如果是新位置则将透明度设置为0.,这样就不会看到新位置时的粒子图形。


if((next.a+current.a)>0.){
v_alpha=0.;
}

在这里插入图片描述

示例效果可到 xt3d 官网 运行查看

消亡与重生

前面我们已经成功处理了粒子越界的问题,接下来继续处理粒子越来越少的问题。程序在运行一段时间后,粒子数量会减少甚至完全消失,这是因为我们的这份风场数据具有旋涡,由于我们的粒子是一直往前走的,所以最后大部分粒子会进入旋涡中心导致速度可能小于等于0,因此粒子就会消失。

要解决这个问题也很简单,我们只需要为粒子赋予一个生命周期就行(即消亡与重生),也就是当一个粒子运行一段时间后就手动让它消亡,但是为了保证粒子数量,我们还需要在其它地方让它重生。消亡与重生的基本规则是速度越快的粒子消失得越快,因为速度越快代表着它跑出的距离就越远,所以就要越早对它进行干预。

更多内容见 Cesium高级教程-教程简介

赞(0)
未经允许不得转载:171主机测评 » Cesium高级教程-三维风场粒子-越界处理与消亡重生
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址