OpenGL着色器对象 Shader Objects

着色器对象

要创建着色器对象,你可以使用以下命令:

uint glCreateShader( enum type );

当创建着色器对象时,它最初是空的。type 参数指定要创建的着色器对象的类型,必须是指示相应着色器阶段的值之一。以下是该命令的简要概述:

  • 参数
    • type:指定要创建的着色器对象的类型。它必须是指示相应着色器阶段的值之一。
      • 顶点着色器:GL_VERTEX_SHADER
      • 片段着色器:GL_FRAGMENT_SHADER
      • 几何着色器:GL_GEOMETRY_SHADER
      • 细分控制着色器:GL_TESS_CONTROL_SHADER
      • 细分评估着色器:GL_TESS_EVALUATION_SHADER
      • 计算着色器:GL_COMPUTE_SHADER
  • 返回值
    • 返回一个非零的无符号整数名称,可用于引用着色器对象。

该命令用于将源代码加载到指定的着色器对象中:

void glShaderSource( uint shader, sizei count, const char * const *string, const int *length );
  • shader:是要加载源代码的着色器对象的名称。
  • count:表示字符串数组中的字符串数量。
  • string:是一个指向可选空终止字符字符串数组的指针数组,这些字符串共同构成了着色器的源代码。
  • length:是一个整数数组,包含每个字符串的字符数量。如果length数组中的某个元素为负数,则对应的字符串以空字符终止。若length参数为NULL,则认为string参数中的所有字符串都是以空字符终止。

此命令将着色器对象的源代码设置为string数组中的文本字符串。如果着色器先前已加载了源代码,则现有的源代码会被完全替换。任何传递给length的值都不包括其计数内的空终止符。

加载到着色器对象中的字符串期望构成符合OpenGL着色语言规范的有效着色器源代码。如果之前通过ShaderBinary命令将SPIR-V模块与shader关联起来,执行此命令后会解除这种关联。在成功完成此命令后,shader对象的SPIR-V_BINARY状态将被设置为FALSE。


加载着色器对象的源代码后,可以使用以下命令编译着色器对象:

void glCompileShader(uint shader);
  • glCompileShader命令用于编译着色器对象shader中的源代码。
  • 每个着色器对象都有一个布尔状态COMPILE_STATUS,它在编译过程中被修改。可以使用GetShaderiv命令查询此状态。如果着色器编译成功且准备就绪,则此状态将设置为TRUE;否则设置为FALSE。编译可能因多种原因而失败,详细列在OpenGL着色语言规范中。
  • 如果glCompileShader失败,则任何关于先前编译的信息都会丢失。因此,编译失败不会恢复着色器的旧状态。
  • 使用ShaderSource更改着色器对象的源代码不会更改其编译状态或已编译的着色器代码。
  • 每个着色器对象都有一个信息日志,它是一个文本字符串,作为编译过程的结果而被覆盖。可以使用GetShaderInfoLog查询此信息日志,以获取有关编译尝试的更多信息。

通过着色器编译器分配的资源可以通过以下命令释放,然而,实际应用中该函数并不常用,因为现代OpenGL实现通常会自动管理这些内部资源。

void glReleaseShaderCompiler(void);
  • 这是应用程序提供的提示,不会阻止后续使用着色器编译器。
  • 如果在调用glReleaseShaderCompiler之后加载和编译着色器源代码,只要着色器源代码没有错误,CompileShader必须成功。
  • 可以使用命令GetShaderPrecisionFormat确定着色器编译器支持的不同数字格式的范围和精度。

着色器对象可以使用以下命令删除:

void glDeleteShader(uint shader);
  • 如果着色器对象未附加到任何程序对象,则立即删除。否则,着色器对象被标记为删除,并将在不再附加到任何程序对象时删除。
  • 如果对象被标记为删除,其布尔状态位DELETE_STATUS将设置为true。可以使用GetShaderiv查询DELETE_STATUS的值。
  • glDeleteShader将静默忽略值为零的情况。

boolean glIsShader(uint shader);
  • 如果 shader 是着色器对象的名称,则返回 TRUE。
  • 如果 shader 是零,或者是一个不是着色器对象名称的非零值,则返回 FALSE。

着色器的二进制文件

glShaderBinary命令用于加载预编译的着色器二进制文件,具体如下:

void glShaderBinary(GLsizei count, const GLuint *shaders,GLenum binaryformat, const void *binary, GLsizei length);
  • count:表示要加载二进制数据的着色器对象数量。
  • shaders:指向包含着色器对象句柄(ID)数组的指针。每个句柄代表一种唯一的着色器类型,可以对应表7.1中列出的任何着色器阶段。
  • binaryformat:指定预编译着色器代码的格式。若要加载SPIR-V模块,则应设置为SHADER_BINARY_FORMAT_SPIR_V
  • binary:指向客户端内存中预编译着色器二进制代码的起始位置。对于SPIR-V,这里应该是指向有效SPIR-V模块二进制的指针。
  • length:表示二进制代码的长度(以字节为单位)。

成功加载SPIR-V模块后:

  1. shaders列表中的每个着色器对象都将与提供的SPIR-V模块关联起来。
  2. 每个着色器的SPIR_V_BINARY状态将被设置为TRUE。
  3. 这些着色器的COMPILE_STATUS将被设为FALSE,因为它们不是通过OpenGL实现编译的;而是从预编译形式加载的。
  4. 从着色器对象中移除所有已存在的源代码字符串(通过glShaderSource指定的)。
  5. 关于先前编译的信息将丢失。

与SPIR-V模块关联的着色器必须通过调用glSpecializeShader进行最终确定。

此外,OpenGL还提供了获取由扩展提供的此类格式令牌值的机制:

  • 通过查询NUM_SHADER_BINARY_FORMATS的值可以获得支持的二进制格式总数。
  • 通过查询SHADER_BINARY_FORMATS的值可以获得GL实现所支持的具体二进制格式列表。

根据着色器对象的类型,glShaderBinary会分别加载单个二进制着色器,或者加载包含一组优化过的、存储在同一个二进制文件中的着色器的可执行二进制文件。

如果glShaderBinary加载二进制文件失败,那么该二进制文件正被加载到的着色器对象的状态不会恢复。需要注意的是,如果着色器二进制接口得到支持,OpenGL实现可能要求在调用LinkProgram时指定一组一起编译并优化过的着色器二进制。如果不提供这样的优化集合,可能会导致LinkProgram操作失败。


着色器专业化(Shader Specialization)

与SPIR-V模块关联的着色器在被链接到程序对象之前必须先进行专业化处理。不过,无需在将着色器附加到程序对象前就对其进行专业化。

专业化过程主要完成两件事:

  1. 从SPIR-V模块中选择该着色器阶段的入口点名称。
  2. 设置SPIR-V模块中所有或部分特殊化常量的值。

要对由SPIR-V模块创建的着色器进行专业化,请调用以下函数:

void glSpecializeShader( uint shader, const char *pEntryPoint, uint umSpecializationConstants, const uint *pConstantIndex, const uint *pConstantValue );
  • shader:指向包含未特殊化的SPIR-V的着色器对象名称,该对象是通过成功调用ShaderBinary并将SPIR-V模块传递给它而创建的。
  • pEntryPoint:指向一个以空字符终止的UTF-8字符串指针,用于指定SPIR-V模块中用于此着色器的入口点名称。
  • numSpecializationConstants:指示在此调用中设置值的特殊化常量数量。
  • pConstantIndex:指向一个包含numSpecializationConstants个无符号整数的数组,每个整数表示SPIR-V模块中要设置其值的一个特殊化常量的索引。pConstantValue中的相应条目用于设置由pConstantIndex中条目索引的特殊化常量的值。
  • pConstantValue:指向一个无符号整数数组,虽然该数组为整型,但每个元素都会转换为其在SPIR-V模块中对应的适当类型。因此,可以通过在pConstantValue数组中包含IEEE-754位表示来设置浮点常量的值。未被pConstantIndex引用的特殊化常量将保留其在SPIR-V模块中指定的默认值。

若着色器成功实现专业化,则着色器的编译状态会被设置为TRUE。如果失败,着色器的编译状态会设为FALSE,并且关于失败原因的更多信息可能可在着色器编译日志中获取。如果SPIR-V模块未能满足附录C中列出的要求,则可能会导致专业化失败。

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

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

相关文章

算法笔记刷题日记——Day1 C_C++在ACM中的常用语法

写在前面 这学期选了ACM课,但平时缺乏练习,不怎么刷题,因此期末考试成绩并不理想。考虑到之后的考研复试中包含机试,且计试可以算是非常重要的印象分,因此我打算寒假刷一下算法笔记,备战3月初的PAT甲级和3…

【前端学习路线】

前端学习路线 1. 大纲: 前端学习路线2. ES6 语法1. let 和 const2. 箭头函数3. 解构3.1 数组解构3.2 对象解构 4 剩余参数4.1 和解构联用4.2 合并数组 5. 可选链6. Set7.数组操作8.字符串扩展方法8.1 startsWith() 和 endsWith()8.2 模板字符串 1. 大纲: 前端学习路线 学习前端…

【Android 字节码插桩】Gradle插件基础 Transform API的使用

前言 啪~我给大家开个会(手机扔桌子上) 什么叫做 客户无感的数据脱敏!? 师爷给翻译翻译什么叫做客户无感的数据脱敏? 什么特么的叫做客户无感数据脱敏? 举个栗子~ 客户端Sdk新升级了一个版本,增…

Jmeter,如何从数组参数中取值

有个post请求,参数“equipment_ids”,是个数组,需求每次执行的时候,按顺序取equipment_ids中不同的值 要实现在 JMeter 中每次执行请求时按顺序取不同的 equipment_ids 中的值,你可以使用 Counter 元件来生成索引&…

Qt读写Execl:QXlsx库

Qt三方库开发技术:QXlsx介绍、编译和使用 我自己记录的实例代码:https://download.csdn.net/download/cao_jie_xin/88795216 目录 一、概述二、下载三、编译四、加载QXlsx静态库五、介绍一些常用的功能1、一些头文件和命名空间2、创建一个excel文件3、…

vue-cli脚手架的安装

vue-cli 1 什么是vue-cli Vue 提供了一个官方的 CLI,为单页面应用 (SPA) 快速搭建繁杂项目的脚手架。它为现代前端工作流提供了 batteries-included 的构建设置。只需要几分钟的时间就可以运行起来并带有热重载、保存时 lint 校验,以及生产环境可用的构…

2024年1月个人工作生活总结

本文为 2024年1月工作生活总结。 研发编码 docker-compose外部网络配置 高版本的docker-compose有些语法变化。 使用如下方式声明外部网络: version: 3.8services:ll-busybox: ...networks:my-net:ipv4_address: 172.100.1.1 networks:my-net:external:name: &q…

在linux(centos)上运行C语言文件

📙 作者简介 :RO-BERRY 📗 学习方向:致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 📒 日后方向 : 偏向于CPP开发以及大数据方向,欢迎各位关注,谢谢各位的支持 目录 1.下载gcc2.创建C语言…

软件价值2-贪吃蛇游戏

贪吃蛇游戏虽然很多,不过它可以作为软件创作的开端,用python来实现,然后dist成windows系统可执行文件。 import pygame import sys import random# 初始化 pygame.init()# 游戏设置 width, height 640, 480 cell_size 20 snake_speed 15# …

SpringBoot 整合多数据源的事务问题

代码 先贴代码:核心就是:Spring给我们提供的一个类 AbstractRoutingDataSource,然后我们再写一个切面来切换数据源,肯定要有一个地方存储key还要保证上下文都可用,所以我们使用 ThreadLocal 来存储数据源的key pom.xml…

【笔记】计算文件夹的大小

目标:遍历文件夹,计算文件夹下包含文件和文件夹的大小。将这些结果存入python自带的数据库。 用大模型帮我设计并实现。 Step1 创建一个测试用的目录结构 创建目录结构如下所示: TestDirectory/ │ ├── EmptyFolder/ │ ├── SmallF…

结合创新!11种多尺度特征融合方法,附论文和代码

随着深度学习和计算机视觉技术的快速发展,多尺度特征融合已经成为一个备受关注的、不断探索的研究方向,它通过捕捉不同尺度和层次上的特征信息,提高对图像和视频内容的理解能力,为图像处理、计算机视觉和深度学习等领域的应用提供…

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之DatePicker组件

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之DatePicker组件 一、操作环境 操作系统: Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1 二、DatePicker组件 日期选择器组件,用于根据指定日期范围创建日期滑…

Delphi TStringList常用的方法和属性

Delphi TStringList 是一个常用的字符串列表类,用于存储和操作字符串列表。以下是一些常用的方法和属性: 方法: Add:向列表末尾添加一个字符串。Insert:在指定位置插入一个字符串。Delete:删除指定位置的…

字符串操作函数1

1.strcpy使用 使用这个函数我们可以进行字符串拷贝。它有两个参数&#xff0c;第一个参数是指向目标空间&#xff0c;第二个参数是指向需要拷贝的字符串。返回值为拷贝完成后指向的字符串首地址。头文件为<string.h> 演示如下&#xff1a; 注意&#xff1a; • 源字符…

TensorFlow2实战-系列教程4:数据增强

&#x1f9e1;&#x1f49b;&#x1f49a;TensorFlow2实战-系列教程 总目录 有任何问题欢迎在下面留言 本篇文章的代码运行界面均在Jupyter Notebook中进行 本篇文章配套的代码资源已经上传 猫狗识别1 数据增强 猫狗识别2------数据增强 猫狗识别3------迁移学习 对于图像数据…

RS485自动收发电路震荡的问题

电路 设计初衷 电源5V 选择5V的原因&#xff0c;差分2.5V比1.5V可以提高传输能力 TTL输入 3.3V电平满足需求 TTL输出 4.5V了&#xff0c;MCU是3.3V平台 这样就分为两种情况 MCU接收端可以容忍5V输入 MCU接收端不可以容忍5V输入&#xff0c;就要进行电压转换&#xff0c;我这里使…

MacOS X 中 OpenGL 环境搭建 Makefile的方式

1&#xff0c;预备环境 安装 brew&#xff1a; /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" 安装glfw&#xff1a; brew install glfw 安装glew&#xff1a; brew install glew 2.编译 下载源代码…

Linux内核--设备驱动(一)驱动的结构介绍

目录 一、引言 二、I/O架构 三、字符设备基本构成 ------>3.1、cdev ------>3.2、char_device_struct ------>3.3、cdev_map 四、打开字符设备 ------>4.1、加载 ------>4.2、创建文件设备 ------>4.3、打开字符设备 ------>4.4、写入字符设备…

本地搭建Plex私人影音网站并结合内网穿透实现公网远程访问

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…