Android OpenGL球体贴图

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

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



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

  • 4
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值