1. <ul id="0c1fb"></ul>

      <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
      <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区

      RELATEED CONSULTING
      相關(guān)咨詢(xún)
      選擇下列產(chǎn)品馬上在線溝通
      服務(wù)時(shí)間:8:30-17:00
      你可能遇到了下面的問(wèn)題
      關(guān)閉右側(cè)工具欄

      新聞中心

      這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
      AndroidOpenGLES2.0如何進(jìn)行繪制紋理

      這篇文章將為大家詳細(xì)講解有關(guān)Android OpenGL ES 2.0如何進(jìn)行繪制紋理,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。

      10年積累的成都網(wǎng)站設(shè)計(jì)、網(wǎng)站制作經(jīng)驗(yàn),可以快速應(yīng)對(duì)客戶對(duì)網(wǎng)站的新想法和需求。提供各種問(wèn)題對(duì)應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認(rèn)識(shí)你,你也不認(rèn)識(shí)我。但先建設(shè)網(wǎng)站后付款的網(wǎng)站建設(shè)流程,更有靜安免費(fèi)網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。

      紋理,在OpenGL中,可以理解為加載到顯卡顯存中的圖片。

      Android設(shè)備在 2.2開(kāi)始支持OpenGL ES2.0,從前都是ES1.0 和 ES1.1的版本。

      簡(jiǎn)單來(lái)說(shuō),OpenGL  ES是為了嵌入設(shè)備進(jìn)行功能剪裁后的OpenGL版本。ES2.0是和1.x版本不兼容的,區(qū)別和兼容性參見(jiàn)android官方文檔。

      首先,android使用openGL提供了特殊的view作為基礎(chǔ)叫做GLSurfaceView。我們的view需要繼承GLSurfaceView。

      java代碼

      public class MyGLSurfaceView extends GLSurfaceView {  public MyGLSurfaceView(Context context) { super(context); setFocusableInTouchMode(true); // Tell the surface view we want to create an OpenGL ES 2.0-compatible // context, and set an OpenGL ES 2.0-compatible renderer. this.setEGLContextClientVersion(2); this.setRenderer(new MyRenderer()); } }

      并沒(méi)有什么特別之處,android view的渲染操作需要實(shí)現(xiàn)一個(gè)render接口,GLSurfaceView的渲染接口為android.opengl.GLSurfaceView.Renderer。我們需要實(shí)現(xiàn)接口的方法。

      java代碼

      public class MyRenderer implements Renderer {  public void onDrawFrame(GL10 gl) {} public void onSurfaceChanged(GL10 gl, int width, int height) {} public void onSurfaceCreated(GL10 gl, EGLConfig config) {} }

      接口實(shí)現(xiàn)3個(gè)方法,對(duì)應(yīng)繪制,繪制區(qū)域變化,區(qū)域創(chuàng)建。需要說(shuō)明的是參數(shù)GL10 gl是OpenGL ES1.x版本的對(duì)象。這里我們不會(huì)使用到。還有一點(diǎn)就是,onDrawFrame方法的調(diào)用是有系統(tǒng)調(diào)用的,不需要手動(dòng)調(diào)用。系統(tǒng)會(huì)以一定的頻率不斷的回調(diào)。

      接下來(lái)我們進(jìn)入ES2.0的使用,上代碼先:

      java代碼

      public void onSurfaceCreated(GL10 gl, EGLConfig config) {  GLES20.glEnable(GLES20.GL_TEXTURE_2D); // Active the texture unit 0 GLES20.glActiveTexture(GLES20.GL_TEXTURE0); loadVertex(); initShader(); loadTexture(); }

      1、啟用2D紋理

      繪制區(qū)域創(chuàng)建的時(shí)候,我們?cè)O(shè)置了啟用2D的紋理,并且激活了紋理單元unit0。什么意思呢,說(shuō)起來(lái)話長(zhǎng),以后慢慢說(shuō)。簡(jiǎn)單說(shuō)一下,記住OpenGL 是基于狀態(tài)的,就是很多狀態(tài)的設(shè)置和切換,這里啟用GL_TEXTURE_2D就是一個(gè)狀態(tài)的開(kāi)啟,表明OpenGL可以使用2D紋理。

      什么是激活紋理單元?這個(gè)和硬件有點(diǎn)關(guān)系,OpenGL要顯卡會(huì)劃分存儲(chǔ)紋理的存儲(chǔ)區(qū)域不止一個(gè)區(qū)域。這里是使用區(qū)域 unit 0,多重紋理繪制可以開(kāi)啟多個(gè),這個(gè)以后說(shuō)。接下來(lái),調(diào)用了三個(gè)函數(shù),載入頂點(diǎn),初始化著色器,載入紋理。

      2、加載頂點(diǎn)

      OpenGL繪制圖形是根據(jù)頂點(diǎn)以后鏈接起來(lái)的。為什么要這樣,其實(shí)這樣很強(qiáng)大是一種設(shè)計(jì)吧。頂點(diǎn)可以暫時(shí)簡(jiǎn)單理解為含有位置信息的坐標(biāo)點(diǎn)。

      java代碼

      private void loadVertex() {  // float size = 4 this.vertex = ByteBuffer.allocateDirect(quadVertex.length * 4) .order(ByteOrder.nativeOrder()) .asFloatBuffer(); this.vertex.put(quadVertex).position(0); // short size = 2 this.index = ByteBuffer.allocateDirect(quadIndex.length * 2) .order(ByteOrder.nativeOrder()) .asShortBuffer(); this.index.put(quadIndex).position(0); } private FloatBuffer vertex; private ShortBuffer index; private float[] quadVertex = new float[] { -0.5f, 0.5f, 0.0f, // Position 0 0, 1.0f, // TexCoord 0 -0.5f, -0.5f, 0.0f, // Position 1 0, 0, // TexCoord 1 0.5f , -0.5f, 0.0f, // Position 2 1.0f, 0, // TexCoord 2 0.5f, 0.5f, 0.0f, // Position 3 1.0f, 1.0f, // TexCoord 3 }; private short[] quadIndex = new short[] { (short)(0), // Position 0 (short)(1), // Position 1 (short)(2), // Position 2 (short)(2), // Position 2 (short)(3), // Position 3 (short)(0), // Position 0 };

      FloatBuffer,ShortBuffer是封裝了本地?cái)?shù)據(jù)結(jié)構(gòu)的封裝對(duì)象。是 的,這個(gè)2個(gè)對(duì)象里面的數(shù)據(jù)不被java虛擬機(jī)管理,相當(dāng)于C語(yǔ)言的存儲(chǔ)方式。quadVertex的數(shù)據(jù)就是一個(gè)矩形的坐標(biāo),和紋理坐標(biāo)。一兩句話很難 解釋清楚,這里涉及到openGL的幾個(gè)經(jīng)典的坐標(biāo)系,下次說(shuō)。概括的說(shuō),openGL的坐標(biāo)是單位化的,都是0.0-1.0的浮點(diǎn)型,屏幕的中心點(diǎn)是 (0,0)。而紋理的坐標(biāo)左下角是(0,0)。 這里的quadVertex是在屏幕中大概花了一個(gè)矩形貼了一個(gè)圖片, position0  是左上點(diǎn),以后左下,右下,右上的順序,紋理坐標(biāo)同理。

      quadIndx是這剛才的這些頂點(diǎn)索引排列。這里一個(gè)矩形也就4個(gè)頂點(diǎn),每個(gè)頂點(diǎn)3個(gè)位置坐標(biāo),2個(gè)紋理坐標(biāo)。也就是說(shuō)一個(gè)頂點(diǎn)有5個(gè)float數(shù)據(jù)。至于為什么頂點(diǎn)為什么這么排列下次說(shuō),是2個(gè)三角形合成了一個(gè)矩形,幾句話很難解釋清楚。

      所以說(shuō),這段代碼就是把矩形的位置和紋理坐標(biāo),存儲(chǔ)到本地?cái)?shù)據(jù),準(zhǔn)備后面使用而已。

      3、初始化著色器

      這個(gè)著色器就是ES2.0的特色,又叫可編程著色器,也是區(qū)別于ES1.x的本質(zhì)。這里只做簡(jiǎn)單的介紹。可編程著色器是一種腳本,語(yǔ)法類(lèi)似C語(yǔ)言,腳本分為頂點(diǎn)著色器和片段著色器,分別對(duì)應(yīng)了openGL不同的渲染流程。

      頂點(diǎn)著色器:

      java代碼

      uniform mat4 u_MVPMatrix;  attribute vec4 a_position; attribute vec2 a_texCoord; varying vec2 v_texCoord; void main() { gl_Position = a_position; v_texCoord = a_texCoord; }

      片段著色器:

      java代碼

      precision lowp float;  varying vec2 v_texCoord; uniform sampler2D u_samplerTexture; void main() { gl_FragColor = texture2D(u_samplerTexture, v_texCoord); }

      這里記住一句話,頂點(diǎn)著色器,會(huì)在頂點(diǎn)上執(zhí)行;片段著色器會(huì)在像素點(diǎn)上執(zhí)行。剛才的矩形就有4個(gè)頂點(diǎn),每個(gè)頂點(diǎn)都會(huì)應(yīng)用這個(gè)腳本。也就是說(shuō),頂點(diǎn)是位置相關(guān)信息,片段是色彩紋理相關(guān)信息。

      這個(gè)2段腳本都是文本,需要編譯,鏈接,等等一些操作才能被ES2.0所使用。過(guò)程就像C語(yǔ)言的編譯運(yùn)行過(guò)程。openGL 提供了相關(guān)函數(shù)去做這些事情。

      java代碼

      private void initShader() {  String vertexSource = Tools.readFromAssets("VertexShader.glsl"); String fragmentSource = Tools.readFromAssets("FragmentShader.glsl"); // Load the shaders and get a linked program program = GLHelper.loadProgram(vertexSource, fragmentSource); // Get the attribute locations attribPosition = GLES20.glGetAttribLocation(program, "a_position"); attribTexCoord = GLES20.glGetAttribLocation(program, "a_texCoord"); uniformTexture = GLES20.glGetUniformLocation(program, "u_samplerTexture"); GLES20.glUseProgram(program); GLES20.glEnableVertexAttribArray(attribPosition); GLES20.glEnableVertexAttribArray(attribTexCoord); // Set the sampler to texture unit 0 GLES20.glUniform1i(uniformTexture, 0); }

      可以看到,頂點(diǎn)和片段一起構(gòu)成一個(gè)program,它可以被openGL所使用,是一個(gè) 編譯好的腳本程序,存儲(chǔ)在顯存。 GLES20.glGetAttribLocation 和 GLES20.glGetUniformLocation   這句話是神馬作用呢。簡(jiǎn)單說(shuō)就是,java程序和著色器腳本數(shù)據(jù)通信的。把就像參數(shù)的傳遞一樣,這樣腳本就能根據(jù)外界的參數(shù)變化,實(shí)時(shí)的改變openGL 流水線渲染的處理流程。

      封裝的加載著色器的輔助方法:

      java代碼

      public static int loadProgram(String vertexSource, String fragmentSource) {  // Load the vertex shaders int vertexShader = GLHelper.loadShader(GLES20.GL_VERTEX_SHADER, vertexSource); // Load the fragment shaders int fragmentShader = GLHelper.loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource); // Create the program object int program = GLES20.glCreateProgram(); if (program == 0) { throw new RuntimeException("Error create program."); } GLES20.glAttachShader(program, vertexShader); GLES20.glAttachShader(program, fragmentShader); // Link the program GLES20.glLinkProgram(program); int[] linked = new int[1]; // Check the link status GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linked, 0); if (linked[0] == 0) { GLES20.glDeleteProgram(program); throw new RuntimeException("Error linking program: " + GLES20.glGetProgramInfoLog(program)); } // Free up no longer needed shader resources GLES20.glDeleteShader(vertexShader); GLES20.glDeleteShader(fragmentShader); return program; }

      java代碼

      public static int loadShader(int shaderType, String source) {  // Create the shader object int shader = GLES20.glCreateShader(shaderType); if (shader == 0) { throw new RuntimeException("Error create shader."); } int[] compiled = new int[1]; // Load the shader source GLES20.glShaderSource(shader, source); // Compile the shader GLES20.glCompileShader(shader); // Check the compile status GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0); if (compiled[0] == 0) { GLES20.glDeleteShader(shader); throw new RuntimeException("Error compile shader: " + GLES20.glGetShaderInfoLog(shader)); } return shader; }

      為什么openGL的很多操作目標(biāo)都是int類(lèi)型的?因?yàn)閛penGL只會(huì)在顯存生成或綁定地址,返回id,以后用id相當(dāng)于句柄去改變它的內(nèi)部狀態(tài)。

      4、加載紋理

      就是把圖片的數(shù)據(jù)上傳到顯存,以后再使用它。請(qǐng)注意紋理圖片的長(zhǎng)和寬***是2的N次方,不然不一定能繪制出來(lái)。

      java代碼

      static int[] loadTexture(String path) {  int[] textureId = new int[1]; // Generate a texture object GLES20.glGenTextures(1, textureId, 0); int[] result = null; if (textureId[0] != 0) { InputStream is = Tools.readFromAsserts(path); Bitmap bitmap; try { bitmap = BitmapFactory.decodeStream(is); } finally { try { is.close(); } catch (IOException e) { throw new RuntimeException("Error loading Bitmap."); } } result = new int[3]; result[TEXTURE_ID] = textureId[0]; // TEXTURE_ID result[TEXTURE_WIDTH] = bitmap.getWidth(); // TEXTURE_WIDTH result[TEXTURE_HEIGHT] = bitmap.getHeight(); // TEXTURE_HEIGHT // Bind to the texture in OpenGL GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId[0]); // Set filtering GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR); GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST); GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); // Load the bitmap into the bound texture. GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0); // Recycle the bitmap, since its data has been loaded into OpenGL. bitmap.recycle(); } else { throw new RuntimeException("Error loading texture."); } return result; }

      這里使用了android的工具類(lèi)吧bitmap直接轉(zhuǎn)換成openGL紋理需要的格式了。過(guò)程是,先生成一個(gè)紋理的id在顯卡上的,以后根據(jù)id上傳紋理數(shù)據(jù),以后保存這個(gè)id就

      可以操作這個(gè)紋理了。至于紋理的一些過(guò)濾特性設(shè)置,將來(lái)再說(shuō)。

      現(xiàn)在貌似就剩下繪制了,準(zhǔn)備好了頂點(diǎn)信息,頂點(diǎn)對(duì)應(yīng)的紋理坐標(biāo)。初始化了著色器,上傳了紋理圖片。接下來(lái)就已把他們合起來(lái)繪制了。

      java代碼

      public void onDrawFrame(GL10 gl) {  // clear screen to black GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId); vertex.position(0); // load the position // 3(x , y , z) // (2 + 3 )* 4 (float size) = 20 GLES20.glVertexAttribPointer(attribPosition, 3, GLES20.GL_FLOAT, false, 20, vertex); vertex.position(3); // load the texture coordinate GLES20.glVertexAttribPointer(attribTexCoord, 2, GLES20.GL_FLOAT, false, 20, vertex); GLES20.glDrawElements(GLES20.GL_TRIANGLES, 6, GLES20.GL_UNSIGNED_SHORT, index); }

      為了保持了代碼的簡(jiǎn)單,OpenGL的基于狀態(tài)體現(xiàn),bind這個(gè)函數(shù)無(wú)處不在,這里 bindTexture就是通知openGL使用那個(gè)id的紋理圖片。接下來(lái)的操作就是針對(duì)bind的圖片的。繪制就需要讓openGL知道繪制神馬。所 以這里需要用到vertex這個(gè)本地?cái)?shù)據(jù)容器,里面裝在的是頂點(diǎn)和紋理坐標(biāo)信息。GLES20.glVertexAttribPointer就是把頂點(diǎn)數(shù)據(jù),按照openGL喜歡的格式上傳到顯卡存儲(chǔ)。draw方法的調(diào)用,是在前面應(yīng) 用了紋理id的情況下,所以繪制紋理坐標(biāo)的時(shí)候,會(huì)使用上傳的紋理圖片。

      每次都需要把數(shù)據(jù)上傳到OpenGL,畢竟顯存和內(nèi)存不是同一個(gè)地方,OpenGL采用了CS模式。當(dāng)然使用VBO等技術(shù)可以把數(shù)據(jù)緩存在顯存,以提高運(yùn)行性能。

      關(guān)于Android OpenGL ES 2.0如何進(jìn)行繪制紋理就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。


      本文標(biāo)題:AndroidOpenGLES2.0如何進(jìn)行繪制紋理
      網(wǎng)頁(yè)鏈接:http://www.ef60e0e.cn/article/jjcdod.html
      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区
      1. <ul id="0c1fb"></ul>

        <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
        <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

        海伦市| 涞源县| 武隆县| 南召县| 乌海市| 黑龙江省| 门头沟区| 阳江市| 漯河市| 延川县| 淮滨县| 石阡县| 兴业县| 平远县| 庆云县| 永吉县| 通海县| 彭州市| 榆树市| 石阡县| 资溪县| 体育| 大渡口区| 宁阳县| 绥江县| 亳州市| 上蔡县| 虎林市| 濮阳市| 杭州市| 日土县| 娄底市| 寿宁县| 新营市| 本溪| 达孜县| 稻城县| 陇川县| 桓台县| 米泉市| 思南县|