OpenGL ES2.0是无法直接绘制文字的,我采用的方法是将文字转为Bitmap,然后以图贴的方式进行渲染。看到网上也有人是将文字生成点,一个个进行绘制的,个人觉得这种方法还是挺麻烦的。文章分为两部分,一部分是在canvas中绘图转Bitmap,第二部分是贴图纹理绘制。
文字转Bitmap
这部分比较麻烦,网上介绍的canvas.drawText()的资料太多,看了都让人一头雾水,我也看了一天才明白。
- 基于文本的样式和大小,动态获取占用的宽度和高度
Paint p = new Paint();
p.setColor(glText.color);
p.setTypeface(glText.font);
p.setTextSize(glText.size);
//获取高度
Paint.FontMetricsInt metrics = p.getFontMetricsInt();
int height=metrics.bottom-metrics.top;
//获取宽度
Rect rect=new Rect();
p.getTextBounds(glText.text, 0, glText.text.length(), rect);
int width = rect.width();//文本的宽度
- 根据文字大小生成对应大小的Bitmap,如果统一Bitmap大小会出现文字变形和失真的现象。
//根据文字高度宽度生成bitmap
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
- 根据文字大小生成对应的OpenGL绘制矩形坐标范围大小
float mHeight=RADIO*this.height;
float mWidth=RADIO*this.width;
return new GLRectangle(glPoint,
new GLPoint(glPoint.getX(),glPoint.getY()+mHeight),
new GLPoint(glPoint.getX()+mWidth,glPoint.getY()+mHeight)
);
- 绘制背景色和文字,drawText()中的x,y设置比较麻烦,设置不正确容易文字显示不全,这里我采用的是
if (glText.backGroundColor != 0) {
//如果有背景色就绘制背景色
canvas.drawColor(glText.backGroundColor);
}
canvas.drawText(glText.text, 0,-metrics.ascent, p);
canvas.save();
OpenGL渲染绘制纹理图片
顶点着色器
final static String VERTEX =
"uniform mat4 u_Matrix;" +
"attribute vec4 a_Position;" +
"attribute vec2 a_TextureCoordinates;" +
"varying vec2 v_TextureCoordinates;" +
"void main()" +
"{" +
" gl_Position = u_Matrix * a_Position;" +
" v_TextureCoordinates = a_TextureCoordinates;" +
"}";
片元着色器
final static String FRAGMENT =
"precision mediump float;" +
"uniform sampler2D u_TextureUnit;" +
"varying vec2 v_TextureCoordinates;" +
"void main()" +
"{" +
" gl_FragColor = texture2D(u_TextureUnit, v_TextureCoordinates); \t\t\n" +
"}";
处理点数据
vertexData = ByteBuffer
.allocateDirect(data.length * BYTES_PER_FLOAT)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
vertexData.put(data);
pointCount = 4;
STRIDE = (POSITION_COMPONENT_COUNT + TEXTURE_COORDINATES_COMPONENT_COUNT) * BYTES_PER_FLOAT;
//开启颜色混合,解决图片背景黑色问题
glEnable(GL_BLEND);
// glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glPixelStorei(GL_UNPACK_ALIGNMENT,1);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
vertexShader = ShaderHelper.compileVertexShader(ShaderCode.VERTEX);
fragmentShader = ShaderHelper
.compileFragmentShader(ShaderCode.FRAGMENT);
program = ShaderHelper.linkProgram(vertexShader, fragmentShader);
glUseProgram(program);
aPositionLocation = glGetAttribLocation(program, A_POSITION);
uMatrixLocation = glGetUniformLocation(program, U_MATRIX);
uTextureUnitLocation = glGetUniformLocation(program, U_TEXTURE_UNIT);
aTextureCoordinatesLocation = glGetAttribLocation(program, A_TEXTURE_COORDINATES);
storeImage(bitmap);
glUniform1i(uTextureUnitLocation, 0);
vertexData.position(0);
glVertexAttribPointer(aPositionLocation, POSITION_COMPONENT_COUNT, GL_FLOAT,
false, STRIDE, vertexData);
glEnableVertexAttribArray(aPositionLocation);
vertexData.position(POSITION_COMPONENT_COUNT);
glVertexAttribPointer(aTextureCoordinatesLocation, TEXTURE_COORDINATES_COMPONENT_COUNT, GL_FLOAT,
false, STRIDE, vertexData);
glEnableVertexAttribArray(aTextureCoordinatesLocation);
//材质纹理处理
protected static void storeImage(Bitmap bitmap) {
int[] texture = new int[1];
glGenTextures(1, texture, 0);
glActiveTexture(GLES20.GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
glGenerateMipmap(GL_TEXTURE_2D);
bitmap.recycle();
}
//设置投影转换
glUniformMatrix4fv(uMatrixLocation, 1, false, matrix, 0);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
最后的效果图如下所示