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 ...
随机推荐
- cppcheck代码检测
cppcheck -hCppcheck - A tool for static C/C++ code analysis Syntax: cppcheck [OPTIONS] [files or pat ...
- Ubuntu 18.04通过命令禁用/开启触控板
Ubuntu下经常遇到无法用快捷键关闭触控板的情况,博主的电脑安装Ubuntu18.04后便出现了该问题. 解决办法: 首先查看输入设备的id,命令行输入: xinput ,插鼠标与不插鼠标时,Tou ...
- Ubuntu14 关机重启、版本、网络、防火墙
关机.重启: 立即关机:halt.poweroff.shutdown -h now 延迟关机:shutdown -h 10 十分钟后关机 立即重启:reboot.shutdown -r now 延迟 ...
- 19、FTP服务器
FTP (File Transfer Protocol) 文件传输协议的简称.主要用跨网络.跨平台的文件 传输. FTP 支持两种工作工作模式:主动模式.被动模式. 主动模式: 客户端使用 ...
- keil mdk+stm32的ac5和 ac6两个编译器下的字节对齐操作方法
最近在使用ac6.9的编译器,编译速度是真的很快,使用stm32的hal库编译速度也比ac5的编译器快很多.本文试验stm32中字节对齐的代码测试,主要是结构体,因为结构体中实际项目中用到最多,同时在 ...
- Task异常捕获的几种方式
在调用Task的Wait()方法或Result属性处会抛出Task中的异常. 但是如果没有返回结果,或者不想调用Wait()方法,该怎么获取异常呢? 可以使用ContinueWith()方法 var ...
- B1042 字符统计 (20 分)
#include<cstdio> #include<iostream> #include<algorithm> #include<string> usi ...
- Spring 常用配置、Bean
spring模块 Spring-Core: Core包是框架的最基础部分,并提供依赖注入(Dependency Injection)管理Bean容器功能. Spring-Context:(Spring ...
- Zabbix的基本功能
zabbix组件: 两核心组件: zabbix-server(监控者) :收集agent发送的数据,写入数据库(mysql.oracal.)中,再通过web展示出来.默认端口为10051. zabbi ...
- 显示隐藏文件.reg
显示隐藏文件.reg Windows Registry Editor Version 5.00 [HKEY_CURRENT_USER\Software\Microsoft\Windows\Curren ...