您的位置:首页 > 移动开发 > Android开发

Android OpenGL球体贴图

2016-08-18 11:15 246 查看
OpenGL球体贴图的的整个流程就是计算出球体和纹理材质坐标,然后画出球体,按照纹理坐标将bitmap贴上去。

具体方法和上一篇文章画一个球体类似OpenGL绘制球体,只是需要创建材质,并且需要构建一个用来渲染的Bitmap对象。
//使用OpenGL库创建一个材质(Texture),首先是获取一个Texture Id。
int[] textures = new int[1];
// 告诉OpenGL去生成textures.textures中存放了创建的Texture ID
gl.glGenTextures(1, textures, 0);
//通知OpenGL库使用这个Texture
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
//用来渲染的Texture可能比要渲染的区域大或者小,所以需要设置Texture需要放大或是缩小时OpenGL的模式
//常用的两种模式为GL10.GL_LINEAR和GL10.GL_NEAREST。
//需要比较清晰的图像使用GL10.GL_NEAREST,而使用GL10.GL_LINEAR则会得到一个较模糊的图像
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);
//当定义的材质坐标点超过UV坐标定义的大小(UV坐标为0,0到1,1),这时需要告诉OpenGL库如何去渲染这些不存在的Texture部分。
//有两种设置:GL_REPEAT 重复Texture。GL_CLAMP_TO_EDGE 只靠边线绘制一次。
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);
//将Bitmap资源和Texture绑定起来
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, mBitmap, 0);


创建好了材质,还需要在makeSphereVertices()这个计算球面坐标的方法里,获取材质纹理坐标.

需要注意的是,纹理坐标的原点是在左上角.
private void makeSphereVertices() {
float altitude;
float altitudeDelta;
float azimuth;
float ex;
float ey;
float ez;
for(int i = 0; i <= divide; i++) {
altitude      = (float) (Math.PI/2.0 -    i    * (Math.PI) / divide);
altitudeDelta = (float) (Math.PI/2.0 - (i + 1) * (Math.PI) / divide);
float[] vertices = new float[divide*6+6];
//创建纹理坐标点数组
float[] texCoords = new float[divide*4+4];
for(int j = 0; j <= divide; j++) {
azimuth = (float)(j * (Math.PI*2) / divide);
ex = (float) (Math.cos(altitude) * Math.cos(azimuth));
ey = (float)  Math.sin(altitude);
ez = (float) - (Math.cos(altitude) * Math.sin(azimuth));
vertices[6*j+0] = radius * ex;
vertices[6*j+1] = radius * ey;
vertices[6*j+2] = radius * ez;
//计算azimuth经度下纬度为altitude的纹理点坐标
texCoords[4*j+0] = j/(float)divide;
texCoords[4*j+1] = i/(float)divide;
ex = (float) (Math.cos(altitudeDelta) * Math.cos(azimuth));
ey = (float) Math.sin(altitudeDelta);
ez = (float) -(Math.cos(altitudeDelta) * Math.sin(azimuth));
vertices[6*j+3] = radius * ex;
vertices[6*j+4] = radius * ey;
vertices[6*j+5] = radius * ez;
//计算azimuth经度下纬度为altitudeDelta的纹理点坐标
texCoords[4*j+2] = j/(float)divide;
texCoords[4*j+3] = (i + 1) / (float)divide;
}
mVertices.add(makeFloatBufferFromArray(vertices));
//将纹理点坐标转换成FloatBuffer类型添加到纹理点坐标集合ArrayList<FloatBuffer>里
mTextureCoords.add(makeFloatBufferFromArray(texCoords));
}
}


最后一步,就是在draw()方法里声明纹理点坐标的位置:

private void draw(GL10 gl) {
gl.glEnable(GL10.GL_TEXTURE_2D);
//打开材质开关
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

for(int i= 0;i<=divide;i++){
gl.glVertexPointer(3,GL10.GL_FLOAT,0,mVertices.get(i));
//声明纹理点坐标
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTextureCoords.get(i));
l.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, divide*2+2);
}
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
//关闭材质开关
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glDisable(GL10.GL_TEXTURE_2D);
}

找了一张地球的图片,贴上去之后就长这样啦~~~~\(≧▽≦)/~



完整代码下载地址:点击打开链接
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: