opengles显示一个图片的大概步骤
这个文章主要是帮助自己记住以下一些函数,opengles很有套路,如果要了解具体如何显示一个图片,还是自行百度看其他文章吧!
1.着色器编写
precision mediump float;
uniform sampler2D vTexture;
varying vec2 aCoordinate;
void main(){
gl_FragColor=texture2D(vTexture,aCoordinate);
}
attribute vec4 vPosition;
attribute vec2 vCoordinate;
uniform mat4 vMatrix;
varying vec2 aCoordinate;
void main(){
gl_Position=vMatrix*vPosition;
aCoordinate=vCoordinate;
}
先初始化一些数据
private final float[]sPos={
-1.0f,1.0f,
-1.0f,-1.0f,
1.0f,1.0f,
1.0f,-1.0f
};
//这个是纹理坐标,纹理坐标是0-1和位置坐标不一样
private final float[]sCoord={
0.0f,0.0f,
0.0f,1.0f,
1.0f,0.0f,
1.0f,1.0f,
};
ByteBufferbb=ByteBuffer.allocateDirect(sPos.length*4);
bb.order(ByteOrder.nativeOrder());
bPos=bb.asFloatBuffer();
bPos.put(sPos);
bPos.position(0);
ByteBuffer cc=ByteBuffer.allocateDirect(sCoord.length*4);
cc.order(ByteOrder.nativeOrder());
bCoord=cc.asFloatBuffer();
bCoord.put(sCoord);
bCoord.position(0);
public static int createProgram(String vertexSource,String fragmentSource){
intvertex=loadShader(GLES20.GL_VERTEX_SHADER,vertexSource);
if(vertex==0)return0;intfragment=loadShader(GLES20.GL_FRAGMENT_SHADER,fragmentSource);
if(fragment==0)return0;intprogram= GLES20.glCreateProgram();
if(program!=0){
GLES20.glAttachShader(program,vertex);
checkGLError("Attach Vertex Shader");
GLES20.glAttachShader(program,fragment);
checkGLError("Attach Fragment Shader");
GLES20.glLinkProgram(program);
int[] linkStatus=new int[1];
GLES20.glGetProgramiv(program,GLES20.GL_LINK_STATUS,linkStatus,0);
if(linkStatus[0]!= GLES20.GL_TRUE){}
Log.e(TAG,"Could not link program:"+ GLES20.glGetProgramInfoLog(program));
GLES20.glDeleteProgram(program);
program=0;
}
}
returnprogram;}
onSurfaceCreated中的代码实现:
public voidonSurfaceCreated(GL10 gl,EGLConfig config) {
GLES20.glClearColor(1.0f,1.0f,1.0f,1.0f);
GLES20.glEnable(GLES20.GL_TEXTURE_2D);
mProgram=createProgram(vertex,fragment);
glHPosition=GLES20.glGetAttribLocation(mProgram,"vPosition");
glHCoordinate=GLES20.glGetAttribLocation(mProgram,"vCoordinate");
glHTexture=GLES20.glGetUniformLocation(mProgram,"vTexture");
glHMatrix=GLES20.glGetUniformLocation(mProgram,"vMatrix");
glHUxy=GLES20.glGetUniformLocation(mProgram,"uXY");
hChangeType=GLES20.glGetUniformLocation(mProgram,"vChangeType");
hChangeColor=GLES20.glGetUniformLocation(mProgram,"vChangeColor");
}
onSurfaceChanged实现:
public voidonSurfaceChanged(GL10 gl, intwidth, intheight) {
GLES20.glViewport(0,0,width,height);
//直接用了surface的宽高,实际图片和这个宽高之间是需要处理的
Matrix.orthoM(mProjectMatrix,0,intwidth,intheight,1,3,5);
//设置相机位置
Matrix.setLookAtM(mViewMatrix,0,0,0,5.0f,0f,0f,0f,0f,1.0f,0.0f);
//计算变换矩阵
Matrix.multiplyMM(mMVPMatrix,0,mProjectMatrix,0,mViewMatrix,0);
}
最后onDrawFrame函数实现
public voidonDrawFrame(GL10 gl) {
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT|GLES20.GL_DEPTH_BUFFER_BIT);
GLES20.glUseProgram(mProgram);
GLES20.glUniformMatrix4fv(glHMatrix,1,false,mMVPMatrix,0);
GLES20.glEnableVertexAttribArray(glHPosition);
GLES20.glEnableVertexAttribArray(glHCoordinate);
//使采样器 vTexture 读取 0号 纹理单元的纹理,createTexture将创建0号单元
GLES20.glUniform1i(glHTexture,0);
textureId=createTexture();
//准备坐标数据和颜色数据
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);
}
private intcreateTexture(){
int[] texture=new int[1];
if(mBitmap!=null&&!mBitmap.isRecycled()){
//生成纹理
GLES20.glGenTextures(1,texture,0);
//激活这个纹理
GLES20.glActiveTexture(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);
//设置环绕方向S,截取纹理坐标到[1/2n,1-1/2n]。将导致永远不会与border融合
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_WRAP_S,GLES20.GL_CLAMP_TO_EDGE);
//设置环绕方向T,截取纹理坐标到[1/2n,1-1/2n]。将导致永远不会与border融合
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_WRAP_T,GLES20.GL_CLAMP_TO_EDGE);
//根据以上指定的参数,生成一个2D纹理, 还有个GLES20.glTexImage2D函数
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D,0,mBitmap,0);
return texture[0];
}
return0;
}
总结:所有的代码都是围绕着着色器代码来写的,就是给着色器里面的代码进行赋值,图片和画三角形的区别就是,片段着色器里面对于图片,需要传入纹理坐标gl_FragColor=texture2D(vTexture,aCoordinate);而三角形的话,直接用一个vec4 color就可以了。纹理坐标传入是通过GLES20.glUniform1i(glHTexture,0)来传递的。