前端-风场可视化研究3
项目 https://github.com/RaymanNg/3D-Wind-Field 是把风场融合到了 cesiumJs 的三维球形地图中。

着色器的调用流程是 calculateSpeed.frag => updatePosition.frag => postProcessingPosition.frag => segmentDraw.vert => segmentDraw.frag => fullscreen.vert => trailDraw.frag => fullscreen.vert => screenDraw.frag
calculateSpeed.frag => updatePosition.frag => postProcessingPosition.frag 这三个着色器的调用在 particlesComputing.js 中,其余的在 particlesRendering.js 中调用
calculateSpeed.frag 中的 currentParticlesPosition 的分辨率为 64 x 64, 每帧都会更新。U纹理 和 V纹理 是风场数据不会每帧都改变,这两个纹理的分辨率是 720 x 361 x 1
var particlesArray = DataProcess.randomizeParticles(userInput.maxParticles, viewerParameters)
var zeroArray = new Float32Array(4 * userInput.maxParticles).fill(0);
this.particlesTextures = {
previousParticlesPosition: Util.createTexture(particlesTextureOptions, particlesArray),
currentParticlesPosition: Util.createTexture(particlesTextureOptions, particlesArray),
nextParticlesPosition: Util.createTexture(particlesTextureOptions, particlesArray),
postProcessingPosition: Util.createTexture(particlesTextureOptions, particlesArray),
particlesSpeed: Util.createTexture(particlesTextureOptions, zeroArray)
};
这里对五张纹理previousParticlesPosition currentParticlesPosition nextParticlesPosition postProcessingPosition particlesSpeed都进行了初始化
五张纹理的分辨率为64 x 64 由风粒子的总数决定这个分辨率
这个着色器中
void main() {
speedScaleFactor = speedFactor * pixelSize;
// texture coordinate must be normalized
vec3 lonLatLev = texture(currentParticlesPosition, v_textureCoordinates).rgb;
vec3 speed = calculateSpeedByRungeKutta2(lonLatLev);
vec3 speedInLonLat = convertSpeedUnitToLonLat(lonLatLev, speed);
vec4 particleSpeed = vec4(speedInLonLat, calculateWindNorm(speed / speedScaleFactor));
outputColor = particleSpeed;
}
pixelSize来自 cesium camera
var pixelSize = this.camera.getPixelSize(
this.globeBoundingSphere,
this.scene.drawingBufferWidth,
this.scene.drawingBufferHeight
);
if (pixelSize > 0) {
this.viewerParameters.pixelSize = pixelSize;
}
我无法理解为什么这里必须是 calculateSpeedByRungeKutta2,RK2数值积分方法,计算下一时刻的风速,通义千问的解释是,这样做得到速度更加精确和稳定。
我尝试过将 calculateSpeedByRungeKutta2 修改为
vec3 calculateSpeedByRungeKutta2(vec3 lonLatLev) {
// see https://en.wikipedia.org/wiki/Runge%E2%80%93Kutta_methods#Second-order_methods_with_two_stages for detail
const float h = 0.5;
vec3 y_n = lonLatLev;
vec3 f_n = linearInterpolation(lonLatLev);
return convertSpeedUnitToLonLat(y_n, f_n) * speedScaleFactor;
}
修改后,风粒子无法流动起来,没有线条轨迹了。二维风场图 https://github.com/mapbox/webgl-wind 都没有使用 RK2 数值积分方法,为什么这里必须使用?
segmentDraw.vert 顶点着色器中使用了 previousParticlesPosition currentParticlesPosition postProcessingPosition 三张纹理来绘制三角形带,组成可以设置宽度的线条

浙公网安备 33010602011771号