Android修炼系列(43),地图上的雨景特效实现思路

上一篇写了关于如何实现雪景的技术方案:

Android修炼系列(42),地图上的雪景特效实现思路

本篇在此基础上,说下雨景的实现思路,效果见下:

方案

之前是打算将模型抽象成一套黑盒,然后对于雨和雪,只需要改变对粒子的贴图即可。但实际操作后发现自己忽视了粒子系统的问题。

粒子系统认为每个点仅仅是一个点,不应该有三维的形状。粒子系统只会将粒子的顶点坐标投射到屏幕像素上,并以该点为中心渲染一个小正方形。

对于雪花来讲,如果直接用一个白色的小球来代表的话,不论从什么角度观察,都是一个白色的圆,所以是各向同性的。所以只需要在小正方形里渲染一个小白圆就可以。

但是对于雨滴来讲,它是一个细长的结构,所以从天空向下看雨滴和平视雨滴看到的是不一样的。所以需要额外设计来保证雨滴具有三维形状。

根据调研,为了使粒子有三维结构:

  • 第一种是对粒子进行贴图,但是贴图不是直接贴在小正方形上,而是让贴图乘上 MVP 矩阵,然后将透视的结果绘制在小正方形里。这种算法需要将 MVP 的 matrix 和 texture 都传入到 fragment shader 中,相当于每一个小像素都需要去变换,有大量的重复计算。
  • 第二种是拿数学公式模拟雨滴,可以直接在 vertex shader 中计算出来雨滴应该绘制的形状,然后将参数传入到 fragment shader 中,将对应的图形绘制在小正方形里。

显然第二种方法更好些,效率高,还能复用雪景模型盒的大部分代码。

椭圆方程

以粒子的空间坐标为椭球的球心,在 vertex shader 中进行计算时,根据该球心坐标,在 Z 轴值上加减 L/2 (半焦距,设定好的固定常数)得到两个焦点的空间坐标,将这两个焦点投影到屏幕上。

由于绘制是以球心在屏幕上的投影坐标为中心的正方形,则需要根据这两个投影后的焦点在屏幕中的位置来确定所绘制的正方形大小。

将上下焦点的投影坐标传入到 fragment shader 中,再以这两点为焦点用椭圆方程绘制一个扁平的椭圆来表示雨滴。

这里要注意一点,这样绘制的椭圆不一定就是该椭球在屏幕上的精确投影,只是当该形状及其狭长时,这样的近似会极其接近,足以满足视觉效果。

考虑风向

在 Z 值上加减 L/2 是默认雨滴是竖直方向的,如果有风时,雨滴会有一定的偏向。

将风抽象成一个模长受限的水平向量(模长最大值可以被设定),然后让风与向量 (0,0,1) 的夹角等于雨滴与 Z 轴的夹角即可。

总结

雨景部分相比于雪景主要就是解决了粒子各向异性问题。既然贴图的路不好走,又不想抛弃粒子系统去渲染大量三维物体,于是就用简易的数学公式来模拟一个三维雨滴形状,从而保证了渲染效率基本不受影响。

而且在雪景的模型盒系统的支持下,雨景还可以有俯视视角、平移、旋转、缩放等等类似的景象,具有良好的视觉效果。

待续。

相关推荐
福柯柯1 小时前
Android ContentProvider的使用
android·contenprovider
不想迷路的小男孩1 小时前
Android Studio 中Palette跟Component Tree面板消失怎么恢复正常
android·ide·android studio
餐桌上的王子1 小时前
Android 构建可管理生命周期的应用(一)
android
菠萝加点糖1 小时前
Android Camera2 + OpenGL离屏渲染示例
android·opengl·camera
用户2018792831671 小时前
🌟 童话:四大Context徽章诞生记
android
yzpyzp1 小时前
Android studio在点击运行按钮时执行过程中输出的compileDebugKotlin 这个任务是由gradle执行的吗
android·gradle·android studio
aningxiaoxixi1 小时前
安卓之service
android
TeleostNaCl2 小时前
Android 应用开发 | 一种限制拷贝速率解决因 IO 过高导致系统卡顿的方法
android·经验分享
用户2018792831672 小时前
📜 童话:FileProvider之魔法快递公司的秘密
android
vocal6 小时前
【我的安卓第一课】Android 多线程与异步通信机制(1)
android