OpenGL笔记(4)纹理
纹理单元的理解
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)纹理的更多相关文章
- Opengl ES之纹理贴图
纹理可以理解为一个二维数组,它可以存储大量的数据,这些数据可以发送到着色器上.一般情况下我们所说的纹理是表示一副2D图,此时纹理存储的数据就是这个图的像素数据. 所谓的纹理贴图,就是使用Opengl将 ...
- opengl笔记——旋转,一段代码的理解
重看:opengl笔记——OpenGL好资料备忘 在找到这段代码,对理解opengl旋转很有帮助 ... glPushMatrix(); // initialze ModelView matrix g ...
- Android OpenGL ES(八)----纹理编程框架
1.把纹理载入进OpenGL中 我们的第一个任务就是把一个图像文件的数据载入到一个OpenGL的纹理中. 作为開始.让我们又一次舍弃第二篇的框架.又一次创建一个程序,新建一个util工具包,在该包下创 ...
- Linux OpenGL 实践篇-5 纹理
纹理 在之前的实践中,我们所渲染的物体的表面颜色都是纯色或者根据顶点位置计算出的一个颜色,这种方式在表现物体细节方面是比较吃资源的,因为我们每增加一个细节,我们就需要定义更多的顶点及其属性.所以美术人 ...
- OpenGL 多线程共享纹理
1:opengl 多线程共享纹理纹理: //解码时候使用opengl进行绘制,需要构建队列和两个线程,分别用于解码数据并且填充纹理和渲染. 主线程常见两个共享上下文: main() { ⋯⋯⋯⋯ gH ...
- OpenGL笔记(一) 绘制三角形
GLTools: 一些有用且可复用的函数 GLEW: OpenGL API的一些扩展机制 GLUT: OpenGL Utility toolkit, OpenGL跨平台相关,隐藏平台相关细节 RC代表 ...
- OpenGL学习笔记(3) 纹理
关于纹理 一般游戏里的物体不一定都是纯色的物体,物体上面会有一些图片贴在上面,比如墙壁,箱子,地板,可以看到砖头.木板和大理石组成的图片,要把图片贴到计算机里的几何图形的话,就要把图片的颜色采样贴到几 ...
- OpenGL超级宝典笔记——深度纹理和阴影 【转】
目录[-] 光源视角 新型的纹理 深度纹理的大小 首先绘制阴影 然后是光照 投影阴影贴图 阴影比较 之前我们介绍过简单的把物体压平到投影平面来制造阴影.但这种阴影方式有其局限性(如投影平面须是平面). ...
- OpenGL的glTexCoord2f纹理坐标配置
纹理坐标配置函数,先看定义: void glTexCoord2f (GLfloat s, GLfloat t); 1.glTexCoord2f()函数 有两个参数:GLfloat s, GLfloat ...
随机推荐
- [TCP/IP] HTTPS的工作原理
一.首先HTTP请求服务端生成证书,客户端对证书的有效期.合法性.域名是否与请求的域名一致.证书的公钥(RSA加密)等进行校验: 二.客户端如果校验通过后,就根据证书的公钥的有效, 生成随机数,随机数 ...
- PHP数组相关算法
一.排序算法 1. 冒泡排序 2. 选择排序 二.查找算法 1. 遍历 2. 二分查找
- JS高阶---H5之Web Workers多线程
大纲: 主体: (1)介绍 (2)案例 编程实现斐波那契数列的计算 递归调用实现案例: Web Workers多线程的新标准并没有改变JS单线程的本质,分离出的子线程完全受主线程控制,且不得操作DOM ...
- 基于 Docker 的 MySQL 主从复制搭建
出处:https://www.jianshu.com/p/ab20e835a73f
- 浙大&川大提出脉冲版ResNet:继承ResNet优势,实现当前最佳
浙大&川大提出脉冲版ResNet:继承ResNet优势,实现当前最佳 选自arXiv,作者:Yangfan Hu等,机器之心编译. 脉冲神经网络(SNN)具有生物学上的合理性,并且其计算潜能和 ...
- sql初——基础
1.JDBC: Java数据库连接(Java Database Connectivity,JDBC),是一种用于执行SQL语句的Java API,它由一组用Java编程语言编写的类和接口组成. JDB ...
- nodejs的一些基操
Nodejs 是基于 CHrome V8 引擎的 JaveScriptnpm: node 包管理器为我们提供了: nodejs 运行时,javascript 代码运行时的环境 提供了核心模块,具体会在 ...
- MySQL binlog三种模式
1.1 Row Level 行模式 日志中会记录每一行数据被修改的形式,然后在slave端再对相同的数据进行修改 优点:在row level模式下,bin-log中可以不记录执行的sql语句的上下文 ...
- 【网络知识之四】HTTP/2
一.HTTP/1.1存在的问题 1.TCP 连接数限制2.线头阻塞 (Head Of Line Blocking) 问题3.Header 内容多,而且每次请求 Header 不会变化太多,没有相应的压 ...
- debian系统配置
使用腾讯docker源 sudo sed -i 's/deb.debian.org/mirrors.cloud.tencent.com/g' /etc/apt/sources.list sudo se ...