前面一篇中简述了基本图形的绘制,并且给出着色,下面看看如何在一个立方体上面覆盖一层纹理,就像在地板上贴了一层地板砖的效果.
同样新建一个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);
运行结果如下: