这是老师布置的课后作业,闲来无事分享出来,也加深一遍自己的印象~
自己定义一个MyRenderer.java类:
package com.example.shiyan3_2;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLSurfaceView.Renderer;
import android.opengl.GLUtils;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
public class MyRenderer implements Renderer
{
// 定义三棱椎的4个顶点
float[] taperVertices = new float[] {
0.0f, 0.5f, 0.0f,
-0.5f, -0.5f, -0.2f,
0.5f, -0.5f, -0.2f,
0.0f, -0.2f, 0.2f
};
// 定义三棱椎的4个三角面(没有使用)
private byte[] taperFacets = new byte[]{
0, 1, 2, // 0、1、2三个顶点组成一个面
0, 1, 3, // 0、1、3三个顶点组成一个面
1, 2, 3, // 1、2、3三个顶点组成一个面
0, 2, 3 // 0、2、3三个顶点组成一个面
};
//定义纹理贴图的坐标数据
private float[] taperTextures = {
1.0000f,1.0000f,
1.0000f,0.0000f,
0.0000f,0.0000f,
0.0000f,1.0000f
};
// 分别定义三棱椎的4个三角面
ByteBuffer i1=ByteBuffer.wrap(new byte[]{
0,1,2,
});
ByteBuffer i2=ByteBuffer.wrap(new byte[]{
0,1,3,
});
ByteBuffer i3=ByteBuffer.wrap(new byte[]{
1,2,3
});
ByteBuffer i4=ByteBuffer.wrap(new byte[]{
0,2,3,
});
Context context;
// 定义Open GL ES绘制所需要的Buffer对象
FloatBuffer taperVerticesBuffer;
//IntBuffer taperColorsBuffer;
ByteBuffer taperFacetsBuffer;
FloatBuffer taperTexturesBuffer;
// 控制旋转的角度
private float rotate;
//定义本程序所使用的纹理
private int texture;
public MyRenderer(Context main)
{
this.context = main;
// 将三棱椎的顶点位置数据数组包装成FloatBuffer
taperVerticesBuffer = floatBufferUtil(taperVertices);
// 将三棱椎的4个面的数组包装成ByteBuffer
taperFacetsBuffer = ByteBuffer.wrap(taperFacets);
//将立方体的纹理贴图的坐标数据包装成FLoatBuffer
taperTexturesBuffer = floatBufferUtil(taperTextures);
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config)
{
// 关闭抗抖动
gl.glDisable(GL10.GL_DITHER);
// 设置系统对透视进行修正
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
gl.glClearColor(0, 0, 0, 0);
// 设置阴影平滑模式
gl.glShadeModel(GL10.GL_SMOOTH);
// 启用深度测试
gl.glEnable(GL10.GL_DEPTH_TEST);
// 设置深度测试的类型
gl.glDepthFunc(GL10.GL_LEQUAL);
//启用2D纹理贴图
gl.glEnable(GL10.GL_TEXTURE_2D);
//装载纹理
loadTexture(gl);
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height)
{
// 设置3D视窗的大小及位置
gl.glViewport(0, 0, width, height);
// 将当前矩阵模式设为投影矩阵
gl.glMatrixMode(GL10.GL_PROJECTION);
// 初始化单位矩阵
gl.glLoadIdentity();
// 计算透视视窗的宽度、高度比
float ratio = (float) width / height;
// 调用此方法设置透视视窗的空间大小。
gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
}
// 绘制图形的方法
int[] tex_id = new int[4];
@Override
public void onDrawFrame(GL10 gl)
{
// 清除屏幕缓存和深度缓存
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
// 启用顶点坐标数据
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
//启用贴图坐标数组数据
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); // ①
// 设置当前矩阵模式为模型视图。
gl.glMatrixMode(GL10.GL_MODELVIEW);
// --------------------绘制图形---------------------
// 重置当前的模型视图矩阵
gl.glLoadIdentity();
gl.glTranslatef(0.0f, 0.0f, -1.5f);
// 沿着Y轴旋转
gl.glRotatef(rotate, 0f, 0.2f, 0f);
// 设置顶点的位置数据
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, taperVerticesBuffer);
//设置贴图的坐标数据
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, taperTexturesBuffer); // ②
//执行纹理贴图
gl.glBindTexture(GL10.GL_TEXTURE_2D, tex_id[0]); // ③
// 按taperFacetsBuffer指定的面绘制三角形
gl.glDrawElements(GL10.GL_TRIANGLE_STRIP
, i1.remaining(),
GL10.GL_UNSIGNED_BYTE, i1);
gl.glBindTexture(GL10.GL_TEXTURE_2D, tex_id[1]); // ③
// 按taperFacetsBuffer指定的面绘制三角形
gl.glDrawElements(GL10.GL_TRIANGLE_STRIP
, i2.remaining(),
GL10.GL_UNSIGNED_BYTE, i2);
gl.glBindTexture(GL10.GL_TEXTURE_2D, tex_id[2]); // ③
// 按taperFacetsBuffer指定的面绘制三角形
gl.glDrawElements(GL10.GL_TRIANGLE_STRIP
, i3.remaining(),
GL10.GL_UNSIGNED_BYTE, i3);
gl.glBindTexture(GL10.GL_TEXTURE_2D, tex_id[3]); // ③
// 按taperFacetsBuffer指定的面绘制三角形
gl.glDrawElements(GL10.GL_TRIANGLE_STRIP
, i4.remaining(),
GL10.GL_UNSIGNED_BYTE, i4);
// 绘制结束
gl.glFinish();
//禁用顶点、纹理坐标数组
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
// 旋转角度增加1
rotate+=1;
}
private void loadTexture(GL10 gl){
// 加载位图
Bitmap[] bm = new Bitmap[4];
bm[0]=BitmapFactory.decodeResource(context.getResources(),
R.drawable.img1);
bm[1]=BitmapFactory.decodeResource(context.getResources(),
R.drawable.img2);
bm[2]=BitmapFactory.decodeResource(context.getResources(),
R.drawable.img3);
bm[3]=BitmapFactory.decodeResource(context.getResources(),
R.drawable.img4);
try{
int[] textures = new int[1];
// 指定生成N个纹理(第一个参数指定生成一个纹理)
// textures数组将负责存储所有纹理的代号
IntBuffer textureBuffer = IntBuffer.allocate(4);
gl.glGenTextures(4,textureBuffer);
tex_id = textureBuffer.array();
for(int i=0;i<4;i++){
// 获取textures纹理数组中的第一个纹理
//texture = textures[i];
// 通知OpenGL将texture纹理绑定到GL10.GL_TEXTURE_2D目标中
gl.glBindTexture(GL10.GL_TEXTURE_2D, tex_id[i]);
//gl.glBindTexture(GL10.GL_TEXTURE_2D, 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);
// 设置在横向、纵向上都是平铺纹理
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,
GL10.GL_REPEAT);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,
GL10.GL_REPEAT);
// 加载位图生成纹理
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bm[i], 0);
if (bm[i] != null)
bm[i].recycle();
}
}
finally {
//生成纹理之后,回收位图
}
}
// 定义一个工具方法,将float[]数组转换为OpenGL ES所需的FloatBuffer
private FloatBuffer floatBufferUtil(float[] arr)
{
FloatBuffer mBuffer;
// 初始化ByteBuffer,长度为arr数组的长度*4,因为一个int占4个字节
ByteBuffer qbb = ByteBuffer.allocateDirect(arr.length * 4);
// 数组排列用nativeOrder
qbb.order(ByteOrder.nativeOrder());
mBuffer = qbb.asFloatBuffer();
mBuffer.put(arr);
mBuffer.position(0);
return mBuffer;
}
}
接下来是MainActivity.java:
package com.example.shiyan3_2;
import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
public class MainActivity extends Activity
{
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// 创建一个GLSurfaceView,用于显示OpenGL绘制的图形
GLSurfaceView glView = new GLSurfaceView(this);
// 创建GLSurfaceView的内容绘制器
MyRenderer myRender = new MyRenderer(this);
// 为GLSurfaceView设置绘制器
glView.setRenderer(myRender);
setContentView(glView);
}
}
记得加入纹理贴图,这里图片的格式是256x256的:
最后展示一下运行结果: