android数据球图,Android OpenGL球体贴图

本文详细介绍了如何在OpenGL中通过计算并应用纹理坐标,将地球图片贴在球体表面,包括创建材质、设置纹理过滤和边界处理,以及在绘制过程中声明和使用纹理坐标。步骤包括生成Texture ID、绑定Texture、计算SphereVertices中的纹理坐标,最后在draw方法中展示整个过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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里

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);

}

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

4b0fc407c2793e51e924f2b6487eb01b.png

完整代码下载地址:点击打开链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值