Android OpenGL ES 2.0 (六) 混合blending

现在来看看的blending效果。

blending分为Additive blending,Multiplicative blending和Interpolative blending。

对应的方法分别为

glBlendFunc(GL_ONE, GL_ONE),

glBlendFunc(GL_DST_COLOR, GL_ZERO)和

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

现在就用Additive blending来写个例子。

这里的GLSurfaceView要处理点击消息来开启和关闭blending效果,所以单独提取一个类。

Test6SurfaceView.java

 1 package com.android.jayce.test;
 2 
 3 import android.content.Context;
 4 import android.opengl.GLSurfaceView;
 5 import android.view.MotionEvent;
 6 
 7 public class Test6SurfaceView extends GLSurfaceView
 8 {
 9     private Test6Renderer mRenderer;
10     
11     public Test6SurfaceView(Context context) {
12         super(context);
13         // TODO Auto-generated constructor stub
14     }
15     
16     public boolean onTouchEvent(MotionEvent event)
17     {
18         if(event != null)
19         {
20             if(event.getAction() == MotionEvent.ACTION_DOWN)
21             {
22                 if(mRenderer != null)
23                 {
24                     queueEvent(new Runnable(){
25 
26                         @Override
27                         public void run() {
28                             // TODO Auto-generated method stub
29                             mRenderer.switchMode();
30                         }});
31                     return true;
32                 }
33             }
34         }
35         return super.onTouchEvent(event);
36     }
37     
38     public void setRenderer(Test6Renderer renderer)
39     {
40         mRenderer = renderer;
41         super.setRenderer(renderer);
42     }
43     
44 }

Renderer里面开关blending效果在switchMode里。

开启是:
            GLES20.glDisable(GLES20.GL_CULL_FACE);
            GLES20.glDisable(GLES20.GL_DEPTH_TEST);
            GLES20.glEnable(GLES20.GL_BLEND);
            GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE);

关闭是:

     GLES20.glEnable(GLES20.GL_CULL_FACE);
            GLES20.glEnable(GLES20.GL_DEPTH_TEST);
            GLES20.glDisable(GLES20.GL_BLEND);

看完整代码:

Test6Renderer.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.common.ShapeBuilder;
 11 
 12 import android.opengl.GLES20;
 13 import android.opengl.Matrix;
 14 import android.opengl.GLSurfaceView;
 15 import android.os.SystemClock;
 16 
 17 public class Test6Renderer implements GLSurfaceView.Renderer
 18 {
 19     private static final int BYTES_PER_FLOAT = 4;
 20     private final FloatBuffer mCubePositions;
 21     private final FloatBuffer mCubeColors;
 22     private float[] mMVPMatrix = new float[16];
 23     private float[] mViewMatrix = new float[16];
 24     private float[] mModelMatrix = new float[16];
 25     private float[] mProjectionMatrix = new float[16];
 26     private int mMVPMatrixHandle;
 27     private int mPositionHandle;
 28     private int mColorHandle;
 29     private int mProgramHandle;
 30     private final int POSITION_DATA_SIZE = 3;
 31     private final int COLOR_DATA_SIZE = 4;
 32     private boolean mBlending = true;
 33     
 34     public Test6Renderer()
 35     {
 36         final float[] p1p = {-1.0f, 1.0f, 1.0f};                    
 37         final float[] p2p = {1.0f, 1.0f, 1.0f};
 38         final float[] p3p = {-1.0f, -1.0f, 1.0f};
 39         final float[] p4p = {1.0f, -1.0f, 1.0f};
 40         final float[] p5p = {-1.0f, 1.0f, -1.0f};
 41         final float[] p6p = {1.0f, 1.0f, -1.0f};
 42         final float[] p7p = {-1.0f, -1.0f, -1.0f};
 43         final float[] p8p = {1.0f, -1.0f, -1.0f};
 44         final float[] cubePosition = ShapeBuilder.generateCubeData(p1p, p2p, p3p, p4p, p5p, p6p, p7p, p8p, p1p.length);
 45         
 46         final float[] p1c = {1.0f, 0.0f, 0.0f, 1.0f};        // red            
 47         final float[] p2c = {1.0f, 0.0f, 1.0f, 1.0f};        // magenta
 48         final float[] p3c = {0.0f, 0.0f, 0.0f, 1.0f};        // black
 49         final float[] p4c = {0.0f, 0.0f, 1.0f, 1.0f};        // blue
 50         final float[] p5c = {1.0f, 1.0f, 0.0f, 1.0f};        // yellow
 51         final float[] p6c = {1.0f, 1.0f, 1.0f, 1.0f};        // white
 52         final float[] p7c = {0.0f, 1.0f, 0.0f, 1.0f};        // green
 53         final float[] p8c = {0.0f, 1.0f, 1.0f, 1.0f};        // cyan
 54         
 55         final float[] cubeColor = ShapeBuilder.generateCubeData(p1c, p2c, p3c, p4c, p5c, p6c, p7c, p8c, p1c.length);
 56         
 57         mCubePositions = ByteBuffer.allocateDirect(cubePosition.length * BYTES_PER_FLOAT)
 58                 .order(ByteOrder.nativeOrder()).asFloatBuffer();
 59         mCubePositions.put(cubePosition).position(0);
 60         mCubeColors = ByteBuffer.allocateDirect(cubeColor.length * BYTES_PER_FLOAT)
 61                 .order(ByteOrder.nativeOrder()).asFloatBuffer();
 62         mCubeColors.put(cubeColor).position(0);
 63     }
 64     
 65     @Override
 66     public void onDrawFrame(GL10 gl) {
 67         // TODO Auto-generated method stub
 68         if (mBlending)
 69         {
 70             GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
 71         }
 72         else
 73         {
 74             GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
 75         }
 76         long time = SystemClock.uptimeMillis() % 10000L;        
 77         float angleInDegrees = (360.0f / 10000.0f) * ((int) time);
 78         GLES20.glUseProgram(mProgramHandle);
 79         mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgramHandle, "u_MVPMatrix");
 80         mPositionHandle = GLES20.glGetAttribLocation(mProgramHandle, "a_Position");
 81         mColorHandle = GLES20.glGetAttribLocation(mProgramHandle, "a_Color");
 82         
 83         Matrix.setIdentityM(mModelMatrix, 0);
 84         Matrix.translateM(mModelMatrix, 0, 0.0f, 0.0f, -5.0f);
 85         Matrix.rotateM(mModelMatrix, 0, angleInDegrees, 1.0f, 1.0f, 0.0f);   
 86         drawCube(mCubePositions, mCubeColors);
 87     }
 88 
 89     public void switchMode()
 90     {        
 91         mBlending = !mBlending;
 92         
 93         if (mBlending)
 94         {
 95             // No culling of back faces
 96             GLES20.glDisable(GLES20.GL_CULL_FACE);
 97             
 98             // No depth testing
 99             GLES20.glDisable(GLES20.GL_DEPTH_TEST);
100             
101             // Enable blending
102             GLES20.glEnable(GLES20.GL_BLEND);
103             GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE);            
104         }
105         else
106         {
107             // Cull back faces
108             GLES20.glEnable(GLES20.GL_CULL_FACE);
109             
110             // Enable depth testing
111             GLES20.glEnable(GLES20.GL_DEPTH_TEST);
112             
113             // Disable blending
114             GLES20.glDisable(GLES20.GL_BLEND);
115         }
116     }
117     
118     private void drawCube(final FloatBuffer cubePositionsBuffer, final FloatBuffer cubeColorsBuffer)
119     {
120         cubePositionsBuffer.position(0);
121         GLES20.glVertexAttribPointer(mPositionHandle, POSITION_DATA_SIZE, GLES20.GL_FLOAT, false, 0, cubePositionsBuffer);
122         GLES20.glEnableVertexAttribArray(mPositionHandle);
123         
124         cubeColorsBuffer.position(0);
125         GLES20.glVertexAttribPointer(mColorHandle, COLOR_DATA_SIZE, GLES20.GL_FLOAT, false, 0, cubeColorsBuffer);
126         GLES20.glEnableVertexAttribArray(mColorHandle);
127         Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);   
128         Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);
129         
130         GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0);
131         GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 36);
132     }
133     
134     @Override
135     public void onSurfaceChanged(GL10 gl, int width, int height) {
136         // TODO Auto-generated method stub
137         GLES20.glViewport(0, 0, width, height);
138         
139         final float ratio = (float) width / height;
140         final float left = -ratio;
141         final float right = ratio;
142         final float bottom = -1.0f;
143         final float top = 1.0f;
144         final float near = 1.0f;
145         final float far = 10.0f;
146         
147         Matrix.frustumM(mProjectionMatrix, 0, left, right, bottom, top, near, far);
148     }
149 
150     @Override
151     public void onSurfaceCreated(GL10 gl, EGLConfig config) {
152         // TODO Auto-generated method stub
153         GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
154         GLES20.glDisable(GLES20.GL_CULL_FACE);
155         GLES20.glDisable(GLES20.GL_DEPTH_TEST);
156         
157         GLES20.glEnable(GLES20.GL_BLEND);
158         GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE);
159         
160         // Position the eye behind the origin.
161         final float eyeX = 0.0f;
162         final float eyeY = 0.0f;
163         final float eyeZ = -0.5f;
164 
165         // We are looking toward the distance
166         final float lookX = 0.0f;
167         final float lookY = 0.0f;
168         final float lookZ = -5.0f;
169 
170         // Set our up vector. This is where our head would be pointing were we holding the camera.
171         final float upX = 0.0f;
172         final float upY = 1.0f;
173         final float upZ = 0.0f;
174 
175         // Set the view matrix. This matrix can be said to represent the camera position.
176         // NOTE: In OpenGL 1, a ModelView matrix is used, which is a combination of a model and
177         // view matrix. In OpenGL 2, we can keep track of these matrices separately if we choose.
178         Matrix.setLookAtM(mViewMatrix, 0, eyeX, eyeY, eyeZ, lookX, lookY, lookZ, upX, upY, upZ);
179         
180         final String vertexShader =
181                 "uniform mat4 u_MVPMatrix;      \n"        // A constant representing the combined model/view/projection matrix.
182                 
183               + "attribute vec4 a_Position;     \n"        // Per-vertex position information we will pass in.
184               + "attribute vec4 a_Color;        \n"        // Per-vertex color information we will pass in.              
185               + "varying vec4 v_Color;          \n"        // This will be passed into the fragment shader.
186               
187               + "void main()                    \n"        // The entry point for our vertex shader.
188               + "{                              \n"
189               + "   v_Color = a_Color;          \n"        // Pass the color through to the fragment shader. 
190                                                           // It will be interpolated across the triangle.
191               + "   gl_Position = u_MVPMatrix   \n"     // gl_Position is a special variable used to store the final position.
192               + "               * a_Position;   \n"     // Multiply the vertex by the matrix to get the final point in                                                                      
193               + "}                              \n";    // normalized screen coordinates.
194             
195         final String fragmentShader =
196                 "precision mediump float;       \n"        // Set the default precision to medium. We don't need as high of a 
197                                                         // precision in the fragment shader.                
198               + "varying vec4 v_Color;          \n"        // This is the color from the vertex shader interpolated across the 
199                                                           // triangle per fragment.              
200               + "void main()                    \n"        // The entry point for our fragment shader.
201               + "{                              \n"
202               + "   gl_FragColor = v_Color;     \n"        // Pass the color directly through the pipeline.          
203               + "}                              \n";    
204             
205         int vertexShaderHandle = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
206         if(vertexShaderHandle != 0)
207         {
208             GLES20.glShaderSource(vertexShaderHandle, vertexShader);
209             GLES20.glCompileShader(vertexShaderHandle);
210             
211             final int[] compileStatus = new int[1];
212             GLES20.glGetShaderiv(vertexShaderHandle, GLES20.GL_COMPILE_STATUS, compileStatus, 0);
213             
214             if(compileStatus[0] == 0)
215             {
216                 GLES20.glDeleteShader(vertexShaderHandle);
217                 vertexShaderHandle = 0;
218             }
219         }
220         
221         if(vertexShaderHandle == 0)
222         {
223             throw new RuntimeException("failed to creating vertex shader");
224         }
225         
226         int fragmentShaderHandle = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
227         if(fragmentShaderHandle != 0)
228         {
229             GLES20.glShaderSource(fragmentShaderHandle, fragmentShader);
230             GLES20.glCompileShader(fragmentShaderHandle);
231             
232             final int[] compileStatus = new int[1];
233             GLES20.glGetShaderiv(fragmentShaderHandle, GLES20.GL_COMPILE_STATUS, compileStatus, 0);
234             
235             if(compileStatus[0] == 0)
236             {
237                 GLES20.glDeleteShader(fragmentShaderHandle);
238                 fragmentShaderHandle = 0;
239             }
240             
241         }
242         
243         if(fragmentShaderHandle == 0)
244         {
245             throw new RuntimeException("failed to create fragment shader");
246         }
247         
248         mProgramHandle = GLES20.glCreateProgram();
249         if(mProgramHandle != 0)
250         {
251             GLES20.glAttachShader(mProgramHandle, vertexShaderHandle);
252             GLES20.glAttachShader(mProgramHandle, fragmentShaderHandle);
253             
254             GLES20.glBindAttribLocation(mProgramHandle, 0, "a_Position");
255             GLES20.glBindAttribLocation(mProgramHandle, 1, "a_Color");
256             
257             GLES20.glLinkProgram(mProgramHandle);
258             
259             final int[] linkStatus = new int[1];
260             GLES20.glGetProgramiv(mProgramHandle, GLES20.GL_LINK_STATUS, linkStatus, 0);
261             
262             if(linkStatus[0] == 0)
263             {
264                 GLES20.glDeleteProgram(mProgramHandle);
265                 mProgramHandle = 0;
266             }
267         }
268         
269         if(mProgramHandle == 0)
270         {
271             throw new RuntimeException("failed to create program");
272         }
273         
274     }
275     
276 }

构造方法里用了内置方法来生成CubePosition和CubeColor。

来看看效果:

开启blending效果:

    

关闭blending效果:

原文地址:https://www.cnblogs.com/jayceli/p/2480348.html