zoukankan      html  css  js  c++  java
  • Android OpenGL ES 2.0 (七) FramebufferObject(FBO)

    Android平台上简单的FramebufferObject示例。

    FramebufferObject的概念就不说了,参考OpenGL ES 2.0 Programming Guide的第10章。

    下面是render framebuffer到texture的例子。

    代码的主要流程是:

    创建framebuffer,绑定framebuffer,render framebuffer到texture,切换回system提供的framebuffer,利用之前产生的texture.

    方便起见,两个render流程用的同样的shader.

    下面是renderer的代码,Test7Renderer.java

      1 package com.android.jayce.test;
      2 
      3 import java.nio.ByteBuffer;
      4 import java.nio.ByteOrder;
      5 import java.nio.FloatBuffer;
      6 import java.nio.IntBuffer;
      7 
      8 import javax.microedition.khronos.egl.EGLConfig;
      9 import javax.microedition.khronos.opengles.GL10;
     10 
     11 import android.content.Context;
     12 import android.opengl.GLES20;
     13 import android.opengl.GLSurfaceView;
     14 import android.opengl.Matrix;
     15 import android.os.SystemClock;
     16 
     17 import com.android.jayce.test.R;
     18 
     19 /**
     20  * This class implements our custom renderer. Note that the GL10 parameter passed in is unused for OpenGL ES 2.0
     21  * renderers -- the static class GLES20 is used instead.
     22  */
     23 public class Test7Renderer implements GLSurfaceView.Renderer
     24 {
     25     /** Used for debug logs. */
     26     private static final String TAG = "Test7Renderer";
     27 
     28     private final Context mActivityContext;
     29 
     30     /**
     31      * Store the model matrix. This matrix is used to move models from object space (where each model can be thought
     32      * of being located at the center of the universe) to world space.
     33      */
     34     private float[] mModelMatrix = new float[16];
     35 
     36     /**
     37      * Store the view matrix. This can be thought of as our camera. This matrix transforms world space to eye space;
     38      * it positions things relative to our eye.
     39      */
     40     private float[] mViewMatrix = new float[16];
     41 
     42     /** Store the projection matrix. This is used to project the scene onto a 2D viewport. */
     43     private float[] mProjectionMatrix = new float[16];
     44 
     45     /** Allocate storage for the final combined matrix. This will be passed into the shader program. */
     46     private float[] mMVPMatrix = new float[16];
     47 
     48     /** Store our model data in a float buffer. */
     49     private final FloatBuffer mCubePositions;
     50     private final FloatBuffer mCubeColors;
     51     private final FloatBuffer mCubeTextureCoordinates;
     52 
     53     /** This will be used to pass in the transformation matrix. */
     54     private int mMVPMatrixHandle;
     55 
     56     /** This will be used to pass in the modelview matrix. */
     57     private int mMVMatrixHandle;
     58 
     59     /** This will be used to pass in the texture. */
     60     private int mTextureUniformHandle;
     61 
     62     /** This will be used to pass in model position information. */
     63     private int mPositionHandle;
     64 
     65     /** This will be used to pass in model color information. */
     66     private int mColorHandle;
     67 
     68     /** This will be used to pass in model texture coordinate information. */
     69     private int mTextureCoordinateHandle;
     70 
     71     /** How many bytes per float. */
     72     private final int mBytesPerFloat = 4;
     73 
     74     /** Size of the position data in elements. */
     75     private final int mPositionDataSize = 3;
     76 
     77     /** Size of the color data in elements. */
     78     private final int mColorDataSize = 4;
     79 
     80     /** Size of the texture coordinate data in elements. */
     81     private final int mTextureCoordinateDataSize = 2;
     82 
     83     /** This is a handle to our cube shading program. */
     84     private int mProgramHandle;
     85 
     86     /** This is a handle to our texture data. */
     87     private int mTextureDataHandle;
     88 
     89     /**
     90      * Initialize the model data.
     91      */
     92     public Test7Renderer(final Context activityContext)
     93     {
     94         mActivityContext = activityContext;
     95 
     96         // Define points for a cube.
     97 
     98         // X, Y, Z
     99         final float[] cubePositionData =
    100         {
    101                 // In OpenGL counter-clockwise winding is default. This means that when we look at a triangle,
    102                 // if the points are counter-clockwise we are looking at the "front". If not we are looking at
    103                 // the back. OpenGL has an optimization where all back-facing triangles are culled, since they
    104                 // usually represent the backside of an object and aren't visible anyways.
    105 
    106                 // Front face
    107                 -1.0f, 1.0f, 1.0f,
    108                 -1.0f, -1.0f, 1.0f,
    109                 1.0f, 1.0f, 1.0f,
    110                 -1.0f, -1.0f, 1.0f,
    111                 1.0f, -1.0f, 1.0f,
    112                 1.0f, 1.0f, 1.0f,
    113 
    114                 // Right face
    115                 1.0f, 1.0f, 1.0f,
    116                 1.0f, -1.0f, 1.0f,
    117                 1.0f, 1.0f, -1.0f,
    118                 1.0f, -1.0f, 1.0f,
    119                 1.0f, -1.0f, -1.0f,
    120                 1.0f, 1.0f, -1.0f,
    121 
    122                 // Back face
    123                 1.0f, 1.0f, -1.0f,
    124                 1.0f, -1.0f, -1.0f,
    125                 -1.0f, 1.0f, -1.0f,
    126                 1.0f, -1.0f, -1.0f,
    127                 -1.0f, -1.0f, -1.0f,
    128                 -1.0f, 1.0f, -1.0f,
    129 
    130                 // Left face
    131                 -1.0f, 1.0f, -1.0f,
    132                 -1.0f, -1.0f, -1.0f,
    133                 -1.0f, 1.0f, 1.0f,
    134                 -1.0f, -1.0f, -1.0f,
    135                 -1.0f, -1.0f, 1.0f,
    136                 -1.0f, 1.0f, 1.0f,
    137 
    138                 // Top face
    139                 -1.0f, 1.0f, -1.0f,
    140                 -1.0f, 1.0f, 1.0f,
    141                 1.0f, 1.0f, -1.0f,
    142                 -1.0f, 1.0f, 1.0f,
    143                 1.0f, 1.0f, 1.0f,
    144                 1.0f, 1.0f, -1.0f,
    145 
    146                 // Bottom face
    147                 1.0f, -1.0f, -1.0f,
    148                 1.0f, -1.0f, 1.0f,
    149                 -1.0f, -1.0f, -1.0f,
    150                 1.0f, -1.0f, 1.0f,
    151                 -1.0f, -1.0f, 1.0f,
    152                 -1.0f, -1.0f, -1.0f,
    153         };
    154 
    155         // R, G, B, A
    156         final float[] cubeColorData =
    157         {
    158                 // Front face (red)
    159                 1.0f, 0.0f, 0.0f, 1.0f,
    160                 1.0f, 0.0f, 0.0f, 1.0f,
    161                 1.0f, 0.0f, 0.0f, 1.0f,
    162                 1.0f, 0.0f, 0.0f, 1.0f,
    163                 1.0f, 0.0f, 0.0f, 1.0f,
    164                 1.0f, 0.0f, 0.0f, 1.0f,
    165 
    166                 // Right face (green)
    167                 0.0f, 1.0f, 0.0f, 1.0f,
    168                 0.0f, 1.0f, 0.0f, 1.0f,
    169                 0.0f, 1.0f, 0.0f, 1.0f,
    170                 0.0f, 1.0f, 0.0f, 1.0f,
    171                 0.0f, 1.0f, 0.0f, 1.0f,
    172                 0.0f, 1.0f, 0.0f, 1.0f,
    173 
    174                 // Back face (blue)
    175                 0.0f, 0.0f, 1.0f, 1.0f,
    176                 0.0f, 0.0f, 1.0f, 1.0f,
    177                 0.0f, 0.0f, 1.0f, 1.0f,
    178                 0.0f, 0.0f, 1.0f, 1.0f,
    179                 0.0f, 0.0f, 1.0f, 1.0f,
    180                 0.0f, 0.0f, 1.0f, 1.0f,
    181 
    182                 // Left face (yellow)
    183                 1.0f, 1.0f, 0.0f, 1.0f,
    184                 1.0f, 1.0f, 0.0f, 1.0f,
    185                 1.0f, 1.0f, 0.0f, 1.0f,
    186                 1.0f, 1.0f, 0.0f, 1.0f,
    187                 1.0f, 1.0f, 0.0f, 1.0f,
    188                 1.0f, 1.0f, 0.0f, 1.0f,
    189 
    190                 // Top face (cyan)
    191                 0.0f, 1.0f, 1.0f, 1.0f,
    192                 0.0f, 1.0f, 1.0f, 1.0f,
    193                 0.0f, 1.0f, 1.0f, 1.0f,
    194                 0.0f, 1.0f, 1.0f, 1.0f,
    195                 0.0f, 1.0f, 1.0f, 1.0f,
    196                 0.0f, 1.0f, 1.0f, 1.0f,
    197 
    198                 // Bottom face (magenta)
    199                 1.0f, 0.0f, 1.0f, 1.0f,
    200                 1.0f, 0.0f, 1.0f, 1.0f,
    201                 1.0f, 0.0f, 1.0f, 1.0f,
    202                 1.0f, 0.0f, 1.0f, 1.0f,
    203                 1.0f, 0.0f, 1.0f, 1.0f,
    204                 1.0f, 0.0f, 1.0f, 1.0f
    205         };
    206 
    207         // S, T (or X, Y)
    208         // Texture coordinate data.
    209         // Because images have a Y axis pointing downward (values increase as you move down the image) while
    210         // OpenGL has a Y axis pointing upward, we adjust for that here by flipping the Y axis.
    211         // What's more is that the texture coordinates are the same for every face.
    212         final float[] cubeTextureCoordinateData =
    213         {
    214                 // Front face
    215                 0.0f, 0.0f,
    216                 0.0f, 1.0f,
    217                 1.0f, 0.0f,
    218                 0.0f, 1.0f,
    219                 1.0f, 1.0f,
    220                 1.0f, 0.0f,
    221 
    222                 // Right face
    223                 0.0f, 0.0f,
    224                 0.0f, 1.0f,
    225                 1.0f, 0.0f,
    226                 0.0f, 1.0f,
    227                 1.0f, 1.0f,
    228                 1.0f, 0.0f,
    229 
    230                 // Back face
    231                 0.0f, 0.0f,
    232                 0.0f, 1.0f,
    233                 1.0f, 0.0f,
    234                 0.0f, 1.0f,
    235                 1.0f, 1.0f,
    236                 1.0f, 0.0f,
    237 
    238                 // Left face
    239                 0.0f, 0.0f,
    240                 0.0f, 1.0f,
    241                 1.0f, 0.0f,
    242                 0.0f, 1.0f,
    243                 1.0f, 1.0f,
    244                 1.0f, 0.0f,
    245 
    246                 // Top face
    247                 0.0f, 0.0f,
    248                 0.0f, 1.0f,
    249                 1.0f, 0.0f,
    250                 0.0f, 1.0f,
    251                 1.0f, 1.0f,
    252                 1.0f, 0.0f,
    253 
    254                 // Bottom face
    255                 0.0f, 0.0f,
    256                 0.0f, 1.0f,
    257                 1.0f, 0.0f,
    258                 0.0f, 1.0f,
    259                 1.0f, 1.0f,
    260                 1.0f, 0.0f
    261         };
    262 
    263         // Initialize the buffers.
    264         mCubePositions = ByteBuffer.allocateDirect(cubePositionData.length * mBytesPerFloat)
    265         .order(ByteOrder.nativeOrder()).asFloatBuffer();
    266         mCubePositions.put(cubePositionData).position(0);
    267 
    268         mCubeColors = ByteBuffer.allocateDirect(cubeColorData.length * mBytesPerFloat)
    269         .order(ByteOrder.nativeOrder()).asFloatBuffer();
    270         mCubeColors.put(cubeColorData).position(0);
    271 
    272         mCubeTextureCoordinates = ByteBuffer.allocateDirect(cubeTextureCoordinateData.length * mBytesPerFloat)
    273         .order(ByteOrder.nativeOrder()).asFloatBuffer();
    274         mCubeTextureCoordinates.put(cubeTextureCoordinateData).position(0);
    275     }
    276 
    277     protected String getVertexShader(int shader)
    278     {
    279         return ToolsUtil.readTextFileFromRawResource(mActivityContext, shader);
    280     }
    281 
    282     protected String getFragmentShader(int shader)
    283     {
    284         return ToolsUtil.readTextFileFromRawResource(mActivityContext, shader);
    285     }
    286 
    287     @Override
    288     public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
    289     {
    290         // Set the background clear color to black.
    291         GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    292 
    293         // Use culling to remove back faces.
    294         GLES20.glEnable(GLES20.GL_CULL_FACE);
    295 
    296         // Enable depth testing
    297         GLES20.glEnable(GLES20.GL_DEPTH_TEST);
    298 
    299         // The below glEnable() call is a holdover from OpenGL ES 1, and is not needed in OpenGL ES 2.
    300         // Enable texture mapping
    301         GLES20.glEnable(GLES20.GL_TEXTURE_2D);
    302 
    303         // Position the eye in front of the origin.
    304         final float eyeX = 0.0f;
    305         final float eyeY = 0.0f;
    306         final float eyeZ = -0.5f;
    307 
    308         // We are looking toward the distance
    309         final float lookX = 0.0f;
    310         final float lookY = 0.0f;
    311         final float lookZ = -5.0f;
    312 
    313         // Set our up vector. This is where our head would be pointing were we holding the camera.
    314         final float upX = 0.0f;
    315         final float upY = 1.0f;
    316         final float upZ = 0.0f;
    317 
    318         // Set the view matrix. This matrix can be said to represent the camera position.
    319         // NOTE: In OpenGL 1, a ModelView matrix is used, which is a combination of a model and
    320         // view matrix. In OpenGL 2, we can keep track of these matrices separately if we choose.
    321         Matrix.setLookAtM(mViewMatrix, 0, eyeX, eyeY, eyeZ, lookX, lookY, lookZ, upX, upY, upZ);
    322 
    323         final String vertexShader = getVertexShader(R.raw.per_pixel_vertex_shader);
    324         final String fragmentShader = getFragmentShader(R.raw.per_pixel_fragment_shader);
    325 
    326         final int vertexShaderHandle = ToolsUtil.compileShader(GLES20.GL_VERTEX_SHADER, vertexShader);
    327         final int fragmentShaderHandle = ToolsUtil.compileShader(GLES20.GL_FRAGMENT_SHADER, fragmentShader);
    328 
    329         mProgramHandle = ToolsUtil.createAndLinkProgram(vertexShaderHandle, fragmentShaderHandle,
    330                 new String[] {"a_Position", "a_Color", "a_TexCoordinate"});
    331 
    332         // Load the texture
    333         mTextureDataHandle = ToolsUtil.loadTexture(mActivityContext, R.drawable.aaa);
    334     }
    335 
    336     @Override
    337     public void onSurfaceChanged(GL10 glUnused, int width, int height)
    338     {
    339         // Set the OpenGL viewport to the same size as the surface.
    340         GLES20.glViewport(0, 0, width, height);
    341 
    342         // Create a new perspective projection matrix. The height will stay the same
    343         // while the width will vary as per aspect ratio.
    344         final float ratio = (float) width / height;
    345         final float left = -ratio;
    346         final float right = ratio;
    347         final float bottom = -1.0f;
    348         final float top = 1.0f;
    349         final float near = 1.0f;
    350         final float far = 10.0f;
    351 
    352         Matrix.frustumM(mProjectionMatrix, 0, left, right, bottom, top, near, far);
    353     }
    354 
    355     @Override
    356     public void onDrawFrame(GL10 glUnused)
    357     {
    358         IntBuffer framebuffer = IntBuffer.allocate(1);
    359         IntBuffer depthRenderbuffer = IntBuffer.allocate(1);
    360         IntBuffer texture = IntBuffer.allocate(1);
    361         int texWidth = 480, texHeight = 480;
    362         IntBuffer maxRenderbufferSize = IntBuffer.allocate(1);
    363         GLES20.glGetIntegerv(GLES20.GL_MAX_RENDERBUFFER_SIZE, maxRenderbufferSize);
    364         // check if GL_MAX_RENDERBUFFER_SIZE is >= texWidth and texHeight
    365         if((maxRenderbufferSize.get(0) <= texWidth) ||
    366         (maxRenderbufferSize.get(0) <= texHeight))
    367         {
    368         // cannot use framebuffer objects as we need to create
    369         // a depth buffer as a renderbuffer object
    370         // return with appropriate error
    371         }
    372         // generate the framebuffer, renderbuffer, and texture object names
    373         GLES20.glGenFramebuffers(1, framebuffer);
    374         GLES20.glGenRenderbuffers(1, depthRenderbuffer);
    375         GLES20.glGenTextures(1, texture);
    376         // bind texture and load the texture mip-level 0
    377         // texels are RGB565
    378         // no texels need to be specified as we are going to draw into
    379         // the texture
    380         GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture.get(0));
    381         GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGB, texWidth, texHeight,
    382         0, GLES20.GL_RGB, GLES20.GL_UNSIGNED_SHORT_5_6_5, null);
    383         GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
    384         GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
    385         GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
    386         GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
    387         // bind renderbuffer and create a 16-bit depth buffer
    388         // width and height of renderbuffer = width and height of
    389         // the texture
    390         GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, depthRenderbuffer.get(0));
    391         GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER, GLES20.GL_DEPTH_COMPONENT16,
    392         texWidth, texHeight);
    393         // bind the framebuffer
    394         GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, framebuffer.get(0));
    395         // specify texture as color attachment
    396         GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0,
    397                 GLES20.GL_TEXTURE_2D, texture.get(0), 0);
    398         // specify depth_renderbufer as depth attachment
    399         GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER, GLES20.GL_DEPTH_ATTACHMENT,
    400                 GLES20.GL_RENDERBUFFER, depthRenderbuffer.get(0));
    401         // check for framebuffer complete
    402         int status = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER);
    403         if(status == GLES20.GL_FRAMEBUFFER_COMPLETE)
    404         {
    405             // render to texture using FBO
    406             GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
    407             GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
    408 
    409             // Do a complete rotation every 10 seconds.
    410             long time = SystemClock.uptimeMillis() % 10000L;
    411             float angleInDegrees = (360.0f / 10000.0f) * (2 * (int) time);
    412 
    413             GLES20.glUseProgram(mProgramHandle);
    414 
    415             // Set program handles for cube drawing.
    416             mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgramHandle, "u_MVPMatrix");
    417             mMVMatrixHandle = GLES20.glGetUniformLocation(mProgramHandle, "u_MVMatrix");
    418             mTextureUniformHandle = GLES20.glGetUniformLocation(mProgramHandle, "u_Texture");
    419             mPositionHandle = GLES20.glGetAttribLocation(mProgramHandle, "a_Position");
    420             mColorHandle = GLES20.glGetAttribLocation(mProgramHandle, "a_Color");
    421             mTextureCoordinateHandle = GLES20.glGetAttribLocation(mProgramHandle, "a_TexCoordinate");
    422 
    423             // Set the active texture unit to texture unit 0.
    424             GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
    425 
    426             // Bind the texture to this unit.
    427             GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureDataHandle);
    428 
    429             // Tell the texture uniform sampler to use this texture in the shader by binding to texture unit 0.
    430             GLES20.glUniform1i(mTextureUniformHandle, 0);
    431 
    432             Matrix.setIdentityM(mModelMatrix, 0);
    433             Matrix.translateM(mModelMatrix, 0, 0.0f, -1.0f, -5.0f);
    434             Matrix.rotateM(mModelMatrix, 0, angleInDegrees, 1.0f, 1.0f, 0.0f);
    435             drawCube();
    436 
    437             // render to window system provided framebuffer
    438             GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
    439             GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    440             GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
    441 
    442             // Do a complete rotation every 10 seconds.
    443             time = SystemClock.uptimeMillis() % 10000L;
    444             angleInDegrees = (360.0f / 10000.0f) * ((int) time);
    445 
    446             GLES20.glUseProgram(mProgramHandle);
    447 
    448             // Set program handles for cube drawing.
    449             mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgramHandle, "u_MVPMatrix");
    450             mMVMatrixHandle = GLES20.glGetUniformLocation(mProgramHandle, "u_MVMatrix");
    451             mTextureUniformHandle = GLES20.glGetUniformLocation(mProgramHandle, "u_Texture");
    452             mPositionHandle = GLES20.glGetAttribLocation(mProgramHandle, "a_Position");
    453             mColorHandle = GLES20.glGetAttribLocation(mProgramHandle, "a_Color");
    454             mTextureCoordinateHandle = GLES20.glGetAttribLocation(mProgramHandle, "a_TexCoordinate");
    455 
    456             // Set the active texture unit to texture unit 0.
    457             GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
    458 
    459             // Bind the texture to this unit.
    460             GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture.get(0)/*mTextureDataHandle*/);
    461 
    462             // Tell the texture uniform sampler to use this texture in the shader by binding to texture unit 0.
    463             GLES20.glUniform1i(mTextureUniformHandle, 0);
    464 
    465             Matrix.setIdentityM(mModelMatrix, 0);
    466             Matrix.translateM(mModelMatrix, 0, 0.0f, 0.0f, -5.0f);
    467             Matrix.rotateM(mModelMatrix, 0, angleInDegrees, 1.0f, 1.0f, 0.0f);
    468             drawCube();
    469             GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
    470         }
    471 
    472         // cleanup
    473         GLES20.glDeleteRenderbuffers(1, depthRenderbuffer);
    474         GLES20.glDeleteFramebuffers(1, framebuffer);
    475         GLES20.glDeleteTextures(1, texture);
    476     }
    477 
    478     /**
    479      * Draws a cube.
    480      */
    481     private void drawCube()
    482     {
    483         // Pass in the position information
    484         mCubePositions.position(0);
    485         GLES20.glVertexAttribPointer(mPositionHandle, mPositionDataSize, GLES20.GL_FLOAT, false,
    486                 0, mCubePositions);
    487 
    488         GLES20.glEnableVertexAttribArray(mPositionHandle);
    489 
    490         // Pass in the color information
    491         mCubeColors.position(0);
    492         GLES20.glVertexAttribPointer(mColorHandle, mColorDataSize, GLES20.GL_FLOAT, false,
    493                 0, mCubeColors);
    494         GLES20.glEnableVertexAttribArray(mColorHandle);
    495 
    496         // Pass in the texture coordinate information
    497         mCubeTextureCoordinates.position(0);
    498         GLES20.glVertexAttribPointer(mTextureCoordinateHandle, mTextureCoordinateDataSize, GLES20.GL_FLOAT, false,
    499                 0, mCubeTextureCoordinates);
    500 
    501         GLES20.glEnableVertexAttribArray(mTextureCoordinateHandle);
    502 
    503         // This multiplies the view matrix by the model matrix, and stores the result in the MVP matrix
    504         // (which currently contains model * view).
    505         Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);
    506 
    507         // Pass in the modelview matrix.
    508         GLES20.glUniformMatrix4fv(mMVMatrixHandle, 1, false, mMVPMatrix, 0);
    509 
    510         // This multiplies the modelview matrix by the projection matrix, and stores the result in the MVP matrix
    511         // (which now contains model * view * projection).
    512         Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);
    513 
    514         // Pass in the combined matrix.
    515         GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0);
    516 
    517         // Draw the cube.
    518         GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 36);
    519     }
    520 }

    还有一个辅助类,ToolsUtil.java:

      1 package com.android.jayce.test;
      2 
      3  import android.content.Context;
      4  import android.graphics.Bitmap;
      5  import android.graphics.BitmapFactory;
      6  import android.opengl.GLES20;
      7 import android.opengl.GLUtils;
      8 import android.util.Log;
      9 
     10 import java.io.BufferedReader;
     11 import java.io.IOException;
     12 import java.io.InputStream;
     13 import java.io.InputStreamReader;
     14 
     15  public class ToolsUtil
     16  {
     17      public static int loadTexture(final Context context, final int resourceId)
     18      {
     19          final int[] textureHandle = new int[1];
     20          GLES20.glGenTextures(1, textureHandle, 0);
     21 
     22          if(textureHandle[0] != 0)
     23          {
     24              final BitmapFactory.Options options = new BitmapFactory.Options();
     25              options.inScaled = false;
     26 
     27              final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resourceId, options);
     28              GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]);
     29 
     30              GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
     31              GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
     32 
     33              GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
     34              bitmap.recycle();
     35          }
     36 
     37          if(textureHandle[0] == 0)
     38          {
     39              throw new RuntimeException("failed to load texture");
     40          }
     41 
     42          return textureHandle[0];
     43      }
     44 
     45      /**
     46       * Helper function to compile a shader.
     47       *
     48       * @param shaderType The shader type.
     49       * @param shaderSource The shader source code.
     50       * @return An OpenGL handle to the shader.
     51       */
     52      public static int compileShader(final int shaderType, final String shaderSource)
     53      {
     54          int shaderHandle = GLES20.glCreateShader(shaderType);
     55 
     56          if (shaderHandle != 0)
     57          {
     58              // Pass in the shader source.
     59              GLES20.glShaderSource(shaderHandle, shaderSource);
     60 
     61              // Compile the shader.
     62              GLES20.glCompileShader(shaderHandle);
     63 
     64              // Get the compilation status.
     65              final int[] compileStatus = new int[1];
     66              GLES20.glGetShaderiv(shaderHandle, GLES20.GL_COMPILE_STATUS, compileStatus, 0);
     67 
     68              // If the compilation failed, delete the shader.
     69              if (compileStatus[0] == 0)
     70              {
     71                  GLES20.glDeleteShader(shaderHandle);
     72                  shaderHandle = 0;
     73              }
     74          }
     75 
     76          if (shaderHandle == 0)
     77          {
     78              throw new RuntimeException("Error creating shader.");
     79          }
     80 
     81          return shaderHandle;
     82      }
     83 
     84      /**
     85       * Helper function to compile and link a program.
     86       *
     87       * @param vertexShaderHandle An OpenGL handle to an already-compiled vertex shader.
     88       * @param fragmentShaderHandle An OpenGL handle to an already-compiled fragment shader.
     89       * @param attributes Attributes that need to be bound to the program.
     90       * @return An OpenGL handle to the program.
     91       */
     92      public static int createAndLinkProgram(final int vertexShaderHandle, final int fragmentShaderHandle, final String[] attributes)
     93      {
     94          int programHandle = GLES20.glCreateProgram();
     95 
     96          if (programHandle != 0)
     97          {
     98              // Bind the vertex shader to the program.
     99              GLES20.glAttachShader(programHandle, vertexShaderHandle);
    100 
    101              // Bind the fragment shader to the program.
    102              GLES20.glAttachShader(programHandle, fragmentShaderHandle);
    103 
    104              // Bind attributes
    105              if (attributes != null)
    106              {
    107                  final int size = attributes.length;
    108                  for (int i = 0; i < size; i++)
    109                  {
    110                      GLES20.glBindAttribLocation(programHandle, i, attributes[i]);
    111                  }
    112              }
    113 
    114              // Link the two shaders together into a program.
    115              GLES20.glLinkProgram(programHandle);
    116 
    117              // Get the link status.
    118              final int[] linkStatus = new int[1];
    119              GLES20.glGetProgramiv(programHandle, GLES20.GL_LINK_STATUS, linkStatus, 0);
    120 
    121              // If the link failed, delete the program.
    122              if (linkStatus[0] == 0)
    123              {
    124                  GLES20.glDeleteProgram(programHandle);
    125                  programHandle = 0;
    126              }
    127          }
    128 
    129          if (programHandle == 0)
    130          {
    131              throw new RuntimeException("Error creating program.");
    132          }
    133 
    134          return programHandle;
    135      }
    136 
    137      public static String readTextFileFromRawResource(final Context context,
    138              final int resourceId)
    139      {
    140          final InputStream inputStream = context.getResources().openRawResource(
    141                  resourceId);
    142          final InputStreamReader inputStreamReader = new InputStreamReader(
    143                  inputStream);
    144          final BufferedReader bufferedReader = new BufferedReader(
    145                  inputStreamReader);
    146 
    147          String nextLine;
    148          final StringBuilder body = new StringBuilder();
    149 
    150          try
    151          {
    152              while ((nextLine = bufferedReader.readLine()) != null)
    153              {
    154                  body.append(nextLine);
    155                  body.append('\n');
    156              }
    157          }
    158          catch (IOException e)
    159          {
    160              return null;
    161          }
    162 
    163          return body.toString();
    164      }
    165 
    166  }

    使用的shader, per_pixel_vertex_shader.glsl:

     1 uniform mat4 u_MVPMatrix;        // A constant representing the combined model/view/projection matrix.                     
     2 uniform mat4 u_MVMatrix;        // A constant representing the combined model/view matrix.               
     3                       
     4 attribute vec4 a_Position;        // Per-vertex position information we will pass in.                   
     5 attribute vec4 a_Color;            // Per-vertex color information we will pass in.                 
     6 attribute vec2 a_TexCoordinate; // Per-vertex texture coordinate information we will pass in.         
     7           
     8 varying vec3 v_Position;        // This will be passed into the fragment shader.               
     9 varying vec4 v_Color;            // This will be passed into the fragment shader.                  
    10 varying vec2 v_TexCoordinate;   // This will be passed into the fragment shader.            
    11           
    12 // The entry point for our vertex shader.  
    13 void main()                                                     
    14 {                                                         
    15     // Transform the vertex into eye space.     
    16     v_Position = vec3(u_MVMatrix * a_Position);            
    17         
    18     // Pass through the color.
    19     v_Color = a_Color;
    20     
    21     // Pass through the texture coordinate.
    22     v_TexCoordinate = a_TexCoordinate;                                      
    23     
    24     // gl_Position is a special variable used to store the final position.
    25     // Multiply the vertex by the matrix to get the final point in normalized screen coordinates.
    26     gl_Position = u_MVPMatrix * a_Position;                                 
    27 }                                                          

    使用的shader, per_pixel_fragment_shader.glsl:

     1 precision mediump float;           // Set the default precision to medium. We don't need as high of a 
     2                                 // precision in the fragment shader.
     3 uniform sampler2D u_Texture;    // The input texture.
     4   
     5 varying vec3 v_Position;        // Interpolated position for this fragment.
     6 varying vec4 v_Color;              // This is the color from the vertex shader interpolated across the 
     7 varying vec2 v_TexCoordinate;   // Interpolated texture coordinate per fragment.
     8   
     9 // The entry point for our fragment shader.
    10 void main()                            
    11 {                              
    12     // Multiply the color by the diffuse illumination level and texture value to get final output color.
    13     gl_FragColor = (v_Color * texture2D(u_Texture, v_TexCoordinate));                                          
    14 }                                                                         

    好了,就这么多了,可以看到旋转立方体每一面的texture都是用的自己创建的framebuffer render的texture,每面都有一个旋转的立方体。

    看看效果图吧:

  • 相关阅读:
    socket套接字通信和粘包问题
    TCP协议
    网络编程
    单例模式
    类的内置方法(魔法方法)
    反射(hasattr和getattr和setattr和delattr)
    isinstance与issubclass
    绑定方法与非绑定方法
    鸭子类型
    类的多态和抽象类
  • 原文地址:https://www.cnblogs.com/jayceli/p/3008472.html
Copyright © 2011-2022 走看看