一、OpenGL图片绘制的一般步骤:
1、编写顶点着色器和片元着色器;
2、编写需要绘制的图形类,包括:加载着色器脚本内容,加载图片数据,图片绘制;
3、配置绘制环境,绘制图片。
二、具体如下:
1、 编写顶点着色器程序(glsl语言):
attribute vec4 vPosition; attribute vec2 vCoordinate;//纹理数据 uniform mat4 vMatrix; //给片元传递数据(纹理,变换前的顶点,变换后的顶点) varying vec2 aCoordinate; varying vec4 aPos; varying vec4 gPosition; void main(){ gl_Position=vMatrix*vPosition; aPos=vPosition; aCoordinate=vCoordinate; gPosition=vMatrix*vPosition; }
2、 编写片元着色器程序(glsl语言):
precision mediump float; uniform sampler2D vTexture; uniform int vChangeType; uniform vec3 vChangeColor; uniform int vIsHalf; uniform float uXY; //给片元传递的数据(纹理数据,变换前顶点,变换后顶点) varying vec2 aCoordinate; varying vec4 aPos; varying vec4 gPosition; //修改颜色(防止颜色值超过一) void modifyColor(vec4 color){ color.r=max(min(color.r,1.0),0.0); color.g=max(min(color.g,1.0),0.0); color.b=max(min(color.b,1.0),0.0); color.a=max(min(color.a,1.0),0.0); } void main() { vec4 nColor=texture2D(vTexture,aCoordinate); if(aPos.x>0.0 || vIsHalf == 0){ if(vChangeType==1){ //浮点算法 Gray=R * 0.3+G * 0.59+B * 0.114 float gray=(nColor.r*0.3+nColor.g*0.59+nColor.b*0.114); gl_FragColor=vec4(gray,gray,gray,nColor.a); }else if(vChangeType==2){ vec4 colorWarm=nColor+vec4(0.1,0.1,0.0,0.0); modifyColor(colorWarm); gl_FragColor=colorWarm; }else if(vChangeType==3){ vec4 colorCold=nColor+vec4(0.0,0.0,0.1,0.0); modifyColor(colorCold); gl_FragColor=colorCold; }else if(vChangeType==4){ vec2 texSize = vec2(1500.0f,1500.0f); vec2 upTex=vec2(aCoordinate.x-1.0/texSize.x,aCoordinate.y-1.0/texSize.y); vec4 newTex=texture2D(vTexture,upTex); vec4 delTex=nColor-newTex; gl_FragColor=delTex; }else if(vChangeType==5){ gl_FragColor=texture2D(vTexture,vec2(1.0-aCoordinate.x,1.0-aCoordinate.y)); }else{ gl_FragColor=nColor; } }else{ gl_FragColor=nColor; } }
3、编写绘制图像类(java)
public class Image extends ShaderUtils { private FloatBuffer bPos; private FloatBuffer bCoord; //图片四个角的坐标 public final float[] sPos = { -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f }; //图片四个角的纹理坐标 public final float[] sCoord = { 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, }; private int mProgram; private int glHPosition; private int glHTexture; private int glHCoordinate; public int glHMatrix; private int hIsHalf; public int glHUxy; private int hChangeType; private int hChangeColor; public Image(GLSurfaceView mView) { initData(); initShader(mView); } private void initShader(GLSurfaceView mv) { /*//加载顶点着色器的脚本内容 String mVertexShader = loadFromAssetsFile("filter/vertex.glsl", mv.getResources()); //加载片元着色器的脚本内容 String mFragmentShader = loadFromAssetsFile("filter/fragment.glsl", mv.getResources()); mProgram=createProgram(mVertexShader,mFragmentShader);*/ mProgram=createProgram(mv.getResources(),"filter/vertex.glsl","filter/fragment.glsl"); glHPosition= GLES20.glGetAttribLocation(mProgram,"vPosition"); glHCoordinate=GLES20.glGetAttribLocation(mProgram,"vCoordinate"); glHTexture=GLES20.glGetUniformLocation(mProgram,"vTexture"); glHMatrix=GLES20.glGetUniformLocation(mProgram,"vMatrix"); hIsHalf=GLES20.glGetUniformLocation(mProgram,"vIsHalf"); glHUxy=GLES20.glGetUniformLocation(mProgram,"uXY"); hChangeType=GLES20.glGetUniformLocation(mProgram,"vChangeType"); hChangeColor=GLES20.glGetUniformLocation(mProgram,"vChangeColor"); } private void initData() { bPos = getFloatBuffer(sPos); bCoord = getFloatBuffer(sCoord); } private int count=1; public float[][] images = new float[][]{ {0.0f, 0.0f, 0.0f}//原图 , {0.299f, 0.587f, 0.114f}//灰度 , {0.1f, 0.1f, 0.0f}//暖色调 , {0.0f, 0.0f, 0.1f}//冷色调 , {0.2125f, 0.7154f, 0.0721f}//浮雕 , {0.0f, 0.0f, 0.0f} , {0.0f, 0.0f, 0.0f} , {0.0f, 0.0f, 0.0f} }; public void drawSelf(int textureId) { GLES20.glUseProgram(mProgram); GLES20.glUniform1i(hChangeType,count); GLES20.glUniform3fv(hChangeColor,1,images[count],0); GLES20.glUniform1i(hIsHalf,0); GLES20.glEnableVertexAttribArray(glHPosition); GLES20.glEnableVertexAttribArray(glHCoordinate); GLES20.glUniform1i(glHTexture,0); GLES20.glVertexAttribPointer(glHPosition,2,GLES20.GL_FLOAT,false,0,bPos); GLES20.glVertexAttribPointer(glHCoordinate,2,GLES20.GL_FLOAT,false,0,bCoord); GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP,0,4); } }
这个里面的ShaderUtils是编写好的工具类,作用是加载着色器程序。
4、编写渲染类SGLView(java)
public class SGLView extends GLSurfaceView implements GLSurfaceView.Renderer{ private Image image; private int textureId; private Bitmap mBitmap; private float uXY; private float[] mViewMatrix = new float[16]; private float[] mProjectMatrix = new float[16]; private float[] mMVPMatrix = new float[16]; public SGLView(Context context) { super(context); init(); } private void init() { setEGLContextClientVersion(2); setRenderer(this); setRenderMode(RENDERMODE_CONTINUOUSLY); } @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { GLES20.glClearColor(1.0f,1.0f,1.0f,1.0f); GLES20.glEnable(GLES20.GL_TEXTURE_2D); image = new Image(this); textureId = createTexture(); } //创建纹理 private int createTexture() { mBitmap = BitmapFactory.decodeResource(this.getResources(), R.drawable.girl); int[] texture = new int[1]; if(mBitmap != null && !mBitmap.isRecycled()){ //生成纹理 GLES20.glGenTextures(1,texture,0); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,texture[0]); GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_MIN_FILTER,GLES20.GL_NEAREST); GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_MAG_FILTER,GLES20.GL_LINEAR); GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_WRAP_S,GLES20.GL_CLAMP_TO_EDGE); GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_WRAP_T,GLES20.GL_CLAMP_TO_EDGE); //根据以上参数,生成纹理 GLUtils.texImage2D(GLES20.GL_TEXTURE_2D,0,mBitmap,0); return texture[0]; } return 0; } @Override public void onSurfaceChanged(GL10 gl, int width, int height) { GLES20.glViewport(0,0,width,height); int w = mBitmap.getWidth(); int h = mBitmap.getHeight(); float swh = (float)w/h; float sWH = (float)width/height; uXY = sWH; if(sWH > swh){ Matrix.orthoM(mProjectMatrix,0,-1,1,-swh/sWH,swh/sWH,3,5); }else{ Matrix.orthoM(mProjectMatrix,0,-1,1,-sWH/swh,sWH/swh,3,5); } //设置相机的位置 Matrix.setLookAtM(mViewMatrix,0,0,0,5.0f,0,0,0,0,1.0f,0); //计算变换矩阵 Matrix.multiplyMM(mMVPMatrix,0,mProjectMatrix,0,mViewMatrix,0); } @Override public void onDrawFrame(GL10 gl) { GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT|GLES20.GL_DEPTH_BUFFER_BIT); GLES20.glUniform1f(image.glHUxy, uXY); GLES20.glUniformMatrix4fv(image.glHMatrix, 1, false, mMVPMatrix, 0); image.drawSelf(textureId); } }
5、在Activity中加载SGLView
public class Main2Activity extends AppCompatActivity { private SGLView sView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); sView = new SGLView(this); setContentView(sView); } @Override protected void onResume() { super.onResume(); sView.onResume(); } @Override protected void onPause() { super.onPause(); sView.onPause(); } }