国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

OpenGL ES紋理詳解

2019-10-22 18:10:33
字體:
來源:轉載
供稿:網友

使用前面學過的技術已經可以利用OpenGL ES構建立體圖形,并通過頂點著色器和片元著色器對其進行各種變化呢和光照等效果使得三維效果更加真實,實際上我看看到很多的3D游戲漂亮多了,那是因為有各種各樣的漂亮的圖像帶給人很多視覺盛宴,這篇文章在前面的基礎上,增加物體的表面貼圖,使得物體更加好看。

紋理概念

紋理用來表示圖像照片或者說一系列的數據,使用紋理可以使物體用用更多的細節。OpenGL ES 2.0 中有兩種貼圖:二維紋理和立方體紋理。

每個二維紋理都由許多小的紋理元素組成,類似與片元和像素,使用紋理最簡單的方式就是直接從一個圖像加載數據。在OpenGL中規定紋理圖像的左下角由stst坐標(0.0,0.0)指定,右上角由stst坐標(1.0,1.0)指定,不過超過1.0的坐標也是允許的,在該區間之外的紋理在讀取時的時候由紋理拉伸模式決定。

OpenGL ES 2.0不必是正方形,但是每個維度都應該是2的冪

在Android中使用的OpenGL ES的紋理坐標系跟官方的紋理坐標系統不一樣,在Android中使用官方的紋理坐標系統,得到的結果是相反的,而是左上角是stst坐標(0.0,0.0)點,右下角是stst坐標(1.0,1.0)點。

二維紋理映射的原理 

OpenGL,ES,紋理

使用紋理就是在紋理圖中進行采樣,因此需要將選定的紋理坐標穿進頂點著色器,經過插值在片元著色器中從紋理圖中的指定位置采樣即可,紋理圖的數據通過往片元插值器傳遞紋理單元指定的。

紋理對象和紋理加載

創建一個紋理對象,保存渲染所需的紋理數據,例如圖像數據、過濾模式、包裝模式。創建生成紋理對象的函數

public static native void glGenTextures(    int n, // 指定要生成的紋理對象的數量    int[] textures, // 保存紋理對象ID的數組    int offset  );

紋理對象在應用程序中不再使用時,需要刪除。

public static native void glDeleteTextures(    int n, // 指定要刪除的紋理數量    int[] textures, // 保存待刪除的紋理ID的數組    int offset  );

紋理對象的 ID 必須是 glGenTextures 產生的,一旦生成紋理ID,就必須綁定紋理對象才能繼續進行后續的操作。后續的操作將影響綁定的紋理對象。一旦紋理被綁定到一個特定的紋理目標,再刪除之前就一直保持著綁定狀態。

public static native void glBindTexture(    int target, // 綁定紋理對象到目標 GL_TEXTURE_2D 或 GL_TEXTURE_CUBE_MAP    int texture // 要綁定的紋理對象ID  );

激活某個紋理單元

public static native void glActiveTexture(    int texture // 要激活的紋理單元  );

對這兩個函數的理解:顯卡中有N個紋理單元(GL_TEXTURE0,GL_TEXTURE1,GL_TEXTURE2…),每個紋理單元中保存著很多紋理目標(targetTexture1D,targetTexture2D,targetTexture3D,targetTextureCube…),OpenGL ES 2.0貌似只支持了targetTexture2D和targetTextureCube。

紋理單元TextureUnit的定義如下

struct TextureUnit{  GLuint targetTexture1D;  GLuint targetTexture2D;  GLuint targetTexture3D;  GLuint targetTextureCube;  ...};

glActiveTexture函數就是設置當前活動的紋理單元

TextureUnit textureUnits[GL_MAX_TEXTURE_IMAGE_UNITS]GLuint currentTextureUnit = 0;// ...void glActiveTexture(GLenum textureUnit){  currentTextureUnit = textureUnit - GL_TEXTURE0 ;}

glBindTexture函數就是將紋理對象ID賦值給當前活動的紋理單元的對應的目標紋理。

void glBindTexture(GLenum textureTarget, GLuint textureObject){  TextureUnit *texUnit = &textureUnits[currentTextureUnit];  switch(textureTarget)  {  case GL_TEXTURE_1D: texUnit->targetTexture1D = textureObject; break;  case GL_TEXTURE_2D: texUnit->targetTexture2D = textureObject; break;  case GL_TEXTURE_3D: texUnit->targetTexture3D = textureObject; break;  case GL_TEXTURE_CUBEMAP: texUnit->targetTextureCube = textureObject; break;  }}

獲取一副圖片的紋理數據

public static void texImage2D(int target, // 常數GL_TEXTURE_2D               int level, // 表示多級分辨率的紋理圖像的級數,若只有一種分辨率,則level設為0。               Bitmap bitmap,               int border // 邊框,一般設為0                )

其他紋理選項的設置使用glTexParameterf系列函數

public static native void glTexParameterf(    int target,     int pname, // 設定的參數,可以是GL_TEXTURE_MAG_FILTER,GL_TEXTURE_MIN_FILTER,GL_TEXTURE_WRAP_S,GL_TEXTURE_WRAP_T    float param // 參數對應的值  );

應用紋理的例子

對前面的立方體的每個面應用一張圖片作為紋理貼圖,效果圖(這個紋理圖是哪個老師來著?) 

OpenGL,ES,紋理

Rectangle.java

public class Rectangle {  private FloatBuffer mVertexBuffer;  private int mProgram;  private int mPositionHandle;  private int muMVPMatrixHandle;  private int mColorHandle;  private int muMMatrixHandle;  private int muLightLocationHandle;  private int mTextureCoordHandle;  private int textureId;  private int muTextureHandle;  private Context mContext;  public Rectangle(Context context) {    this.mContext = context;    initVetexData();  }  public void initVetexData() {    float vertices[] = new float[] {        // 頂點  顏色   紋理坐標        //前面        0, 0, 1, 1,1,1,0, 0.5f, 0.5f,        1, 1, 1, 1,0,0,0, 1.0f, 0.0f,        -1, 1, 1, 1,0,0,0, 0.0f, 0.0f,        0, 0, 1, 1,1,1,0, 0.5f, 0.5f,        -1, 1, 1, 1,0,0,0, 0.0f, 0.0f,        -1,-1, 1, 1,0,0,0, 0.0f, 1.0f,        0, 0, 1, 1,1,1,0, 0.5f, 0.5f,        -1,-1, 1, 1,0,0,0, 0.0f, 1.0f,        1,-1, 1, 1,0,0,0, 1.0f, 1.0f,        0, 0, 1, 1,1,1,0, 0.5f, 0.5f,        1,-1, 1, 1,0,0,0, 1.0f, 1.0f,        1, 1, 1, 1,0,0,0, 1.0f, 0.0f,        //后面        0, 0,-1, 1,1,1,0, 0.5f, 0.5f,        1, 1,-1, 1,0,0,0, 1.0f, 0.0f,        1,-1,-1, 1,0,0,0,  0.0f, 0.0f,        0, 0,-1, 1,1,1,0, 0.5f, 0.5f,        1,-1,-1, 1,0,0,0,  0.0f, 0.0f,        -1,-1,-1, 1,0,0,0, 0.0f, 1.0f,        0, 0,-1, 1,1,1,0, 0.5f, 0.5f,        -1,-1,-1, 1,0,0,0, 0.0f, 1.0f,        -1, 1,-1, 1,0,0,0, 1.0f, 1.0f,        0, 0,-1, 1,1,1,0, 0.5f, 0.5f,        -1, 1,-1, 1,0,0,0, 1.0f, 1.0f,        1, 1,-1, 1,0,0,0, 1.0f, 0.0f,        //左面        -1, 0, 0, 1,1,1,0, 0.5f, 0.5f,        -1, 1, 1, 1,0,0,0, 1.0f, 0.0f,        -1, 1,-1, 1,0,0,0, 0.0f, 0.0f,        -1, 0, 0, 1,1,1,0, 0.5f, 0.5f,        -1, 1,-1, 1,0,0,0, 0.0f, 0.0f,        -1,-1,-1, 1,0,0,0, 0.0f, 1.0f,        -1, 0, 0, 1,1,1,0, 0.5f, 0.5f,        -1,-1,-1, 1,0,0,0, 0.0f, 1.0f,        -1,-1, 1, 1,0,0,0, 1.0f, 1.0f,        -1, 0, 0, 1,1,1,0, 0.5f, 0.5f,        -1,-1, 1, 1,0,0,0, 1.0f, 1.0f,        -1, 1, 1, 1,0,0,0, 1.0f, 0.0f,        //右面        1, 0, 0, 1,1,1,0, 0.5f, 0.5f,        1, 1, 1, 1,0,0,0, 1.0f, 0.0f,        1,-1, 1, 1,0,0,0, 0.0f, 0.0f,        1, 0, 0, 1,1,1,0, 0.5f, 0.5f,        1,-1, 1, 1,0,0,0, 0.0f, 0.0f,        1,-1,-1, 1,0,0,0, 0.0f, 1.0f,        1, 0, 0, 1,1,1,0, 0.5f, 0.5f,        1,-1,-1, 1,0,0,0, 0.0f, 1.0f,        1, 1,-1, 1,0,0,0, 1.0f, 1.0f,        1, 0, 0, 1,1,1,0, 0.5f, 0.5f,        1, 1,-1, 1,0,0,0, 1.0f, 1.0f,        1, 1, 1, 1,0,0,0, 1.0f, 0.0f,        //上面        0, 1, 0, 1,1,1,0, 0.5f, 0.5f,        1, 1, 1, 1,0,0,0, 1.0f, 0.0f,        1, 1,-1, 1,0,0,0,  0.0f, 0.0f,        0, 1, 0, 1,1,1,0, 0.5f, 0.5f,        1, 1,-1, 1,0,0,0,  0.0f, 0.0f,        -1, 1,-1, 1,0,0,0, 0.0f, 1.0f,        0, 1, 0, 1,1,1,0, 0.5f, 0.5f,        -1, 1,-1, 1,0,0,0, 0.0f, 1.0f,        -1, 1, 1, 1,0,0,0, 1.0f, 1.0f,        0, 1, 0, 1,1,1,0, 0.5f, 0.5f,        -1, 1, 1, 1,0,0,0, 1.0f, 1.0f,        1, 1, 1, 1,0,0,0, 1.0f, 0.0f,        //下面        0,-1, 0, 1,1,1,0, 0.5f, 0.5f,        1,-1, 1, 1,0,0,0, 1.0f, 0.0f,        -1,-1, 1, 1,0,0,0, 0.0f, 0.0f,        0,-1, 0, 1,1,1,0, 0.5f, 0.5f,        -1,-1, 1, 1,0,0,0, 0.0f, 0.0f,        -1,-1,-1, 1,0,0,0, 0.0f, 1.0f,        0,-1, 0, 1,1,1,0, 0.5f, 0.5f,        -1,-1,-1, 1,0,0,0, 0.0f, 1.0f,        1,-1,-1, 1,0,0,0, 1.0f, 1.0f,        0,-1, 0, 1,1,1,0, 0.5f, 0.5f,        1,-1,-1, 1,0,0,0, 1.0f, 1.0f,        1,-1, 1, 1,0,0,0, 1.0f, 0.0f      };    ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);    vbb.order(ByteOrder.nativeOrder());    mVertexBuffer = vbb.asFloatBuffer();    mVertexBuffer.put(vertices);    mVertexBuffer.position(0);    int vertexShader = loaderShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);    int fragmentShader = loaderShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);    mProgram = GLES20.glCreateProgram();    GLES20.glAttachShader(mProgram, vertexShader);    GLES20.glAttachShader(mProgram, fragmentShader);    GLES20.glLinkProgram(mProgram);    mPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");    mColorHandle = GLES20.glGetAttribLocation(mProgram, "aColor");    mTextureCoordHandle = GLES20.glGetAttribLocation(mProgram, "aTextureCoord");    muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");    muMMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMMatrix");    muLightLocationHandle = GLES20.glGetUniformLocation(mProgram, "uLightLocation");    muTextureHandle = GLES20.glGetUniformLocation(mProgram, "uTexture");    initTexture();  }  // 初始化紋理  public void initTexture() {    int [] textures = new int[1];    GLES20.glGenTextures(1, textures, 0);    textureId = textures[0];    // 激活紋理單元,默認激活的就是0號紋理單元    //GLES20.glActiveTexture(GLES20.GL_TEXTURE0);    // 將紋理對象ID綁定到當前活動的紋理單元0上的GL_TEXTURE_2D目標    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId);    // 后面對紋理的設置都是對綁定了的紋理所生效的    //縮小采樣使用最近點采樣    GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,GLES20.GL_NEAREST);    //縮小采樣使用最近點采樣    GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_MAG_FILTER,GLES20.GL_LINEAR);    //紋理包裹拉伸方式在st軸采用截取拉伸方式,這些設置指的是對坐標范圍超過1的部分的限制    GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,GLES20.GL_CLAMP_TO_EDGE);    GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,GLES20.GL_CLAMP_TO_EDGE);    Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.texture);    GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);    // 圖片已經加載到了顯存,可以回收    bitmap.recycle();  }  public void draw() {    GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 12*6);  }  public void setValue(float[] mvpMatrix, float[] mMatrix) {    GLES20.glUseProgram(mProgram);    mVertexBuffer.position(0);    GLES20.glVertexAttribPointer(mPositionHandle, 3, GLES20.GL_FLOAT, false, (4+3+2) * 4, mVertexBuffer);    mVertexBuffer.position(3);    GLES20.glVertexAttribPointer(mColorHandle, 4, GLES20.GL_FLOAT, false, (4+3+2) * 4, mVertexBuffer);    mVertexBuffer.position(7);    GLES20.glVertexAttribPointer(mTextureCoordHandle, 2, GLES20.GL_FLOAT, false, (4+3+2) * 4, mVertexBuffer);    GLES20.glEnableVertexAttribArray(mPositionHandle);    GLES20.glEnableVertexAttribArray(mColorHandle);    GLES20.glEnableVertexAttribArray(mTextureCoordHandle);    GLES20.glUniform3f(muLightLocationHandle, 0, 0, 20);    GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mvpMatrix, 0);    GLES20.glUniformMatrix4fv(muMMatrixHandle, 1, false, mMatrix, 0);    // 將使用的紋理單元0傳遞給片元著色器    GLES20.glUniform1i(muTextureHandle, 0);  }  private int loaderShader(int type, String shaderCode) {    int shader = GLES20.glCreateShader(type);    GLES20.glShaderSource(shader, shaderCode);    GLES20.glCompileShader(shader);    return shader;  }  private String vertexShaderCode = "uniform mat4 uMVPMatrix;"      + "attribute vec2 aTextureCoord;"      + "varying vec2 vTextureCoord;"      + "uniform mat4 uMMatrix;"      + "uniform vec3 uLightLocation;"      + "attribute vec4 aColor;"      + "varying vec4 vColor;"       + "varying vec4 vDiffuse;"      + "attribute vec3 aPosition;"      + "void main(){"       + "vec3 normalVectorOrigin = aPosition;"      + "vec3 normalVector = normalize((uMMatrix*vec4(normalVectorOrigin,1)).xyz);"      + "vec3 vectorLight = normalize(uLightLocation - (uMMatrix * vec4(aPosition,1)).xyz);"      + "float factor = max(0.0, dot(normalVector, vectorLight));"      + "vDiffuse = factor*vec4(1,1,1,1.0);"      + "gl_Position = uMVPMatrix * vec4(aPosition,1);"      + "vColor = aColor;"      + "vTextureCoord = aTextureCoord;" // 將紋理坐標傳到片元著色器,得到更多的插值紋理坐標      + "}";  private String fragmentShaderCode = "precision mediump float;"      + "uniform sampler2D uTexture;" // 這個uniform變量表示了紋理數據,從java中傳過來的是所在的紋理單元編號      + "varying vec2 vTextureCoord;"      + "varying vec4 vColor;"      + "varying vec4 vDiffuse;"      + "void main(){"      + "gl_FragColor = (vColor*vDiffuse + vColor*vec4(0.6,0.6,0.6,1))*texture2D(uTexture, vTextureCoord);" // 在紋理的基礎上還考慮到光照,texture2D函數用于紋理采樣      + "}";}

需要注意的還是傳入的頂點的時候數組里面包含了頂點、顏色和紋理坐標,因此要用ByteBuffer的position方法定位。 

代碼下載

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 武陟县| 肇源县| 乌鲁木齐县| 康保县| 上思县| 开江县| 揭西县| 祁阳县| 营口市| 河北区| 安溪县| 凤凰县| 永昌县| 东辽县| 文水县| 肥西县| 诏安县| 错那县| 邵阳市| 东平县| 呈贡县| 特克斯县| 大姚县| 林甸县| 崇仁县| 息烽县| 呼图壁县| 长阳| 凌源市| 长兴县| 鄂州市| 太康县| 神农架林区| 揭西县| 阳曲县| 清新县| 宜兰县| 祁门县| 巴南区| 滦平县| 湟源县|