opengles特效之飘扬的旗帜

来源:互联网 发布:js随机动态显示 编辑:程序博客网 时间:2024/05/02 04:56

效果图





核心代码 主要看shader中的实现

x方向飘扬shader

uniform mat4 uMVPMatrix; //总变换矩阵uniform float uStartAngle;//本帧起始角度uniform float uWidthSpan;//横向长度总跨度attribute vec3 aPosition;  //顶点位置attribute vec2 aTexCoor;    //顶点纹理坐标varying vec2 vTextureCoord;  //用于传递给片元着色器的变量void main(){   //计算X向波浪   float angleSpanH=4.0*3.14159265;//横向角度总跨度   float startX=-uWidthSpan/2.0;//起始X坐标   //根据横向角度总跨度、横向长度总跨度及当前点X坐标折算出当前点X坐标对应的角度   float currAngle=uStartAngle+((aPosition.x-startX)/uWidthSpan)*angleSpanH;   float tz=sin(currAngle)*0.1;   //根据总变换矩阵计算此次绘制此顶点位置   gl_Position = uMVPMatrix * vec4(aPosition.x,aPosition.y,tz,1);    // gl_Position = uMVPMatrix * vec4(aPosition.x,tz,aPosition.y,1);   vTextureCoord = aTexCoor;//将接收的纹理坐标传递给片元着色器}

斜向飘扬shader

uniform mat4 uMVPMatrix; //总变换矩阵uniform float uStartAngle;//本帧起始角度uniform float uWidthSpan;//横向长度总跨度attribute vec3 aPosition;  //顶点位置attribute vec2 aTexCoor;    //顶点纹理坐标varying vec2 vTextureCoord;  //用于传递给片元着色器的变量void main(){   //计算X向角度   float angleSpanH=4.0*3.14159265;//横向角度总跨度   float startX=-uWidthSpan/2.0;//起始X坐标   //根据横向角度总跨度、横向长度总跨度及当前点X坐标折算出当前点X坐标对应的角度   float currAngleH=uStartAngle+((aPosition.x-startX)/uWidthSpan)*angleSpanH;   //计算出随Y向发展起始角度的扰动值   float angleSpanZ=4.0*3.14159265;//纵向角度总跨度   float uHeightSpan=0.75*uWidthSpan;//纵向长度总跨度   float startY=-uHeightSpan/2.0;//起始Y坐标   //根据纵向角度总跨度、纵向长度总跨度及当前点Y坐标折算出当前点Y坐标对应的角度   float currAngleZ=((aPosition.y-startY)/uHeightSpan)*angleSpanZ;   //计算斜向波浪   float tzH=sin(currAngleH-currAngleZ)*0.1;   //根据总变换矩阵计算此次绘制此顶点位置   gl_Position = uMVPMatrix * vec4(aPosition.x,aPosition.y,tzH,1);   vTextureCoord = aTexCoor;//将接收的纹理坐标传递给片元着色器}
xy双向飘扬shader

uniform mat4 uMVPMatrix; //总变换矩阵uniform float uStartAngle;//本帧起始角度uniform float uWidthSpan;//横向长度总跨度attribute vec3 aPosition;  //顶点位置attribute vec2 aTexCoor;    //顶点纹理坐标varying vec2 vTextureCoord;  //用于传递给片元着色器的变量void main(){   //计算X向波浪   float angleSpanH=4.0*3.14159265;//横向角度总跨度   float startX=-uWidthSpan/2.0;//起始X坐标   //根据横向角度总跨度、横向长度总跨度及当前点X坐标折算出当前点X坐标对应的角度   float currAngleH=uStartAngle+((aPosition.x-startX)/uWidthSpan)*angleSpanH;   float tzH=sin(currAngleH)*0.1;   //计算Y向波浪   float angleSpanZ=4.0*3.14159265;//纵向角度总跨度   float uHeightSpan=0.75*uWidthSpan;//纵向长度总跨度   float startY=-uHeightSpan/2.0;//起始Y坐标   //根据纵向角度总跨度、纵向长度总跨度及当前点Y坐标折算出当前点Y坐标对应的角度   float currAngleZ=uStartAngle+3.14159265/3.0+((aPosition.y-startY)/uHeightSpan)*angleSpanZ;   float tzZ=sin(currAngleZ)*0.1;   //根据总变换矩阵计算此次绘制此顶点位置   gl_Position = uMVPMatrix * vec4(aPosition.x,aPosition.y,tzH+tzZ,1);   vTextureCoord = aTexCoor;//将接收的纹理坐标传递给片元着色器}

同时需要启动一个线程不断修改当前帧起始角度

package test.com.opengles_1_1;import java.nio.ByteBuffer;import java.nio.ByteOrder;import java.nio.FloatBuffer;import android.annotation.SuppressLint;import android.opengl.GLES20;/** * Created by hbin on 2016/11/1. * 有波浪效果的纹理矩形 */public class TextureRect {    int[] mPrograms=new int[3];//自定义渲染管线着色器程序id    int[] muMVPMatrixHandle=new int[3];//总变换矩阵引用    int[] maPositionHandle=new int[3]; //顶点位置属性引用    int[] maTexCoorHandle=new int[3]; //顶点纹理坐标属性引用    int[] maStartAngleHandle=new int[3]; //本帧起始角度属性引用    int[] muWidthSpanHandle=new int[3];//横向长度总跨度引用    int currIndex=0;//当前着色器索引    FloatBuffer   mVertexBuffer;//顶点坐标数据缓冲    FloatBuffer   mTexCoorBuffer;//顶点纹理坐标数据缓冲    int vCount=0;    final float WIDTH_SPAN=3.3f;//2.8f;//横向长度总跨度    float currStartAngle=0;//当前帧的起始角度0~2PI    public TextureRect(MySurfaceView mv)    {        //初始化顶点坐标与着色数据        initVertexData();        //初始化shader        initShader(mv,0,"vertex_tex_x.sh");        initShader(mv,1,"vertex_tex_xie.sh");        initShader(mv,2,"vertex_tex_xy.sh");        //启动一个线程定时换帧        new Thread()        {            public void run()            {                while(Constant.threadFlag)                {                    currStartAngle+=(float) (Math.PI/16);                    try                    {                        Thread.sleep(50);                    } catch (InterruptedException e)                    {                        e.printStackTrace();                    }                }            }        }.start();    }    private void initVertexData()    {        final int cols=12;//列数        final int rows=cols*3/4;//行数        final float UNIT_SIZE=WIDTH_SPAN/cols;//每格的单位长度        vCount=cols*rows*6;//每个格子两个三角形,每个三角形3个顶点        float vertices[]=new float[vCount*3];//每个顶点xyz三个坐标        int count=0;        for (int j=0;j<rows;j++){            for (int i=0;i<cols;i++){                float zsx=-UNIT_SIZE*cols/2+i*UNIT_SIZE;                float zsy=UNIT_SIZE*rows/2-j*UNIT_SIZE;                float zsz=0;                vertices[count++]=zsx;                vertices[count++]=zsy;                vertices[count++]=zsz;                vertices[count++]=zsx;                vertices[count++]=zsy-UNIT_SIZE;                vertices[count++]=zsz;                vertices[count++]=zsx+UNIT_SIZE;                vertices[count++]=zsy;                vertices[count++]=zsz;                vertices[count++]=zsx+UNIT_SIZE;                vertices[count++]=zsy;                vertices[count++]=zsz;                vertices[count++]=zsx;                vertices[count++]=zsy-UNIT_SIZE;                vertices[count++]=zsz;                vertices[count++]=zsx+UNIT_SIZE;                vertices[count++]=zsy-UNIT_SIZE;                vertices[count++]=zsz;            }        }        //创建顶点坐标数据缓冲        //vertices.length*4是因为一个整数四个字节        ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);        vbb.order(ByteOrder.nativeOrder());//设置字节顺序        mVertexBuffer = vbb.asFloatBuffer();//转换为Float型缓冲        mVertexBuffer.put(vertices);//向缓冲区中放入顶点坐标数据        mVertexBuffer.position(0);//设置缓冲区起始位置        //顶点纹理坐标数据的初始化================begin============================        float texCoor[]=generateTexCoor(cols,rows);        //创建顶点纹理坐标数据缓冲        ByteBuffer cbb = ByteBuffer.allocateDirect(texCoor.length*4);        cbb.order(ByteOrder.nativeOrder());//设置字节顺序        mTexCoorBuffer = cbb.asFloatBuffer();//转换为Float型缓冲        mTexCoorBuffer.put(texCoor);//向缓冲区中放入顶点着色数据        mTexCoorBuffer.position(0);//设置缓冲区起始位置    }    public void initShader(MySurfaceView mv,int index,String vertexName)    {        //加载顶点着色器的脚本内容        String mVertexShader=ShaderUtil.loadFromAssetsFile(vertexName, mv.getResources());        //加载片元着色器的脚本内容        String mFragmentShader=ShaderUtil.loadFromAssetsFile("frag_tex.sh", mv.getResources());        //基于顶点着色器与片元着色器创建程序        mPrograms[index] = ShaderUtil.createProgram(mVertexShader, mFragmentShader);        //获取程序中顶点位置属性引用        maPositionHandle[index] = GLES20.glGetAttribLocation(mPrograms[index], "aPosition");        //获取程序中顶点纹理坐标属性引用        maTexCoorHandle[index]= GLES20.glGetAttribLocation(mPrograms[index], "aTexCoor");        //获取程序中总变换矩阵引用        muMVPMatrixHandle[index] = GLES20.glGetUniformLocation(mPrograms[index], "uMVPMatrix");        //获取本帧起始角度属性引用        maStartAngleHandle[index]=GLES20.glGetUniformLocation(mPrograms[index], "uStartAngle");        //获取横向长度总跨度引用        muWidthSpanHandle[index]=GLES20.glGetUniformLocation(mPrograms[index], "uWidthSpan");    }    public void drawSelf(int texId)    {        //制定使用某套shader程序        GLES20.glUseProgram(mPrograms[currIndex]);        //将最终变换矩阵传入shader程序        GLES20.glUniformMatrix4fv(muMVPMatrixHandle[currIndex], 1, false, MatrixState.getFinalMatrix(), 0);        //将本帧起始角度传入shader程序        GLES20.glUniform1f(maStartAngleHandle[currIndex], currStartAngle);        //将横向长度总跨度传入shader程序        GLES20.glUniform1f(muWidthSpanHandle[currIndex], WIDTH_SPAN);        //将顶点位置数据传入渲染管线        GLES20.glVertexAttribPointer                (                        maPositionHandle[currIndex],                        3,                        GLES20.GL_FLOAT,                        false,                        3*4,                        mVertexBuffer                );        //将顶点纹理坐标数据传入渲染管线        GLES20.glVertexAttribPointer                (                        maTexCoorHandle[currIndex],                        2,                        GLES20.GL_FLOAT,                        false,                        2*4,                        mTexCoorBuffer                );        //启用顶点位置、纹理坐标数据        GLES20.glEnableVertexAttribArray(maPositionHandle[currIndex]);        GLES20.glEnableVertexAttribArray(maTexCoorHandle[currIndex]);        //绑定纹理        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texId);        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vCount);    }    //自动切分纹理产生纹理数组的方法    public float[] generateTexCoor(int bw,int bn)    {        float[] result=new float[bw*bn*6*2];        float sizew=1.0f/bw;//列数        float sizeh=0.75f/bn;//行数        int c=0;        for(int i=0;i<bn;i++)        {            for(int j=0;j<bw;j++)            {                //每行列一个矩形,由两个三角形构成,共六个点,12个纹理坐标                float s=j*sizew;                float t=i*sizeh;                //第一个纹理三角形                result[c++]=s;                result[c++]=t;                result[c++]=s;                result[c++]=t+sizeh;                result[c++]=s+sizew;                result[c++]=t;                //第二个纹理三角形                result[c++]=s+sizew;                result[c++]=t;                result[c++]=s;                result[c++]=t+sizeh;                result[c++]=s+sizew;                result[c++]=t+sizeh;            }        }        return result;    }}


完整代码下载地址

http://download.csdn.net/detail/hb707934728/9670345

0 0
原创粉丝点击