<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 189,comments - 115,trackbacks - 0

    LiveWallPaper 讓您的壁紙動起來 連載(三)——OpenGL ES特輯

    http://www.cnblogs.com/ClassroomStudio/archive/2010/08/15/CS_wallpaper_3OpenGLES.html

     

    CS——LiveWallPaper  動態壁紙程序開發(三)之 OpenGL ES 持續更新中

                         首屆 Google 暑期大學生博客分享大賽——2010 Android 篇

                                 《Ed Burnette's  Hello,Android  Third Edition》 重點篇章讀書學習改編筆記

      

       上回書說到OpenGL ES來構建我們的立方體,那我們就先要了解一下何為OpenGL 以及OpenGL ES。

     

       OpenGL的前世今生

     

        1992年Silicon Graphics 開發出了OpenGL。它從此開始為程序員提供一個統一的平臺讓他們能夠駕馭來自不同生產商的硬件。它的核心,OpenGL迎合了三維圖形開發的一些經典 概念如viewpoints和lighting并試圖讓開發者可以基本不去考慮錯綜復雜的硬件層就能實現3D的效果。您可以瀏覽http://www.opengl.org了解OpenGL的更多內容。

        不過正是因為當初它是為工作站設計的,所以OpenGL對于一部手機來說實在是太大了。所以Google Android采用了OpenGL的一個子集——(OpenGL for Embedded Systems 針對嵌入式系統的OpenGL 簡稱OpenGL ES)。這個標準是由Intel、AMD、Nividia、Nokia、SONY、三星等行業巨頭共同支持的 Khronos Group行業協會提出來的,包括Android、塞班和Iphone在內的主要手機平臺都采用了這個庫。雖然他們彼此之間還是有著細微的差別。您可以瀏 覽http://www.khronos.org/opengles了解OpenGL ES的更多內容。

        幾乎每種計算機語言都有他自己與OpenGL ES相綁定的部分。當然JAVA也不例外。在JAVA Specification Request(JSR)239中定義了這部分綁定。

     

        Android的OpenGL ES

     

        OpenGL ES 1.0 基于完整的OpenGL 1.3,而 ES 1.1 基于 OpenGL 1.5。JSR 239 有兩個版本:一個原有的1.0 和正式的1.0.1。而我們這次使用的便是OpenGL ES1.1

        不過從Android2.2開始,OpenGL ES 2.0開始通過android.opengl 包得到支持。您也可以通過NDK來調用它。OpenGL ES 2.0  。不過還沒有對應于OpenGL ES 2.0的JSR標準。如下圖五所示

      

                                                         圖五

     

        現在讓我們用OpenGL ES來建立我們自己的立方體模型吧。 

              

    GLCube.java
    1 package org.example.opengl;
    2  -
    3  - import java.nio.ByteBuffer;
    4  - import java.nio.ByteOrder;
    5  5 import java.nio.IntBuffer;
    6  -
    7  - import javax.microedition.khronos.opengles.GL10;
    8  -
    9  - import android.content.Context;
    10  10 import android.graphics.Bitmap;
    11  - import android.graphics.BitmapFactory;
    12  - import android.opengl.GLUtils;
    13  -
    14  - class GLCube {
    15 private final IntBuffer mVertexBuffer;
    16  - public GLCube() {
    17  - int one = 65536;
    18  - int half = one / 2;
    19  - int vertices[] = {
    20 //
    21  - -half, -half, half, half, -half, half,
    22  - -half, half, half, half, half, half,
    23  - //
    24  - -half, -half, -half, -half, half, -half,
    25 half, -half, -half, half, half, -half,
    26  - //
    27  - -half, -half, half, -half, half, half,
    28  - -half, -half, -half, -half, half, -half,
    29  - //
    30 half, -half, -half, half, half, -half,
    31  - half, -half, half, half, half, half,
    32  - //
    33  - -half, half, half, half, half, half,
    34  - -half, half, -half, half, half, -half,
    35 //
    36  - -half, -half, half, -half, -half, -half,
    37  - half, -half, half, half, -half, -half, };
    38  -

    45 ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
    46  - vbb.order(ByteOrder.nativeOrder());
    47  - mVertexBuffer = vbb.asIntBuffer();
    48  - mVertexBuffer.put(vertices);
    49  - mVertexBuffer.position(0);
    50  5 }- public void draw(GL10 gl) {
    51  - gl.glVertexPointer(3, GL10.GL_FIXED, 0, mVertexBuffer);
    52  -
    53 gl.glColor4f(1, 1, 1, 1);
    54  - gl.glNormal3f(0, 0, 1);
    55  - gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
    56  - gl.glNormal3f(0, 0, -1);
    57  - gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 4, 4);
    58
    59  - gl.glColor4f(1, 1, 1, 1);
    60  - gl.glNormal3f(-1, 0, 0);
    61  - gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 8, 4);
    62  - gl.glNormal3f(1, 0, 0);
    63 gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 12, 4);
    64  -
    65  - gl.glColor4f(1, 1, 1, 1);
    66 - gl.glNormal3f(0, 1, 0);
    67 - gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 16, 4);
    68 gl.glNormal3f(0, -1, 0);
    69 - gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 20, 4);
    70 - }
    71 - }

     

         在上述代碼的第19行的矩陣通過點坐標確定了立方體的各個頂點。我們都知道立方體的每一個面都是個正方形。而這個正方形又是由兩個等腰直角三角形組成的。 我們可以使用OpenGL中一個常用的繪圖模型——GL_TRIANGLE_STRIP來畫這個正方形。在這個模型中,我們指定兩個起始點,隨后標出的每 一個點都將與起始點確定一個三角形。這是在圖形加速硬件上繪出大量幾何圖形的一種十分快捷的方法。需要注意的是每個點都有x、y、z三個坐標。x軸指向屏 幕右端、y軸指向屏幕上端而z軸則指向屏幕外朝向用戶的視角。在代碼第45行繪圖方法中,我們使用構造的VertexBuffer并且為立方體的六條邊畫 出六個不同向的等腰直角三角形。在項目實戰中,您可能會把幾個調用組合在一或兩個strips中,因為您代碼中的OpenGL命令調用越少,您的程序運行 起來越快。

     

      光、動作與質地

     

             在真實的的生活中,我們周圍有很多光源如太陽、燈光、火炬或是螢火蟲的生物光。為了打造虛擬的3D世界,OpenGL讓我們可以在場景中給出8種光源。并 且如果我們想要它成為一個動態的背景,那么就一定要加入動作。當然這還不夠,如果不給它加入質地(材質)的話,沒人會相信它是個真東西。那在接下來的代碼中我們將一一實現這些功能。

      

     

     

    GlRenderer.java
    1 package org.example.opengl;
    2
    3 import javax.microedition.khronos.egl.EGLConfig;
    4 import javax.microedition.khronos.opengles.GL10;
    5
    6 import android.content.Context;
    7 import android.opengl.GLSurfaceView;
    8 import android.opengl.GLU;
    9 import android.util.Log;
    10
    11 class GLRenderer implements GLSurfaceView.Renderer {
    12 private static final String TAG = "GLRenderer";
    13 private final Context context;
    14
    15
    16 private final GLCube cube = new GLCube();
    17
    18
    19 private long startTime;
    20 private long fpsStartTime;
    21 private long numFrames;
    22
    23
    24
    25 GLRenderer(Context context) {
    26 this.context = context;
    27 }
    28
    29
    30
    31 public void onSurfaceCreated(GL10 gl, EGLConfig config) {
    32

    37 boolean SEE_THRU = false;
    38 // 定義了一個布爾變量用于設置是否使程序執行第79行使立方體變得透明的語句
    39
    40 startTime = System.currentTimeMillis();
    41 fpsStartTime = startTime;
    42 numFrames = 0;
    43
    44
    45 // 定義光源
    46
    47 float lightAmbient[] = new float[] { 0.2f, 0.2f, 0.2f, 1 };
    48 float lightDiffuse[] = new float[] { 1, 1, 1, 1 };
    49 float[] lightPos = new float[] { 1, 1, 1, 1 };
    50 gl.glEnable(GL10.GL_LIGHTING);
    51 gl.glEnable(GL10.GL_LIGHT0);
    52 gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, lightAmbient, 0);
    53 gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, lightDiffuse, 0);
    54 gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, lightPos, 0);
    55
    56
    57 // 立方體的材質,這可以決定光照在它上面的效果 漫反射還是鏡面反射。
    58
    59 float matAmbient[] = new float[] { 1, 1, 1, 1 };
    60 float matDiffuse[] = new float[] { 1, 1, 1, 1 };
    61 gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_AMBIENT,
    62 matAmbient, 0);
    63 gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_DIFFUSE,
    64 matDiffuse, 0);
    65
    66
    67
    68 // 設置我們需要的各種參數
    69 gl.glEnable(GL10.GL_DEPTH_TEST);
    70 gl.glDepthFunc(GL10.GL_LEQUAL);
    71 gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
    72
    73 // 選項:禁用抖動特效,以提高性能。
    74 // gl.glDisable(GL10.GL_DITHER);
    75
    76
    77
    78 // 如上面提到的使透明的語句
    79 if (SEE_THRU) {
    80 gl.glDisable(GL10.GL_DEPTH_TEST);
    81 gl.glEnable(GL10.GL_BLEND);
    82 gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE);
    83 }
    84
    85
    86 // 啟用紋理特效
    87 gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
    88 gl.glEnable(GL10.GL_TEXTURE_2D);
    89
    90 // 將一張點陣圖加載為立方體的紋理。
    91 GLCube.loadTexture(gl, context, R.drawable.android);
    92
    93
    94
    95
    96 }
    97
    98
    99
    100
    101 public void onSurfaceChanged(GL10 gl, int width, int height) {
    102
    103 // ...
    104
    105
    106 // 定義視角
    107 gl.glViewport(0, 0, width, height);
    108 gl.glMatrixMode(GL10.GL_PROJECTION);
    109 gl.glLoadIdentity();
    110 float ratio = (float) width / height;
    111 GLU.gluPerspective(gl, 45.0f, ratio, 1, 100f);
    112
    113 }
    114
    115
    116
    117
    118
    119 public void onDrawFrame(GL10 gl) {
    120
    121 // ...
    122
    123
    124
    125
    126 // 清到黑屏
    127 gl.glClear(GL10.GL_COLOR_BUFFER_BIT
    128 | GL10.GL_DEPTH_BUFFER_BIT);
    129
    130 // ...
    131 gl.glMatrixMode(GL10.GL_MODELVIEW);
    132 gl.glLoadIdentity();
    133 gl.glTranslatef(0, 0, -3.0f);
    134
    135 // 您的其它的繪圖命令可以寫在這里。
    136
    137
    138 // 根據時間設置每次旋轉的角度
    139 long elapsed = System.currentTimeMillis() - startTime;
    140 gl.glRotatef(elapsed * (25f / 1000f), 0, 1, 0); //每秒鐘它都會沿Y軸轉25度
    141 gl.glRotatef(elapsed * (10f / 1000f), 1, 0, 0); //每秒鐘它沿x軸轉10度
    142
    143
    144 // 畫出模型
    145 cube.draw(gl);
    146
    147
    148 // 隨時跟蹤得出的幀數
    149
    150 numFrames++;
    151 long fpsElapsed = System.currentTimeMillis() - fpsStartTime;
    152 if (fpsElapsed > 3 * 1000) { // 每3秒一次
    153 float fps = (numFrames * 1000.0F) / fpsElapsed;
    154 Log.d(TAG, "Frames per second: " + fps + " (" + numFrames
    155 + " frames in " + fpsElapsed + " ms)");
    156 fpsStartTime = System.currentTimeMillis();
    157 numFrames = 0;
    158 }
    159
    160
    161
    162
    163
    164 }
    165
    166
    167
    168 }
    169

        

     在代碼的第69行,我們設置了一組OpenGL 參數。當然OpenGL那幾十個參數都是通過glEnable( ) 來啟用,通過 glDisable( )來禁用。在下面列出的是最常用到的參數選項。
          選項說明:

     

    GL_BLEND 允許將新進來的顏色值與已經在緩沖區中的顏色值融合。
    GL_CULL_FACE

    Ignore polygons(多邊形) based on their

    winding (clockwise or counterclockwise

    (順時針還是逆時針)) in window coordinates.

     This is a cheap way to eliminate back faces.

    (正在琢磨如何解釋)

    GL_DEPTH_TEST

    進行更深入的比較,并且更新緩沖區的深度

    忽略掉像素數已經遠高于之前繪制好的

    GL_LIGHTi Include light number i when ?guring out an object’s
    brightness and color.(正在琢磨如何解釋)

    GL_LIGHTING 開啟照明和材質計算。
    GL_LINE_SMOOTH 繪制抗鋸齒線(無鋸齒線)。
    GL_MULTISAMPLE 啟動多重采樣抗鋸齒和其他效果。
    GL_POINT_SMOOTH 繪制抗鋸齒點。
    GL_TEXTURE_2D 使用紋理繪制表面。

       
        除了GL_DITHER和GL_MULTISAMPLE以外其他選項都是默認關閉的。請注意,我們啟動的任何一項特性都會帶有一定的性能開銷。

       

        請注意一下第150行開始的代碼,請問我們為什么要檢測每秒鐘的幀數呢?

     

        為的是檢測畫面的流暢程度

     

        我們如何界定流暢程度。對一個游戲或 對圖形加速能力要求較高的程序,可以通過它刷洗屏幕的速度來看出它的流暢度。我們經常使用FPS即每秒幀數來衡量。不同的人對于流暢與否的尺度是不同的。 一般來講 15–30FPS對于普通玩家來說就可以接受了。但較骨灰級的玩家來說可能要60FPS或是更高才能讓他們滿意。作為專業的程序員,我們應該向 著60FPS的目標而努力。但這可能不太現實,畢竟一些服務于低端的Android手機,他們的3D硬件加速相對于他們的分辨率要弱一些。當然對于越快的 設備,達到這個標準越是沒有問題。高幀頻是具有挑戰性的,因為我們要在60fps下 即1/60th秒(16.67毫秒之間)調用onDrawFrame()做一切需要做的事情,包括任何動畫、物理計算、游戲計算,再加上花費在實際繪制圖形上的時間。而唯一能夠檢驗程序的FPS是否達到了我們設計的預期的方法,就是就是通過程序自己來測量它。

     

         如上面的代碼所示。每三秒它就會將您的平均FPS值發到Android系統的Log Messages上。如果這個數字低于您的預期,您就可以調整您的算法并重試。當然AVD畢竟是模擬。我們最終還是要看實際真機測試。

     

              Continuous update......

       

    posted on 2011-08-16 09:44 MEYE 閱讀(893) 評論(0)  編輯  收藏 所屬分類: Android3D
    主站蜘蛛池模板: 在线观看亚洲AV每日更新无码| 精品亚洲福利一区二区| 精品国产无限资源免费观看| 亚洲高清有码中文字| 亚洲精品国自产拍在线观看| 日韩免费无码一区二区三区| 亚洲色无码国产精品网站可下载| 亚洲人成无码网站久久99热国产| 久久国产免费观看精品3| 久久精品国产亚洲AV天海翼| 亚洲国产成人久久精品动漫| 午夜寂寞在线一级观看免费| 9久热这里只有精品免费| 一本天堂ⅴ无码亚洲道久久| 久久99国产亚洲高清观看首页| 亚洲啪啪免费视频| 黄人成a动漫片免费网站| 亚洲色大成网站www永久| 亚洲乱亚洲乱少妇无码| 亚洲国产精品免费在线观看| 曰韩无码AV片免费播放不卡| 亚洲免费闲人蜜桃| 亚洲无人区午夜福利码高清完整版| 亚洲免费网站观看视频| 美女在线视频观看影院免费天天看 | 亚洲国产精品毛片av不卡在线| 国产成人AV片无码免费| 特级无码毛片免费视频| 97se亚洲国产综合自在线| 亚洲精品无码av人在线观看| 日本免费无遮挡吸乳视频电影| 91人成网站色www免费下载| 一边摸一边爽一边叫床免费视频| 成人亚洲国产va天堂| 亚洲小视频在线观看| 亚洲午夜久久久久久久久电影网| 在线观看免费国产视频| 4hu四虎最新免费地址| 在线播放免费人成毛片乱码| 一区二区三区免费看| 久久精品国产亚洲av瑜伽|