纹理单元的理解

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. 十五、Mysql字符集的那些事

    1. 设置默认字符集 #vim /etc/mysql/my.cnf .(5.5以后系统)如下修改: [client] default-character-set=utf8 [mysqld] defau ...

  2. 解决chrome插件安装时出现的“程序包无效”问题信息:程序包无效。

    https://blog.csdn.net/bluexuemei/article/details/35213117 2014-06-27 09:00:51 bluexuemei 阅读数 14374更多 ...

  3. 错误: 找不到或无法加载主类 com.leyou.LeyouItemApplication Process finished with exit code 1

    在IDEA的使用过程中,经常断掉服务或者重启服务,最近断掉服务重启时突然遇到了一个启动报错: 错误:找不到或无法加载主类 猜测:1,未能成功编译: 尝试:菜单--->Build--->Re ...

  4. shell之seq

    seq 用于生成从一个数到另一个数之间的所有整数 seq [选项]... 尾数 seq [选项]... 首数 尾数 seq [选项]... 首数 增量 尾数 例如: 1.  -s 指定分隔符,默认分隔 ...

  5. JAVA HashMap与ConcurrentHashMap

    HashMap Fast-Fail(遍历时写入操作异常) 在使用迭代器的过程中如果HashMap被修改,那么ConcurrentModificationException将被抛出,也即Fast-fai ...

  6. JetBrains优惠码分享

    A quick summary [feel free to pass it on to your team]: Your Promo code is: S2W69-N3VY3-YGACY-7WC7X- ...

  7. batch、epoch、iteration

    深度学习的优化算法,说白了就是梯度下降.每次的参数更新有两种方式. 第一种,遍历全部数据集算一次损失函数,然后算函数对各个参数的梯度,更新梯度.这种方法每更新一次参数都要把数据集里的所有样本都看一遍, ...

  8. LG5201 「USACO2019JAN」Shortcut 最短路树

    \(\mathrm{Shortcut}\) 问题描述 LG5201 题解 最短路树. 显然奶牛的路径就是从\(1\)走到各个草地,于是从\(1\)跑最短路,构建最短路树. 为了保证字典序,从\(1\) ...

  9. bcc 基于bpf 分析linux 系统性能的强大工具包

    bcc 是一个基于bpf 的强大linux io,网络监控分析工具集(当然也可以分析java,ruby,python...) 一张工具图 说明 bcc 好多工具是需要kernel 4.1 的,但是大部 ...

  10. streamsets 测试框架说明

    streamsets 团队为了方便进行sdc以及sdh 的测试基于streamsets python sdk 开发了 streamsets Test Framework 安装 注意python 3.7 ...