当前位置: 首页 > news >正文

learnopengl——纹理

原文网址:https://learnopengl.com/Getting-started/Textures

纹理单元
你可能很想知道为什么sampler2D变量是一个全局变量,如果我们不适用glUniform对其赋值。使用glUniform1i,这样我们可以一次指定一个纹理对象,也可以一次指定多个纹理对象。这个纹理的位置就是通常所说的纹理单元。默认的纹理单元是0,这个是默认的激活的纹理单元,所以之前的章节我们没有对其指定位置。注意到不是所有的图形设备需要一个默认的纹理单元,所以之前的章节也许渲染不出对象。

纹理单元的主要目的是,它允许我们的shader使用多张纹理。通过指定纹理单元给采样器,我们可以一次绑定多个纹理,只要我们激活对应的纹理单元即可。像glBindTexture,我们可以使用glActiveTexture激活一个纹理单元,如下:

glActiveTexture(GL_TEXTURE0); // activate the texture unit first before binding texture
glBindTexture(GL_TEXTURE_2D, texture);

在激活纹理单元之后,紧接着使用glBindTexture,会绑定纹理到当前激活的纹理单元。纹理单元GL_TEXTURE0通常默认是激活的,所以之前的章节,我们不需要激活纹理单元,而直接调用了glBindTexture。

OpenGL应该至少有16个纹理单元供你使用。我们可以使用GL_TEXTURE0到GL_TEXTURE15激活对应的纹理单元。它们是按照顺序定义的,为了得到GL_TEXTURE8,可以使用GL_TEXTURE0+8形式。这个在循环迭代的时候获取指定的纹理单元很有用。

我们还需要编辑片段着色器来接收另外一个采样器,如下:

#version 330 core
...

uniform sampler2D texture1;
uniform sampler2D texture2;

void main()
{
    FragColor = mix(texture(texture1, TexCoord), texture(texture2, TexCoord), 0.2);
}

最后的输出颜色,是结合了两张纹理。GLSL的内置函数mix,接收两个参数,然后在两者之间根据第三个参数进行线性插值。如果第三个参数是0,它返回第一个参数。如果第三个参数是1,则返回第二个参数。如果第三个参数是0.2,则返回80%的第一个参数,20%的第二个参数,这样就混合了两张贴图。

现在我们需要加载并创建另外一个纹理。你应该很熟悉这个过程了。确保创建另外一个纹理对象,加载和创建最终的纹理使用glTexImage2D。

unsigned char *data = stbi_load("awesomeface.png", &width, &height, &nrChannels, 0);
if (data)
{
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
    glGenerateMipmap(GL_TEXTURE_2D);
}

注意到,我们加载了一张png后缀的图,它包含了透明通道。所以我们需要指定图片数据包含透明通道,使用GL_RGBA即可。否则OpenGL会不正确解析图片数据。

为了使用第二个纹理,我们需要修改对应的程序,绑定两个纹理。

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

glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); 

我们还需要告诉OpenGL,哪个纹理单元属于哪个shader采样器,通过glUniform1i设定每个采样器。我们仅仅需要设定一次即可,所以我们可以在进入循环之前调用一次。

ourShader.use(); // don't forget to activate the shader before setting uniforms!  
glUniform1i(glGetUniformLocation(ourShader.ID, "texture1"), 0); // set it manually
ourShader.setInt("texture2", 1); // or with shader class
  
while(...) 
{
    [...]
}

相关文章:

  • [转帖]Application Request Route实现IIS Server Farms集群负载详解
  • learnopengl——三角形
  • songho——OpenGL的帧缓冲
  • while 循环 及 and or not
  • songho——OpenGL的顶点缓冲对象
  • OGL(教程35)——延迟渲染1——代码结构梳理
  • 安装MySQL_安装Navicat_启动数据库服务
  • android studio查看android手机日志
  • Python02(Linux命令)
  • luaforwindws安装与调用方式
  • vs添加链接文件
  • httpclient
  • 继成ScriptableObject的静态类对象竟然没有销毁
  • 国内镜像站
  • unity地形
  • Angular js 常用指令ng-if、ng-class、ng-option、ng-value、ng-click是如何使用的?
  • Cookie 在前端中的实践
  • js 实现textarea输入字数提示
  • Laravel 菜鸟晋级之路
  • open-falcon 开发笔记(一):从零开始搭建虚拟服务器和监测环境
  • vue-cli3搭建项目
  • WebSocket使用
  • 分享自己折腾多时的一套 vue 组件 --we-vue
  • 力扣(LeetCode)965
  • 前端技术周刊 2018-12-10:前端自动化测试
  • 前端设计模式
  • 融云开发漫谈:你是否了解Go语言并发编程的第一要义?
  • 如何优雅地使用 Sublime Text
  • 微信小程序上拉加载:onReachBottom详解+设置触发距离
  • 译自由幺半群
  • 与 ConTeXt MkIV 官方文档的接驳
  • 在Docker Swarm上部署Apache Storm:第1部分
  • Spring第一个helloWorld
  • $GOPATH/go.mod exists but should not goland
  • (zz)子曾经曰过:先有司,赦小过,举贤才
  • (附源码)ssm捐赠救助系统 毕业设计 060945
  • (一)插入排序
  • (已解决)报错:Could not load the Qt platform plugin “xcb“
  • (中等) HDU 4370 0 or 1,建模+Dijkstra。
  • (转载)利用webkit抓取动态网页和链接
  • **python多态
  • .NET MAUI学习笔记——2.构建第一个程序_初级篇
  • .net 微服务 服务保护 自动重试 Polly
  • .Net6支持的操作系统版本(.net8已来,你还在用.netframework4.5吗)
  • /proc/interrupts 和 /proc/stat 查看中断的情况
  • [@Controller]4 详解@ModelAttribute
  • [20150904]exp slow.txt
  • [Assignment] C++1
  • [BZOJ4337][BJOI2015]树的同构(树的最小表示法)
  • [C#]winform部署PaddleOCRV3推理模型
  • [Django 0-1] Core.Handlers 模块
  • [Electron]ipcMain.on和ipcMain.handle的区别
  • [JavaWeb]—前端篇
  • [Java性能剖析]Sun JDK基本性能剖析工具介绍
  • [JS7] 显示从0到99的100个数字