OpenGLES:3D立方体纹理贴图

效果展示

一.概述

前几篇博文讲解了OpenGLES绘制多种3D图形,并赋予丰富的色彩,但是在这些3D图形绘制过程中,有一点还没有涉及,就是纹理贴图。

今天这篇博文我会用如下六张图片 对立方体进行纹理贴图,实现六个面都是贴图的3D旋转立方体

二.GLRender:变量定义

2.1 常规变量定义

cpp 复制代码
//顶点坐标属性
private int vPosition;
//纹理坐标属性
private int aTextureCoord;
//转换矩阵属性
private int mvpMatrix;
//采样器
private int sampler;      

//surface宽高比
private float ratio;

2.2 顶点、纹理相关变量定义

之前绘制混色旋转立方体的博文:《OpenGLES:绘制一个混色旋转的3D立方体》,定义了三个数组,在onDrawFrame() 绘制时直接绘制索引实现立方体

  • 顶点坐标数组
  • 顶点颜色数组
  • 顶点索引数组

今天这篇博文对立方体的实现与之前并不相同,不再使用索引绘制,只定义并实现了两个数组:

  • 顶点坐标数组
  • 纹理坐标数组

这两个数组是必须的

cpp 复制代码
//顶点坐标数组
public static float[] vertexData = new float[] {
   ...
}
//纹理坐标数组
public static float[] textureData = new float[] {
   ...
}

//顶点坐标缓冲
private FloatBuffer vertexBuffer;
//纹理坐标缓冲
private FloatBuffer textureBuffer;

纹理和贴图也定了两个数组:

  • 纹理Id数组
  • 图片资源Id数组

图片资源Id数组并不是必须的,主要是优化纹理操作时的流程代码

cpp 复制代码
//纹理id数组
private int[] textureIds;

//图片资源id数组
public static int[] textureResIds = new int[]{
		R.drawable.cube_texture_1,
		R.drawable.cube_texture_2,
		R.drawable.cube_texture_3,
		R.drawable.cube_texture_4,
		R.drawable.cube_texture_5,
		R.drawable.cube_texture_6
};

2.3 定义MVP矩阵

cpp 复制代码
//MVP矩阵
private float[] mMVPMatrix = new float[16];

三.GLRender:着色器、内存分配等

3.1 着色器创建、链接、使用

3.2 着色器属性获取、赋值

3.3 缓冲内存分配

这几个部分的代码实现2D图形绘制基本一致

可参考以前2D绘制的相关博文,里面都有详细的代码实现

不再重复展示代码

三.GLRender:多纹理加载

多纹理加载在之前这篇博客中有讲解过:《OpenGLES:多纹理贴图,文字水印》,其中实现了一个LoadTexture() 函数,通过多次调用该函数,传入纹理Id图片资源Id实现纹理生成和贴图绑定。

本篇博文对这个函数进行优化,只需要传入图片资源Id数组,在函数内部根据图片数量完成纹理生成和绑定,并返回生成的纹理数组

代码如下:

cpp 复制代码
//纹理Id根据贴图数量在Api内部创建,加载纹理贴图后返回纹理Id数组
public static int[] LoadTexture(Context context, int[] resIds) {
	BitmapFactory.Options options = new BitmapFactory.Options();
	options.inScaled = false;
	Bitmap[] bitmaps = new Bitmap[resIds.length];
	// 生成纹理id
	final int[] textureIds = new int[resIds.length];
	glGenTextures(resIds.length, textureIds, 0);
	for (int i = 0; i < resIds.length; i++) {
		bitmaps[i] = BitmapFactory.decodeResource(context.getResources(), resIds[i], options);
		// 绑定纹理到OpenGL
		glBindTexture(GL_TEXTURE_2D, textureIds[i]);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		// 加载bitmap到纹理中
		GLUtils.texImage2D(GL_TEXTURE_2D, 0, bitmaps[i], 0);
		// 生成MIP贴图
		glGenerateMipmap(GL_TEXTURE_2D);
		// 取消绑定纹理
		glBindTexture(GL_TEXTURE_2D, 0);
		bitmaps[i].recycle();
	}
	return textureIds;
}

五.GLRender:绘制

**onDrawFrame()**中的关键点有两处

5.1 MVP矩阵

cpp 复制代码
//MVP矩阵赋值
mMVPMatrix = TransformUtils.getCubeTextureMVPMatrix(ratio);
//设置MVP变换矩阵到着色器程序/渲染器
glUniformMatrix4fv(mvpMatrix, 1, false, mMVPMatrix, 0);

**getCubeTextureMVPMatrix()**函数代码:

cpp 复制代码
//计算MVP变换矩阵
public static float[] getCubeTextureMVPMatrix(float ratio) {
	//初始化modelMatrix, viewMatrix, projectionMatrix
	float[] modelMatrix = getIdentityMatrix(16, 0); //模型变换矩阵
	float[] viewMatrix = getIdentityMatrix(16, 0); //观测变换矩阵/相机矩阵
	float[] projectionMatrix = getIdentityMatrix(16, 0); //投影变换矩阵

	//获取modelMatrix, viewMatrix, projectionMatrix
	mCubeTextureRotateAgree = (mCubeTextureRotateAgree + 0.5f) % 360;
	Matrix.rotateM(modelMatrix, 0, mCubeTextureRotateAgree, -1, -1, 1); //获取模型旋转变换矩阵
	Matrix.setLookAtM(viewMatrix, 0, 0, 5, 10, 0, 0, 0, 0, 1, 0); //获取观测变换矩阵,设置相机位置
	Matrix.frustumM(projectionMatrix, 0, -ratio, ratio, -1, 1, 3, 20); //获取透视投影变换矩阵,正交投影:Matrix.orthoM(...)

	//计算MVP变换矩阵: mvpMatrix = projectionMatrix * viewMatrix * modelMatrix
	float[] tempMatrix = new float[16];
	float[] mvpMatrix = new float[16];
	Matrix.multiplyMM(tempMatrix, 0, viewMatrix, 0, modelMatrix, 0);
	Matrix.multiplyMM(mvpMatrix, 0, projectionMatrix, 0, tempMatrix, 0);

	return mvpMatrix;
}

5.2 激活、绑定和绘制纹理

cpp 复制代码
/********* 纹理操作:激活、绑定 **********/
glActiveTexture(GL_TEXTURE);
int count = 4;
for (int i =0; i < textureIds.length; i++) {
	int first = i * count;
	//绑定纹理
	glBindTexture(GL_TEXTURE_2D, textureIds[i]);
	//绘制正方体的表面(6个面,每个面2个三角形)
	glDrawArrays(GL_TRIANGLE_FAN, first, count);
}

六.着色器代码

就是最基础的着色器实现,并无特别之处

(1).cube_texture_vertex_shader.glsl

cpp 复制代码
#version 300 es

layout (location = 0) in vec4 vPosition;
layout (location = 1) in vec2 aTextureCoord;

uniform mat4 mvpMatrix;

out vec2 vTexCoord;

void main() {
    gl_Position = mvpMatrix * vPosition;
    vTexCoord = aTextureCoord;
}

(2).cube_texture_fragtment_shader.glsl

cpp 复制代码
#version 300 es
#extension GL_OES_EGL_image_external_essl3 : require
precision mediump float;

uniform sampler2D sampler;

in vec2 vTexCoord;

out vec4 outColor;

void main(){
    outColor = texture(sampler,vTexCoord);
}

八.结束语

3D立方体纹理贴图的讲解到此就结束了

最终实现效果如本博文开头所示

相关推荐
无限码力7 小时前
8.26华为OD机试真题 新系统【字符串回文判断】
算法·华为od·华为od机考·华为od机试·华为od上机考试真题·华为od最新机试真题题解·华为od机试真题题库
玖玥拾9 小时前
LeetCode 125 验证回文串
算法·leetcode
小成很成14 小时前
mysql 8.0.21 升级 mysql 8.0.45(经过生产环境验证)
android·mysql·adb
Asize15 小时前
146. LRU 缓存
算法
Asize15 小时前
543. 二叉树的直径
算法
lemon_sjdk15 小时前
ObjectProperty
java·开发语言·算法
Zentceh16 小时前
AI-ISP在夜视机芯中的应用:从传统ISP到PixelClean全彩夜视的进化
人工智能·科技·算法·计算机视觉·车载系统·视频·智能硬件
xier_ran16 小时前
【infra之路】AWQ 详解:激活感知权重保护,让 W4A16 量化精度超越 GPTQ
线性代数·算法·机器学习·量化·infra
亦皓ai17 小时前
AI时代后端工程(二):AI把代码写得越来越快,我却越来越不敢让它直接开工了
人工智能·算法·机器学习·搜索引擎·transformer