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;
    }
 }