1. 程式人生 > >Android Shader著色器/渲染器

Android Shader著色器/渲染器

一、介紹Shader是繪圖過程中的著色器,它有五個子類:
  1. BitmapShader:         點陣圖渲染
  2. LinearGradient:        線性渲染
  3. SweepGradient:        梯度渲染
  4. RadialGradient:        光束渲染
  5. ComposeShader:     組合渲染
渲染模式:Shader.TileMode
  • Shader.TileMode.CLAMP:    邊緣拉伸模式,它會拉伸邊緣的一個畫素來填充其他區域。
  • Shader.TileMode.MIRROR:    映象模式,通過映象變化來填充其他區域。需要注意的是,映象模式先進行y軸方向的映象操作,然後在進行x軸方向上的映象操作。
  • Shader.TileMode.REPEAT:重複模式,通過複製來填充其他區域

下面的圖:X軸是邊緣拉伸模式,Y重複模式


映象模式:xy軸均是映象模式


二、效果介紹:

1.BitmapShader:         點陣圖渲染

    構造方法:BitmapShader (Bitmap bitmap, Shader.TileMode tileX, Shader.TileMode tileY)

    引數:

        bitmap:要處理的bitmap物件

        tileX:在X軸處理的效果,Shader.TileMode裡有三種模式:CLAMP、MIRROR和REPETA

        tileY:在Y軸處理的效果,Shader.TileMode裡有三種模式:CLAMP、MIRROR和REPETA

我們給畫筆填充一個五角星,然後繪製一條直線

Shader shader[] = new Shader[8];
bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.star);
shader[0] = new BitmapShader(bitmap,Shader.TileMode.REPEAT,Shader.TileMode.REPEAT);
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setStrokeWidth(32);
paint
.setShader(shader[0]); int lineHeight = 100,lineOffset = 50; canvas.drawLine(0,lineHeight,parentWidth,100,paint);

2.LinearGradient:        線性渲染

    LinearGradient是顏色線性漸變的著色器。

    建構函式:

        LinearGradient (float x0, float y0, float x1, float y1, int color0, int color1, Shader.TileMode tile)

        LinearGradient (float x0, float y0, float x1, float y1, int[] colors, float[] positions, Shader.TileMode tile)

    引數:

        (x0,y0)表示漸變的起點,(x1,y1)表示漸變的終點座標,這兩點都是相對於螢幕座標系。

        color0,color1分別表示起點的顏色和終點的顏色。

        也傳入多個顏色,和每個顏色的起始位置。

        colors[]傳入多個顏色值進去

        positions[] 位置陣列

        而且當positions引數傳入null時,代表顏色是均勻的填充整個漸變區域的,顯得比較柔和。

通過兩個建構函式分別畫兩條線:

lineHeight += lineOffset;
shader[1] = new LinearGradient(0,lineHeight,parentWidth,lineHeight,Color.RED,Color.GREEN,Shader.TileMode.REPEAT);
paint.setShader(shader[1]);
canvas.drawLine(0,lineHeight,parentWidth,lineHeight,paint);
lineHeight += lineOffset;
shader[2] = new LinearGradient(0,lineHeight,parentWidth,lineHeight,GRADIENT_COLORS,null,Shader.TileMode.REPEAT);
paint.setShader(shader[2]);
canvas.drawLine(0,lineHeight,parentWidth,lineHeight,paint);

3.SweepGradient:        梯度渲染

        SweepGradient是梯度漸變,也稱為掃描式漸變,可以實現雷達掃描效果。

        建構函式:

            SweepGradient(float cx, float cy, int color0, int color1)

        引數:

            (cx,cy)表示漸變效果的中心點,也就是雷達掃描的圓點。color0和color1表示漸變的起點色和終點色。

            顏色漸變是順時針的,從中心點的x軸正方形開始。

            注意:這裡建構函式並不需要TileMode,因為梯度漸變的邊界相當於無限大的。

        建構函式:

            SweepGradient(float cx, float cy,int colors[], float positions[])

引數:

            colors[]顏色陣列

            positions陣列,該陣列中每一個position對應colors陣列中每個顏色在360度中的相對位置,

            position取值範圍為[0,1],0和1都表示3點鐘位置,0.25表示6點鐘位置,0.5表示9點鐘位置,0.75表示12點鐘位置,

通過要個建構函式繪製兩個實心圓,其中第二個圓指定positions

public static final int[] GRADIENT_COLORS = new int[]{
        Color.RED,Color.YELLOW,Color.BLUE, Color.GREEN, Color.WHITE, Color.RED };
public static final float[] GRADIENT_POSITONS = new float[]{
        0.0f,0.5f,0.55f,0.6f,0.65f,1.0f};

lineHeight += lineOffset +32;
shader[3] = new SweepGradient(150,lineHeight,GRADIENT_COLORS,null);
paint.setShader(shader[3]);
canvas.drawCircle(150,lineHeight,50,paint);
shader[4] = new SweepGradient(450,lineHeight,GRADIENT_COLORS,GRADIENT_POSITONS);
paint.setShader(shader[4]);
canvas.drawCircle(450,lineHeight,50,paint);

4.RadialGradient:        光束渲染

        RadialGradient:建立從中心向四周發散的輻射漸變效果,

        建構函式:

      RadialGradient(float centerX, float centerY, float radius, int centerColor, int edgeColor, Shader.TileMode tileMode)

        引數:

        centerX  圓心的X座標

        centerY  圓心的Y座標

        radius   圓的半徑

        centerColor  中心顏色

        edgeColor   邊緣顏色

        建構函式:

            RadialGradient(float centerX, float centerY, float radius, int[] colors, float[] stops, Shader.TileMode tileMode)

        引數:

            colors[]傳入多個顏色值進去,這樣就會用colors陣列中指定的顏色值一起進行顏色線性插值。

            stops陣列,該陣列中每一個stop對應colors陣列中每個顏色在半徑中的相對位置,

            stop[]取值範圍為[0,1],0表示圓心位置,1表示圓周位置。如果stops陣列為null,那麼Android會自動為colors設定等間距的位置。

private float period = 0;   //偏移量變化週期值
lineHeight += lineOffset + 150;
shader[5] = new RadialGradient(150,lineHeight,10,Color.GREEN,Color.RED,Shader.TileMode.MIRROR);
paint.setShader(shader[5]);
canvas.drawCircle(150,lineHeight,100,paint);
if ( period < 250 || period >= 650){
    period = 250;
}else {
    period += 5F;
}
shader[6] = new RadialGradient(period,lineHeight,30,GRADIENT_COLORS,null,Shader.TileMode.MIRROR);
paint.setShader(shader[6]);
canvas.drawCircle(450,lineHeight,100,paint);

這裡多指定了一個period,設定為漸變的圓心x軸座標,這樣就可以實現滾動的小球


同樣也可以設定繪製的圓心跟隨滾動:將圓心Y軸座標設定為period,實現小球從上往下掉的效果

canvas.drawCircle(450,period,100,paint);

5.ComposeShader:     組合渲染

        ComposeShader用來組合不同的Shader,可以將兩個不同的Shader組合在一起

    建構函式:

        ComposeShader (Shader shaderA, Shader shaderB, Xfermode mode)

        ComposeShader (Shader shaderA, Shader shaderB, PorterDuff.Mode mode)

    引數:

        shaderA shaderB 兩種渲染效果

將bitmapShader和RadialGradient模式複合

lineHeight += lineOffset + 350;
bitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.head);
shader[0] = new BitmapShader(bitmap, Shader.TileMode.REPEAT,Shader.TileMode.REPEAT);
shader[6] = new RadialGradient(150,lineHeight,550,Color.BLACK,Color.TRANSPARENT, Shader.TileMode.CLAMP);
//混合產生新的Shader.
shader[7] = new ComposeShader(shader[0],shader[6],PorterDuff.Mode.DST_IN);
paint.setShader(shader[7]);
//以新的Shader繪製一個圓。
canvas.drawCircle(150,lineHeight,550,paint);

左下角的漸漸模糊的圖片便是組合效果

全部程式碼:

//shader 畫筆填充
private void my_shader(Canvas canvas){

    //Shader.TileMode是指平鋪模式
    //Shader.TileMode.CLAMP是邊緣拉伸模式,它會拉伸邊緣的一個畫素來填充其他區域。
    //Shader.TileMode.MIRROR是映象模式,通過映象變化來填充其他區域。需要注意的是,映象模式先進行y軸方向的映象操作,然後在進行x軸方向上的映象操作。
    //Shader.TileMode.REPEAT是重複模式,通過複製來填充其他區域
    //bitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.head);
Shader shader[] = new Shader[8];
bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.star);
shader[0] = new BitmapShader(bitmap,Shader.TileMode.REPEAT,Shader.TileMode.REPEAT);
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setStrokeWidth(32);
paint.setShader(shader[0]);
int lineHeight = 100,lineOffset = 50;
canvas.drawLine(0,lineHeight,parentWidth,100,paint);
//canvas.drawCircle(240,240,100,paint);
    //LinearGradient是顏色線性漸變的著色器。
    //LinearGradient (float x0, float y0, float x1, float y1, int color0, int color1, Shader.TileMode tile)
    //(x0,y0)表示漸變的起點,(x1,y1)表示漸變的終點座標,這兩點都是相對於螢幕座標系。color0,color1分別表示起點的顏色和終點的顏色。
    //LinearGradient (float x0, float y0, float x1, float y1, int[] colors, float[] positions, Shader.TileMode tile)
    //多色漸變的建構函式中,我們可以傳入多個顏色,和每個顏色的佔比。而且當positions引數傳入null時,代表顏色是均勻的填充整個漸變區域的,顯得比較柔和。
lineHeight += lineOffset;
shader[1] = new LinearGradient(0,lineHeight,parentWidth,lineHeight,Color.RED,Color.GREEN,Shader.TileMode.REPEAT);
paint.setShader(shader[1]);
canvas.drawLine(0,lineHeight,parentWidth,lineHeight,paint);
lineHeight += lineOffset;
shader[2] = new LinearGradient(0,lineHeight,parentWidth,lineHeight,GRADIENT_COLORS,null,Shader.TileMode.REPEAT);
paint.setShader(shader[2]);
canvas.drawLine(0,lineHeight,parentWidth,lineHeight,paint);
//SweepGradient是梯度漸變,也稱為掃描式漸變,效果有點類似與雷達掃描效果。
    //SweepGradient(float cx, float cy, int color0, int color1)
    // (cx,cy)表示漸變效果的中心點,也就是雷達掃描的圓點。color0和color1表示漸變的起點色和終點色。
    // 顏色漸變是順時針的,從中心點的x軸正方形開始。
    // 注意:這裡建構函式並不需要TileMode,因為梯度漸變的邊界相當於無限大的。
    //SweepGradient(float cx, float cy,int colors[], float positions[])
    //colors[]顏色陣列
    //positions陣列,該陣列中每一個position對應colors陣列中每個顏色在360度中的相對位置,
    // position取值範圍為[0,1],0和1都表示3點鐘位置,0.25表示6點鐘位置,0.5表示9點鐘位置,0.75表示12點鐘位置,
lineHeight += lineOffset +32;
shader[3] = new SweepGradient(150,lineHeight,GRADIENT_COLORS,null);
paint.setShader(shader[3]);
canvas.drawCircle(150,lineHeight,50,paint);
shader[4] = new SweepGradient(450,lineHeight,GRADIENT_COLORS,GRADIENT_POSITONS);
paint.setShader(shader[4]);
canvas.drawCircle(450,lineHeight,50,paint);
//RadialGradient:建立從中心向四周發散的輻射漸變效果,其有兩個建構函式:
    //RadialGradient(float centerX, float centerY, float radius, int centerColor, int edgeColor, Shader.TileMode tileMode)
    //centerX  圓心的X座標
    //centerY  圓心的Y座標
    //radius   圓的半徑
    //centerColor  中心顏色
    //edgeColor   邊緣顏色
    //RadialGradient(float centerX, float centerY, float radius, int[] colors, float[] stops, Shader.TileMode tileMode)
    //colors[]傳入多個顏色值進去,這樣就會用colors陣列中指定的顏色值一起進行顏色線性插值。
    // stops陣列,該陣列中每一個stop對應colors陣列中每個顏色在半徑中的相對位置,
    // stop[]取值範圍為[0,1],0表示圓心位置,1表示圓周位置。如果stops陣列為null,那麼Android會自動為colors設定等間距的位置。
lineHeight += lineOffset + 150;
shader[5] = new RadialGradient(150,lineHeight,10,Color.GREEN,Color.RED,Shader.TileMode.MIRROR);
paint.setShader(shader[5]);
canvas.drawCircle(150,lineHeight,100,paint);
if ( period < 250 || period >= 650){
        period = 250;
}else {
        period += 5F;
}
    shader[6] = new RadialGradient(period,lineHeight,30,GRADIENT_COLORS,null,Shader.TileMode.MIRROR);
paint.setShader(shader[6]);
canvas.drawCircle(450,period,100,paint);
//ComposeShader用來組合不同的Shader,可以將兩個不同的Shader組合在一起,它有兩個建構函式:
    //ComposeShader (Shader shaderA, Shader shaderB, Xfermode mode)
    //ComposeShader (Shader shaderA, Shader shaderB, PorterDuff.Mode mode)
lineHeight += lineOffset + 350;
bitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.head);
shader[0] = new BitmapShader(bitmap, Shader.TileMode.REPEAT,Shader.TileMode.REPEAT);
shader[6] = new RadialGradient(150,lineHeight,550,Color.BLACK,Color.TRANSPARENT, Shader.TileMode.CLAMP);
//混合產生新的Shader.
shader[7] = new ComposeShader(shader[0],shader[6],PorterDuff.Mode.DST_IN);
paint.setShader(shader[7]);
//以新的Shader繪製一個圓。
canvas.drawCircle(150,lineHeight,550,paint);
}