Android ApiDemos 里有个LabelMaker, 封装了OpenGl 的text lables的生产和显示,用起来非常方便:

LabelMaker: OpenGL text labels通过创建Bitmap、将所有text labels绘制到Bitmap、将Bitmap转换为alpha texture 以及使用gldrawtexios绘制部分texture来实现。

 

Example code:

import android.app.Activity;import android.graphics.Paint;import android.opengl.GLSurfaceView;import android.os.Bundle;import javax.microedition.khronos.egl.EGLConfig;import javax.microedition.khronos.opengles.GL10;public class TextLablesActivity extends Activity implements GLSurfaceView.Renderer{    private GLSurfaceView mGLView;    private LabelMaker mLabels;    private int mWidth;    private int mHeight;    private int mLabelId1;  //text label id    private int mLabelId2;  //text label id    @Override    protected void onCreate( Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        mGLView = new GLSurfaceView(this);        mGLView.setRenderer(this);        setContentView(mGLView);    }    @Override    public void onDrawFrame(GL10 gl) {        mLabels.beginDrawing(gl,mWidth,mHeight);        mLabels.draw(gl,600,600, mLabelId1);     //指定坐标,显示label 1         mLabels.draw(gl,600,700, mLabelId2);     //指定坐标,显示label 2        mLabels.endDrawing(gl);    }    @Override    public void onSurfaceCreated(GL10 gl, EGLConfig config) {        //调用LabelMaker 生成text label        mLabels = new LabelMaker(true, 1080, 256); //Bitmap的宽和高, 可以根据你的text lable来调整大小        Paint labelPaint = new Paint();  //text label的画笔        labelPaint.setTextSize(32);        labelPaint.setAntiAlias(true);        labelPaint.setARGB(0xff, 0xff, 0x00, 0x00);        mLabels.initialize(gl);        mLabels.beginAdding(gl);        mLabelId1 = mLabels.add(gl,"OpenGL 显示的文字",labelPaint);  //add lable1        mLabelId2 = mLabels.add(gl,"Hello world !",labelPaint);  //add label2        mLabels.endAdding(gl);    }    @Override    public void onSurfaceChanged(GL10 gl, int width, int height) {        mWidth = width;        mHeight = height;        gl.glViewport(0, 0, width, height);        float ratio = (float) width / height;        gl.glMatrixMode(GL10.GL_PROJECTION);        gl.glLoadIdentity();        gl.glFrustumf(-ratio, ratio, -1, 1, 1, 15);        gl.glMatrixMode(GL10.GL_MODELVIEW);        gl.glLoadIdentity();    }}

 

LabelMaker code:

import android.graphics.Bitmap;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.Rect;import android.graphics.Paint.Style;import android.graphics.drawable.Drawable;import android.opengl.GLUtils;import java.util.ArrayList;import javax.microedition.khronos.opengles.GL10;import javax.microedition.khronos.opengles.GL11;import javax.microedition.khronos.opengles.GL11Ext;/** * An OpenGL text label maker. * * * OpenGL labels are implemented by creating a Bitmap, drawing all the labels * into the Bitmap, converting the Bitmap into an Alpha texture, and drawing * portions of the texture using glDrawTexiOES. * * The benefits of this approach are that the labels are drawn using the high * quality anti-aliased font rasterizer, full character set support, and all the * text labels are stored on a single texture, which makes it faster to use. * * The drawbacks are that you can only have as many labels as will fit onto one * texture, and you have to recreate the whole texture if any label text * changes. * */public class LabelMaker {    /**     * Create a label maker     * or maximum compatibility with various OpenGL ES implementations,     * the strike width and height must be powers of two,     * We want the strike width to be at least as wide as the widest window.     *     * @param fullColor true if we want a full color backing store (4444),     * otherwise we generate a grey L8 backing store.     * @param strikeWidth width of strike     * @param strikeHeight height of strike     */    public LabelMaker(boolean fullColor, int strikeWidth, int strikeHeight) {        mFullColor = fullColor;        mStrikeWidth = strikeWidth;        mStrikeHeight = strikeHeight;        mTexelWidth = (float) (1.0 / mStrikeWidth);        mTexelHeight = (float) (1.0 / mStrikeHeight);        mClearPaint = new Paint();        mClearPaint.setARGB(0, 0, 0, 0);        mClearPaint.setStyle(Style.FILL);        mState = STATE_NEW;    }    /**     * Call to initialize the class.     * Call whenever the surface has been created.     *     * @param gl     */    public void initialize(GL10 gl) {        mState = STATE_INITIALIZED;        int[] textures = new int[1];        gl.glGenTextures(1, textures, 0);        mTextureID = textures[0];        gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureID);        // Use Nearest for performance.        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,                GL10.GL_NEAREST);        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER,                GL10.GL_NEAREST);        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,                GL10.GL_CLAMP_TO_EDGE);        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,                GL10.GL_CLAMP_TO_EDGE);        gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE,                GL10.GL_REPLACE);    }    /**     * Call when the surface has been destroyed     */    public void shutdown(GL10 gl) {        if ( gl != null) {            if (mState > STATE_NEW) {                int[] textures = new int[1];                textures[0] = mTextureID;                gl.glDeleteTextures(1, textures, 0);                mState = STATE_NEW;            }        }    }    /**     * Call before adding labels. Clears out any existing labels.     *     * @param gl     */    public void beginAdding(GL10 gl) {        checkState(STATE_INITIALIZED, STATE_ADDING);        mLabels.clear();        mU = 0;        mV = 0;        mLineHeight = 0;        Bitmap.Config config = mFullColor ?                Bitmap.Config.ARGB_4444 : Bitmap.Config.ALPHA_8;        mBitmap = Bitmap.createBitmap(mStrikeWidth, mStrikeHeight, config);        mCanvas = new Canvas(mBitmap);        mBitmap.eraseColor(0);    }    /**     * Call to add a label     *     * @param gl     * @param text the text of the label     * @param textPaint the paint of the label     * @return the id of the label, used to measure and draw the label     */    public int add(GL10 gl, String text, Paint textPaint) {        return add(gl, null, text, textPaint);    }    /**     * Call to add a label     *     * @param gl     * @param text the text of the label     * @param textPaint the paint of the label     * @return the id of the label, used to measure and draw the label     */    public int add(GL10 gl, Drawable background, String text, Paint textPaint) {        return add(gl, background, text, textPaint, 0, 0);    }    /**     * Call to add a label     * @return the id of the label, used to measure and draw the label     */    public int add(GL10 gl, Drawable drawable, int minWidth, int minHeight) {        return add(gl, drawable, null, null, minWidth, minHeight);    }    /**     * Call to add a label     *     * @param gl     * @param text the text of the label     * @param textPaint the paint of the label     * @return the id of the label, used to measure and draw the label     */    public int add(GL10 gl, Drawable background, String text, Paint textPaint,            int minWidth, int minHeight) {        checkState(STATE_ADDING, STATE_ADDING);        boolean drawBackground = background != null;        boolean drawText = (text != null) && (textPaint != null);        Rect padding = new Rect();        if (drawBackground) {            background.getPadding(padding);            minWidth = Math.max(minWidth, background.getMinimumWidth());            minHeight = Math.max(minHeight, background.getMinimumHeight());        }        int ascent = 0;        int descent = 0;        int measuredTextWidth = 0;        if (drawText) {            // Paint.ascent is negative, so negate it.            ascent = (int) Math.ceil(-textPaint.ascent());            descent = (int) Math.ceil(textPaint.descent());            measuredTextWidth = (int) Math.ceil(textPaint.measureText(text));        }        int textHeight = ascent + descent;        int textWidth = Math.min(mStrikeWidth,measuredTextWidth);        int padHeight = padding.top + padding.bottom;        int padWidth = padding.left + padding.right;        int height = Math.max(minHeight, textHeight + padHeight);        int width = Math.max(minWidth, textWidth + padWidth);        int effectiveTextHeight = height - padHeight;        int effectiveTextWidth = width - padWidth;        int centerOffsetHeight = (effectiveTextHeight - textHeight) / 2;        int centerOffsetWidth = (effectiveTextWidth - textWidth) / 2;        // Make changes to the local variables, only commit them        // to the member variables after we've decided not to throw        // any exceptions.        int u = mU;        int v = mV;        int lineHeight = mLineHeight;        if (width > mStrikeWidth) {            width = mStrikeWidth;        }        // Is there room for this string on the current line?        if (u + width > mStrikeWidth) {            // No room, go to the next line:            u = 0;            v += lineHeight;            lineHeight = 0;        }        lineHeight = Math.max(lineHeight, height);        if (v + lineHeight > mStrikeHeight) {            throw new IllegalArgumentException("Out of texture space.");        }        int u2 = u + width;        int vBase = v + ascent;        int v2 = v + height;        if (drawBackground) {            background.setBounds(u, v, u + width, v + height);            background.draw(mCanvas);        }        if (drawText) {            mCanvas.drawText(text,                    u + padding.left + centerOffsetWidth,                    vBase + padding.top + centerOffsetHeight,                    textPaint);        }        // We know there's enough space, so update the member variables        mU = u + width;        mV = v;        mLineHeight = lineHeight;        mLabels.add(new Label(width, height, ascent,                u, v + height, width, -height));        return mLabels.size() - 1;    }    /**     * Call to end adding labels. Must be called before drawing starts.     *     * @param gl     */    public void endAdding(GL10 gl) {        checkState(STATE_ADDING, STATE_INITIALIZED);        gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureID);        GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, mBitmap, 0);        // Reclaim storage used by bitmap and canvas.        mBitmap.recycle();        mBitmap = null;        mCanvas = null;    }    /**     * Get the width in pixels of a given label.     *     * @param labelID     * @return the width in pixels     */    public float getWidth(int labelID) {        return mLabels.get(labelID).width;    }    /**     * Get the height in pixels of a given label.     *     * @param labelID     * @return the height in pixels     */    public float getHeight(int labelID) {        return mLabels.get(labelID).height;    }    /**     * Get the baseline of a given label. That's how many pixels from the top of     * the label to the text baseline. (This is equivalent to the negative of     * the label's paint's ascent.)     *     * @param labelID     * @return the baseline in pixels.     */    public float getBaseline(int labelID) {        return mLabels.get(labelID).baseline;    }    /**     * Begin drawing labels. Sets the OpenGL state for rapid drawing.     *     * @param gl     * @param viewWidth     * @param viewHeight     */    public void beginDrawing(GL10 gl, float viewWidth, float viewHeight) {        checkState(STATE_INITIALIZED, STATE_DRAWING);        gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureID);        gl.glShadeModel(GL10.GL_FLAT);        gl.glEnable(GL10.GL_BLEND);        gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);        gl.glColor4x(0x10000, 0x10000, 0x10000, 0x10000);        gl.glMatrixMode(GL10.GL_PROJECTION);        gl.glPushMatrix();        gl.glLoadIdentity();        gl.glOrthof(0.0f, viewWidth, 0.0f, viewHeight, 0.0f, 1.0f);        gl.glMatrixMode(GL10.GL_MODELVIEW);        gl.glPushMatrix();        gl.glLoadIdentity();        // Magic offsets to promote consistent rasterization.        gl.glTranslatef(0.375f, 0.375f, 0.0f);    }    /**     * Draw a given label at a given x,y position, expressed in pixels, with the     * lower-left-hand-corner of the view being (0,0).     *     * @param gl     * @param x     * @param y     * @param labelID     */    public void draw(GL10 gl, float x, float y, int labelID) {        checkState(STATE_DRAWING, STATE_DRAWING);        Label label = mLabels.get(labelID);        gl.glEnable(GL10.GL_TEXTURE_2D);        ((GL11)gl).glTexParameteriv(GL10.GL_TEXTURE_2D,                GL11Ext.GL_TEXTURE_CROP_RECT_OES, label.mCrop, 0);        ((GL11Ext)gl).glDrawTexiOES((int) x, (int) y, 0,                (int) label.width, (int) label.height);    }    /**     * Ends the drawing and restores the OpenGL state.     *     * @param gl     */    public void endDrawing(GL10 gl) {        checkState(STATE_DRAWING, STATE_INITIALIZED);        gl.glDisable(GL10.GL_BLEND);        gl.glMatrixMode(GL10.GL_PROJECTION);        gl.glPopMatrix();        gl.glMatrixMode(GL10.GL_MODELVIEW);        gl.glPopMatrix();    }    private void checkState(int oldState, int newState) {        if (mState != oldState) {            throw new IllegalArgumentException("Can't call this method now.");        }        mState = newState;    }    private static class Label {        public Label(float width, float height, float baseLine,                int cropU, int cropV, int cropW, int cropH) {            this.width = width;            this.height = height;            this.baseline = baseLine;            int[] crop = new int[4];            crop[0] = cropU;            crop[1] = cropV;            crop[2] = cropW;            crop[3] = cropH;            mCrop = crop;        }        public float width;        public float height;        public float baseline;        public int[] mCrop;    }    private int mStrikeWidth;    private int mStrikeHeight;    private boolean mFullColor;    private Bitmap mBitmap;    private Canvas mCanvas;    private Paint mClearPaint;    private int mTextureID;    private float mTexelWidth;  // Convert texel to U    private float mTexelHeight; // Convert texel to V    private int mU;    private int mV;    private int mLineHeight;    private ArrayList

 

更多相关文章

  1. Android(安卓)adb devices显示no permission
  2. Graphical layout无法正确显示的解决方法
  3. 浅谈Android的BaseAdapter适配器模式
  4. android 控制软键盘显示和隐藏
  5. Android(安卓)Studio中TextView文本过长滚动显示方法
  6. 暂时只会这种导航,实时显示自己的位置,,求其他更好的方法,或api
  7. Android实现图片 高斯模糊,以及图片镜像 翻转。
  8. MPAndroidChart项目实战(四)——柱状图实现及X轴文字不显示问题和
  9. android开发之修改ListView默认滑动条样式

随机推荐

  1. 在Vue3中使用Provide / Inject
  2. 巧用状态伪类:让你的链接不尴尬
  3. JavaScript初学习之常量、变量、函数、匿
  4. Detach RDM Luns from single ESXi host
  5. Java与php的一些关联
  6. Druid源码分析与架构介绍
  7. 全息电力行业解决方案
  8. 1209表格
  9. 1209列表元素
  10. 我的第27个代码