OpenGL(四) 纹理贴图

news2024/11/18 1:31:28

几何模型&材质&纹理

渲染一个物体需要:

  • 几何模型:决定了物体的形状
  • 材质:绝对了当灯光照到上面时的作用效果
  • 纹理:决定了物体的外观

纹理对象

纹理有2D的,有3D的。2D图像就是一张图片,3D图像是在渲染大气层等立体物体的时候会用到。此外多个2D纹理还可以组成Texture Array,如进行大地渲染的时候,需要沙砾,石头,杂草等多种纹理混合,就可以使用Texture Array进行存储,读取的时候加上index就可以读取出相应的纹理。
虽然被称为纹理,但是里面存储的数据也可以不是外观信息,如在进行天空渲染的时候,Precomputed Atmospheric Scattering算法需要与预计算并存储大气中点的通透度和散射值,就可以使用2D Texture存储大气中点的通透度,使用3DTexture存储大气中点的散射值。
即,纹理作为一种属性存储形式,根据需要有2D纹理和3D纹理,他们不仅可以存储外观属性,还可以存储描述物体的其他数据。

在渲染时,有些时候物理离相机很远,可能经过变换后,到显示中只占用极少的像素点,这几个像素点的值如何决定?
如果仍然使用采样方式,可能会出现相机稍微移动,采样对应的位置就大幅变化,效果就是这几个像素一直在抖动。
而且这么远的情况下,完全不需要使用相同精细度的纹理图像,可以节省很多空间。
为了适应不同远近情况下的纹理使用,提出了mipmap,即,存储不同精细程度的纹理,方便不同距离使用,这种思想和计算机视觉中的图像金字塔思想基本相同。其存储代价非常小,只占用了不到 4 3 \frac{4}{3} 34大小的存储空间【每次边长对半,存储为四分之一,级数求和】。
在这里插入图片描述
OpenGL中提供了一键生成mipmap的API

glGenerateMipmap(GL_TEXTURE_2D);

读取纹理涉及到图像解析,libpng、FreeImage、stb_image都是图像解析的开源库,这里使用stb_image,因为stb_image非常简单,只有头文件,但是相应的支持的图片格式也只有常用的几种。FreeImage支持的格式比较多,功能全面,但是相应的也复杂一些。
直接在此处下载stb_image.h文件,然后加入到自己的工程中,并新建一个cpp文件输入:

#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

使用stb_iamge的stbi_load函数加载纹理图像文件并生成纹理:

int width, height, nrChannels;
unsigned char *data = stbi_load("container.jpg", &width, &height, &nrChannels, 0);
unsigned int texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
stbi_image_free(data); //注意释放已经不用的图片

OpenGL每种纹理有多个纹理单元,默认纹理单元是0,且默认激活。可以通过激活别的纹理单元位置,来存储多个纹理,当需要使用多个纹理时很有用。

glActiveTexture(GL_TEXTURE0); // 在绑定纹理之前先激活纹理单元
//OpenGL规定至少16个纹理单元,可以通过GL_TEXTURE15访问,也可以通过GL_TEXTURE0 + 15来访问
glBindTexture(GL_TEXTURE_2D, texture);

采样器

模型大小通常与纹理大小是不一样的,需要进行采样,负责采样的被称为采样器。

采样方式

纹理坐标的范围通常是从(0, 0)到(1, 1),(u,v)代表%u,%v处的纹理值。
如果将uv值设到了这个范围以外,OpenGL默认的行为是重复这个纹理图像,但是也可以自定义

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
// 第一个表示要设置的纹理,第二个表示要设置的坐标轴,
// 第三个是策略,REPEAT就是重复,MIRRORED_REPEAT镜像重复,CLAMP_TO_EDGE边缘拉伸,CLAMP_TO_BORDER默认颜色

因为uv是浮点值,不一定对应某一个像素,尤其是在纹理较小,物体较大的时候。输入uv,如何计算出输出像素值,称为纹理过滤,OpenGL提供了多种不同选择,如:

  • GL_NEAREST:选取临近像素的值输出
  • GL_LINEAR:选择附近的像素进行线性插值,计算出的值作为结果。

设置方式:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// 第一个选择设置的纹理,第二个表示要设置的情况,放大or缩小,第三个表示过滤模式。

根据上篇blog讲解的,渲染的流程中,在片段着色器中进行纹理渲染,所以片段着色器才是真正使用纹理的地方,GLSL有一个供纹理对象使用的内建数据类型,叫做采样器(Sampler)。

#version 330 core
out vec4 FragColor;

in vec3 ourColor;
in vec2 TexCoord;

uniform sampler2D ourTexture;

void main()
{
    FragColor = texture(ourTexture, TexCoord);
}

OpenGL中还内置了texture函数,第一个参数是采样器,第二个是纹理uv坐标点,输出就是该点对应的像素值。不用考虑采样器与纹理间的绑定,在进行glBindTexture时就自动将纹理绑定到采样器上了。多个纹理单元时需要配多个采样器,会依次与采样器绑定。

混合

纹理体现的是对不同颜色光照的反射程度,光照体现的是不同光照的射入量,二者分量相乘得到的结果就是最终的显示效果。
多个纹理混合时,需要使用GLSL中内置的函数mix进行混合。

当没有纹理时,可以理解为纹理是(1,1,1,1),所以前面的三角形颜色变化,可以理解为光照颜色变化导致的,而三角形本身始终是不变的。只不过(1,1,1,1)的纹理表示全反射,光照没有损失全部反射出来了。如果纹理是渐变的,那么最终渲染出来的结果就也是不一样的

只有一个纹理的时候,其实约等于默认乘以了一个(1,1,1,1)的白光光照,如果想没有光照,需要乘以(0,0,0,1)

FragColor = texture(Texture1, TexCoord);

在这里插入图片描述

纹理和光照间需要分量相乘

FragColor = texture(Texture1, TexCoord) * timeColor;

在这里插入图片描述
当两个纹理的时候,要使用mix进行混合,

FragColor = mix(texture(Texture1, TexCoord),texture(Texture2, TexCoord),0.5) * timeColor;

在这里插入图片描述

参考

LearnOpenGL
LearnOpenGL CN
《计算机图形学编程(使用OpenGL和C++)第二版》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2133207.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

记得忘记密码情况下如何退出苹果Apple ID

在日常使用苹果手机时,我们可能会遇到需要退出Apple ID的情况,比如更换手机、不再使用某些服务或出于安全考虑等。下面,我们就来详细介绍一下苹果手机如何退出Apple ID。 情况一:记得Apple ID密码 若是记得Apple ID密码&#xff…

3. 轴指令(omron 机器自动化控制器)——>MC_HomeWithParameterMC_Move

机器自动化控制器——第三章 轴指令 3 MC_HomeWithParameter变量▶输入变量▶输出变量 功能说明▶原点复位动作与原点复位参数的关系▶重启运动指令▶多重启动运动指令▶错误代码 MC_Move变量▶输入变量▶输出变量▶输入输出变量 功能说明▶指令详情▶重启运动指令▶多重启动运…

pytorch入门(1)——pytorch加载数据初认识

环境配置及其安装: 2023最新pytorch安装(超详细版)-CSDN博客 pytorch加载数据初认识 Dataset:创建可被Pytorch使用的数据集 提供一种方式获取数据及其label Dataloader:向模型传递数据 为网络提供不同的数据形式 …

算法_队列+宽度优先搜索---持续更新

文章目录 前言N叉树的层序遍历题目要求题目解析代码如下 二叉树最大宽度题目要求题目解析代码如下 在每个树中找最大值题目要求题目解析代码如下 二叉树的锯齿形层序遍历题目要求题目解析代码如下 前言 本文将会向你介绍有关队列宽度优先搜索的题目:N叉树的层序遍历…

【每日一题】LeetCode 2398.预算内的最多机器人数目(滑动窗口、数组、二分查找、前缀和、堆(优先队列))

【每日一题】LeetCode 2398.预算内的最多机器人数目(滑动窗口、数组、二分查找、前缀和、堆(优先队列)) 题目描述 给定两个整数数组 chargeTimes 和 runningCosts,分别代表 n 个机器人的充电时间和运行成本。再给定一…

喂料机和失重秤的区别?

喂料机和失重秤的区别?在硬件结构上的具体差异: 1. 喂料机的硬件结构 喂料机的结构比较简单,主要功能是传送物料,不涉及精确的称重系统。其硬件结构通常包括以下部分: 料斗:用于存储物料,物料…

cesium.js 入门到精通(7)

我们说一下相机的概念: 生活中的相机是一个用来拍照的设备,而这里的相机应该理解成一个人机交互的媒介。地图的缩放、平移、旋转,以及相关的鼠标操作都是由相机作为媒介来实现的。相机的位置和姿态参数决定了我们能看到的地图的样子。 可以…

centos7.9安装clamav教程

本章教程主要记录在centos7.9安装clamav过程。 ClamAV(Clam AntiVirus)是一个开源的防病毒软件工具,主要用于检测和消除恶意软件。它最初由 Tomasz Kojm 于 2001 年开发,并由 Cisco Systems 维护和支持。ClamAV 广泛应用于邮件网关、文件服务器和其他需要防病毒保护的环境中…

Linux软件包循环依赖解决 彻底删除i386架构 更新软件源

0.问题 之前为了wine和intel核显驱动加了32位的库,现在每次apt upgrade更新都被循环依赖弄得不堪其扰,apt --fix-broken install解决缺失都循环报错,寸步难行,忍无可忍、 而且一看全是i386的依赖,这32位我不用也罢&…

apache文件共享和访问控制

实现apache文件共享 文件共享路径 <Directory "/var/www/html"> #默认发布路径&#xff0c;功能限制 Options Indexes FollowSymLinks #indexes支持文件共享功能 AllowOverride None Require all granted </Directory> 进入到该路径下 cd…

【Java Bean Validation API】Spring3 集成 Bean 参数校验框架

Spring3 集成 Bean 参数校验框架 Java Bean Validation API 1. 依赖 Spring 版本&#xff1a;3.0.5 Java 版本&#xff1a;jdk21 检验框架依赖&#xff08;也可能不需要&#xff0c;在前面 spring 的启动依赖里就有&#xff09;&#xff1a; <!-- 自定义验证注解 -->…

【原创】java+springboot+mysql高校社团网系统设计与实现

个人主页&#xff1a;程序猿小小杨 个人简介&#xff1a;从事开发多年&#xff0c;Java、Php、Python、前端开发均有涉猎 博客内容&#xff1a;Java项目实战、项目演示、技术分享 文末有作者名片&#xff0c;希望和大家一起共同进步&#xff0c;你只管努力&#xff0c;剩下的交…

spring内置的

程序里注入了spring内置的线程池&#xff0c;但没有看到线程池相关参数配置&#xff08;corePoolSize maxPoolSize 队列大小&#xff09;&#xff0c;网上查说默认是1个线程&#xff0c;结果和生产实际看到的不一致。 从生产可以看到有8个线程在跑&#xff0c;task-1 task-8&am…

buildroot移植qt报错Info: creating stash file (补充qt添加字库)

移植qt库&#xff0c;编译文件报错Info: creating stash file /home/rbing/QT/uart/.qmake.stash Project ERROR: Unknown module(s) in QT: serialport rbingouc:~/QT/uart$ /home/rbing/linux/tool/buildroot-2022.02.9/output/host/usr/bin/qmake Info: creating stash fil…

PCI Express 体系结构导读摘录(六)

系列文章目录 PCI Express 体系结构导读摘录&#xff08;一&#xff09; PCI Express 体系结构导读摘录&#xff08;二&#xff09; PCI Express 体系结构导读摘录&#xff08;三&#xff09; PCI Express 体系结构导读摘录&#xff08;四&#xff09; PCI Express 体系结构导读…

HarmonyOS开发实战( Beta5.0)画笔调色板案例实践

鸿蒙HarmonyOS开发往期必看&#xff1a; HarmonyOS NEXT应用开发性能实践总结 最新版&#xff01;“非常详细的” 鸿蒙HarmonyOS Next应用开发学习路线&#xff01;&#xff08;从零基础入门到精通&#xff09; 介绍 本示例实现了一个网格渐变的画笔调色板&#xff0c;能够根…

Vector - VT System - 板卡_VT板卡使用介绍_01

总体介绍 在常规的车载网络测试中&#xff0c;除了我们常用的使用VN系列设备进行总线协议测试&#xff0c;大多数公司都会将协议强相关的功能测试放在了功能侧&#xff0c;但是实际上这块对于车载网络测试工程师来说也是需要去了解的&#xff0c;毕竟只有懂协议的人才能更好的测…

Python with 关键字语法糖

参考文章: Python with 关键字 | 菜鸟教程 (runoob.com)https://www.runoob.com/python3/python-with.html Python 中的 with 语句用于异常处理&#xff0c;封装了 try…except…finally 编码范式&#xff0c;提高了易用性。 with 语句使代码更清晰、更具可读性&#xff0c; 它…

Fake Location模拟定位,刷跑 “运动世界校园”

前言:"科技改变生活&#xff0c;如果本文章对你有帮助&#xff0c;别忘记留下你的点赞&#xff0c;以下我对环境特变刁钻的运动世界校园为实例&#xff0c;也是成功安全正常上传数据&#xff0c;如果遇到问题&#xff0c;请留言评论区&#xff0c;所有链接我会放在文章头部…

157-安全开发-Python 自动化挖掘项目SRC 目标FOFA 资产Web 爬虫解析库

案例一&#xff1a;Python-WEB 爬虫库&数据解析库 这里开发的内容不做过多描述&#xff0c;贴上自己写的代码 爬取数据 要爬取p标签&#xff0c;利用Beautyfulsoup模块 import requests,time from bs4 import BeautifulSoup#url"https://src.sjtu.edu.cn/rank/firm…