15.2 OpenGL可编程片段处理:着色器执行

着色器执行 Shader Execution

在片段阶段存在活动的程序对象时,该程序对象的可执行代码用于处理由光栅化产生的传入片段。

实现允许跳过对某些片段着色器调用的执行,并且由于实现相关原因(包括在片段着色器阶段不存在活动的程序对象时),允许执行额外的片段着色器调用,只要渲染结果在其他方面保持不变。

在着色器执行之后,将执行第17章描述的固定功能操作。

片段着色器执行的特殊考虑因素在接下来的部分中描述。

纹理访问 Texture Access

第11.1.3.1节描述了顶点着色器可访问的纹理查找功能。在那里描述的texel fetch和纹理大小查询功能也适用于片段着色器。

当在片段着色器中执行纹理查找时,OpenGL会按照第8.14节和8.15节中描述的方式计算过滤后的纹理值τ,并将其转换为纹理基色Cb,如表15.1所示,然后根据纹理参数TEXTURE_SWIZZLE_R、TEXTURE_SWIZZLE_G、TEXTURE_SWIZZLE_B和TEXTURE_SWIZZLE_A的值对Cb的分量进行重新排列。如果TEXTURE_SWIZZLE_R的值由swizzler表示,则根据以下规则计算Cs的第一个分量:

if (swizzler == RED)Cs[0] = Cb[0];
else if (swizzler == GREEN)Cs[0] = Cb[1];
else if (swizzler == BLUE)Cs[0] = Cb[2];
else if (swizzler == ALPHA)Cs[0] = Ab;
else if (swizzler == ZERO)Cs[0] = 0;
else if (swizzler == ONE)Cs[0] = 1; // float or int depending on texture component type

Cs的其他分量(Cs[1]、Cs[2]和As)的重新排列方式由TEXTURE_SWIZZLE_G、TEXTURE_SWIZZLE_B和TEXTURE_SWIZZLE_A的值类似地控制。

最终的四分量向量(Rs,Gs,Bs,As)被返回给片段着色器。对于细节级别计算,可以通过差分算法来近似计算du/dx、du/dy、dv/dx、dv/dy、dw/dx和dw/dy的导数,方法在OpenGL着色语言规范的第8.13.1节(“导数函数”)中描述。

涉及深度和/或模板分量数据的纹理查找按照第11.1.3.5节中的描述执行。

着色器输入 Shader Inputs

片段着色器可以访问的内置输入值

  1. gl_FragCoord:该内置变量包含了当前正在处理的片段在窗口坐标系中的位置信息,其包含四个分量(xf, yf, zf, wf)。xf 和 yf 分别是片段在窗口空间中的二维坐标,计算方式会根据像素中心和原点约定进行调整;zf 是片段的深度值(zw),已包含了启用时的多边形偏移量;wf 是裁剪空间中 w 成分的倒数,用于归一化操作。

  2. gl_FrontFacing:这是一个布尔型变量,表示当前片段是否来自正向面对观察者的图元。对于三角形图元,通过计算面积的符号来确定正反面;其他类型的图元默认为正向面。

  3. gl_PrimitiveID:如果几何着色器处于活动状态,此变量存储由几何着色器输出的触发顶点对应的ID号。若无几何着色器,则存储自上次绘图命令以来光栅器处理过的图元总数,并且每次处理一个点、线或面片时递增计数。

  4. gl_SampleID:只读内置变量,提供了当前被处理样本的唯一编号,在多重采样帧缓冲区中范围从0到gl_NumSamples - 1,而在非多重采样缓冲区中始终为0。使用此变量将导致片段着色器按每个样本独立执行。

  5. gl_SamplePosition:同样为只读内置变量,它包含了当前样本在多重采样绘制缓冲区内的子像素位置,其x和y分量表示子像素坐标,范围在[0, 1]之间,像素中心的子像素坐标固定为(0.5, 0.5)。在非多重采样情况下,其值始终为(0.5, 0.5)。

  6. gl_SampleMaskIn:这是一个整数数组,储存了位字段,表示对应片段着色器调用的图元所覆盖的所有样本集合。数组大小基于实现支持的最大颜色样本数,并按照一定的规则设置各个样本是否被当前图元覆盖的标志位。当渲染至非多重采样帧缓冲区或禁用多重采样光栅化时,所有位都为零,仅第一个元素的第一个位反映了像素是否被覆盖。同时,因SAMPLE_COVERAGE或SAMPLE_MASK导致被丢弃的样本对应的位不会被置1。在每样本着色模式下,只有当前样本对应的位会被设置。

此外,GLSL还规定了一个限制,即片段着色器可读取的内建及用户定义输入变量组件数量的最大值,这个值由实施相关的常数MAX_FRAGMENT_INPUT_COMPONENTS决定。在链接程序时,片段着色器引用的所有输入变量的所有组件都会计入这个限制。如果片段着色器超出这一限制,除非设备特定的优化能够使其适应可用硬件资源,否则可能导致程序无法成功链接。对不同类型的变量以及变量声明的组件计数规则与MAX_VERTEX_OUTPUT_COMPONENTS一致。

着色器输出 Shader Outputs

片段着色器允许程序员定义和输出自定义变量以及使用内置输出变量。

关键的内置输出包括:

  1. gl_FragDepth:片段着色器可以重写此值来指定片段在深度缓冲区中的深度,从而影响像素是否可见以及如何进行深度测试。

  2. gl_SampleMask:通过这个内置数组,片段着色器可以精细控制哪些样本应当参与后续的混合和其他操作,但不能用它使原本未被覆盖的样本生效。

用户自定义输出主要涉及颜色值,它们可以是多种数据类型,并且需要与颜色缓冲区格式相匹配。片段着色器可以输出多个颜色,这些颜色可以通过BindFragDataLocationIndexed函数绑定到不同的颜色附件上,用于多重渲染目标(MRT)或自定义混合效果。

将着色器代码中的用户自定义输出变量绑定到片段颜色编号的组件上

这个绑定可以在着色器文本或 SPIR-V 着色器中明确指定,也可以通过函数调用来完成。

void glBindFragDataLocationIndexed( uint program, uint colorNumber, uint index, const char * name );
  • program:要将绑定应用于的着色器程序的 ID。
  • colorNumber:要将输出变量绑定到的片段颜色编号。
  • index:指定颜色将用作混合方程的第一个(0)还是第二个(1)颜色输入。
  • name:着色器代码中输出变量的名称。

当调用 glBindFragDataLocationIndexed 时, OpenGL 将着色器程序中名为 name 的输出变量绑定到由 colorNumber 指定的片段颜色上。index 参数确定此颜色将作为混合方程的第一个或第二个颜色输入。

如果之前已经绑定了输出变量 name,使用新的 colorNumber 调用 glBindFragDataLocationIndexed 将替换其分配的绑定。

请注意,绑定将在下次链接程序时生效。

void glBindFragDataLocation( uint program, uint colorNumber, const char * name );// 等价于glBindFragDataLocationIndexed(program, colorNumber, 0, name);

glBindFragDataLocation 在程序链接之前没有任何效果。特别地,它不会修改已经链接的程序中输出变量的绑定。


在链接包含片段着色器的程序时,每个活跃的用户自定义片段着色器输出变量都会分配一个由片段颜色编号、片段颜色索引和组件索引组成的绑定。这些绑定可以通过布局限定符在着色器代码中指定(如SPIR-V中的Location, Component, Index),或者通过BindFragDataLocationIndexedBindFragDataLocation API函数来指定。未显式指定位置的变量将由链接器自动分配,并遵循特定规则以避免冲突。

当片段着色器执行结束时,其输出变量的值会被写入到相应绑定的颜色输出组件中,根据变量类型和绑定确定具体哪些组件被写入。数组类型的输出变量会按照其元素顺序和组件索引映射到连续的片段颜色编号上。

若出现以下情况,链接程序将会失败:

  • 活跃输出数量超过MAX_DRAW_BUFFERS限制;
  • 程序有输出与MAX_DUAL_SOURCE_DRAW_BUFFERS相关的限制冲突;
  • 两个输出变量绑定到了相同的输出数和索引且存在重叠组件;
  • 不同数据类型(整型或浮点型)的输出变量绑定到了同一输出数;
  • 显式绑定导致链接器无法为输出数组自动分配足够的连续位置。

此外,即使片段着色器还未附加至程序对象,也可以使用BindFragDataLocationIndexed预先进行颜色编号和索引的绑定,对于实际不存在的变量名的绑定操作将被忽略。

最后,为了获取程序中片段着色器使用的输出属性变量信息,应用程序可以查询相关接口PROGRAM_OUTPUT的资源和属性。

查询分配给片段着色器输出变量的位置和片段颜色索引

int glGetFragDataLocation( uint program, const char *name );
int glGetFragDataIndex( uint program, const char *name );// 等价于glGetProgramResourceLocation(program, PROGRAM_OUTPUT, name);
glGetProgramResourceLocationIndex(program, PROGRAM_OUTPUT, name);

在SPIR-V片段阶段中,通过OpEntryPoint和Output存储类声明的变量形成了片段输出接口。这些变量必须使用Location装饰,并且可以使用Component和/或Index装饰。

用户定义的片段着色器输出变量只通过它们的Location、Component和Index装饰进行匹配。如果两个输出位于同一位置,则它们必须具有相同的基本类型(浮点或整数)。不允许有输出变量的组件别名。换句话说,不能有两个具有相同位置、组件和索引的输出变量,无论是显式声明还是隐式声明。

由片段着色器写入的输出值必须使用OpTypeFloat或OpTypeInt声明,并且宽度为32。也可以使用这些类型的复合类型。

早期片段测试 Early Fragment Tests

提供了显式控制以允许片段着色器启用早期片段测试。

layout(early_fragment_tests) in;

如果片段着色器指定了early_fragment_tests布局限定符,那么描述在第14.9节中的每个片段测试将在片段着色器执行之前进行。否则,它们将在片段着色器执行之后进行。

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

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

相关文章

微服务多级缓存

多级缓存 1.什么是多级缓存 传统的缓存策略一般是请求到达Tomcat后,先查询Redis,如果未命中则查询数据库,如图: 存在下面的问题: •请求要经过Tomcat处理,Tomcat的性能成为整个系统的瓶颈 •Redis缓存…

python-自动化篇-办公-Excel-Openpyxl库

文章目录 1.1 Openpyxl库的安装使用1.2 Excel的新建、读取、保存1.2.1新建保存工作簿1.2.2读取保存工作簿1.2.3实例(批量建新工作表) 1.3工作表对象的获取方法1.3.1工作表获取方式1.3.2实例(批量修改工作表名) 1.4工作表的新建、复制、删除1.4.1新建工作表1.4.2复制工作表1.4.3…

MATLAB实现朴素贝叶斯分类

朴素贝叶斯(Naive Bayes)是一种基于贝叶斯定理的分类算法,它假设特征之间相互独立,从而简化了计算复杂性。该算法常用于文本分类、垃圾邮件过滤、情感分析等应用场景。 MATLAB实现鸢尾花数据集分类代码如下: clear lo…

2024 前端面试题 附录2

这里记录的是今天原篇的知识点补充 原篇地址:2024 前端面试题(GPT回答 示例代码 解释)No.21 - No.40 目录 这里记录的是今天原篇的知识点补充原篇地址:[2024 前端面试题(GPT回答 示例代码 解释)No.21 …

2024 CKS 题库 | 7、Dockerfile检测

不等更新题库 CKS 题库 7、Dockerfile检测 Task 分析和编辑给定的Dockerfile /cks/docker/Dockerfile(基于ubuntu:16.04 镜像), 并修复在文件中拥有的突出的安全/最佳实践问题的两个指令。 分析和编辑给定的清单文件 /cks/docker/deployme…

Python·turtle库编程之:怎么画一个五角星?

文章目录 前言源码附: 前言 大家好,我是BoBo仔,这节课我要带来一期turtle库的使用教程——画五角星。话不多说,我们直接上代码。 源码 import turtle as t t.pencolor(yellow) t.fillcolor("yellow") t.penup() t.go…

全栈笔记_插件篇(谷歌扩展插件开发系列之 manifest.json配置文件)

manifest.json介绍 是web扩展技术必不可少的插件配置文件,放在根目录作用: 指定插件的基本信息 name:名称manifest_version:manifest.json文件的版本号,可以写2或3version:版本description:描述定义插件的行为: browser_action:定义插件在浏览器工具栏中的操作按钮,例…

react 【七】各种hooks的使用/SPA的缺点

文章目录 1、Hook1.1 为什么会出现hook1.2 useState1.3 useEffect1.4 useContext1.5 useReducer1.6 useCallback1.7 useMemo1.8 useRef1.8.1 ref绑定dom1.8.2 ref解决闭包缺陷 1.9 useImperativeHandle1.10 useLayoutEffect1.11 自定义Hook1.11.1 什么是自定义Hook1.11.2 Conte…

Rust 数据结构与算法:3栈:用栈实现符号匹配

1、符号匹配 如: (56)(78)/(43)、{ { ( [ ] [ ])}}、(ab)(c*d)func() 等各类语句的符号匹配。 这里我们关注的不是数字而是括号,因为括号更改了操作优先级,限定了语言的语义,这是非常重要的。如果括号不完整,那么整个…

【Deep Learning 1】神经网络的搭建

🌞欢迎来到PyTorch的世界 🌈博客主页:卿云阁 💌欢迎关注🎉点赞👍收藏⭐️留言📝 🌟本文由卿云阁原创! 📆首发时间:🌹2024年2月16日&a…

消息队列RabbitMQ-使用过程中面临的问题与解决思路

消息队列在使用过程中会出现很多问题 首先就是消息的可靠性,也就是消息从发送到消费者接收,消息在这中间过程中可能会丢失 生产者到交换机的过程、交换机到队列的过程、消息队列中、消费者接收消息的过程中,这些过程中消息都可能会丢失。 …

gem5 garnet 合成流量: packet注入流程

代码流程 下图就是全部. 剩下文字部分是细节补充,但是内容不变: bash调用python,用python配置好configuration, 一个cpu每个tick运行一次,requestport发出pkt. bash 启动 python文件并配置 ./build/NULL/gem5.debug configs/example/garnet_synth_traffic.py \--num-cpus…

安卓游戏开发框架应用场景以及优劣分析

一、引言 在移动游戏开发领域,选择合适的开发框架是项目成功的关键因素之一。特别是对于安卓平台,由于其开放性和庞大的用户基础,不同的游戏开发框架应运而生,旨在帮助开发者高效地构建游戏应用。以下是一些流行的安卓游戏开发框架…

你好,C++(15)0.1*10不等于1.0——4.1.4 关系操作符4.1.5 逻辑操作符

4.1.4 关系操作符 在C中,除了需要用算术操作符对数据进行加减乘除的算术操作之外,我们有时候还需要对数据之间的关系进行操作,也就是对两个数据进行大小比较,得出它们之间的大小关系。在现实世界中,这种大小关系的比较…

vue-组件组成和组件通信(四)

组件的三大组成部分 (结构/样式/逻辑) scoped样式冲突 默认情况:写在组件中的样式会 全局生效 → 因此很容易造成多个组件之间的样式冲突问题。 1. 全局样式: 默认组件中的样式会作用到全局 2. 局部样式: 可以给组件加上 scoped 属性, 可以让样式只作用于当前组…

探索未来科技:人工智能与量子计算的新纪元

引言 在这个科技飞速发展的时代,我们正站在一个全新的起点。人工智能(AI)和量子计算作为两项颠覆性的技术,正引领着科技的未来。在这篇博客中,我们将深入探讨人工智能与量子计算的最新进展,以及它们如何改…

pytorch创建模型方式

1.继承自nn.Module的方式 from torch import nn import torch.nn.functional as F 继承自nn.Moduleclass LModel(nn.Module):def __init__(self):super().__init__()self.L1 nn.Linear(10,10)self.L2 nn.Linear(10,64)self.L3 nn.Linear(64,10)self.L4 nn.Linear(10,5)se…

C++初阶:适合新手的手撕list(模拟实现list)

上次讲了常用的接口:今天就来进行模拟实现啦 文章目录 1.基本结构与文件规划2.空参构造函数(constructor)3.完善迭代器(iterator)(begin(),end())4.List Capacity(size(),empty())4.增删改查(push_back,pop_back,pop_f…

C++ bfs反向搜索(五十七)【第四篇】

今天我们来学习bfs的反向搜索。 1.反向搜索 反向搜索:是从目标状态出发进行的搜索,一般用于终点状态唯一,起点状态有多种,且状态转移是可逆的(无向边)情况。 例题:在一个长度为 n 的坐标轴上&a…

医药零售企业运营BI解决方案 连锁药房大数据解决方案 药店大数据解决方案

一、项目背景 连锁药店大数据项目建设的背景可以从以下几个方面进行分析: 行业趋势:随着医药行业的快速发展,连锁药店已成为药品零售的主要渠道。然而,随着市场竞争的加剧,连锁药店需要寻找新的竞争优势。通过大数据技术,连锁药店可以更好地了解消费者需求,提供个性化的…