android:GLSurfaceView绘制bitmap图片及glViewport调整的效果-亲测可用

215 篇文章 4 订阅

https://blog.csdn.net/nupt123456789/article/details/40375731

 

首先看一下GLSurfaceView是如何绘制的。正如android开发文档中描述的那样,我们需要new一个GLSurfaceView对象,然后设置一个实现了Renderer接口的对象,我们需要写一个MyRender类,实现Renderer的方法等等。我们先看一下Activity的写法。它不需要一个布局文件,我们将GLSurfaceView对象作为activity的contentview即可。如下:


package net.mobctrl.glsurfaceviewbmp;
 
import java.util.Random;
 
import android.annotation.SuppressLint;
import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.view.WindowManager;
 
/**
 * 
 * @author Zheng Haibo
 * @web http://www.mobctrl.net
 *
 */
public class MainActivity extends Activity {
 
    private GLSurfaceView glView; // Use GLSurfaceView
    Random rnd = new Random();
 
    @SuppressLint("NewApi")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setTheme(android.R.style.Theme_Translucent_NoTitleBar);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        glView = new GLSurfaceView(this); // Allocate a GLSurfaceView
        glView.setRenderer(new MyGLRenderer(this)); // Use a custom renderer
        glView.getAlpha();
        this.setContentView(glView); 
 
    }
 
    @Override
    protected void onPause() {
        super.onPause();
        glView.onPause();
    }
 
    @Override
    protected void onResume() {
        super.onResume();
        glView.onResume();
        android.provider.Settings.System.putInt(this.getContentResolver(),
                android.provider.Settings.System.SCREEN_BRIGHTNESS,
                rnd.nextInt(256));
 
    }
}

下面,我们主要看一下MyGLRender类的写法,它实现了Renderer接口,具体如下:

package net.mobctrl.glsurfaceviewbmp;
 
import java.util.Random;
 
import javax.microedition.khronos.opengles.GL10;
 
import android.content.Context;
import android.opengl.GLSurfaceView.Renderer;
import android.opengl.GLU;
 
/**
 * @date 2014年10月20日 下午2:49:17
 * @author Zheng Haibo
 * @Description: TODO
 */
public class MyGLRenderer implements Renderer {
    Context context; // Application's context
    Random r = new Random();
    //private Square square;
    private GLBitmap glBitmap;
    private int width = 0;
    private int height = 0;
    private long frameSeq = 0;
    private int viewportOffset = 0;
    private int maxOffset = 400;
 
    public MyGLRenderer(Context context) {
        this.context = context;
        //square = new Square();
        glBitmap = new GLBitmap();
    }
 
    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        if (height == 0) { // Prevent A Divide By Zero By
            height = 1; // Making Height Equal One
        }
        this.width = width;
        this.height = height;
        gl.glViewport(0, 0, width, height); // Reset The
                                            // Current
        // Viewport
        gl.glMatrixMode(GL10.GL_PROJECTION); // Select The Projection Matrix
        gl.glLoadIdentity(); // Reset The Projection Matrix
 
        // Calculate The Aspect Ratio Of The Window
        GLU.gluPerspective(gl, 45.0f, (float) width / (float) height, 0.1f,
                100.0f);
 
        gl.glMatrixMode(GL10.GL_MODELVIEW); // Select The Modelview Matrix
        gl.glLoadIdentity();
    }
 
    /**
     * 每隔16ms调用一次
     */
    @Override
    public void onDrawFrame(GL10 gl) {
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
        // Reset the Modelview Matrix
        gl.glLoadIdentity();
        gl.glTranslatef(0.0f, 0.0f, -5.0f); // move 5 units INTO the screen is
                                            // the same as moving the camera 5
                                            // units away
        // square.draw(gl);
        glBitmap.draw(gl);
        changeGLViewport(gl);
    }
 
    /**
     * 通过改变gl的视角获取
     * 
     * @param gl
     */
    private void changeGLViewport(GL10 gl) {
        System.out.println("time=" + System.currentTimeMillis());
        frameSeq++;
        viewportOffset++;
        // The
        // Current
        if (frameSeq % 100 == 0) {// 每隔100帧,重置
            gl.glViewport(0, 0, width, height);
            viewportOffset = 0;
        } else {
            int k = 4;
            gl.glViewport(-maxOffset + viewportOffset * k, -maxOffset
                    + viewportOffset * k, this.width - viewportOffset * 2 * k
                    + maxOffset * 2, this.height - viewportOffset * 2 * k
                    + maxOffset * 2);
        }
    }
 
    @Override
    public void onSurfaceCreated(GL10 gl,
            javax.microedition.khronos.egl.EGLConfig arg1) {
        glBitmap.loadGLTexture(gl, this.context);
 
        gl.glEnable(GL10.GL_TEXTURE_2D); // Enable Texture Mapping ( NEW )
        gl.glShadeModel(GL10.GL_SMOOTH); // Enable Smooth Shading
        gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black Background
        gl.glClearDepthf(1.0f); // Depth Buffer Setup
        gl.glEnable(GL10.GL_DEPTH_TEST); // Enables Depth Testing
        gl.glDepthFunc(GL10.GL_LEQUAL); // The Type Of Depth Testing To Do
 
        gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
    }
}

注意,这里主要实现了如下三个方法:onSurfaceCreated,onSurfaceChanged和onDrawFrame,其中,关键就是onDrawFrame方法,它的绘制机制是:1s的时间内,onDrawFrame方法会调用60次,大约每隔16ms调用一次。我们先看里面的glBitmap对象,changeGLViewport方法待会再说。

package net.mobctrl.glsurfaceviewbmp;
 
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
 
import javax.microedition.khronos.opengles.GL10;
 
import net.mobctrl.glsurfaceviewbmp.R;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLUtils;
 
/**
 * @date 2014年10月20日 下午3:09:33
 * @author Zheng Haibo
 * @Description: TODO
 */
public class GLBitmap {
    private FloatBuffer textureBuffer; // buffer holding the texture coordinates
    private float texture[] = {
            // Mapping coordinates for the vertices
            0.0f, 1.0f, // top left (V2)
            0.0f, 0.0f, // bottom left (V1)
            1.0f, 1.0f, // top right (V4)
            1.0f, 0.0f // bottom right (V3)
    };
 
    private FloatBuffer vertexBuffer; // buffer holding the vertices
 
    private float vertices[] = { -1.0f, -1.0f, 0.0f, // V1 - bottom left
            -1.0f, 1.0f, 0.0f, // V2 - top left
            1.0f, -1.0f, 0.0f, // V3 - bottom right
            1.0f, 1.0f, 0.0f // V4 - top right
    };
 
    public GLBitmap() {
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(vertices.length * 4);
        byteBuffer.order(ByteOrder.nativeOrder());
        vertexBuffer = byteBuffer.asFloatBuffer();
        vertexBuffer.put(vertices);
        vertexBuffer.position(0);
 
        byteBuffer = ByteBuffer.allocateDirect(texture.length * 4);
        byteBuffer.order(ByteOrder.nativeOrder());
        textureBuffer = byteBuffer.asFloatBuffer();
        textureBuffer.put(texture);
        textureBuffer.position(0);
    }
 
    /** The texture pointer */
    private int[] textures = new int[1];
 
    public void loadGLTexture(GL10 gl, Context context) {
        // loading texture
        Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(),
                R.drawable.plane_image);
 
        // generate one texture pointer
        gl.glGenTextures(1, textures, 0);
        // ...and bind it to our array
        gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
 
        // create nearest filtered texture
        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_LINEAR);
 
        // Use Android GLUtils to specify a two-dimensional texture image from
        // our bitmap
        GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
 
        // Clean up
        bitmap.recycle();
    }
 
    public void draw(GL10 gl) {
        // bind the previously generated texture
        gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
 
        // Point to our buffers
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
 
        // Set the face rotation
        gl.glFrontFace(GL10.GL_CW);
 
        // Point to our vertex buffer
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
        gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
 
        // Draw the vertices as triangle strip
        gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3);
 
        // Disable the client state before leaving
        gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
    }
 
}


从GLBitmap可以看出,我们首先需要加载一个图片资源,然后生成texture。在这里,特别说明一下changeGLViewport这个方法如果在MyRender里面去掉这个方法,运行结果是,GLSurfaceView绘制出一张图片。添加这个方法以后,则是周期性得绘制一个由远到近的一个“动画”。注意,这种动画,并没有改变图像本身,而且调整不通的视角产生的,因此效率很高。它的原理,就像你拿一个相机,去拍摄墙壁上得一幅画,相机离画越来越近时,画面在放大,而墙壁本身并没有变化。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在android.opengl.glsurfaceview显示立方体,需要进行以下步骤: 1. 首先,在项目的布局文件中添加一个GLSurfaceView的元素,用于显示OpenGL的内容: ``` <android.opengl.GLSurfaceView android:id="@+id/glsurfaceview" android:layout_width="match_parent" android:layout_height="match_parent" /> ``` 2. 在Activity或Fragment中,获取GLSurfaceView对象并设置Renderer: ``` GLSurfaceView glSurfaceView = findViewById(R.id.glsurfaceview); glSurfaceView.setEGLContextClientVersion(2); // 设置OpenGL ES版本 Renderer renderer = new CubeRenderer(); // 创建自定义的Renderer glSurfaceView.setRenderer(renderer); ``` 3. 创建一个自定义的Renderer类,用于绘制立方体: ``` public class CubeRenderer implements Renderer { private Cube cube; // 自定义的立方体类 @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { // 设置OpenGL的环境参数 GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); GLES20.glEnable(GLES20.GL_DEPTH_TEST); // 创建立方体对象 cube = new Cube(); } @Override public void onSurfaceChanged(GL10 gl, int width, int height) { // 设置OpenGL视口 GLES20.glViewport(0, 0, width, height); } @Override public void onDrawFrame(GL10 gl) { // 清除屏幕 GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); // 绘制立方体 cube.draw(); } } ``` 4. 创建一个Cube类,用于绘制立方体的顶点、纹理、颜色等信息: ``` public class Cube { // 定义顶点、纹理、颜色等数据 public void draw() { // 使用OpenGL方法绘制立方体 } } ``` 以上是在android.opengl.glsurfaceview显示立方体的基本步骤,具体的绘制立方体的代码需要根据具体需求进行实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值