zoukankan      html  css  js  c++  java
  • Android OpenGL ES 2.0 (三) 灯光pervertex lighting

    画完立方体后,在立方体旁边加了一个灯光point light,也加上了旋转效果。

    这里新加了normal data,用来作光计算的。

    这里用的是per vertex lighting,所以光移动到立方体顶点位置的时候,可以看到,立方体平面的对边顶点沿线周围部分会特别亮。

    对光的计算都在物体的vertex shader里。

    Test3Renderer.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 android.opengl.GLES20;
     11 import android.opengl.Matrix;
     12 import android.opengl.GLSurfaceView;
     13 import android.os.SystemClock;
     14 import android.util.Log;
     15 
     16 public class Test3Renderer implements GLSurfaceView.Renderer
     17 {
     18     private static final String TAG = "Test3Renderer";
     19     private static final int BYTES_PER_FLOAT = 4;
     20     private final FloatBuffer mCubePositions;
     21     private final FloatBuffer mCubeColors;
     22     private final FloatBuffer mCubeNormals;
     23     
     24     private float[] mMVPMatrix = new float[16];
     25     private float[] mViewMatrix = new float[16];
     26     private float[] mModelMatrix = new float[16];
     27     private float[] mProjectionMatrix = new float[16];
     28     private float[] mLightModelMatrix = new float[16];
     29     
     30     private final float[] mLightPosInModelSpace = new float[] {0.0f, 0.0f, 0.0f, 1.0f};
     31     private final float[] mLightPosInWorldSpace = new float[4];
     32     private final float[] mLightPosInEyeSpace = new float[4];
     33     
     34     private int mMVPMatrixHandle;
     35     private int mMVMatrixHandle;
     36     private int mPositionHandle;
     37     private int mLightPosHandle;
     38     private int mColorHandle;
     39     private int mNormalHandle;
     40     private int mPerVertexProgramHandle;
     41     private int mPointProgramHandle;
     42     private final int POSITION_DATA_SIZE = 3;
     43     private final int COLOR_DATA_SIZE = 4;
     44     private final int NORMAL_DATA_SIZE = 3;
     45     
     46     public Test3Renderer()
     47     {
     48         final float cubePosition[] = 
     49         {
     50                 // Front face
     51                 -1.0f, 1.0f, 1.0f,                
     52                 -1.0f, -1.0f, 1.0f,
     53                 1.0f, 1.0f, 1.0f, 
     54                 -1.0f, -1.0f, 1.0f,                 
     55                 1.0f, -1.0f, 1.0f,
     56                 1.0f, 1.0f, 1.0f,
     57                 
     58                 // Right face
     59                 1.0f, 1.0f, 1.0f,                
     60                 1.0f, -1.0f, 1.0f,
     61                 1.0f, 1.0f, -1.0f,
     62                 1.0f, -1.0f, 1.0f,                
     63                 1.0f, -1.0f, -1.0f,
     64                 1.0f, 1.0f, -1.0f,
     65                 
     66                 // Back face
     67                 1.0f, 1.0f, -1.0f,                
     68                 1.0f, -1.0f, -1.0f,
     69                 -1.0f, 1.0f, -1.0f,
     70                 1.0f, -1.0f, -1.0f,                
     71                 -1.0f, -1.0f, -1.0f,
     72                 -1.0f, 1.0f, -1.0f,
     73                 
     74                 // Left face
     75                 -1.0f, 1.0f, -1.0f,                
     76                 -1.0f, -1.0f, -1.0f,
     77                 -1.0f, 1.0f, 1.0f, 
     78                 -1.0f, -1.0f, -1.0f,                
     79                 -1.0f, -1.0f, 1.0f, 
     80                 -1.0f, 1.0f, 1.0f, 
     81                 
     82                 // Top face
     83                 -1.0f, 1.0f, -1.0f,                
     84                 -1.0f, 1.0f, 1.0f, 
     85                 1.0f, 1.0f, -1.0f, 
     86                 -1.0f, 1.0f, 1.0f,                 
     87                 1.0f, 1.0f, 1.0f, 
     88                 1.0f, 1.0f, -1.0f,
     89                 
     90                 // Bottom face
     91                 1.0f, -1.0f, -1.0f,                
     92                 1.0f, -1.0f, 1.0f, 
     93                 -1.0f, -1.0f, -1.0f,
     94                 1.0f, -1.0f, 1.0f,                 
     95                 -1.0f, -1.0f, 1.0f,
     96                 -1.0f, -1.0f, -1.0f,    
     97         };
     98         
     99         final float[] cubeColor = 
    100         {
    101                 // Front face (red)
    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                 1.0f, 0.0f, 0.0f, 1.0f,                
    106                 1.0f, 0.0f, 0.0f, 1.0f,
    107                 1.0f, 0.0f, 0.0f, 1.0f,
    108                 
    109                 // Right face (green)
    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                 0.0f, 1.0f, 0.0f, 1.0f,                
    114                 0.0f, 1.0f, 0.0f, 1.0f,
    115                 0.0f, 1.0f, 0.0f, 1.0f,
    116                 
    117                 // Back face (blue)
    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                 0.0f, 0.0f, 1.0f, 1.0f,                
    122                 0.0f, 0.0f, 1.0f, 1.0f,
    123                 0.0f, 0.0f, 1.0f, 1.0f,
    124                 
    125                 // Left face (yellow)
    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                 1.0f, 1.0f, 0.0f, 1.0f,                
    130                 1.0f, 1.0f, 0.0f, 1.0f,
    131                 1.0f, 1.0f, 0.0f, 1.0f,
    132                 
    133                 // Top face (cyan)
    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                 0.0f, 1.0f, 1.0f, 1.0f,                
    138                 0.0f, 1.0f, 1.0f, 1.0f,
    139                 0.0f, 1.0f, 1.0f, 1.0f,
    140                 
    141                 // Bottom face (magenta)
    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                 1.0f, 0.0f, 1.0f, 1.0f,                
    146                 1.0f, 0.0f, 1.0f, 1.0f,
    147                 1.0f, 0.0f, 1.0f, 1.0f    
    148         };
    149         
    150         final float[] cubeNormal =
    151             {                                                
    152                     // Front face
    153                     0.0f, 0.0f, 1.0f,                
    154                     0.0f, 0.0f, 1.0f,
    155                     0.0f, 0.0f, 1.0f,
    156                     0.0f, 0.0f, 1.0f,                
    157                     0.0f, 0.0f, 1.0f,
    158                     0.0f, 0.0f, 1.0f,
    159                     
    160                     // Right face 
    161                     1.0f, 0.0f, 0.0f,                
    162                     1.0f, 0.0f, 0.0f,
    163                     1.0f, 0.0f, 0.0f,
    164                     1.0f, 0.0f, 0.0f,                
    165                     1.0f, 0.0f, 0.0f,
    166                     1.0f, 0.0f, 0.0f,
    167                     
    168                     // Back face 
    169                     0.0f, 0.0f, -1.0f,                
    170                     0.0f, 0.0f, -1.0f,
    171                     0.0f, 0.0f, -1.0f,
    172                     0.0f, 0.0f, -1.0f,                
    173                     0.0f, 0.0f, -1.0f,
    174                     0.0f, 0.0f, -1.0f,
    175                     
    176                     // Left face 
    177                     -1.0f, 0.0f, 0.0f,                
    178                     -1.0f, 0.0f, 0.0f,
    179                     -1.0f, 0.0f, 0.0f,
    180                     -1.0f, 0.0f, 0.0f,                
    181                     -1.0f, 0.0f, 0.0f,
    182                     -1.0f, 0.0f, 0.0f,
    183                     
    184                     // Top face 
    185                     0.0f, 1.0f, 0.0f,            
    186                     0.0f, 1.0f, 0.0f,
    187                     0.0f, 1.0f, 0.0f,
    188                     0.0f, 1.0f, 0.0f,                
    189                     0.0f, 1.0f, 0.0f,
    190                     0.0f, 1.0f, 0.0f,
    191                     
    192                     // Bottom face 
    193                     0.0f, -1.0f, 0.0f,            
    194                     0.0f, -1.0f, 0.0f,
    195                     0.0f, -1.0f, 0.0f,
    196                     0.0f, -1.0f, 0.0f,                
    197                     0.0f, -1.0f, 0.0f,
    198                     0.0f, -1.0f, 0.0f
    199             };
    200         
    201         mCubePositions = ByteBuffer.allocateDirect(cubePosition.length * BYTES_PER_FLOAT)
    202                 .order(ByteOrder.nativeOrder()).asFloatBuffer();
    203         mCubePositions.put(cubePosition).position(0);
    204         mCubeColors = ByteBuffer.allocateDirect(cubeColor.length * BYTES_PER_FLOAT)
    205                 .order(ByteOrder.nativeOrder()).asFloatBuffer();
    206         mCubeColors.put(cubeColor).position(0);
    207         mCubeNormals = ByteBuffer.allocateDirect(cubeNormal.length * BYTES_PER_FLOAT)
    208                 .order(ByteOrder.nativeOrder()).asFloatBuffer();
    209         mCubeNormals.put(cubeNormal).position(0);
    210     }
    211     
    212     @Override
    213     public void onDrawFrame(GL10 gl) {
    214         // TODO Auto-generated method stub
    215         GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
    216         long time = SystemClock.uptimeMillis() % 10000L;        
    217         float angleInDegrees = (360.0f / 10000.0f) * ((int) time);
    218         
    219         GLES20.glUseProgram(mPerVertexProgramHandle);
    220         mMVPMatrixHandle = GLES20.glGetUniformLocation(mPerVertexProgramHandle, "u_MVPMatrix");
    221         mPositionHandle = GLES20.glGetAttribLocation(mPerVertexProgramHandle, "a_Position");
    222         mMVMatrixHandle = GLES20.glGetUniformLocation(mPerVertexProgramHandle, "u_MVMatrix"); 
    223         mLightPosHandle = GLES20.glGetUniformLocation(mPerVertexProgramHandle, "u_LightPos");
    224         mColorHandle = GLES20.glGetAttribLocation(mPerVertexProgramHandle, "a_Color");
    225         mNormalHandle = GLES20.glGetAttribLocation(mPerVertexProgramHandle, "a_Normal"); 
    226         
    227         Matrix.setIdentityM(mLightModelMatrix, 0);
    228         Matrix.translateM(mLightModelMatrix, 0, 0.0f, 0.0f, -5.0f);      
    229         Matrix.rotateM(mLightModelMatrix, 0, angleInDegrees, 0.0f, 1.0f, 0.0f);
    230         Matrix.translateM(mLightModelMatrix, 0, 0.0f, 0.0f, 2.0f);
    231                
    232         Matrix.multiplyMV(mLightPosInWorldSpace, 0, mLightModelMatrix, 0, mLightPosInModelSpace, 0);
    233         Matrix.multiplyMV(mLightPosInEyeSpace, 0, mViewMatrix, 0, mLightPosInWorldSpace, 0); 
    234         
    235         Matrix.setIdentityM(mModelMatrix, 0);
    236         Matrix.translateM(mModelMatrix, 0, 0.0f, 0.0f, -5.0f);
    237         Matrix.rotateM(mModelMatrix, 0, angleInDegrees, 1.0f, 1.0f, 0.0f);   
    238         drawCube(mCubePositions, mCubeColors, mCubeNormals);
    239         
    240         GLES20.glUseProgram(mPointProgramHandle);
    241         drawLight();
    242     }
    243 
    244     private void drawCube(final FloatBuffer cubePositionsBuffer, final FloatBuffer cubeColorsBuffer,final FloatBuffer cubeNormalsBuffer)
    245     {
    246         cubePositionsBuffer.position(0);
    247         GLES20.glVertexAttribPointer(mPositionHandle, POSITION_DATA_SIZE, GLES20.GL_FLOAT, false, 0, cubePositionsBuffer);
    248         GLES20.glEnableVertexAttribArray(mPositionHandle);
    249         
    250         cubeColorsBuffer.position(0);
    251         GLES20.glVertexAttribPointer(mColorHandle, COLOR_DATA_SIZE, GLES20.GL_FLOAT, false, 0, cubeColorsBuffer);
    252         GLES20.glEnableVertexAttribArray(mColorHandle);
    253         
    254         cubeNormalsBuffer.position(0);
    255         GLES20.glVertexAttribPointer(mNormalHandle, NORMAL_DATA_SIZE, GLES20.GL_FLOAT, false, 0, cubeNormalsBuffer);
    256         GLES20.glEnableVertexAttribArray(mNormalHandle);
    257         
    258         Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);   
    259         GLES20.glUniformMatrix4fv(mMVMatrixHandle, 1, false, mMVPMatrix, 0); 
    260         
    261         Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);
    262         GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0);
    263         
    264         GLES20.glUniform3f(mLightPosHandle, mLightPosInEyeSpace[0], mLightPosInEyeSpace[1], mLightPosInEyeSpace[2]);
    265         
    266         GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 36);
    267     }
    268     
    269     private void drawLight()
    270     {
    271         final int pointMVPMatrixHandle = GLES20.glGetUniformLocation(mPointProgramHandle, "u_MVPMatrix");
    272         final int pointPositionHandle = GLES20.glGetAttribLocation(mPointProgramHandle, "a_Position");
    273         
    274         GLES20.glVertexAttrib3f(pointPositionHandle, mLightPosInModelSpace[0], mLightPosInModelSpace[1], mLightPosInModelSpace[2]);
    275         GLES20.glDisableVertexAttribArray(pointPositionHandle); 
    276         
    277         Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mLightModelMatrix, 0);
    278         Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);
    279         GLES20.glUniformMatrix4fv(pointMVPMatrixHandle, 1, false, mMVPMatrix, 0);
    280         
    281         GLES20.glDrawArrays(GLES20.GL_POINTS, 0, 1);
    282     }
    283     
    284     @Override
    285     public void onSurfaceChanged(GL10 gl, int width, int height) {
    286         // TODO Auto-generated method stub
    287         GLES20.glViewport(0, 0, width, height);
    288         
    289         final float ratio = (float) width / height;
    290         final float left = -ratio;
    291         final float right = ratio;
    292         final float bottom = -1.0f;
    293         final float top = 1.0f;
    294         final float near = 1.0f;
    295         final float far = 10.0f;
    296         
    297         Matrix.frustumM(mProjectionMatrix, 0, left, right, bottom, top, near, far);
    298     }
    299 
    300     @Override
    301     public void onSurfaceCreated(GL10 gl, EGLConfig config) {
    302         // TODO Auto-generated method stub
    303         GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    304         GLES20.glEnable(GLES20.GL_CULL_FACE);
    305         GLES20.glEnable(GLES20.GL_DEPTH_TEST);
    306         // Position the eye behind the origin.
    307         final float eyeX = 0.0f;
    308         final float eyeY = 0.0f;
    309         final float eyeZ = -0.5f;
    310 
    311         // We are looking toward the distance
    312         final float lookX = 0.0f;
    313         final float lookY = 0.0f;
    314         final float lookZ = -5.0f;
    315 
    316         // Set our up vector. This is where our head would be pointing were we holding the camera.
    317         final float upX = 0.0f;
    318         final float upY = 1.0f;
    319         final float upZ = 0.0f;
    320 
    321         // Set the view matrix. This matrix can be said to represent the camera position.
    322         // NOTE: In OpenGL 1, a ModelView matrix is used, which is a combination of a model and
    323         // view matrix. In OpenGL 2, we can keep track of these matrices separately if we choose.
    324         Matrix.setLookAtM(mViewMatrix, 0, eyeX, eyeY, eyeZ, lookX, lookY, lookZ, upX, upY, upZ);
    325         
    326         final String vertexShader = getVertexShader();
    327         final String fragmentShader = getFragmentShader();
    328         
    329         final int vertexShaderHandle = compileShader(GLES20.GL_VERTEX_SHADER, vertexShader);
    330         final int fragmentShaderHandle = compileShader(GLES20.GL_FRAGMENT_SHADER, fragmentShader);
    331         mPerVertexProgramHandle = createAndLinkProgram(vertexShaderHandle, fragmentShaderHandle, 
    332                 new String[]{"a_Position", "a_Color", "a_Normal"});
    333         
    334         final String pointVertexShader =
    335                 "uniform mat4 u_MVPMatrix;      \n"        
    336               +    "attribute vec4 a_Position;     \n"        
    337               + "void main()                    \n"
    338               + "{                              \n"
    339               + "   gl_Position = u_MVPMatrix   \n"
    340               + "               * a_Position;   \n"
    341               + "   gl_PointSize = 20.0;         \n"
    342               + "}                              \n";
    343             
    344         final String pointFragmentShader = 
    345                 "precision mediump float;       \n"                              
    346               + "void main()                    \n"
    347               + "{                              \n"
    348               + "   gl_FragColor = vec4(1.0,    \n" 
    349               + "   1.0, 1.0, 1.0);             \n"
    350               + "}                              \n";
    351         
    352         final int pointVertexShaderHandle = compileShader(GLES20.GL_VERTEX_SHADER, pointVertexShader);
    353         final int pointFragmentShaderHandle = compileShader(GLES20.GL_FRAGMENT_SHADER, pointFragmentShader);
    354         mPointProgramHandle = createAndLinkProgram(pointVertexShaderHandle, pointFragmentShaderHandle,
    355                 new String[]{"a_Position"});    
    356         
    357     }
    358     
    359     private String getVertexShader()
    360     {
    361         final String vertexShader =
    362                 "uniform mat4 u_MVPMatrix;      \n"        // A constant representing the combined model/view/projection matrix.
    363               + "uniform mat4 u_MVMatrix;       \n"        // A constant representing the combined model/view matrix.    
    364               + "uniform vec3 u_LightPos;       \n"        // The position of the light in eye space.
    365                 
    366               + "attribute vec4 a_Position;     \n"        // Per-vertex position information we will pass in.
    367               + "attribute vec4 a_Color;        \n"        // Per-vertex color information we will pass in.
    368               + "attribute vec3 a_Normal;       \n"        // Per-vertex normal information we will pass in.
    369               
    370               + "varying vec4 v_Color;          \n"        // This will be passed into the fragment shader.
    371               
    372               + "void main()                    \n"     // The entry point for our vertex shader.
    373               + "{                              \n"        
    374             // Transform the vertex into eye space.
    375               + "   vec3 modelViewVertex = vec3(u_MVMatrix * a_Position);              \n"
    376             // Transform the normal's orientation into eye space.
    377               + "   vec3 modelViewNormal = vec3(u_MVMatrix * vec4(a_Normal, 0.0));     \n"
    378             // Will be used for attenuation.
    379               + "   float distance = length(u_LightPos - modelViewVertex);             \n"
    380             // Get a lighting direction vector from the light to the vertex.
    381               + "   vec3 lightVector = normalize(u_LightPos - modelViewVertex);        \n"
    382             // Calculate the dot product of the light vector and vertex normal. If the normal and light vector are
    383             // pointing in the same direction then it will get max illumination.
    384               + "   float diffuse = max(dot(modelViewNormal, lightVector), 0.1);       \n"                                                                       
    385             // Attenuate the light based on distance.
    386               + "   diffuse = diffuse * (1.0 / (1.0 + (0.25 * distance * distance)));  \n"
    387             // Multiply the color by the illumination level. It will be interpolated across the triangle.
    388               + "   v_Color = a_Color * diffuse;                                       \n"      
    389             // gl_Position is a special variable used to store the final position.
    390             // Multiply the vertex by the matrix to get the final point in normalized screen coordinates.        
    391               + "   gl_Position = u_MVPMatrix * a_Position;                            \n"     
    392               + "}                                                                     \n"; 
    393             
    394         return vertexShader;    
    395     }
    396     
    397     private String getFragmentShader()
    398     {
    399         final String fragmentShader =
    400                 "precision mediump float;       \n"        // Set the default precision to medium. We don't need as high of a 
    401                                                         // precision in the fragment shader.                
    402               + "varying vec4 v_Color;          \n"        // This is the color from the vertex shader interpolated across the 
    403                                                           // triangle per fragment.              
    404               + "void main()                    \n"        // The entry point for our fragment shader.
    405               + "{                              \n"
    406               + "   gl_FragColor = v_Color;     \n"        // Pass the color directly through the pipeline.          
    407               + "}                              \n";
    408             
    409         return fragmentShader;        
    410     }
    411     
    412     private int compileShader(final int shaderType, final String shaderSource)
    413     {
    414         int shaderHandle = GLES20.glCreateShader(shaderType);
    415 
    416         if (shaderHandle != 0) 
    417         {
    418             GLES20.glShaderSource(shaderHandle, shaderSource);
    419             GLES20.glCompileShader(shaderHandle);
    420 
    421             final int[] compileStatus = new int[1];
    422             GLES20.glGetShaderiv(shaderHandle, GLES20.GL_COMPILE_STATUS, compileStatus, 0);
    423 
    424             if (compileStatus[0] == 0) 
    425             {
    426                 Log.e(TAG, "Error compiling shader: " + GLES20.glGetShaderInfoLog(shaderHandle));
    427                 GLES20.glDeleteShader(shaderHandle);
    428                 shaderHandle = 0;
    429             }
    430         }
    431 
    432         if (shaderHandle == 0)
    433         {            
    434             throw new RuntimeException("Error creating shader.");
    435         }
    436         
    437         return shaderHandle;
    438     }
    439     
    440     private int createAndLinkProgram(final int vertexShaderHandle, final int fragmentShaderHandle, final String[] attributes) 
    441     {
    442         int programHandle = GLES20.glCreateProgram();
    443         
    444         if (programHandle != 0) 
    445         {
    446             GLES20.glAttachShader(programHandle, vertexShaderHandle);            
    447             GLES20.glAttachShader(programHandle, fragmentShaderHandle);
    448             
    449             if (attributes != null)
    450             {
    451                 final int size = attributes.length;
    452                 for (int i = 0; i < size; i++)
    453                 {
    454                     GLES20.glBindAttribLocation(programHandle, i, attributes[i]);
    455                 }                        
    456             }
    457             
    458             GLES20.glLinkProgram(programHandle);
    459 
    460             final int[] linkStatus = new int[1];
    461             GLES20.glGetProgramiv(programHandle, GLES20.GL_LINK_STATUS, linkStatus, 0);
    462 
    463             if (linkStatus[0] == 0) 
    464             {                
    465                 Log.e(TAG, "Error compiling program: " + GLES20.glGetProgramInfoLog(programHandle));
    466                 GLES20.glDeleteProgram(programHandle);
    467                 programHandle = 0;
    468             }
    469         }
    470         
    471         if (programHandle == 0)
    472         {
    473             throw new RuntimeException("Error creating program.");
    474         }
    475         
    476         return programHandle;
    477     }
    478 }

    这个程序里,把生成物体vertex shader 和 gragment shader的source string单独提取出了两个方法,便于使用。

    分别是getVertexShader和getFragmentShader。

    同样,把编译shader也提取成方法compileShader。

    还有生成和连接program的方法createAndLinkProgram。

    看下效果图:

  • 相关阅读:
    个人介绍
    实验三
    第二次实验
    实验一
    ATM管理系统
    第二次作业
    实验四 决策树算法及应用
    实验三 朴素贝叶斯算法及应用
    实验二 K-近邻算法及应用
    实验一 感知器及其应用
  • 原文地址:https://www.cnblogs.com/jayceli/p/2475091.html
Copyright © 2011-2022 走看看