Android OpenGL(六) 纹理
纹理
纹理是一个2D图片(甚至也有1D和3D的纹理),
它可以用来添加物体的细节;你可以想象纹理是一张绘有砖块的纸,无缝折叠贴合到你的3D的
房子上,这样你的房子看起来就像有砖墙外表了
纹理环绕方式
纹理坐标的范围通常是从(0, 0)到(1, 1),那如果我们把纹理坐标设置在范围之外会发生什么?
OpenGL默认的行为是重复这个纹理图像(我们基本上忽略浮点纹理坐标的整数部分),但
OpenGL提供了更多的选择:
使用方式类似:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
纹理过滤
纹理过滤:GL_NEAREST 、GL_LINEAR和多级渐远纹理
GL_NEAREST(也叫邻近过滤,Nearest Neighbor Filtering)是OpenGL默认的纹理过滤方
式。当设置为GL_NEAREST的时候,OpenGL会选择中心点最接近纹理坐标的那个像素。
GL_LINEAR(也叫线性过滤,(Bi)linear Filtering)它会基于纹理坐标附近的纹理像素,计算出
一个插值,近似出这些纹理像素之间的颜色。一个纹理像素的中心距离纹理坐标越近,那么这个
纹理像素的颜色对最终的样本颜色的贡献越大。
当进行放大(Magnify)和缩小(Minify)操作的时候可以设置纹理过滤的选项,比如你可以在纹理
被缩小的时候使用邻近过滤,被放大时使用线性过滤。我们需要使用glTexParameter*函数为
放大和缩小指定过滤方式。这段代码看起来会和纹理环绕方式的设置很相似:
多级
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
多级渐远纹理
过滤方式
GL_NEAREST_MIPMAP_NEAREST :使用最邻近的多级渐远纹理来匹配像素大小,并使用邻近插值进行纹理采样
GL_LINEAR_MIPMAP_NEAREST: 使用最邻近的多级渐远纹理级别,并使用线性插值进行采样
GL_NEAREST_MIPMAP_LINEAR 在两个最匹配像素大小的多级渐远纹理之间进行线性插值,使用邻近插值进行采样
GL_LINEAR_MIPMAP_LINEAR 在两个邻近的多级渐远纹理之间使用线性插值,并使用线性插值进行采样
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
纹理的使用
-
生成纹理
GLES30.glGenTextures(1, textureIds, 0)
-
绑定纹理
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textureIds[0])
-
设置纹理环绕方式、纹理过滤
GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_LINEAR) GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR)
-
载入图片数据
GLUtils.texImage2D(GLES30.GL_TEXTURE_2D,0,GLES30.GL_RGBA,bitmap,0)
- 取消绑定纹理
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, 0)
纹理加载
private fun loadTexture() {GLES30.glGenTextures(1, textureIds, 0)GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textureIds[0])GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D,GLES30.GL_TEXTURE_MIN_FILTER,GLES30.GL_LINEAR)GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D,GLES30.GL_TEXTURE_MAG_FILTER,GLES30.GL_LINEAR)// 加载bitmap到纹理中GLUtils.texImage2D(GLES30.GL_TEXTURE_2D,0,GLES30.GL_RGBA,bitmap,0)GLES30.glGenerateMipmap(GLES30.GL_TEXTURE_2D)bitmap.recycle()// 取消绑定纹理GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, 0)}
纹理应用
展示图片
布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><android.opengl.GLSurfaceViewandroid:id="@+id/glSurfaceView_img"android:layout_width="match_parent"android:layout_height="match_parent" />
</LinearLayout>
Activity
class OpenGlImgActivity : AppCompatActivity() {private var glSurfaceView: GLSurfaceView? = nulloverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_opengl_img_demo)glSurfaceView = findViewById(R.id.glSurfaceView_img)glSurfaceView?.setEGLContextClientVersion(3)glSurfaceView?.setRenderer(GLImageViewRender(BitmapFactory.decodeResource(resources, R.drawable.flower)))glSurfaceView?.renderMode = GLSurfaceView.RENDERMODE_WHEN_DIRTY}
}
GLSurfaceView.Renderer
import android.graphics.Bitmap
import android.opengl.GLES30
import android.opengl.GLSurfaceView
import android.opengl.GLUtils
import android.opengl.Matrix
import android.util.Log
import java.nio.ByteBuffer
import java.nio.ByteOrder
import java.nio.FloatBuffer
import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.opengles.GL10class GLImageViewRender(val bitmap:Bitmap) : GLSurfaceView.Renderer {/** 顶点位置程序*/private val vertexShaderCode ="uniform mat4 uTMatrix;" +"attribute vec4 aPosition;" +"attribute vec2 aTexCoord;" +"varying vec2 vTexCoord;" +"void main() { " +" gl_Position = uTMatrix * aPosition;" +" vTexCoord = aTexCoord;" +"}"/*** 片元颜色程序*/private val fragmentShaderCode ="precision mediump float;" +"uniform sampler2D uSampler;" +"varying vec2 vTexCoord;" +"void main() { " +" gl_FragColor = texture2D(uSampler,vTexCoord);" +"}"/*** 三角形顶点位置*/private val coodData = floatArrayOf(// 顶点坐标 纹理坐标-1f, 1f, 0.0f, 0f, 0f, // 左上角-1f, -1f, 0.0f, 0f, 1f, //左下角1f, 1.0f, 0.0f, 1f, 0f, //右上角1f, -1f, 0.0f, 1f, 1f //右下角)private var translateMatrix = FloatArray(16)private var program: Int = 0private var positionHandle: Int = -1private var texCoordHandle: Int = -1private var samplerHandle: Int = -1private var uMatrixHandle: Int = -1// vboprivate var vboId = IntArray(1)// 纹理id arrayprivate var textureIds= IntArray(1)private lateinit var coordBuffer: FloatBufferprivate lateinit var byteBuffer: ByteBufferoverride fun onSurfaceCreated(p0: GL10?, p1: EGLConfig?) {// 设置背景颜色GLES30.glClearColor(1f, 0f, 0f, 1.0f)// 清理缓存GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT)// 顶点坐标内存申请createFloatBuffer()// 创建定点着色程序val vertexShader = loadShader(GLES30.GL_VERTEX_SHADER, vertexShaderCode)// 创建片元着色程序val fragmentShader = loadShader(GLES30.GL_FRAGMENT_SHADER, fragmentShaderCode)if (vertexShader != 0 && fragmentShader != 0) {linkProgram(vertexShader, fragmentShader)GLES30.glDeleteShader(vertexShader)GLES30.glDeleteShader(fragmentShader)// 生成VBOGLES30.glGenBuffers(1, vboId, 0)GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vboId[0])GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER, byteBuffer.capacity(), byteBuffer, GLES30.GL_STATIC_DRAW)GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, 0)//Matrix.setIdentityM(translateMatrix, 0)// 将数据传递shaderpositionHandle = GLES30.glGetAttribLocation(program, "aPosition")GLES30.glEnableVertexAttribArray(positionHandle)texCoordHandle = GLES30.glGetAttribLocation(program, "aTexCoord")GLES30.glEnableVertexAttribArray(texCoordHandle)uMatrixHandle = GLES30.glGetUniformLocation(program, "uTMatrix")samplerHandle = GLES30.glGetUniformLocation(program, "uSampler")loadTexture()}}private fun linkProgram(vertexShader: Int, fragmentShader: Int) {// 创建空的opengl es 程序program = GLES30.glCreateProgram()program.let {// 将顶点着色器加入程序GLES30.glAttachShader(it, vertexShader)// 将片元着色器加入程序GLES30.glAttachShader(it, fragmentShader)// 链接到着色器程序GLES30.glLinkProgram(it)// 将程序加入到opengl30环境中GLES30.glUseProgram(it)val info = GLES30.glGetProgramInfoLog(it)// 打印链接程序日志Log.e("wdf", "info==" + info)}}private fun createFloatBuffer() {// 申请物理层空间byteBuffer = ByteBuffer.allocateDirect(coodData.size * 4).apply {this.order(ByteOrder.nativeOrder())}// 坐标数据转换coordBuffer = byteBuffer.asFloatBuffer()coordBuffer.put(coodData, 0, coodData.size)coordBuffer.position(0)}override fun onSurfaceChanged(p0: GL10?, width: Int, height: Int) {// 设置绘制窗口GLES30.glViewport(0, 0, width, height)}override fun onDrawFrame(p0: GL10?) {if (program <= 0) {return}GLES30.glUseProgram(program)GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vboId[0])program?.let {GLES30.glVertexAttribPointer(positionHandle, 3, GLES30.GL_FLOAT, false, 5 * Float.SIZE_BYTES, 0)GLES30.glVertexAttribPointer(texCoordHandle, 2, GLES30.GL_FLOAT, false, 5 * Float.SIZE_BYTES, 3 * Float.SIZE_BYTES)GLES30.glUniformMatrix4fv(uMatrixHandle, 1, false, translateMatrix, 0)// 激活纹理单元GLES30.glActiveTexture(GLES30.GL_TEXTURE0)// 绑定纹理单元GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textureIds[0])// 第二个参数传递激活的纹理单元,因为激活的是GLES30.GL_TEXTURE0,因此传递0GLES30.glUniform1i(samplerHandle, 0)GLES30.glDrawArrays(GLES30.GL_TRIANGLE_STRIP, 0, 4)GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, 0)}}private fun loadTexture() {GLES30.glGenTextures(1, textureIds, 0)GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textureIds[0])GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D,GLES30.GL_TEXTURE_MIN_FILTER,GLES30.GL_LINEAR)GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D,GLES30.GL_TEXTURE_MAG_FILTER,GLES30.GL_LINEAR)// 加载bitmap到纹理中GLUtils.texImage2D(GLES30.GL_TEXTURE_2D,0,GLES30.GL_RGBA,bitmap,0)GLES30.glGenerateMipmap(GLES30.GL_TEXTURE_2D)bitmap.recycle()// 取消绑定纹理GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, 0)}/*** 创建shader,加载shader程序*/private fun loadShader(type: Int, shaderCode: String): Int {val shader = GLES30.glCreateShader(type)GLES30.glShaderSource(shader, shaderCode)GLES30.glCompileShader(shader)return shader}
}
相关文章:

Android OpenGL(六) 纹理
纹理 纹理是一个2D图片(甚至也有1D和3D的纹理), 它可以用来添加物体的细节;你可以想象纹理是一张绘有砖块的纸,无缝折叠贴合到你的3D的 房子上,这样你的房子看起来就像有砖墙外表了 纹理环绕方式 纹理坐…...

git和idea重新安装后提交异常
场景:我重装了系统,idea装了2024.3版本的,git也重新装了,但是项目中还是有.git文件夹的,下载了idea的码云插件后,提交报错如下: 异常:Error updating changes: detected dubious ow…...

leetcode刷题记录(八十一)——236. 二叉树的最近公共祖先
(一)问题描述 236. 二叉树的最近公共祖先 - 力扣(LeetCode)236. 二叉树的最近公共祖先 - 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。百度百科 [https://baike.baidu.com/item/%E6%9C%80%E8%BF%91%E5%85%AC%E5%85%B…...

STM32-CAN总线
1.CAN总线简介 CAN总线是由BOSCH公司开发的一种简洁易用、传输速度快、易扩展、可靠性高的串行通信总线 2.CAN总线特征 两根通信线(CAN_H、CAN_L),线路少,无需共地差分信号通信(相对的是单端信号)&#…...

node.js 07.npm下包慢的问题与nrm的使用
一.npm下包慢 因为npm i 默认从npm官网服务器进行下包,但是npm官网服务器是海外服务器所以响应很慢. 于是我们通过npm下包的时候通常用淘宝镜像进行下包,下面是切换到淘宝镜像地址下包的操作. 二.nrm的使用 nrm是一个管理切换npm下包地址的工具,可以快速切换下包的地址. 安…...

ubuntu改变swap存储空间,遇到 fallocate 失败: 文本文件忙
ubuntu改变swap存储空间,遇到 fallocate 失败: 文本文件忙 sudo fallocate -l 16G /swapfile fallocate: fallocate 失败: 文本文件忙这种情况是swap空间正在使用,需要先关闭swap分区: sudo swapoff /swapfile sudo fallocate -l 16G /swap…...

20250122-正则表达式
1. 正则标记 表示一位字符:\\ 表示指定的一位字符:x 表示任意的一位字符:. 表示任意一位数字:\d 表示任意一位非数字:\D 表示任意一个字母:[a-zA-Z](大写或小写) 表示任意一个…...

QT之CMAKE教程
介绍 CMake 是一个跨平台的自动化构建系统,它使用配置文件(称为 CMakeLists.txt)来生成标准的构建文件,如 Unix 的 Makefile 或 Windows 的 Visual Studio 工程文件。CMake 能够支持多种编程语言,尤其是 C 和 C&#…...

网络安全 | 0day漏洞介绍
关注:CodingTechWork 引言 在网络安全领域,0day漏洞(Zero-day Vulnerability)是指一个尚未被厂商、开发者或安全人员发现、修复或发布修补程序的安全漏洞。0day漏洞是黑客利用的一个重要攻击工具,因其未被披露或未被修…...

关于WPF中ComboBox文本查询功能
一种方法是使用事件(包括MVVM的绑定) <ComboBox TextBoxBase.TextChanged"ComboBox_TextChanged" /> 然而运行时就会发现,这个事件在疯狂的触发,很频繁 在实际应用中,如果关联查询数据库࿰…...

07_游戏加载窗口
隐藏动态提示窗口 创建空节点 命名为 LoadingWnd 意为加载窗口 并设置全屏 在子级下创建Image作为加载背景 也设置成全屏 将以下资源放进Art文件夹中 设置好精灵模式后拖拽至 Image的Source Image框选 创建文本作为提示内容 增加描边组件OutLine可以美化字体 创建Image作为加载…...

awk命令进阶
1.连接文件 awk NRFNR{a[$1]$0;next} NR!FNR{ if(($5) in a) print a[$1],$0 } file1 file2 命令详解: 这个命令的目的是将 file1 和 file2 基于某个共同字段进行连接(类似于 SQL 中的 JOIN 操作)。下面我们逐步解析它的工作原理。 1. NRF…...

解锁Java中的国密算法:安全保障的密钥
一、引言 在数字化浪潮席卷全球的当下,信息安全已然成为国家、企业乃至个人无法忽视的重要议题。国密算法,作为我国自主研发的密码算法体系,宛如坚固的盾牌,为国家信息安全筑起了一道坚不可摧的防线。它的诞生,不仅承载…...

基于迁移学习的ResNet50模型实现石榴病害数据集多分类图片预测
完整源码项目包获取→点击文章末尾名片! 番石榴病害数据集 背景描述 番石榴 (Psidium guajava) 是南亚的主要作物,尤其是在孟加拉国。它富含维生素 C 和纤维,支持区域经济和营养。不幸的是,番石榴生产受到降…...

在现有 Docker Desktop 环境下安装与配置独立 Kubernetes环境(Mac)
在现有 Docker Desktop 环境下安装与配置独立 Kubernetes 集群环境 目标 在已安装Docker Desktop自带Kubernetes的情况下,搭建一个独立 Kubernetes 集群环境。配置独立的 kubectl 工具,使其默认管理独立的 Kubernetes 集群。保留 Docker Desktop 的 Ku…...

Linux探秘坊-------3.开发工具详解(1)
1 初识vim编辑器 创建第一个vim编辑的代码 1.新建文件 2.使用vim打开 3.打开默认是命令模式,写代码需要在屏幕上输出“i”字符 1.写完代码后要按Esc键退出到指令模式2.再按shift:wq即可保存并退出vim (因为不支持鼠标,通常 使用键盘上的箭…...

Spring Boot整合Thymeleaf、JDBC Template与MyBatis配置详解
本文将详细介绍如何在Spring Boot项目中整合Thymeleaf模板引擎、JDBC Template和MyBatis,涵盖YAML配置、依赖版本匹配、项目结构设计及代码示例。 一、版本兼容性说明 Spring Boot版本与Java版本对应关系 Spring Boot 2.x:支持Java 8、11(推…...

白玉微瑕:闲谈 SwiftUI 过渡(Transition)动画的“口是心非”(下)
概述 秃头小码农们都知道,SwiftUI 不仅仅是一个静态 UI 构建框架那么简单,辅以海量默认或自定义的动画和过渡(Transition)特效,我们可以将 App 界面的绚丽升华到极致。 不过,目前 SwiftUI 中的过渡&#x…...

论文:深度可分离神经网络存内计算处理芯片
引言:SRAM - CIM芯片在处理深度可分离神经网络时面临的挑战 深度可分离卷积(Depthwise separable convolution, DSC)由逐深度卷积(DW)和逐点卷积(PW)组成,逐深度卷积用于提取空间特征ÿ…...

hdrnet,Deep Bilateral Learning for Real-Time Image Enhancement解读
论文、代码和ppt地址:Deep Bilateral Learning for Real-Time Image Enhancement 论文使用的数据集: HDR: 这是一个复杂的摄影管道,包括色彩校正、自动曝光、去雾和色调映射等操作。 MIT “FiveK” 数据集: 这个数据集由 Bychkovsky 等人 提…...

Android系统开发(十五):从 60Hz 到 120Hz,多刷新率进化简史
引言 欢迎来到“帧率探索实验室”!今天,我们要聊聊 Android 11 中对多种刷新率设备的支持。你可能会问:“这和我写代码有什么关系?”别急,高刷新率不仅仅让屏幕更顺滑,还会直接影响用户体验。想象一下&…...

js判断一个数组对象中是否有相同的值
let userTitleLevelList[{title:医生,code:20},{title:老师,code:21}]; 如果一个数组对象格式如上面。如果有一样的对象就提示。即:title和code都是一样的内容、 const hasDuplicate userTitleLevelList.some((item, index, array) > { return array.filter(…...

基于深度学习的视觉检测小项目(十五) 用户的登录界面
用户管理离不开的是消息框(QMessageBox)和对话框(QDialog),比如对话框用于用户名和密码输入,消息框用于提示登录成功、密码错误。 • 基础知识:PySide6(PyQT5)的常用对话…...

redis-排查命中率降低问题
1.命中率降低带来的问题 高并发系统,当命中率低于平常的的运行情况,或者低于70%时,会产生2个影响。 有大量的请求需要查DB,加大DB的压力;影响redis自身的性能 不同的业务场景,阈值不一样,一般…...

ui文件转py程序的工具
源博客连接: PyCharm中利用外部工具uic转成的py文件,里面全是C代码,并非python类型的代码,导致大量报错。。。_pyside6-uic为什么把ui转为了c-CSDN博客 如果想把ui文件转为py文件,首先设置pycharm的外部工具…...

Alluxio 联手 Solidigm 推出针对 AI 工作负载的高级缓存解决方案
作者:Wayne Gao, Yi Wang, Jie Chen, Sarika Mehta Alluxio 作为全球领先的 AI 缓存解决方案供应商, 提供针对 GPU 驱动 AI 负载的高速缓存。其可扩展架构支持数万个节点,能显著降低存储带宽的消耗。Alluxio 在解决 AI 存储挑战方面的前沿技…...

Oracle 数据库常见字段类型大全及详细解析
在工作期间会遇到数据库建表的业务,经常会使用复制粘帖等操作,而不清楚数据库的字段类型。本文记录了 Oracle 数据库常见字段类型,根据不同的数据需求,可以选择不同的字段类型来存储数据。 文章目录 一、字符类型(Char…...

U3D的.Net学习
Mono:这是 Unity 最初采用的方式,它将 C# 代码编译为中间语言 (IL),然后在目标平台上使用虚拟机 (VM) 将其转换为本地机器码执行。 IL2CPP:这是一种较新的方法,它会将 C# 代码先编译为 C 代码,再由 C 编译器…...

Tomcat下载配置
目录 Win下载安装 Mac下载安装配置 Win 下载 直接从官网下载https://tomcat.apache.org/download-10.cgi 在圈住的位置点击下载自己想要的版本 根据自己电脑下载64位或32位zip版本 安装 Tomcat是绿色版,直接解压到自己想放的位置即可 Mac 下载 官网 https://tomcat.ap…...

adb常用指令(完整版)
1、adb devices 查看是否连接到设备 2、adb install [-r] [-s] 安装app,-r强制,-s安装sd卡上 3、adb uninstall [-k] 卸载app,-k保留配置和参数 4、adb push 把本地文件上传设备 5、adb pull 下载文件到本地 6、cd D:\sdk\platform-tool…...