1 前言

纹理贴图是指:将图片贴在模型的表面。

纹理贴图的本质是:将图片划分为一系列三角形,使得图片顶点序列模型顶点序列中的顶点一一对应,对于模型中任意三角形内部的坐标和图片中对应三角形内部的坐标,可以通过插值,建立一一对应关系,模型中任意位置的颜色由其对应的图片位置的颜色填充

本文完整代码资源见→【OpenGL ES】纹理贴图

项目目录如下:

2 案例

MainActivity.java

package com.zhyan8.texture;import android.opengl.GLSurfaceView;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;public class MainActivity extends AppCompatActivity {private GLSurfaceView mGlSurfaceView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);mGlSurfaceView = new MyGLSurfaceView(this);setContentView(mGlSurfaceView);mGlSurfaceView.setRenderer(new MyRender(this));}@Overrideprotected void onResume() {super.onResume();mGlSurfaceView.onResume();}@Overrideprotected void onPause() {super.onPause();mGlSurfaceView.onPause();}
}

MyGLSurfaceView.java

package com.zhyan8.texture;import android.content.Context;
import android.opengl.GLSurfaceView;
import android.util.AttributeSet;public class MyGLSurfaceView extends GLSurfaceView {public MyGLSurfaceView(Context context) {super(context);setEGLContextClientVersion(3);}public MyGLSurfaceView(Context context, AttributeSet attrs) {super(context, attrs);setEGLContextClientVersion(3);}
}

MyRender.java

package com.zhyan8.texture;import android.content.Context;
import android.opengl.GLES30;
import android.opengl.GLSurfaceView;
import java.nio.FloatBuffer;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;public class MyRender implements GLSurfaceView.Renderer {private FloatBuffer vertexBuffer;private FloatBuffer textureBuffer;private MyGLUtils mGLUtils;private float[] mvpMatrix = new float[16];private int mvpMatrixLocation;private int mTextureId;public MyRender(Context context) {mGLUtils = new MyGLUtils(context);getFloatBuffer();}@Overridepublic void onSurfaceCreated(GL10 gl, EGLConfig eglConfig) {//设置背景颜色GLES30.glClearColor(0.1f, 0.2f, 0.3f, 0.4f);//编译着色器final int vertexShaderId = mGLUtils.compileShader(GLES30.GL_VERTEX_SHADER, R.raw.vertex_shader);final int fragmentShaderId = mGLUtils.compileShader(GLES30.GL_FRAGMENT_SHADER, R.raw.fragment_shader);//链接程序片段int programId = mGLUtils.linkProgram(vertexShaderId, fragmentShaderId);GLES30.glUseProgram(programId);mvpMatrixLocation = GLES30.glGetUniformLocation(programId, "mvpMatrix");mTextureId = mGLUtils.loadTexture(R.raw.xxx);}@Overridepublic void onSurfaceChanged(GL10 gl, int width, int height) {//设置视图窗口GLES30.glViewport(0, 0, width, height);mGLUtils.transform(width, height, mvpMatrix);}@Overridepublic void onDrawFrame(GL10 gl) {//将颜色缓冲区设置为预设的颜色GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);GLES30.glUniformMatrix4fv(mvpMatrixLocation, 1, false, mvpMatrix, 0);//启用顶点的数组句柄GLES30.glEnableVertexAttribArray(0);GLES30.glEnableVertexAttribArray(1);//准备顶点坐标和纹理坐标GLES30.glVertexAttribPointer(0, 3, GLES30.GL_FLOAT, false, 0, vertexBuffer);GLES30.glVertexAttribPointer(1, 2, GLES30.GL_FLOAT, false, 0, textureBuffer);//激活纹理GLES30.glActiveTexture(GLES30.GL_TEXTURE);//绑定纹理GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, mTextureId);//绘制贴图GLES30.glDrawArrays(GLES30.GL_TRIANGLE_FAN, 0, 4);//禁止顶点数组句柄GLES30.glDisableVertexAttribArray(0);GLES30.glDisableVertexAttribArray(1);}private void getFloatBuffer() {float[] vertex = new float[] {1f, 1f, 0f,     //V0-1f, 1f, 0f,    //V1-1f, -1f, 0f,   //V21f, -1f, 0f     //V3};float[] texture = {1f, 0f,     //V00f, 0f,     //V10f, 1.0f,   //V21f, 1.0f    //V3};vertexBuffer = mGLUtils.getFloatBuffer(vertex);textureBuffer = mGLUtils.getFloatBuffer(texture);}
}

MyGLUtils.java

package com.zhyan8.texture;import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES30;
import android.opengl.GLUtils;
import android.opengl.Matrix;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;public class MyGLUtils {private Context mContext;private Bitmap mBitmap;public MyGLUtils(Context context) {mContext = context;}public FloatBuffer getFloatBuffer(float[] floatArr) {FloatBuffer fb = ByteBuffer.allocateDirect(floatArr.length * Float.BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer();fb.put(floatArr);fb.position(0);return fb;}//通过代码片段编译着色器public int compileShader(int type, String shaderCode){int shader = GLES30.glCreateShader(type);GLES30.glShaderSource(shader, shaderCode);GLES30.glCompileShader(shader);return shader;}//通过外部资源编译着色器public int compileShader(int type, int shaderId){String shaderCode = readShaderFromResource(shaderId);return compileShader(type, shaderCode);}//链接到着色器public int linkProgram(int vertexShaderId, int fragmentShaderId) {final int programId = GLES30.glCreateProgram();//将顶点着色器加入到程序GLES30.glAttachShader(programId, vertexShaderId);//将片元着色器加入到程序GLES30.glAttachShader(programId, fragmentShaderId);//链接着色器程序GLES30.glLinkProgram(programId);return programId;}//从shader文件读出字符串private String readShaderFromResource(int shaderId) {InputStream is = mContext.getResources().openRawResource(shaderId);BufferedReader br = new BufferedReader(new InputStreamReader(is));String line;StringBuilder sb = new StringBuilder();try {while ((line = br.readLine()) != null) {sb.append(line);sb.append("\n");}br.close();} catch (Exception e) {e.printStackTrace();}return sb.toString();}//加载纹理贴图public int loadTexture(int resourceId) {BitmapFactory.Options options = new BitmapFactory.Options();options.inScaled = false;mBitmap = BitmapFactory.decodeResource(mContext.getResources(), resourceId, options);final int[] textureIds = new int[1];// 生成纹理idGLES30.glGenTextures(1, textureIds, 0);// 绑定纹理到OpenGLGLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textureIds[0]);GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_LINEAR_MIPMAP_LINEAR);GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR);// 加载bitmap到纹理中GLUtils.texImage2D(GLES30.GL_TEXTURE_2D, 0, mBitmap, 0);// 生成MIP贴图GLES30.glGenerateMipmap(GLES30.GL_TEXTURE_2D);// 取消绑定纹理GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, 0);return textureIds[0];}//调整图片宽高适配屏幕尺寸public void transform(int width, int height, float[] matrix) {int mapWidth = mBitmap.getWidth();int mapHeight = mBitmap.getHeight();float mapRatio = mapWidth / (float)mapHeight;float ratio = width / (float)height;float w = 1.0f;float h = 1.0f;if (mapRatio > ratio) { //宽度最大,高度适配h = mapRatio / ratio;} else { //高度最大,宽度适配w = ratio / mapRatio;}Matrix.orthoM(matrix, 0, -w, w, -h, h,-1, 1);}
}

vertex_shader.glsl

#version 300 es
layout (location = 0) in vec4 aPosition;
layout (location = 1) in vec2 aTextureCoord;
uniform mat4 mvpMatrix;
out vec2 vTexCoord;
void main() {gl_Position  = mvpMatrix * aPosition;vTexCoord = aTextureCoord;
}//attribute vec4 aPosition;
//attribute vec2 aTextureCoord;
//uniform mat4 mvpMatrix;
//varying vec2 vTexCoord;
//void main() {
//     gl_Position  = mvpMatrix * aPosition;
//     vTexCoord = aTextureCoord;
//}

顶点着色器的作用:进行矩阵变换位置、根据光照公式计算顶点颜⾊⽣成 / 变换纹理坐标,并且把位置和纹理坐标发送到片元着色器。

顶点着色器中,如果没有指定默认精度,则 int 和 float 的默认精度都为 highp。

fragment_shader.glsl

#version 300 es
precision mediump float;
uniform sampler2D uTextureUnit;
in vec2 vTexCoord;
out vec4 fragColor;
void main() {fragColor = texture(uTextureUnit, vTexCoord);
}//precision mediump float;
//uniform sampler2D uTextureUnit;
//varying vec2 vTexCoord;
//void main() {
//     gl_FragColor = texture2D(uTextureUnit, vTexCoord);
//}

片元着色器的作用:处理经光栅化阶段生成的每个片元,计算每个像素的颜色和透明度。

在片元着色器中,浮点值没有默认的精度值,每个着色器必须声明一个默认的 float 精度。

        运行结果:

【OpenGL ES】纹理贴图相关推荐

  1. opengl es纹理贴图效果实例

    一.先准备好一张用来贴图的照片 二.纹理效果代码: gl.glEnable(GL10.GL_TEXTURE_2D);// 创建纹理gl.glGenTextures(1, textureids, 0); ...

  2. OpenGL立方体纹理贴图

    OpenGL正方体纹理贴图 0. 写在最前面 1. 正方体顶点属性构建 2. 绑定多个VAO.VBO 3. 创建多个纹理 4. 渲染循环 5. 实现代码 6. 多个立方体纹理贴图 0. 写在最前面 要 ...

  3. openCV读入图片,openGL实现纹理贴图

    本文结合结合openCV,openGL的优点,实现混合编程. (1)OpenCV提供图形处理和计算机视觉方面的通用算法,读入二维图片很方便: (2)OpenGL是跨平台的图形程序接口,它用于二维,三维 ...

  4. opengl android 纹理贴图 代码,Android 使用opengl es的纹理贴图白屏问题请教。

    各位大侠好: 我在使用open gl es的做显示的时候,发现一个问题,请各位帮助一下,谢谢. 环境:opengl es 1.x,2D的模式显示纹理图片. 在LG-P990,HTC-C510E上显示附 ...

  5. OpenGL ES 纹理

    纹理概念 纹理对象和纹理加载 应用纹理的例子 使用前面学过的技术已经可以利用OpenGL ES构建立体图形,并通过顶点着色器和片元着色器对其进行各种变化呢和光照等效果使得三维效果更加真实,实际上我看看 ...

  6. android opengl es 纹理 不同设备 白色,android – OpenGL ES 2.0纹理没有在某些设备上显示...

    早上好,这是2个纹理非幂的典型例子. 由于多种原因,纹理在分辨率上需要2的幂,这是一个非常常见的错误,每个人都碰巧陷入这个陷阱:)我也是. 2个纹理的非功率在某些设备/ GPU上运行平稳的事实,仅仅取 ...

  7. 纹理窗口Qt+OpenGL之纹理贴图

    上班之余抽点时间出来写写博文,希望对新接触的朋友有帮助.今天在这里和大家一起学习一下纹理窗口 NeNe的代码中是加载到了一个正方体当中,代码很长.其实单纯的想要纹理贴图是很便利的.具体的纹理贴图技巧在 ...

  8. 手把手教会OpenGL之纹理贴图、包含纹理载入、纹理过滤、边界处理、纹理参数设置(入门级别案例,棋盘)

    一.OpenGL中纹理的加载(对glTexImage2D函数的使用) 二.纹理过滤(glTexParameteri参数中的GL_TEXTURE_MAG_FILTER与 GL_TEXTURE_MIN_F ...

  9. Opengl实现纹理贴图

    纹理贴图的步骤 创建纹理对象,并为它指定一个纹理 确定纹理如何应用到每个像素上 启用纹理贴图功能 绘制场景,提供纹理坐标和几何图形坐 Tips:纹理坐标必须在RGBA模式下才能使用,在颜色索引模式下是 ...

  10. OpenGL:纹理贴图

    纹理贴图是在栅格化的模型表面上覆盖图像的技术.它是为渲染场景添加真实感的最基本和最重要的方法之一.硬件也为纹理贴图提供了硬件支持,使得它具备实现实时的照片级真实感的超高性能.纹理单元是专为纹理设计的硬 ...

最新文章

  1. ASP.NET 防盗链源码
  2. 《Redis设计与实现》阅读笔记(二)--简单动态字符串
  3. hexo博客系统安装
  4. java关闭ie提示_java 关闭IE
  5. 一起讨论系统架构设计师考试大纲中样题参考答案
  6. [置顶] Java Socket实战之一 单线程通信
  7. REVERSE-PRACTICE-BUUCTF-14
  8. IPC--进程间通信四(信号量)
  9. php学语法,PHP入门学习——PHP语法
  10. python生成的字符画怎么查看_通过python将图片生成字符画
  11. 凸优化第五章对偶 5.2 Lagrange对偶问题
  12. 给定一个数值,计算最合适的行列数量的代码
  13. pdf转word乱码怎么办,可能是你没用对工具
  14. yml文件读取方式_1
  15. wifi信号桥怎么设置_用手机怎么桥设置桥接无线路由器?(步要祥细)
  16. UT000020: Connection terminated as request was larger than 10485760
  17. 青龙面板滴滴果园自动签到
  18. 三分钟了解大数据是什么
  19. R语言对京东商品进行文本爬虫
  20. 从PD充电器取9V12V给产品供电快充,PD取电芯片概述

热门文章

  1. 换一种视角看《百度SEM竞价推广》
  2. 涉案金额2亿多!贺金虎、刘国庆非法吸收公众存款案开庭
  3. QCustomPlot之光标划过曲线显示点的坐标
  4. CSS星星闪烁流星划过动画特效
  5. 最短路径——DFS、Dijkstra、Floyd、Bellman-Ford、spfa
  6. word文档怎么删除论文末尾尾注的横线
  7. 网络共享计算机网络无法访问,局域网电脑无法访问共享文件网络共享失败怎么解决...
  8. 27_Pandas按星期,月份,季度和年份的天计算时间序列数据的总计和平均值
  9. 永中Office 2004 增强版上市,试用版免费下载
  10. win10安装visio2010出错_四种解决安装Office 2010时出现错误1907的提示方法介绍