Android 动态壁纸水波纹效果
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10326039/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Live Wallpaper Water Ripple Effect
提问by Gatekeeper
I'm working on a live wallpaper that incorporates some water ripple effects on touching the screen but I'm a little stuck.
我正在制作一个动态壁纸,在触摸屏幕时加入了一些水波纹效果,但我有点卡住了。
Would it be better to create multiple images and loop through them to create a ripple animation or would it be better to distort the bitmap a bit before I place it on the canvas?
创建多个图像并循环它们以创建波纹动画会更好,还是在将位图放置在画布上之前稍微扭曲位图会更好?
Thisis a video of a very nice ripple effect done through OpenGL.
这是一个通过 OpenGL 完成的非常好的涟漪效果的视频。
I don't have any experience yet with OpenGL and was wondering if it is still possible to create a 2D water effect on the live wallpaper?
我对 OpenGL 还没有任何经验,想知道是否仍然可以在动态壁纸上创建 2D 水效果?
回答by esteewhy
I wanted to implemented a realistic ripple effect in Android too, so will share my experience:
我也想在 Android 中实现一个逼真的涟漪效果,所以将分享我的经验:
As a reference implementation i took Sergey's Chikuyonok JavaScript port of Neil Wallis Java algo. Here's a playground where you can experiment with original JS code: http://jsfiddle.net/esteewhy/5Ht3b/6/
作为参考实现,我采用了 Sergey 的 Neil Wallis Java 算法的 Chikuyonok JavaScript 端口。这里有一个操场,您可以在其中试验原始 JS 代码:http: //jsfiddle.net/esteewhy/5Ht3b/6/
At first, i've ported JS code to Java only to realize that there's no way to squeeze more than 1 fps on my Huawei U8100 hardware. (There're several similar attempts on the net with the only conclusion: they're ridiculously slow).
起初,我将 JS 代码移植到 Java 只是为了意识到在我的华为 U8100 硬件上没有办法挤压超过 1 fps。(网上有几个类似的尝试,唯一的结论是:它们慢得可笑)。
BTW, this SO answer was quite useful to get basic understanding of how to code an interactive graphics in Android: https://stackoverflow.com/a/4946893/35438. I've borrowed fps counter from there.
顺便说一句,这个 SO 答案对于基本了解如何在 Android 中编写交互式图形非常有用:https: //stackoverflow.com/a/4946893/35438。我从那里借了 fps 计数器。
Then i decided to try Android NDK to reimplement original algo in pure C (my first encounter with it in 10+ yrs!). Despite NDK's docs being somewhat confusing (especially as to requirements and prerequisites), it all worked like a charm, so i was able to achieve up to 30 fps -- it might not be too impressive, but still, a radical improvement over Java code.
然后我决定尝试使用 Android NDK 用纯 C 重新实现原始算法(我在 10 多年后第一次遇到它!)。尽管 NDK 的文档有些令人困惑(尤其是在要求和先决条件方面),但它的运行非常吸引人,所以我能够达到 30 fps——它可能不会太令人印象深刻,但仍然是对 Java 代码的根本改进.
Finally, i've put all my work online: https://github.com/esteewhy/whater, so feel free to play with that. It contains:
最后,我把我所有的工作都放到了网上:https: //github.com/esteewhy/whater,所以请随意使用它。它包含了:
- Interactive bouncing ball code mentioned above (just for the reference).
- Water ripples Java port (slow like hell!)
- Water ripples C implementation (needs NDK to compile and JDK to create .h file).
- 上面提到的交互式弹跳球代码(仅供参考)。
- 水波纹Java端口(慢得像地狱!)
- 水波纹 C 实现(需要 NDK 编译和 JDK 创建 .h 文件)。
(The project is not "clean", i.e.: all binaries are there, so can try to run it "as is" even without NDK.)
(该项目不是“干净的”,即:所有二进制文件都在那里,因此即使没有 NDK,也可以尝试“按原样”运行它。)
回答by Steve C.
You can find an example of a touch ripple effect here:
您可以在此处找到触摸波纹效果的示例:
https://github.com/MasDennis/RajawaliExamples
https://github.com/MasDennis/RajawaliExamples
It utilizes the rajawali OpenGL ES framework/library. You can download the rajawali examples app from the market to see how it looks. Browse through the "src" folder and you will see the TouchRippleEffect activity and renderer. Hope that helps.
它利用 rajawali OpenGL ES 框架/库。您可以从市场下载 rajawali 示例应用程序以查看它的外观。浏览“src”文件夹,您将看到 TouchRippleEffect 活动和渲染器。希望有帮助。
回答by Wyzard
I'm no expert in this, but I believe the typical way to do water effects in OpenGL is with a fragment shader. With a static image as a texture, your shader can vary the texture coordinates used for sampling that image, to distort it in arbitrary ways.
我不是这方面的专家,但我相信在 OpenGL 中制作水效果的典型方法是使用片段着色器。使用静态图像作为纹理,您的着色器可以改变用于对该图像进行采样的纹理坐标,以任意方式对其进行扭曲。
Calculate the pixel's direction and distance from the center of the circle, and adjust the texture coordinate toward or away from the circle's center based on a sinusoidal function of the distance, and you should get a nice ripple effect.
计算像素的方向和距圆心的距离,根据距离的正弦函数调整纹理坐标朝向或远离圆心,应该会得到很好的波纹效果。
Judging by the description of that YouTube video you linked, it sounds like that's done by using a grid of triangles and adjusting the texture coordinates only at the vertices. That should work too, but it won't look as good unless you use a rather fine grid. Doing it per-pixel with a fragment shader is the ideal, but I don't know whether that would cause performance problems on a phone's GPU.
从您链接的 YouTube 视频的描述来看,这听起来像是通过使用三角形网格并仅在顶点处调整纹理坐标来完成的。这也应该有效,但除非您使用相当精细的网格,否则它看起来不会那么好。使用片段着色器按像素执行是理想的,但我不知道这是否会导致手机 GPU 的性能问题。