編輯:關於Android編程
package com.cumt.shape; import android.content.Context; public class Triangle { private Context context; // 數組中每個頂點的坐標數 static final int COORDS_PER_VERTEX = 2; // 每個頂點的坐標數 X , Y static float triangleCoords[] = { 0.0f, 0.5f , // top -0.5f, -0.5f , // bottom left 0.5f, -0.5f }; // bottom right public Triangle(Context context){ this.context = context; } }
package com.cumt.shape; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import android.content.Context; public class Triangle { private Context context; private static final int BYTES_PER_FLOAT = 4; private FloatBuffer vertexBuffer; // 數組中每個頂點的坐標數 static final int COORDS_PER_VERTEX = 2; // 每個頂點的坐標數 X , Y static float triangleCoords[] = { 0.0f, 0.5f , // top -0.5f, -0.5f , // bottom left 0.5f, -0.5f }; // bottom right public Triangle(Context context){ this.context = context; vertexBuffer = ByteBuffer .allocateDirect(triangleCoords.length * BYTES_PER_FLOAT) .order(ByteOrder.nativeOrder()) .asFloatBuffer(); // 把坐標們加入FloatBuffer中 vertexBuffer.put(triangleCoords); // 設置buffer,從第一個坐標開始讀 vertexBuffer.position(0); } }
attribute vec4 a_Position; void main() { gl_Position = a_Position; }gl_Position即opengl定義的頂點的坐標,我們目的就是通過這個來告訴opengl我們的頂點數據。vec4是著色器語言中的向量類型的一種,包含了四個浮點數的向量。 接下來在raw文件夾內新建文件simple_fragment_shader.glsl ,其內容如下:
precision mediump float; uniform vec4 u_Color; void main() { gl_FragColor = u_Color; }
package com.cumt.utils; public class LoggerConfig { public static final boolean ON = true; }再在該包下新建類ShaderHelper用於加載著色器程序以及編譯著色器:
package com.cumt.utils; import static android.opengl.GLES20.GL_COMPILE_STATUS; import static android.opengl.GLES20.GL_FRAGMENT_SHADER; import static android.opengl.GLES20.GL_LINK_STATUS; import static android.opengl.GLES20.GL_VALIDATE_STATUS; import static android.opengl.GLES20.GL_VERTEX_SHADER; import static android.opengl.GLES20.glAttachShader; import static android.opengl.GLES20.glCompileShader; import static android.opengl.GLES20.glCreateProgram; import static android.opengl.GLES20.glCreateShader; import static android.opengl.GLES20.glDeleteProgram; import static android.opengl.GLES20.glDeleteShader; import static android.opengl.GLES20.glGetProgramInfoLog; import static android.opengl.GLES20.glGetProgramiv; import static android.opengl.GLES20.glGetShaderInfoLog; import static android.opengl.GLES20.glGetShaderiv; import static android.opengl.GLES20.glLinkProgram; import static android.opengl.GLES20.glShaderSource; import static android.opengl.GLES20.glValidateProgram; import android.util.Log; public class ShaderHelper { private static final String TAG = "ShaderHelper"; /** * 加載並編譯頂點著色器,返回得到的opengl id * @param shaderCode * @return */ public static int compileVertexShader(String shaderCode) { return compileShader(GL_VERTEX_SHADER, shaderCode); } /** * 加載並編譯片段著色器,返回opengl id * @param shaderCode * @return */ public static int compileFragmentShader(String shaderCode) { return compileShader(GL_FRAGMENT_SHADER, shaderCode); } /** * 加載並編譯著色器,返回opengl id * @param type * @param shaderCode * @return */ private static int compileShader(int type, String shaderCode) { // 建立新的著色器對象 final int shaderObjectId = glCreateShader(type); if (shaderObjectId == 0) { if (LoggerConfig.ON) { Log.w(TAG, "不能創建新的著色器."); } return 0; } // 傳遞著色器資源代碼. glShaderSource(shaderObjectId, shaderCode); //編譯著色器 glCompileShader(shaderObjectId); // 獲取編譯的狀態 final int[] compileStatus = new int[1]; glGetShaderiv(shaderObjectId, GL_COMPILE_STATUS, compileStatus, 0); if (LoggerConfig.ON) { //打印log Log.v(TAG, "代碼編譯結果:" + "\n" + shaderCode + "\n:" + glGetShaderInfoLog(shaderObjectId)); } // 確認編譯的狀態 if (compileStatus[0] == 0) { // 如果編譯失敗,則刪除該對象 glDeleteShader(shaderObjectId); if (LoggerConfig.ON) { Log.w(TAG, "編譯失敗!."); } return 0; } // 返回著色器的opengl id return shaderObjectId; } /** * 鏈接頂點著色器和片段著色器成一個program * 並返回這個pragram的opengl id * @param vertexShaderId * @param fragmentShaderId * @return */ public static int linkProgram(int vertexShaderId, int fragmentShaderId) { // 新建一個program對象 final int programObjectId = glCreateProgram(); if (programObjectId == 0) { if (LoggerConfig.ON) { Log.w(TAG, "不能新建一個 program"); } return 0; } // Attach the vertex shader to the program. glAttachShader(programObjectId, vertexShaderId); // Attach the fragment shader to the program. glAttachShader(programObjectId, fragmentShaderId); // 將兩個著色器連接成一個program glLinkProgram(programObjectId); // 獲取連接狀態 final int[] linkStatus = new int[1]; glGetProgramiv(programObjectId, GL_LINK_STATUS, linkStatus, 0); if (LoggerConfig.ON) { // Print the program info log to the Android log output. Log.v( TAG, "Results of linking program:\n" + glGetProgramInfoLog(programObjectId)); } // 驗證連接狀態 if (linkStatus[0] == 0) { // If it failed, delete the program object. glDeleteProgram(programObjectId); if (LoggerConfig.ON) { Log.w(TAG, "連接 program 失敗!."); } return 0; } // Return the program object ID. return programObjectId; } /** * Validates an OpenGL program. Should only be called when developing the * application. */ public static boolean validateProgram(int programObjectId) { glValidateProgram(programObjectId); final int[] validateStatus = new int[1]; glGetProgramiv(programObjectId, GL_VALIDATE_STATUS, validateStatus, 0); Log.v(TAG, "Results of validating program: " + validateStatus[0] + "\nLog:" + glGetProgramInfoLog(programObjectId)); return validateStatus[0] != 0; } /** * /** * 編譯,連接 ,返回 program 的 ID * @param vertexShaderSource * @param fragmentShaderSource * @return */ public static int buildProgram(String vertexShaderSource, String fragmentShaderSource) { int program; // Compile the shaders. int vertexShader = compileVertexShader(vertexShaderSource); int fragmentShader = compileFragmentShader(fragmentShaderSource); // Link them into a shader program. program = linkProgram(vertexShader, fragmentShader); if (LoggerConfig.ON) { validateProgram(program); } return program; } }
package com.cumt.utils; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import android.content.Context; import android.content.res.Resources; public class TextResourceReader { /** * Reads in text from a resource file and returns a String containing the * text. */ public static String readTextFileFromResource(Context context, int resourceId) { StringBuilder body = new StringBuilder(); try { InputStream inputStream = context.getResources().openRawResource(resourceId); InputStreamReader inputStreamReader = new InputStreamReader(inputStream); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); String nextLine; while ((nextLine = bufferedReader.readLine()) != null) { body.append(nextLine); body.append('\n'); } } catch (IOException e) { throw new RuntimeException( "Could not open resource: " + resourceId, e); } catch (Resources.NotFoundException nfe) { throw new RuntimeException("Resource not found: " + resourceId, nfe); } return body.toString(); } }
package com.cumt.shape; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import com.cumt.openglestwo_test_one.R; import com.cumt.utils.ShaderHelper; import com.cumt.utils.TextResourceReader; import android.content.Context; import android.opengl.GLES20; public class Triangle { private Context context; private static final int BYTES_PER_FLOAT = 4; private FloatBuffer vertexBuffer; // 數組中每個頂點的坐標數 static final int COORDS_PER_VERTEX = 2; // 每個頂點的坐標數 X , Y static float triangleCoords[] = { 0.0f, 0.5f , // top -0.5f, -0.5f , // bottom left 0.5f, -0.5f }; // bottom right private int program; public Triangle(Context context){ this.context = context; vertexBuffer = ByteBuffer .allocateDirect(triangleCoords.length * BYTES_PER_FLOAT) .order(ByteOrder.nativeOrder()) .asFloatBuffer(); // 把坐標們加入FloatBuffer中 vertexBuffer.put(triangleCoords); // 設置buffer,從第一個坐標開始讀 vertexBuffer.position(0); getProgram(); } //獲取program的id private void getProgram(){ //獲取頂點著色器文本 String vertexShaderSource = TextResourceReader .readTextFileFromResource(context, R.raw.simple_vertex_shader); //獲取片段著色器文本 String fragmentShaderSource = TextResourceReader .readTextFileFromResource(context, R.raw.simple_fragment_shader); //獲取program的id program = ShaderHelper.buildProgram(vertexShaderSource, fragmentShaderSource); GLES20.glUseProgram(program); } }至此我們已經勝利在望了,接下來思考一下,我們應該做哪些工作?顯然我們需要將定義的數據傳入著色器中來使用。詳細的步驟見下面的代碼(Triangle.java):
package com.cumt.shape; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import com.cumt.openglestwo_test_one.R; import com.cumt.utils.ShaderHelper; import com.cumt.utils.TextResourceReader; import android.content.Context; import android.opengl.GLES20; public class Triangle { private Context context; private static final int BYTES_PER_FLOAT = 4; private FloatBuffer vertexBuffer; //---------第四步:定義坐標元素的個數,這裡有三個頂點 private static final int POSITION_COMPONENT_COUNT = 3; // 數組中每個頂點的坐標數 static final int COORDS_PER_VERTEX = 2; // 每個頂點的坐標數 X , Y static float triangleCoords[] = { 0.0f, 0.5f , // top -0.5f, -0.5f , // bottom left 0.5f, -0.5f }; // bottom right private int program; //------------第一步 : 定義兩個標簽,分別於著色器代碼中的變量名相同, //------------第一個是頂點著色器的變量名,第二個是片段著色器的變量名 private static final String A_POSITION = "a_Position"; private static final String U_COLOR = "u_Color"; //------------第二步: 定義兩個ID,我們就是通ID來實現數據的傳遞的,這個與前面 //------------獲得program的ID的含義類似的 private int uColorLocation; private int aPositionLocation; public Triangle(Context context){ this.context = context; vertexBuffer = ByteBuffer .allocateDirect(triangleCoords.length * BYTES_PER_FLOAT) .order(ByteOrder.nativeOrder()) .asFloatBuffer(); // 把坐標們加入FloatBuffer中 vertexBuffer.put(triangleCoords); // 設置buffer,從第一個坐標開始讀 vertexBuffer.position(0); getProgram(); //----------第三步: 獲取這兩個ID ,是通過前面定義的標簽獲得的 uColorLocation = GLES20.glGetUniformLocation(program, U_COLOR); aPositionLocation = GLES20.glGetAttribLocation(program, A_POSITION); //---------第五步: 傳入數據 GLES20.glVertexAttribPointer(aPositionLocation, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, 0, vertexBuffer); GLES20.glEnableVertexAttribArray(aPositionLocation); } //獲取program private void getProgram(){ //獲取頂點著色器文本 String vertexShaderSource = TextResourceReader .readTextFileFromResource(context, R.raw.simple_vertex_shader); //獲取片段著色器文本 String fragmentShaderSource = TextResourceReader .readTextFileFromResource(context, R.raw.simple_fragment_shader); //獲取program的id program = ShaderHelper.buildProgram(vertexShaderSource, fragmentShaderSource); GLES20.glUseProgram(program); } //----------第七步:繪制 public void draw(){ GLES20.glUniform4f(uColorLocation, 0.0f, 0.0f, 1.0f, 1.0f); GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, POSITION_COMPONENT_COUNT); } }
package com.cumt.render; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import com.cumt.shape.Triangle; import android.content.Context; import android.opengl.GLSurfaceView.Renderer; import android.util.Log; import static android.opengl.GLES20.glClear; import static android.opengl.GLES20.glClearColor; import static android.opengl.GLES20.glViewport; import static android.opengl.GLES20.GL_COLOR_BUFFER_BIT; public class MyRender implements Renderer { private Context context; public MyRender(Context context){ this.context = context; } //定義三角形對象 Triangle triangle; public void onSurfaceCreated(GL10 gl, EGLConfig config) { Log.w("MyRender","onSurfaceCreated"); // TODO Auto-generated method stub //First:設置清空屏幕用的顏色,前三個參數對應紅綠藍,最後一個對應alpha glClearColor(0.0f, 0.0f, 0.0f, 0.0f); triangle = new Triangle(context); } public void onSurfaceChanged(GL10 gl, int width, int height) { Log.w("MyRender","onSurfaceChanged"); // TODO Auto-generated method stub //Second:設置視口尺寸,即告訴opengl可以用來渲染的surface大小 glViewport(0,0,width,height); } public void onDrawFrame(GL10 gl) { Log.w("MyRender","onDrawFrame"); // TODO Auto-generated method stub //Third:清空屏幕,擦除屏幕上所有的顏色,並用之前glClearColor定義的顏色填充整個屏幕 glClear(GL_COLOR_BUFFER_BIT); //繪制三角形 triangle.draw(); } }
在上一篇中我們討論了計算機網絡的體系結構和各層次的作用,在我們編程中TCP或UDP都提供了socket接口進行實現,實現的例子在上一篇中,這一篇我們主要討論一下Http協
這是一篇遲來的博客,Android M已經發布一年多了(6.0的變化),在Android M中權限系統被重新設計,發生了顛覆性的變化,很多人把握不好這個變化,一是對這個權
android中提供了4中動畫: AlphaAnimation 透明度動畫效果 ScaleAnimation 縮放動畫效果 TranslateAnimation 位移動畫
前言:上篇文中最後介紹了數據解碼放到Buffer過程,今天分析的是stagefright框架中音視頻輸出過程:先看下今天的Agenda:一張圖回顧數據處理過程 視頻渲染器