OpenGLES:3D立方体纹理贴图

news2024/11/13 14:41:48

效果展示

一.概述

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

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

二.GLRender:变量定义

2.1 常规变量定义

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

//surface宽高比
private float ratio;

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

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

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

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

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

这两个数组是必须的

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

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

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

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

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

//纹理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矩阵

//MVP矩阵
private float[] mMVPMatrix = new float[16];

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

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

3.2 着色器属性获取、赋值

3.3 缓冲内存分配

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

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

不再重复展示代码

三.GLRender:多纹理加载

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

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

代码如下:

//纹理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矩阵

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

getCubeTextureMVPMatrix() 函数代码:

//计算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 激活、绑定和绘制纹理

/********* 纹理操作:激活、绑定 **********/
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

#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

#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立方体纹理贴图的讲解到此就结束了

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1061228.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vscoe设置if __name__ == ‘__main__‘: 自动提示

解决Vscode 无 if __name__ __main__: 自动提示问题 配置步骤&#xff1a; 设置——》用户代码片段——》python.json配置文件——》添加"Print to console"项 添加代码内容&#xff1a; "Print to console": {"prefix": "main",&q…

数据可视化工具在成绩分析中的作用与意义

数据可视化是将数据转化为图表、图形和可交互式界面的过程&#xff0c;它在成绩分析中扮演着重要的角色。通过将学生成绩数据以图形化方式展示&#xff0c;数据可视化工具可以帮助教育者更好地理解和解释学生的表现&#xff0c;发现隐藏在数据背后的模式和趋势。本文将详细介绍…

添加驱动模块到内核的两种方法

添加驱动模块到内核的两种方法 1. 放在内核源代码树中 步骤总结&#xff1a; 新建文件夹编写Makefile、编写Kconfig修改上层Kconfig执行make menuconfig执行make zImage 或 make modules 1.1 源码放入文件夹 例如&#xff1a;添加一个按键字符设备模块 在内核目录下的 dri…

代码:对鱼眼相机图像进行去畸变处理

图像投影模型&#xff1a;针孔[fx, fy, cx, cy] 图像畸变模型&#xff1a;切向径向畸变[k1, k2, p1, p2] 说明&#xff1a;用于备忘 第一部分是常规的去畸变操作&#xff0c;在已知内参的情况下对鱼眼相机进行去畸变&#xff0c;这里使用的是remap映射在对图像去畸变后&#x…

毛玻璃 has 选择器卡片悬停效果

效果展示 页面结构 从上述的效果展示可以看到&#xff0c;页面是由多个卡片组成&#xff0c;并且鼠标悬停在卡片上时&#xff0c;会旋转用户图片并且韩式对应的用户信息框。 CSS3 知识点 :has 属性的运用 实现页面整体结构 <div class"container"><div…

复原akshare的股票代码缺失前面000代码

原始的akshare保存成文件&#xff0c;再读取时&#xff0c;代码会被自动转换为如下形式&#xff1a; 我们需要对每一个元素&#xff0c;补齐前面的0&#xff0c;将代码补充为6位 示例程序 import pandas as pdmy_df pd.read_csv("akshare下载文件.csv") my_df[代码…

【Linux基础】Linux发展史

&#x1f449;系列专栏&#xff1a;【Linux基础】 &#x1f648;个人主页&#xff1a;sunny-ll 一、前言 本篇主要介绍Linux的发展历史&#xff0c;这里并不需要我们掌握&#xff0c;但是作为一个合格的Linux学习者与操作者&#xff0c;这些东西是需要了解的&#xff0c;而且…

线程的概述

#include <pthread.h> int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg); 功能&#xff1a;创建一个子线程 参数&#xff1a; -thread:传出参数&#xff0c;线程创建成功后&#xff0c;子线程的ID被写到…

SSRF+redis未授权漏洞复现

1.SSRF漏洞简介 SSRF&#xff08;Server-Side Request Forgery&#xff09;即服务器端请求伪造&#xff0c;是一种由攻击者构造攻击链传给服务器&#xff0c;服务器执行并发起请求造成安全问题的漏洞&#xff0c;一般用来在外网探测或攻击内网服务。当网站需要调用指定URL地址…

Inno Setup新手使用教程

1.编写脚本.iss文件 2.使用Inno Setup打开脚本 3.点击运行 4.打包好的文件在output文件夹下 注&#xff1a;运行不通过可能是文件不存在或者路径错误 推荐一个零声学院项目课&#xff0c;个人觉得老师讲得不错&#xff0c;分享给大家&#xff1a; 零声白金学习卡&#xff08;含…

重生奇迹MU刷装备注意事项

在打斗游戏里面装备的作用非常巨大&#xff0c;较好的武器装备可以为玩家带来不错的体验&#xff0c;很多玩家甚至不惜花重金打造属于好装备。那么游戏中刷装备需要注意什么。 一、对武器装备的认识 对于玩家来说需要对武器装备有一定的认识&#xff0c;连基本的武器装备分类都…

# Flink的状态

1.什么是时状态(state)&#xff1f; 有状态的计算是流处理框架要实现的重要功能&#xff0c;因为稍复杂的流处理场景都需要记录状态&#xff0c;然后在新流入数据的基础上不断更新状态。 例如以下状态都需要使用流处理的状态功能&#xff1a; 数据流中的数据有重复&#xff0c…

1.springcloudalibaba nacos2.2.3部署

前言 nacos是springcloudalibaba体系的注册中心&#xff0c;演示如何搭建最新稳定版本的linux搭建。 前置条件&#xff0c;安装好jdk1.8 一、二进制压缩包下载 1.1 下载压缩包 nacos下载 点击下载下载后得到二进制包如下 nacos-2.2.3.tar.gz二、安装步骤 2.1.解压二进制…

十、2023.10.4.计算机网络(one).10

文章目录 1、简述静态路由和动态路由&#xff1f;2、说说有哪些路由协议&#xff0c;都是如何更新的&#xff1f;3、简述域名解析过程&#xff0c;本机如何干预域名解析&#xff1f;4、简述 DNS 查询服务器的基本流程是什么&#xff1f;DNS 劫持是什么&#xff1f;5、简述网关的…

Lwip的接收邮箱大小的影响

LwIP&#xff08;Lightweight IP&#xff09;是一个用于嵌入式系统的轻量级的TCP/IP协议栈&#xff0c;它支持UDP和其他网络协议。 接收邮箱大小 在LwIP中&#xff0c;UDP接收邮箱的大小对系统性能和可靠性有一定影响。 首先&#xff0c;UDP接收邮箱的大小决定了可以同时接收…

如何去占用windows端口

一、问题: 测试的服务使用的端口号范围为6881~6888&#xff0c;一般使用6881&#xff0c;如果该端口被占用&#xff0c;应该去使用其他端口&#xff0c;验证是不是真的这样 二、占用windows端口号方法 1、修改注册表 修改window现有远程连接服务的端口号&#xff08;可能有其他…

计算机中的进制转换

在计算机软件中&#xff0c;经常需要进行进制转换&#xff0c;这包括二进制、八进制、十进制和十六进制之间的转换。以下是一些常见的转换方法&#xff1a; 二进制转十进制&#xff1a;这是最直接的转换&#xff0c;基本上不需要什么特别的算法。你只需要按照二进制的权值进行…

MacBook 录制电脑内部声音

MacBook 录制电脑内部声音 老妈喜欢跳广场舞&#xff0c;现在广场舞音频下载都收费了&#xff01;没办法&#xff0c;只能自己录歌了&#xff0c;外录有杂音大家也都知道&#xff0c;所以就只能采用内录的方式然后再用 Audition 调整一下音量大小。 一、&#xff08;前置条件&a…

【计算机网络】高级IO——select

文章目录 1. select函数介绍为什么要有select&#xff1f;select 接口第一个参数 nfds的理解什么是 输入 输出型参数最后一个参数 timeout 的理解readfds writefds exceptfds 参数的理解select的返回值 2. select的使用SelectServer_v1start 最初版本start 最终版本HandlerEven…

【成像光敏描记图提取和处理】成像-光电容积描记-提取-脉搏率-估计(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…