前面一篇中简述了基本图形的绘制,并且给出着色,下面看看如何在一个立方体上面覆盖一层纹理,就像在地板上贴了一层地板砖的效果.
同样新建一个android studio工程,PumpKinBasicTexture工程:
主类如下:
package org.pumpkin.pumpkinbasictexture;
import android.app.Activity;
import android.app.ActionBar;
import android.app.Fragment;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.os.Build;
import org.pumpkin.pumpkinbasictexture.texture.DurianTextureRender;
public class PumpKinMainActivity extends Activity {
private GLSurfaceView glSurfaceView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
glSurfaceView=new GLSurfaceView(this);
glSurfaceView.setRenderer(new DurianTextureRender(this));
setContentView(glSurfaceView);
}
}
绘制纹理类如下:
package org.pumpkin.pumpkinbasictexture.texture;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLUtils;
import org.pumpkin.pumpkinbasictexture.R;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import javax.microedition.khronos.opengles.GL10;
/**
* Created by Administrator on 2016/5/4.
*/
public class TextureCube {
private FloatBuffer vertexBuffer;
private FloatBuffer texBuffer;
private float[] vertices={
-1.0f, -1.0f, 0.0f, // 0. left-bottom-front
1.0f, -1.0f, 0.0f, // 1. right-bottom-front
-1.0f, 1.0f, 0.0f, // 2. left-top-front
1.0f, 1.0f, 0.0f // 3. right-top-front
};
float[] texCoords={
0.0f, 1.0f, // A. left-bottom (NEW)
1.0f, 1.0f, // B. right-bottom (NEW)
0.0f, 0.0f, // C. left-top (NEW)
1.0f, 0.0f // D. right-top (NEW)
};
int[] textureIDs=new int[1];
public TextureCube(){
ByteBuffer vbb=ByteBuffer.allocateDirect(vertices.length*4);
vbb.order(ByteOrder.nativeOrder());
vertexBuffer=vbb.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);
ByteBuffer tbb=ByteBuffer.allocateDirect(texCoords.length*4);
tbb.order(ByteOrder.nativeOrder());
texBuffer=tbb.asFloatBuffer();
texBuffer.put(texCoords);
texBuffer.position(0);
}
public void draw(GL10 gl){
gl.glFrontFace(GL10.GL_CCW);
gl.glEnable(GL10.GL_CULL_FACE);
gl.glCullFace(GL10.GL_BACK);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glVertexPointer(3,GL10.GL_FLOAT,0,vertexBuffer);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glTexCoordPointer(2,GL10.GL_FLOAT,0,texBuffer);
//front
gl.glPushMatrix();
gl.glTranslatef(0.0f,0.0f,1.0f);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP,0,4);
gl.glPopMatrix();
//left
gl.glPushMatrix();
gl.glRotatef(270.0f,0.0f,1.0f,0.0f);
gl.glTranslatef(0.0f,0.0f,1.0f);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP,0,4);
gl.glPopMatrix();
//back
gl.glPushMatrix();
gl.glRotatef(180.0f, 0.0f, 1.0f, 0.0f);
gl.glTranslatef(0.0f, 0.0f, 1.0f);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
gl.glPopMatrix();
// right
gl.glPushMatrix();
gl.glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
gl.glTranslatef(0.0f, 0.0f, 1.0f);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
gl.glPopMatrix();
// top
gl.glPushMatrix();
gl.glRotatef(270.0f, 1.0f, 0.0f, 0.0f);
gl.glTranslatef(0.0f, 0.0f, 1.0f);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
gl.glPopMatrix();
// bottom
gl.glPushMatrix();
gl.glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
gl.glTranslatef(0.0f, 0.0f, 1.0f);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
gl.glPopMatrix();
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisable(GL10.GL_CULL_FACE);
}
public void loadTexture(GL10 gl,Context context){
gl.glGenTextures(1,textureIDs,0);
gl.glBindTexture(GL10.GL_TEXTURE_2D,textureIDs[0]);
gl.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_NEAREST);
gl.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_LINEAR);
InputStream istream=context.getResources().openRawResource(R.drawable.ghh);
Bitmap bitmap;
bitmap= BitmapFactory.decodeStream(istream);
try {
istream.close();
} catch (IOException e) {
e.printStackTrace();
}
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
bitmap.recycle();
}
}
其中:
gl.glPushMatrix();
gl.glPopMatrix();
glPushMatrix()和glPopMatrix()的配对使用可以消除上一次的变换对本次变换的影响。使本次变换是以世界坐标系的原点为参考点进行.有点类似画地为牢的概念,即在绘制图形的时候,在设定某一个坐标系中绘制后,然后坐标变换,并不会影响前面,那个绘制的图形还在以前的位置,不会因为坐标变换了,图形位置发生了变化.
gl.glGenTextures(1,textureIDs,0);
生成一个纹理对象,并将其ID保存到成员变量 texture 中.
gl.glBindTexture(GL10.GL_TEXTURE_2D,textureIDs[0]);
将生成的空纹理绑定到当前2D纹理通道
gl.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_NEAREST);
gl.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_LINEAR);
设置2D纹理通道当前绑定的纹理的属性
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
将bitmap应用到2D纹理通道当前绑定的纹理中
下面是渲染器:
package org.pumpkin.pumpkinbasictexture.texture;
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.opengl.GLU;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
/**
* Created by Administrator on 2016/5/4.
*/
public class DurianTextureRender implements GLSurfaceView.Renderer {
private Context mContext;
private TextureCube textureCube;
private float angleTex=0;
private float speechTex=-1.5f;
public DurianTextureRender(Context context){
mContext=context;
textureCube=new TextureCube();
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
gl.glClearColor(0.0f,0.0f,0.0f,1.0f);
gl.glClearDepthf(1.0f);
gl.glEnable(GL10.GL_DEPTH_TEST);
gl.glDepthFunc(GL10.GL_LEQUAL);
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,GL10.GL_NICEST);
gl.glShadeModel(GL10.GL_SMOOTH);
gl.glDisable(GL10.GL_DITHER);
textureCube.loadTexture(gl,mContext);
gl.glEnable(GL10.GL_TEXTURE_2D);
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
if(height==0){
height=1;
}
float aspect=(float)width/height;
gl.glViewport(0,0,width,height);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
GLU.gluPerspective(gl, 45, aspect, 0.1f, 100.0f);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
}
@Override
public void onDrawFrame(GL10 gl) {
gl.glClear(GL10.GL_COLOR_BUFFER_BIT|GL10.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();
gl.glTranslatef(0.0f,0.0f,-6.0f);
gl.glRotatef(angleTex,0.1f,1.0f,0.2f);
textureCube.draw(gl);
angleTex+=speechTex;
}
}
添加纹理需要使能:
gl.glEnable(GL10.GL_TEXTURE_2D);
运行结果如下: