• Android OpenGL ES 2.0 (五) 添加材质


    还是一个旋转的立方体,现在给它加上材质。载入一个图片,立方体的每一面都贴上此图片。

    现在相较第二篇画的立方体,又多了个参数材质。先看看载入图片的方法。

    这是个辅助方法。单独写了个类。

    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 
     9 public class ToolsUtil
    10 {
    11     public static int loadTexture(final Context context, final int resourceId)
    12     {
    13         final int[] textureHandle = new int[1];
    14         GLES20.glGenTextures(1, textureHandle, 0);
    15         
    16         if(textureHandle[0] != 0)
    17         {
    18             final BitmapFactory.Options options = new BitmapFactory.Options();
    19             options.inScaled = false;
    20             
    21             final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resourceId, options);
    22             GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]);
    23             
    24             GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
    25             GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
    26             
    27             GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
    28             bitmap.recycle();
    29         }
    30         
    31         if(textureHandle[0] == 0)
    32         {
    33             throw new RuntimeException("failed to load texture");
    34         }
    35         
    36         return textureHandle[0];
    37     }
    38 }

    在Renderer里多了材质坐标,mCubeTextureCoordinates。

    在fragmentShader里,颜色计算变成了gl_FragColor = v_Color * texture2D(u_Texture, v_TexCoordinate)。

    看Renderer的实现:

    Test5Renderer.java

      1 package com.android.jayce.test;
      2 
      3 import java.nio.ByteBuffer;
      4 import java.nio.ByteOrder;
      5 import java.nio.FloatBuffer;
      6 
      7 import javax.microedition.khronos.egl.EGLConfig;
      8 import javax.microedition.khronos.opengles.GL10;
      9 
     10 import com.learnopengles.android.R;
     11 
     12 import android.content.Context;
     13 import android.opengl.GLES20;
     14 import android.opengl.Matrix;
     15 import android.opengl.GLSurfaceView;
     16 import android.os.SystemClock;
     17 import android.util.Log;
     18 
     19 public class Test5Renderer implements GLSurfaceView.Renderer
     20 {
     21     private static final String TAG = "Test5Renderer";
     22     private Context mContext;
     23     private static final int BYTES_PER_FLOAT = 4;
     24     private final FloatBuffer mCubePositions;
     25     private final FloatBuffer mCubeColors;
     26     private final FloatBuffer mCubeTextureCoordinates;
     27     private float[] mMVPMatrix = new float[16];
     28     private float[] mViewMatrix = new float[16];
     29     private float[] mModelMatrix = new float[16];
     30     private float[] mProjectionMatrix = new float[16];
     31     private int mMVPMatrixHandle;
     32     private int mPositionHandle;
     33     private int mColorHandle;
     34     private int mTextureUniformHandle;
     35     private int mTextureCoordinateHandle;
     36     private int mTextureDataHandle;
     37     private int mProgramHandle;
     38     private final int POSITION_DATA_SIZE = 3;
     39     private final int COLOR_DATA_SIZE = 4;
     40     private final int TEXTURE_COORDINATE_DATA_SIZE = 2;
     41     
     42     public Test5Renderer(final Context context)
     43     {
     44         mContext = context;
     45         final float cubePosition[] = 
     46         {
     47                 // Front face
     48                 -1.0f, 1.0f, 1.0f,                
     49                 -1.0f, -1.0f, 1.0f,
     50                 1.0f, 1.0f, 1.0f, 
     51                 -1.0f, -1.0f, 1.0f,                 
     52                 1.0f, -1.0f, 1.0f,
     53                 1.0f, 1.0f, 1.0f,
     54                 
     55                 // Right face
     56                 1.0f, 1.0f, 1.0f,                
     57                 1.0f, -1.0f, 1.0f,
     58                 1.0f, 1.0f, -1.0f,
     59                 1.0f, -1.0f, 1.0f,                
     60                 1.0f, -1.0f, -1.0f,
     61                 1.0f, 1.0f, -1.0f,
     62                 
     63                 // Back face
     64                 1.0f, 1.0f, -1.0f,                
     65                 1.0f, -1.0f, -1.0f,
     66                 -1.0f, 1.0f, -1.0f,
     67                 1.0f, -1.0f, -1.0f,                
     68                 -1.0f, -1.0f, -1.0f,
     69                 -1.0f, 1.0f, -1.0f,
     70                 
     71                 // Left face
     72                 -1.0f, 1.0f, -1.0f,                
     73                 -1.0f, -1.0f, -1.0f,
     74                 -1.0f, 1.0f, 1.0f, 
     75                 -1.0f, -1.0f, -1.0f,                
     76                 -1.0f, -1.0f, 1.0f, 
     77                 -1.0f, 1.0f, 1.0f, 
     78                 
     79                 // Top face
     80                 -1.0f, 1.0f, -1.0f,                
     81                 -1.0f, 1.0f, 1.0f, 
     82                 1.0f, 1.0f, -1.0f, 
     83                 -1.0f, 1.0f, 1.0f,                 
     84                 1.0f, 1.0f, 1.0f, 
     85                 1.0f, 1.0f, -1.0f,
     86                 
     87                 // Bottom face
     88                 1.0f, -1.0f, -1.0f,                
     89                 1.0f, -1.0f, 1.0f, 
     90                 -1.0f, -1.0f, -1.0f,
     91                 1.0f, -1.0f, 1.0f,                 
     92                 -1.0f, -1.0f, 1.0f,
     93                 -1.0f, -1.0f, -1.0f,    
     94         };
     95         
     96         final float[] cubeColor = 
     97         {
     98                 // Front face (red)
     99                 1.0f, 0.0f, 0.0f, 1.0f,                
    100                 1.0f, 0.0f, 0.0f, 1.0f,
    101                 1.0f, 0.0f, 0.0f, 1.0f,
    102                 1.0f, 0.0f, 0.0f, 1.0f,                
    103                 1.0f, 0.0f, 0.0f, 1.0f,
    104                 1.0f, 0.0f, 0.0f, 1.0f,
    105                 
    106                 // Right face (green)
    107                 0.0f, 1.0f, 0.0f, 1.0f,                
    108                 0.0f, 1.0f, 0.0f, 1.0f,
    109                 0.0f, 1.0f, 0.0f, 1.0f,
    110                 0.0f, 1.0f, 0.0f, 1.0f,                
    111                 0.0f, 1.0f, 0.0f, 1.0f,
    112                 0.0f, 1.0f, 0.0f, 1.0f,
    113                 
    114                 // Back face (blue)
    115                 0.0f, 0.0f, 1.0f, 1.0f,                
    116                 0.0f, 0.0f, 1.0f, 1.0f,
    117                 0.0f, 0.0f, 1.0f, 1.0f,
    118                 0.0f, 0.0f, 1.0f, 1.0f,                
    119                 0.0f, 0.0f, 1.0f, 1.0f,
    120                 0.0f, 0.0f, 1.0f, 1.0f,
    121                 
    122                 // Left face (yellow)
    123                 1.0f, 1.0f, 0.0f, 1.0f,                
    124                 1.0f, 1.0f, 0.0f, 1.0f,
    125                 1.0f, 1.0f, 0.0f, 1.0f,
    126                 1.0f, 1.0f, 0.0f, 1.0f,                
    127                 1.0f, 1.0f, 0.0f, 1.0f,
    128                 1.0f, 1.0f, 0.0f, 1.0f,
    129                 
    130                 // Top face (cyan)
    131                 0.0f, 1.0f, 1.0f, 1.0f,                
    132                 0.0f, 1.0f, 1.0f, 1.0f,
    133                 0.0f, 1.0f, 1.0f, 1.0f,
    134                 0.0f, 1.0f, 1.0f, 1.0f,                
    135                 0.0f, 1.0f, 1.0f, 1.0f,
    136                 0.0f, 1.0f, 1.0f, 1.0f,
    137                 
    138                 // Bottom face (magenta)
    139                 1.0f, 0.0f, 1.0f, 1.0f,                
    140                 1.0f, 0.0f, 1.0f, 1.0f,
    141                 1.0f, 0.0f, 1.0f, 1.0f,
    142                 1.0f, 0.0f, 1.0f, 1.0f,                
    143                 1.0f, 0.0f, 1.0f, 1.0f,
    144                 1.0f, 0.0f, 1.0f, 1.0f    
    145         };
    146         
    147         final float[] cubeTextureCoordinate =
    148             {                                                
    149                     // Front face
    150                     0.0f, 0.0f,                 
    151                     0.0f, 1.0f,
    152                     1.0f, 0.0f,
    153                     0.0f, 1.0f,
    154                     1.0f, 1.0f,
    155                     1.0f, 0.0f,                
    156                     
    157                     // Right face 
    158                     0.0f, 0.0f,                 
    159                     0.0f, 1.0f,
    160                     1.0f, 0.0f,
    161                     0.0f, 1.0f,
    162                     1.0f, 1.0f,
    163                     1.0f, 0.0f,    
    164                     
    165                     // Back face 
    166                     0.0f, 0.0f,                 
    167                     0.0f, 1.0f,
    168                     1.0f, 0.0f,
    169                     0.0f, 1.0f,
    170                     1.0f, 1.0f,
    171                     1.0f, 0.0f,    
    172                     
    173                     // Left face 
    174                     0.0f, 0.0f,                 
    175                     0.0f, 1.0f,
    176                     1.0f, 0.0f,
    177                     0.0f, 1.0f,
    178                     1.0f, 1.0f,
    179                     1.0f, 0.0f,    
    180                     
    181                     // Top face 
    182                     0.0f, 0.0f,                 
    183                     0.0f, 1.0f,
    184                     1.0f, 0.0f,
    185                     0.0f, 1.0f,
    186                     1.0f, 1.0f,
    187                     1.0f, 0.0f,    
    188                     
    189                     // Bottom face 
    190                     0.0f, 0.0f,                 
    191                     0.0f, 1.0f,
    192                     1.0f, 0.0f,
    193                     0.0f, 1.0f,
    194                     1.0f, 1.0f,
    195                     1.0f, 0.0f
    196             };
    197         
    198         mCubePositions = ByteBuffer.allocateDirect(cubePosition.length * BYTES_PER_FLOAT)
    199                 .order(ByteOrder.nativeOrder()).asFloatBuffer();
    200         mCubePositions.put(cubePosition).position(0);
    201         mCubeColors = ByteBuffer.allocateDirect(cubeColor.length * BYTES_PER_FLOAT)
    202                 .order(ByteOrder.nativeOrder()).asFloatBuffer();
    203         mCubeColors.put(cubeColor).position(0);
    204         mCubeTextureCoordinates = ByteBuffer.allocateDirect(cubeTextureCoordinate.length * BYTES_PER_FLOAT)
    205                 .order(ByteOrder.nativeOrder()).asFloatBuffer();
    206         mCubeTextureCoordinates.put(cubeTextureCoordinate).position(0);
    207     }
    208     
    209     @Override
    210     public void onDrawFrame(GL10 gl) {
    211         // TODO Auto-generated method stub
    212         GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
    213         long time = SystemClock.uptimeMillis() % 10000L;        
    214         float angleInDegrees = (360.0f / 10000.0f) * ((int) time);
    215         GLES20.glUseProgram(mProgramHandle);
    216         mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgramHandle, "u_MVPMatrix");
    217         mTextureUniformHandle = GLES20.glGetUniformLocation(mProgramHandle, "u_Texture");
    218         mPositionHandle = GLES20.glGetAttribLocation(mProgramHandle, "a_Position");
    219         mColorHandle = GLES20.glGetAttribLocation(mProgramHandle, "a_Color");
    220         mTextureCoordinateHandle = GLES20.glGetAttribLocation(mProgramHandle, "a_TexCoordinate");
    221         
    222         GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
    223         GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureDataHandle);
    224         GLES20.glUniform1i(mTextureUniformHandle, 0);
    225         
    226         Matrix.setIdentityM(mModelMatrix, 0);
    227         Matrix.translateM(mModelMatrix, 0, 0.0f, 0.0f, -5.0f);
    228         Matrix.rotateM(mModelMatrix, 0, angleInDegrees, 1.0f, 1.0f, 0.0f);   
    229         drawCube(mCubePositions, mCubeColors, mCubeTextureCoordinates);
    230     }
    231 
    232     private void drawCube(final FloatBuffer cubePositionsBuffer, final FloatBuffer cubeColorsBuffer, final FloatBuffer cubeTextureCoordinatesBuffer)
    233     {
    234         cubePositionsBuffer.position(0);
    235         GLES20.glVertexAttribPointer(mPositionHandle, POSITION_DATA_SIZE, GLES20.GL_FLOAT, false, 0, cubePositionsBuffer);
    236         GLES20.glEnableVertexAttribArray(mPositionHandle);
    237         
    238         cubeColorsBuffer.position(0);
    239         GLES20.glVertexAttribPointer(mColorHandle, COLOR_DATA_SIZE, GLES20.GL_FLOAT, false, 0, cubeColorsBuffer);
    240         GLES20.glEnableVertexAttribArray(mColorHandle);
    241         
    242         cubeTextureCoordinatesBuffer.position(0);
    243         GLES20.glVertexAttribPointer(mTextureCoordinateHandle, TEXTURE_COORDINATE_DATA_SIZE, 
    244                 GLES20.GL_FLOAT, false, 0, cubeTextureCoordinatesBuffer);
    245         GLES20.glEnableVertexAttribArray(mTextureCoordinateHandle);
    246         
    247         Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);   
    248         Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);
    249         GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0);
    250         GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 36);
    251     }
    252     
    253     @Override
    254     public void onSurfaceChanged(GL10 gl, int width, int height) {
    255         // TODO Auto-generated method stub
    256         GLES20.glViewport(0, 0, width, height);
    257         
    258         final float ratio = (float) width / height;
    259         final float left = -ratio;
    260         final float right = ratio;
    261         final float bottom = -1.0f;
    262         final float top = 1.0f;
    263         final float near = 1.0f;
    264         final float far = 10.0f;
    265         
    266         Matrix.frustumM(mProjectionMatrix, 0, left, right, bottom, top, near, far);
    267     }
    268 
    269     @Override
    270     public void onSurfaceCreated(GL10 gl, EGLConfig config) {
    271         // TODO Auto-generated method stub
    272         GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    273         GLES20.glEnable(GLES20.GL_CULL_FACE);
    274         GLES20.glEnable(GLES20.GL_DEPTH_TEST);
    275         // Position the eye behind the origin.
    276         final float eyeX = 0.0f;
    277         final float eyeY = 0.0f;
    278         final float eyeZ = -0.5f;
    279 
    280         // We are looking toward the distance
    281         final float lookX = 0.0f;
    282         final float lookY = 0.0f;
    283         final float lookZ = -5.0f;
    284 
    285         // Set our up vector. This is where our head would be pointing were we holding the camera.
    286         final float upX = 0.0f;
    287         final float upY = 1.0f;
    288         final float upZ = 0.0f;
    289 
    290         // Set the view matrix. This matrix can be said to represent the camera position.
    291         // NOTE: In OpenGL 1, a ModelView matrix is used, which is a combination of a model and
    292         // view matrix. In OpenGL 2, we can keep track of these matrices separately if we choose.
    293         Matrix.setLookAtM(mViewMatrix, 0, eyeX, eyeY, eyeZ, lookX, lookY, lookZ, upX, upY, upZ);
    294         
    295         final String vertexShader = getVertexShader();
    296         final String fragmentShader = getFragmentShader();
    297         
    298         final int vertexShaderHandle = compileShader(GLES20.GL_VERTEX_SHADER, vertexShader);
    299         final int fragmentShaderHandle = compileShader(GLES20.GL_FRAGMENT_SHADER, fragmentShader);
    300         
    301         mProgramHandle = createAndLinkProgram(vertexShaderHandle, fragmentShaderHandle, 
    302                 new String[]{"a_Position", "a_Color", "a_TexCoordinate"});
    303         
    304         mTextureDataHandle = ToolsUtil.loadTexture(mContext, R.drawable.bumpy_bricks_public_domain);
    305         
    306     }
    307     
    308     private String getVertexShader()
    309     {
    310         final String vertexShader =
    311                 "uniform mat4 u_MVPMatrix;      \n"        // A constant representing the combined model/view/projection matrix.
    312                 
    313               + "attribute vec4 a_Position;     \n"        // Per-vertex position information we will pass in.
    314               + "attribute vec4 a_Color;        \n"        // Per-vertex color information we will pass in.    
    315               + "attribute vec2 a_TexCoordinate;\n"    // Per-vertex texture coordinate information we will pass in. 
    316               
    317               + "varying vec4 v_Color;          \n"        // This will be passed into the fragment shader.
    318               + "varying vec2 v_TexCoordinate;  \n"     // This will be passed into the fragment shader.  
    319               
    320               + "void main()                    \n"        // The entry point for our vertex shader.
    321               + "{                              \n"
    322               + "   v_Color = a_Color;          \n"        // Pass the color through to the fragment shader. 
    323                                                           // It will be interpolated across the triangle.
    324               + "   v_TexCoordinate = a_TexCoordinate;\n"// Pass through the texture coordinate.
    325               + "   gl_Position = u_MVPMatrix   \n"     // gl_Position is a special variable used to store the final position.
    326               + "               * a_Position;   \n"     // Multiply the vertex by the matrix to get the final point in                                                                      
    327               + "}                              \n";    // normalized screen coordinates.                                                               \n"; 
    328             
    329         return vertexShader;    
    330     }
    331     
    332     private String getFragmentShader()
    333     {
    334         final String fragmentShader =
    335                 "precision mediump float;       \n"        // Set the default precision to medium. We don't need as high of a 
    336                                                         // precision in the fragment shader.
    337               + "uniform sampler2D u_Texture;   \n"     // The input texture.
    338               + "varying vec4 v_Color;          \n"        // This is the color from the vertex shader interpolated across the 
    339                                                           // triangle per fragment.    
    340               + "varying vec2 v_TexCoordinate;  \n"     // Interpolated texture coordinate per fragment.
    341               
    342               + "void main()                    \n"        // The entry point for our fragment shader.
    343               + "{                              \n"
    344               + "   gl_FragColor = v_Color * texture2D(u_Texture, v_TexCoordinate);     \n"        // Pass the color directly through the pipeline.          
    345               + "}                              \n";
    346             
    347         return fragmentShader;        
    348     }
    349     
    350     private int compileShader(final int shaderType, final String shaderSource)
    351     {
    352         int shaderHandle = GLES20.glCreateShader(shaderType);
    353 
    354         if (shaderHandle != 0) 
    355         {
    356             GLES20.glShaderSource(shaderHandle, shaderSource);
    357             GLES20.glCompileShader(shaderHandle);
    358 
    359             final int[] compileStatus = new int[1];
    360             GLES20.glGetShaderiv(shaderHandle, GLES20.GL_COMPILE_STATUS, compileStatus, 0);
    361 
    362             if (compileStatus[0] == 0) 
    363             {
    364                 Log.e(TAG, "Error compiling shader: " + GLES20.glGetShaderInfoLog(shaderHandle));
    365                 GLES20.glDeleteShader(shaderHandle);
    366                 shaderHandle = 0;
    367             }
    368         }
    369 
    370         if (shaderHandle == 0)
    371         {            
    372             throw new RuntimeException("Error creating shader.");
    373         }
    374         
    375         return shaderHandle;
    376     }
    377     
    378     private int createAndLinkProgram(final int vertexShaderHandle, final int fragmentShaderHandle, final String[] attributes) 
    379     {
    380         int programHandle = GLES20.glCreateProgram();
    381         
    382         if (programHandle != 0) 
    383         {
    384             GLES20.glAttachShader(programHandle, vertexShaderHandle);            
    385             GLES20.glAttachShader(programHandle, fragmentShaderHandle);
    386             
    387             if (attributes != null)
    388             {
    389                 final int size = attributes.length;
    390                 for (int i = 0; i < size; i++)
    391                 {
    392                     GLES20.glBindAttribLocation(programHandle, i, attributes[i]);
    393                 }                        
    394             }
    395             
    396             GLES20.glLinkProgram(programHandle);
    397 
    398             final int[] linkStatus = new int[1];
    399             GLES20.glGetProgramiv(programHandle, GLES20.GL_LINK_STATUS, linkStatus, 0);
    400 
    401             if (linkStatus[0] == 0) 
    402             {                
    403                 Log.e(TAG, "Error compiling program: " + GLES20.glGetProgramInfoLog(programHandle));
    404                 GLES20.glDeleteProgram(programHandle);
    405                 programHandle = 0;
    406             }
    407         }
    408         
    409         if (programHandle == 0)
    410         {
    411             throw new RuntimeException("Error creating program.");
    412         }
    413         
    414         return programHandle;
    415     }
    416     
    417 }

    在Activity里初始化Renderer时要加参数context.

    看效果图:

  • 相关阅读:
    ie下table无法设置宽度的坑,解决方案:在td里面添加div把td宽度撑开即可。
    js simple drag.
    javascript事件捕获机制,dom tree
    WPF,布局,Menu,MenuItem,DockPanel,Grid,DockPanel.Dock='',ToolBar,Content,Image,Uri
    .net IntPtr ==interoperable pointer
    Why do I keep getting mixed tabs and spaces in a Visual Studio C# code window?[vs power tools issue transfered]
    vs nuget package control.
    Introduction to the WinPcap Networking Libraries
    读懂这一篇,集群节点不下线
    函数组合的 N 种模式
  • 原文地址:https://www.cnblogs.com/jayceli/p/2475559.html
Copyright © 2020-2023  润新知