纹理单元的理解

Shader中要用到纹理:

  uniform sampler2D texture1;

Main读取图片数据,创建了纹理:

  unsigned int texture1;

怎么把c++里加载的纹理传给shader程序里呢?

这就要用到纹理单元。

glBindTexture(GL_TEXTURE_2D, texture1);

这条代码将纹理texture1传递给了正在使用的着色器程序里的uniform sampler2D texture1

中间隐含过程是,opengl有许多默认的纹理单元(GL_TEXTURE0,GL_TEXTURE1,GL_TEXTURE2~GL_TEXTUREn),

其中,默认激活的是纹理单元0——GL_TEXTURE0,上面的代码就把纹理传递给了这个默认激活的纹理单元0;

另一方面,在shader里声明的采样器——unigorm sampler,他会从一个特定的纹理单元里取得纹理数据,而这个特定的纹理单元是GL_TEXTURE0~n中的哪一个呢?

答案是,在shader里声明的每一个采样器,其默认对应的纹理单元是GL_TEXTURE0;

所以,使用上面的一行代码,其中的过程是这样的:

  1、没有选择激活纹理单元,所以使用默认的纹理单元0

  2、把纹理texture1传递给了纹理单元0

  3、没有设置shader里的采样器对应的纹理单元,所以采样器从默认的纹理单元0读取数据

这样会使shader里所有的采样器(如果声明多个的话)都从纹理单元0中获取纹理数据,很明显这样就会使声明的采样器都一样了。

但是我们声明多个采样器明显是想在一个着色器里使用多个不同的纹理,那么该怎么做?

着色器里有多个采样器,像是这样:

#version  core
out vec4 FragColor; in vec3 ourColor;
in vec2 TexCoord; uniform sampler2D texture1;
uniform sampler2D texture2; void main()
{
FragColor=mix(texture(texture1,TexCoord),texture(texture2,TexCoord),0.5);
//FragColor=texture(texture1,TexCoord);
}

回头看之前的步骤,只要完成原先省略做的事就好了

1、绑定纹理时,先选择激活相应的纹理单元

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture1);

2、设置shader里声明的采样器所对应的纹理单元

glUniform1i(glGetUniformLocation(myShader.ID, "texture1"), );
myShader.setInt("texture2", ); // 或者使用着色器类设置

两中方法,都是先找到shader中的采样器”texture1”/”texture2”的地址,然后设置其对应的纹理单元,0是指GL_TEXTURE0,1对应GL_TEXTURE1,2、3以此类推。

Texture类

模仿Shader类写了自己的Texture类(重复操作实在太多了

class lxlTexture {
public:
unsigned int Id;
lxlTexture(){}
lxlTexture(const GLchar* texPath,GLint format) {
glGenTextures(, &Id);
glBindTexture(GL_TEXTURE_2D, Id); // 为当前绑定的纹理对象设置环绕、过滤方式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//读取图片文件
int width, height, nrChannels;//颜色通道个数
stbi_set_flip_vertically_on_load(false);
unsigned char* data = stbi_load(texPath, &width, &height, &nrChannels, );
//导入读取的图片文件数据,处理生成纹理
glTexImage2D(GL_TEXTURE_2D, , format, width, height, , format, GL_UNSIGNED_BYTE, data);
////-解释-
//上面把纹理绑定到了GL_TEXTURE_2D,现在这个参数选择了GL_TEXTURE_2D为目标,处理绑定在上面的纹理
//参数为纹理指定多级渐远纹理的级别,如果你希望单独手动设置每个多级渐远纹理的级别的话。这里我们填0,也就是基本级别。
//第三个参数告诉OpenGL我们希望把纹理储存为何种格式。我们的图像只有RGB值,因此我们也把纹理储存为RGB值。
//第四个和第五个参数设置最终的纹理的宽度和高度。我们之前加载图像的时候储存了它们,所以我们使用对应的变量。
//下个参数应该总是被设为0(历史遗留的问题)。
//第七第八个参数定义了源图的格式和数据类型。我们使用RGB值加载这个图像,并把它们储存为char(byte)数组
//最后一个参数是真正的图像数据。 //自动生成多级纹理
glGenerateMipmap(GL_TEXTURE_2D);
//释放
stbi_image_free(data);
std::cout << Id << std::endl;
}
void bindTexture(int num) {
switch (num) {
case :
glActiveTexture(GL_TEXTURE0);
break;
case :
glActiveTexture(GL_TEXTURE1);
break;
case :
glActiveTexture(GL_TEXTURE2);
break;
case :
glActiveTexture(GL_TEXTURE3);
break;
case :
glActiveTexture(GL_TEXTURE4);
break;
case :
glActiveTexture(GL_TEXTURE5);
break;
case :
glActiveTexture(GL_TEXTURE6);
break;
case :
glActiveTexture(GL_TEXTURE7);
break;
default:
std::cout << "纹理绑定支持0~7"<<std::endl;
}
glBindTexture(GL_TEXTURE_2D, Id);
}
void SetWrap(GLint pname) {
if (pname == GL_REPEAT || pname == GL_MIRRORED_REPEAT || pname == GL_CLAMP_TO_EDGE || pname==GL_CLAMP_TO_BORDER) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, pname);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, pname);
}
else {
std::cout << "输入不是设置环绕方式" << std::endl;
}
}
void SetWrapS(GLint pname) {
if (pname == GL_REPEAT || pname == GL_MIRRORED_REPEAT || pname == GL_CLAMP_TO_EDGE || pname == GL_CLAMP_TO_BORDER) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, pname);
}
else {
std::cout << "输入不是设置环绕方式" << std::endl;
}
}
void SetWrapT(GLint pname) {
if (pname == GL_REPEAT || pname == GL_MIRRORED_REPEAT || pname == GL_CLAMP_TO_EDGE || pname == GL_CLAMP_TO_BORDER) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, pname);
}
else {
std::cout << "输入不是设置环绕方式" << std::endl;
}
} void SetFilterMag(GLint pname) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, pname);
}
void SetFilterMin(GLint pname) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
};

使用

//初始化
mytexture1 = Texture("Resource/Texture/container.jpg",GL_RGB);
mytexture2 = Texture("Resource/Texture/awesomeface.png",GL_RGBA);
//传递
mytexture1.bindTexture();
mytexture2.bindTexture();

OpenGL笔记(4)纹理的更多相关文章

  1. Opengl ES之纹理贴图

    纹理可以理解为一个二维数组,它可以存储大量的数据,这些数据可以发送到着色器上.一般情况下我们所说的纹理是表示一副2D图,此时纹理存储的数据就是这个图的像素数据. 所谓的纹理贴图,就是使用Opengl将 ...

  2. opengl笔记——旋转,一段代码的理解

    重看:opengl笔记——OpenGL好资料备忘 在找到这段代码,对理解opengl旋转很有帮助 ... glPushMatrix(); // initialze ModelView matrix g ...

  3. Android OpenGL ES(八)----纹理编程框架

    1.把纹理载入进OpenGL中 我们的第一个任务就是把一个图像文件的数据载入到一个OpenGL的纹理中. 作为開始.让我们又一次舍弃第二篇的框架.又一次创建一个程序,新建一个util工具包,在该包下创 ...

  4. Linux OpenGL 实践篇-5 纹理

    纹理 在之前的实践中,我们所渲染的物体的表面颜色都是纯色或者根据顶点位置计算出的一个颜色,这种方式在表现物体细节方面是比较吃资源的,因为我们每增加一个细节,我们就需要定义更多的顶点及其属性.所以美术人 ...

  5. OpenGL 多线程共享纹理

    1:opengl 多线程共享纹理纹理: //解码时候使用opengl进行绘制,需要构建队列和两个线程,分别用于解码数据并且填充纹理和渲染. 主线程常见两个共享上下文: main() { ⋯⋯⋯⋯ gH ...

  6. OpenGL笔记(一) 绘制三角形

    GLTools: 一些有用且可复用的函数 GLEW: OpenGL API的一些扩展机制 GLUT: OpenGL Utility toolkit, OpenGL跨平台相关,隐藏平台相关细节 RC代表 ...

  7. OpenGL学习笔记(3) 纹理

    关于纹理 一般游戏里的物体不一定都是纯色的物体,物体上面会有一些图片贴在上面,比如墙壁,箱子,地板,可以看到砖头.木板和大理石组成的图片,要把图片贴到计算机里的几何图形的话,就要把图片的颜色采样贴到几 ...

  8. OpenGL超级宝典笔记——深度纹理和阴影 【转】

    目录[-] 光源视角 新型的纹理 深度纹理的大小 首先绘制阴影 然后是光照 投影阴影贴图 阴影比较 之前我们介绍过简单的把物体压平到投影平面来制造阴影.但这种阴影方式有其局限性(如投影平面须是平面). ...

  9. OpenGL的glTexCoord2f纹理坐标配置

    纹理坐标配置函数,先看定义: void glTexCoord2f (GLfloat s, GLfloat t); 1.glTexCoord2f()函数 有两个参数:GLfloat s, GLfloat ...

随机推荐

  1. android内存管理-ION/PMEM【转】

    转自:https://www.jianshu.com/p/0eac3d3ff6bb ION debug ION 在/sys/kernel/debug/ion/ 提供一个debugfs 接口. 每个he ...

  2. kali下ll命令无法使用

    重装了系统之后,使用ll命令竟然发现报错了. bash: ll:未找到命令   果断解决一波: vim ~/.bashrc   将alias ll=’ls -l‘前面的注释符号#删掉 运行   问题完 ...

  3. GCC 预处理,汇编,编译,链接,连接静态库,动态库

    gcc Record gcc -E file1.c > output gcc -E file1.c -o file1.i gcc -S file1.i -o file1.s gcc -S fil ...

  4. 免费音乐播放器-airplay(网上收集,仅供学习与研究,支持正版)

    AirPlay媒体播放器无需安装,并不会修改注册表,生成桌面快捷方式,加入启动菜单及快速启动. 因此,您只需要下载本软件,保存在任何地方即可使用.使用方便,界面酷炫. 自动下载和显示歌词.专辑封面.汇 ...

  5. zz深度学习在美团配送 ETA 预估中的探索与实践

    深度学习在美团配送 ETA 预估中的探索与实践 比前一版本有改进:   基泽 周越 显杰 阅读数:32952019 年 4 月 20 日   1. 背景 ETA(Estimated Time of A ...

  6. spring讲解

    今日先简单介绍一下Spring bean 的 5 种效果域,然后详细介绍 singleton 和 prototype 这两种最常用的效果域. JavaSpring Bean的五种效果域 效果域的种类 ...

  7. Visualforce 页面的生命周期

    了解 Visualforce 页面的生命周期可以让我们明白其各个元素的执行顺序.改变逻辑,从而提高开发效率,避免不必要的错误. 在官方文档中有详细的讲解.本文摘取其中的要点,作为一个总结. Visua ...

  8. control+shift + o热键冲突?????

    不知道有没有宝贝跟我遇到一样的问题 就是    control +shift+o    热键冲突了 进过我的严密调查. 这是因为你用的是A卡. 只要你把A卡换成N卡就可以了, 但是因为我太贫穷了,只能 ...

  9. ESP8266 LUA脚本语言开发: 准备工作-LUA文件加载与变量调用

    前言 这节说一下多个文件调用 多个文件之间变量调用 准备两个文件 init.lua other.lua 开始 模块默认一开始调用的是init.lua 咱让init.lua调用 other.lua 很简 ...

  10. appium--解决中文输入不了的问题

    配置 from appium import webdriver desired_caps={} desired_caps['platformName']='Android' #模拟器 desired_ ...