中文字幕日韩精品一区二区免费_精品一区二区三区国产精品无卡在_国精品无码专区一区二区三区_国产αv三级中文在线

OpenGLES紋理詳解

使用前面學(xué)過(guò)的技術(shù)已經(jīng)可以利用OpenGL ES構(gòu)建立體圖形,并通過(guò)頂點(diǎn)著色器和片元著色器對(duì)其進(jìn)行各種變化呢和光照等效果使得三維效果更加真實(shí),實(shí)際上我看看到很多的3D游戲漂亮多了,那是因?yàn)橛懈鞣N各樣的漂亮的圖像帶給人很多視覺盛宴,這篇文章在前面的基礎(chǔ)上,增加物體的表面貼圖,使得物體更加好看。

創(chuàng)新互聯(lián)公司專注于企業(yè)成都營(yíng)銷網(wǎng)站建設(shè)、網(wǎng)站重做改版、通許網(wǎng)站定制設(shè)計(jì)、自適應(yīng)品牌網(wǎng)站建設(shè)、HTML5、商城網(wǎng)站建設(shè)、集團(tuán)公司官網(wǎng)建設(shè)、外貿(mào)網(wǎng)站制作、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁(yè)設(shè)計(jì)等建站業(yè)務(wù),價(jià)格優(yōu)惠性價(jià)比高,為通許等各大城市提供網(wǎng)站開發(fā)制作服務(wù)。

紋理概念

紋理用來(lái)表示圖像照片或者說(shuō)一系列的數(shù)據(jù),使用紋理可以使物體用用更多的細(xì)節(jié)。OpenGL ES 2.0 中有兩種貼圖:二維紋理和立方體紋理。

每個(gè)二維紋理都由許多小的紋理元素組成,類似與片元和像素,使用紋理最簡(jiǎn)單的方式就是直接從一個(gè)圖像加載數(shù)據(jù)。在OpenGL中規(guī)定紋理圖像的左下角由stst坐標(biāo)(0.0,0.0)指定,右上角由stst坐標(biāo)(1.0,1.0)指定,不過(guò)超過(guò)1.0的坐標(biāo)也是允許的,在該區(qū)間之外的紋理在讀取時(shí)的時(shí)候由紋理拉伸模式?jīng)Q定。

OpenGL ES 2.0不必是正方形,但是每個(gè)維度都應(yīng)該是2的冪

在Android中使用的OpenGL ES的紋理坐標(biāo)系跟官方的紋理坐標(biāo)系統(tǒng)不一樣,在Android中使用官方的紋理坐標(biāo)系統(tǒng),得到的結(jié)果是相反的,而是左上角是stst坐標(biāo)(0.0,0.0)點(diǎn),右下角是stst坐標(biāo)(1.0,1.0)點(diǎn)。

二維紋理映射的原理

OpenGL ES紋理詳解

使用紋理就是在紋理圖中進(jìn)行采樣,因此需要將選定的紋理坐標(biāo)穿進(jìn)頂點(diǎn)著色器,經(jīng)過(guò)插值在片元著色器中從紋理圖中的指定位置采樣即可,紋理圖的數(shù)據(jù)通過(guò)往片元插值器傳遞紋理單元指定的。

紋理對(duì)象和紋理加載

創(chuàng)建一個(gè)紋理對(duì)象,保存渲染所需的紋理數(shù)據(jù),例如圖像數(shù)據(jù)、過(guò)濾模式、包裝模式。創(chuàng)建生成紋理對(duì)象的函數(shù)

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

紋理對(duì)象在應(yīng)用程序中不再使用時(shí),需要?jiǎng)h除。

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

紋理對(duì)象的 ID 必須是 glGenTextures 產(chǎn)生的,一旦生成紋理ID,就必須綁定紋理對(duì)象才能繼續(xù)進(jìn)行后續(xù)的操作。后續(xù)的操作將影響綁定的紋理對(duì)象。一旦紋理被綁定到一個(gè)特定的紋理目標(biāo),再刪除之前就一直保持著綁定狀態(tài)。

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

激活某個(gè)紋理單元

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

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

紋理單元TextureUnit的定義如下

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

glActiveTexture函數(shù)就是設(shè)置當(dāng)前活動(dòng)的紋理單元

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

glBindTexture函數(shù)就是將紋理對(duì)象ID賦值給當(dāng)前活動(dòng)的紋理單元的對(duì)應(yīng)的目標(biāo)紋理。

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;
  }
}

獲取一副圖片的紋理數(shù)據(jù)

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

其他紋理選項(xiàng)的設(shè)置使用glTexParameterf系列函數(shù)

public static native void glTexParameterf(
    int target, 
    int pname, // 設(shè)定的參數(shù),可以是GL_TEXTURE_MAG_FILTER,GL_TEXTURE_MIN_FILTER,GL_TEXTURE_WRAP_S,GL_TEXTURE_WRAP_T
    float param // 參數(shù)對(duì)應(yīng)的值
  );

應(yīng)用紋理的例子

對(duì)前面的立方體的每個(gè)面應(yīng)用一張圖片作為紋理貼圖,效果圖(這個(gè)紋理圖是哪個(gè)老師來(lái)著?)

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[] {
        // 頂點(diǎn)  顏色   紋理坐標(biāo)
        //前面
        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];
    // 激活紋理單元,默認(rèn)激活的就是0號(hào)紋理單元
    //GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
    // 將紋理對(duì)象ID綁定到當(dāng)前活動(dòng)的紋理單元0上的GL_TEXTURE_2D目標(biāo)
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId);
    // 后面對(duì)紋理的設(shè)置都是對(duì)綁定了的紋理所生效的
    //縮小采樣使用最近點(diǎn)采樣
    GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,GLES20.GL_NEAREST);
    //縮小采樣使用最近點(diǎn)采樣
    GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_MAG_FILTER,GLES20.GL_LINEAR);
    //紋理包裹拉伸方式在st軸采用截取拉伸方式,這些設(shè)置指的是對(duì)坐標(biāo)范圍超過(guò)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);
    // 圖片已經(jīng)加載到了顯存,可以回收
    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;" // 將紋理坐標(biāo)傳到片元著色器,得到更多的插值紋理坐標(biāo)
      + "}";

  private String fragmentShaderCode = "precision mediump float;"
      + "uniform sampler2D uTexture;" // 這個(gè)uniform變量表示了紋理數(shù)據(jù),從java中傳過(guò)來(lái)的是所在的紋理單元編號(hào)
      + "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);" // 在紋理的基礎(chǔ)上還考慮到光照,texture2D函數(shù)用于紋理采樣
      + "}";
}

需要注意的還是傳入的頂點(diǎn)的時(shí)候數(shù)組里面包含了頂點(diǎn)、顏色和紋理坐標(biāo),因此要用ByteBuffer的position方法定位。

代碼下載

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。

網(wǎng)站欄目:OpenGLES紋理詳解
鏈接分享:http://www.rwnh.cn/article42/jieeec.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供商城網(wǎng)站、App設(shè)計(jì)、關(guān)鍵詞優(yōu)化、Google、網(wǎng)站收錄、企業(yè)建站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

h5響應(yīng)式網(wǎng)站建設(shè)
大洼县| 汉中市| 江达县| 兴隆县| 株洲县| 五莲县| 炉霍县| 南召县| 斗六市| 托克托县| 织金县| 宁津县| 行唐县| 邢台县| 鹿泉市| 大化| 都江堰市| 黑龙江省| 固镇县| 晴隆县| 社旗县| 彰化市| 西宁市| 澜沧| 兴宁市| 通渭县| 同江市| 嘉善县| 湟源县| 虎林市| 宣武区| 扎兰屯市| 云和县| 鹿邑县| 云和县| 兰坪| 榕江县| 禄劝| 武平县| 晋宁县| 抚松县|