【我的安卓进阶之旅】Opengl Es(6)纹理贴图(附Github地址)

前面几篇博客,我们将了Android中利用OpenGL ES 2.0绘制各种形体。但是我们看到的基于OpenGL开发的应用和游戏,可不仅仅是那些规则形体和一些简单的色彩构成,而是各种不规则的形体构成了现实世界或者卡通世界的人和事物,他们都是外面穿着漂亮“衣服”的。本篇博客就是来讲解这些“衣服”的基础的。这些衣服就是纹理贴图

什么是纹理贴图

一般说来,纹理是表示物体表面的一幅或几幅二维图形,也称纹理贴图(texture)。当把纹理按照特定的方式映射到物体表面上的时候,能使物体看上去更加真实。当前流行的图形系统中,纹理绘制已经成为一种必不可少的渲染方法。在理解纹理映射时,可以将纹理看做应用在物体表面的像素颜色。在真实世界中,纹理表示一个对象的颜色、图案以及触觉特征。纹理只表示对象表面的彩色图案,它不能改变对象的几何形式。更进一步的说,它只是一种高强度的计算行为。——百度百科

比如我们在利用OpenGL做游戏的时候,加载了一个人物模型进来了,这个人物模型上是没有色彩的。我们需要给它绘上需要的色彩才行。但是这些色彩从哪里来呢?我们不可能像之前处理球体那样,根据顶点取生成需要的色彩,那样对于我们给这个人物模型绘色的工作量实在太大了。这个时候我们就需要用到纹理贴图的技术了——把一个纹理(对于2D贴图,可以简单的理解为图片),按照所期望的方式显示在诸多三角形组成的物体的表面。

纹理映射原理

启用纹理映射后,如果想把一幅纹理映射到相应的几何图元,就必须告诉GPU如何进行纹理映射,也就是为图元的顶点指定恰当的纹理坐标。纹理坐标用浮点数来表示,范围一般从0.0到1.0,左上角坐标为(0.0,0.0),右上角坐标为(1.0,0.0),左下角坐标为(0.0,1.0),右下角坐标为(1.0,1.0),如下图所示:
这里写图片描述 顶点图
左图为纹理图和纹理坐标,右图为顶点图和顶点坐标。
将纹理映射到右边的两个三角形上(也就是一个矩形),需要将纹理坐标指定到正确的顶点上,才能使纹理正确的显示,否则显示出来的纹理会无法显示,或者出现旋转、翻转、错位等情况。
将右图顶点按照V2V1V4V3传入,以三角形条带方式绘制,则纹理坐标应按照V2V1V4V3传入。如果按照V3V4V1V2传入,会得到一个旋转了180度的纹理。如果按照V4V3V2V1传入,则会得到一个左右翻转的纹理。

显示图片

根据纹理映射原理,结合之前绘制正方形的经验,我们可以根据以下步骤利用OpenGL ES显示一张图片:

第一步,修改着色器
首先,我们需要修改我们的着色器,将顶点着色器修改为:

attribute vec4 vPosition;
attribute vec2 vCoordinate;
uniform mat4 vMatrix;

varying vec2 aCoordinate;

void main(){
    gl_Position=vMatrix*vPosition;
    aCoordinate=vCoordinate;
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

可以看到,顶点着色器中增加了一个vec2变量,并将这个变量传递给了片元着色器,这个变量就是纹理坐标。接着我们修改片元着色器为:

precision mediump float;

uniform sampler2D vTexture;
varying vec2 aCoordinate;

void main(){
    gl_FragColor=texture2D(vTexture,aCoordinate);
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

片元着色器中,增加了一个sampler2D的变量,sampler2D我们在前一篇博客GLSL语言基础中提到过,是GLSL的变量类型之一的取样器。texture2D也有提到,它是GLSL的内置函数,用于2D纹理取样,根据纹理取样器和纹理坐标,可以得到当前纹理取样得到的像素颜色。

第二步,设置顶点坐标和纹理坐标

根据纹理映射原理中的介绍,我们将顶点坐标设置为:

private final float[] sPos={
            -1.0f,1.0f,    //左上角
            -1.0f,-1.0f,   //左下角
            1.0f,1.0f,     //右上角
            1.0f,-1.0f     //右下角
    };
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

相应的,对照顶点坐标,我们可以设置纹理坐标为:

private final float[] sCoord={
            0.0f,0.0f,
            0.0f,1.0f,
            1.0f,0.0f,
            1.0f,1.0f,
    };
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

第三步,计算变换矩阵

按照上步设置顶点坐标和纹理坐标,大多数情况下我们得到的一定是一张拉升或者压缩的图片。为了让图片完整的显示,且不被拉伸和压缩,我们需要向绘制等腰直角三角形一样,计算一个合适的变换矩阵,传入顶点着色器,代码如下:

 @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        GLES20.glViewport(0,0,width,height);;

        float ratio = height/width;

        int w=mBitmap.getWidth();
        int h=mBitmap.getHeight();
        float sWH=w/(float)h;
        float sWidthHeight=width/(float)height;
        uXY=sWidthHeight;
        //设置正交投影参数
        if(width>height){
            if(sWH>sWidthHeight){
                Matrix.orthoM(mProjectMatrix, 0, -sWidthHeight*sWH,sWidthHeight*sWH, -1,1, 3, 5);
            }else{
                Matrix.orthoM(mProjectMatrix, 0, -sWidthHeight/sWH,sWidthHeight/sWH, -1,1, 3, 5);
            }
        }else{
            if(sWH>sWidthHeight){
                Matrix.orthoM(mProjectMatrix, 0, -1, 1, -1/sWidthHeight*sWH, 1/sWidthHeight*sWH,3, 5);
            }else{
                Matrix.orthoM(mProjectMatrix, 0, -1, 1, -sWH/sWidthHeight, sWH/sWidthHeight,3, 5);
            }
        }
        //  Matrix.frustumM(mProjectMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
        //设置相机位置
        //eyex,eyey,eyez 代表相机在坐标轴的位置,centerX,centerY,centerZ代表物体的中心坐标,upX,upY,upZ代表相机往哪边看
        //设置相机位置
        Matrix.setLookAtM(mViewMatrix, 0, 0, 0, 5.0f, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
        //计算变换矩阵
        Matrix.multiplyMM(mMVPMatrix,0,mProjectMatrix,0,mViewMatrix,0);
    }

mMVPMatrix即为我们所需要的变换矩阵。

第四步,显示图片

然后我们需要做的,就和之前绘制正方形一样容易了。和之前不同的是,在绘制之前,我们还需要将纹理和纹理坐标传入着色器:


    @Override
    public void onDrawFrame(GL10 gl) {
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT|GLES20.GL_DEPTH_BUFFER_BIT);
        //告知OpenGL所要使用的Program
        GLES20.glUseProgram(mProgramId);
        //允许指向顶点数据
        GLES20.glEnableVertexAttribArray(mPositionId);
        //传入顶点数据
        GLES20.glVertexAttribPointer(mPositionId, 3,
                GLES20.GL_FLOAT, false,
                3*4, vertexBuffer);

        //启用指向纹理数据的句柄
        GLES20.glEnableVertexAttribArray(glHCoordinate);

//        GLES20.glUniform1i(glVTexture, 0);
        createTexture();
        //传入纹理坐标
        GLES20.glVertexAttribPointer(glHCoordinate,2,GLES20.GL_FLOAT,false,2*4,textureBuffer);
 
        //指定vMatrix的值
        GLES20.glUniformMatrix4fv(mMatrixHandler,1,false,mMVPMatrix,0);

        //索引法绘制正方形
        GLES20.glDrawElements(GLES20.GL_TRIANGLES,index.length, GLES20.GL_UNSIGNED_SHORT,indexBuffer);
        //禁用指向三角形的顶点数据
        GLES20.glDisableVertexAttribArray(mPositionId);
    }

这样我们就可以显示出我们需要显示的图片,并且保证它完整的居中显示而且不会变形了,如下图:

竖屏显示

源码

附上github下载地址

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: opengles编程指南是一本介绍如何使用OpenGL ES进行图形渲染的书籍。OpenGL ES是一套跨平台的图形处理API,专门为移动和嵌入式设备设计。本书详细介绍了OpenGL ES 3.0及更高版本的基础知识和技术,并提供了丰富的示例和实地操作经验。这本书是一本非常实用的OpenGL ES编程入门指南。 同时,本书的作者也将pdf版放到了github上,方便读者进行在线阅读和下载。在github的页面上,读者可以通过查看文件的历史记录来了解每次更新的细节,可以通过Pull Request来提交修改建议和bug报告,也可以通过Fork功能将该书的源代码分支到自己的GitHub账号下进行开发或修改,这是非常方便的学习方式。 总的来说,opengles编程指南 pdf github是一本非常实用的OpenGL ES编程入门指南,书籍通过讲授基础知识和技术,同时也提供丰富的示例和实地操作经验,还可以通过github进一步获取更多信息和互动。对于从事OpenGL ES开发的程序员来说,这是一本非常值得阅读的书籍,并为他们提供了很好的学习和开发参考。 ### 回答2: opengles编程指南 pdf github是一个开源项目,提供了OpenGL ES编程指南的PDF版本和源代码。OpenGL ES是一款流行的图形渲染库,可以用于在移动设备上实现高性能3D图形渲染。通过该指南,开发者可以学习如何在Android、iOS和WebGL等平台上使用OpenGL ES开发应用程序。 该项目通过在GitHub上托管源代码和文档,使它更容易得到维护和更新。开发者们可以随时提交代码,分享自己的经验和知识。这个项目也有不少贡献者,他们提出了自己的建议和改进,使得OpenGL ES编程指南更加完善。 OpenGL ES编程指南pdf github项目也提供了一个完整的开发环境。开发者们可以使用该项目中的代码示例和示意图进行实践,从而更好地掌握OpenGL ES的编程方法。这个项目有很多开发者在使用,他们通过这个项目来提升自己的技能和开发能力。 总之,OpenGL ES编程指南pdf github项目是一个非常有用的资源,它为开发者们提供了一个学习OpenGL ES编程的良好平台。在这个项目中,开发者们可以轻松地获得指南、源代码和开发环境等一切必要的资源,使其更加方便高效地学习和应用OpenGL ES
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值