Android 上的动画噪声
Animate noise on Android
我想用 Perlin 3D 噪声做一些 "mist effect",动画帧数的 Z 轴。
我为此使用了 16x9 LinearLayouts 网格,它们都具有相同的背景颜色,并将它们的 alpha 透明度更改为 Perlin 噪声值。
在我的平板电脑上工作得很好,但是 32x18 的东西开始有点爬行,在我的 phone 上我什么也看不到,只有一些伪像 - 比如随机图像撕裂。
直接在 canvas 上自定义视图和绘图(然后放大整个东西)会更快更安全吗?
或者更新屏幕时生成 3D 噪声的问题如此之快?
直接画成canvas是合适的做法。不再有 "artifact" 问题,而且帧速率更好。做起来也很简单。
这是一个 MistView
class:
的工作示例
package com.example.yourapp; // don't forget to change this
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.util.AttributeSet;
import android.view.View;
import android.os.Handler;
import java.util.Random;
public class MistView extends View {
SimplexNoise sN = new SimplexNoise(); // you'll need a working SimplexNoise class
Paint[][] paints = null;
float floathex[][];
final static int W = 32;
final static int H = 18;
float widthf, heightf;
int z = 0;
final static int R = 128; // you can play with color here
final static int G = 128;
final static int B = 128;
Random rand = new Random();
final int xoff = random(-100000, 100000);
final int yoff = random(-100000, 100000);
final int zoff = random(-100000, 100000);
Handler myHandler = new Handler();
Runnable myRunnable = new Runnable() {
@Override
public void run() {
z++;
reDraw();
}
};
public MistView(Context context) {
super(context);
this.paints = new Paint[W][H];
for (int w = 0; w < W; w++)
{
for (int h = 0; h < H; h++)
{
this.paints[w][h] = new Paint();
this.paints[w][h].setStyle(Paint.Style.FILL);
}
}
}
public MistView(Context context, AttributeSet attributeSet)
{
super(context, attributeSet);
this.paints = new Paint[W][H];
for (int w = 0; w < W; w++)
{
for (int h = 0; h < H; h++)
{
this.paints[w][h] = new Paint();
this.paints[w][h].setStyle(Paint.Style.FILL);
}
}
}
@Override
public void onDraw(Canvas canvas) {
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.MULTIPLY);
if (widthf == 0)
widthf = canvas.getWidth() / (float) W;
if (heightf == 0)
heightf = canvas.getHeight() / (float) H;
floathex = sN.generateOctavedSimplexNoise(W, H, z, xoff, yoff, zoff, 8, 0.05f, 0.05f);
for (int w = 0; w < W; w++)
{
for (int h = 0; h < H; h++)
{
int a = Math.round(64* ((floathex[w][h] + 1f)/2f));
if (a < 0)
a = 0;
this.paints[w][h].setColor(Color.argb(a, R, G, B));
canvas.drawRect(w * widthf, h * heightf, (w + 1) * widthf, (h + 1) * heightf, this.paints[w][h]);
}
}
myHandler.postDelayed(myRunnable, 60);
}
protected void reDraw() {
this.invalidate();
}
public int random(int min, int max) {
return (int) (rand.nextFloat() * (max - min + 1)) + min;
}
}
我想用 Perlin 3D 噪声做一些 "mist effect",动画帧数的 Z 轴。
我为此使用了 16x9 LinearLayouts 网格,它们都具有相同的背景颜色,并将它们的 alpha 透明度更改为 Perlin 噪声值。
在我的平板电脑上工作得很好,但是 32x18 的东西开始有点爬行,在我的 phone 上我什么也看不到,只有一些伪像 - 比如随机图像撕裂。
直接在 canvas 上自定义视图和绘图(然后放大整个东西)会更快更安全吗?
或者更新屏幕时生成 3D 噪声的问题如此之快?
直接画成canvas是合适的做法。不再有 "artifact" 问题,而且帧速率更好。做起来也很简单。
这是一个 MistView
class:
package com.example.yourapp; // don't forget to change this
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.util.AttributeSet;
import android.view.View;
import android.os.Handler;
import java.util.Random;
public class MistView extends View {
SimplexNoise sN = new SimplexNoise(); // you'll need a working SimplexNoise class
Paint[][] paints = null;
float floathex[][];
final static int W = 32;
final static int H = 18;
float widthf, heightf;
int z = 0;
final static int R = 128; // you can play with color here
final static int G = 128;
final static int B = 128;
Random rand = new Random();
final int xoff = random(-100000, 100000);
final int yoff = random(-100000, 100000);
final int zoff = random(-100000, 100000);
Handler myHandler = new Handler();
Runnable myRunnable = new Runnable() {
@Override
public void run() {
z++;
reDraw();
}
};
public MistView(Context context) {
super(context);
this.paints = new Paint[W][H];
for (int w = 0; w < W; w++)
{
for (int h = 0; h < H; h++)
{
this.paints[w][h] = new Paint();
this.paints[w][h].setStyle(Paint.Style.FILL);
}
}
}
public MistView(Context context, AttributeSet attributeSet)
{
super(context, attributeSet);
this.paints = new Paint[W][H];
for (int w = 0; w < W; w++)
{
for (int h = 0; h < H; h++)
{
this.paints[w][h] = new Paint();
this.paints[w][h].setStyle(Paint.Style.FILL);
}
}
}
@Override
public void onDraw(Canvas canvas) {
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.MULTIPLY);
if (widthf == 0)
widthf = canvas.getWidth() / (float) W;
if (heightf == 0)
heightf = canvas.getHeight() / (float) H;
floathex = sN.generateOctavedSimplexNoise(W, H, z, xoff, yoff, zoff, 8, 0.05f, 0.05f);
for (int w = 0; w < W; w++)
{
for (int h = 0; h < H; h++)
{
int a = Math.round(64* ((floathex[w][h] + 1f)/2f));
if (a < 0)
a = 0;
this.paints[w][h].setColor(Color.argb(a, R, G, B));
canvas.drawRect(w * widthf, h * heightf, (w + 1) * widthf, (h + 1) * heightf, this.paints[w][h]);
}
}
myHandler.postDelayed(myRunnable, 60);
}
protected void reDraw() {
this.invalidate();
}
public int random(int min, int max) {
return (int) (rand.nextFloat() * (max - min + 1)) + min;
}
}