LearnOpenGL学习笔记——高级GLSL

【OpenGL】笔记二十六、高级GLSL 之前我们对于GLSL只是进行了比较简单的应用,接下来就来介绍一下更有趣的应用我们已经学会使用顶点属性、uniform和采样器来往着色器传入数据了,然而,除此之外,GLSL还定义了另外几个以gl_为前缀的变量,它们能提供给我们更多的方式来读取/写入数据。(我们已经在前面教程中接触过其中的两个了:顶点着色器的输出向量gl_Position,和片段着色器的gl_FragCoord)我们能够选用的其中一个图元是GL_POINTS,如果使用它的话,每一个顶点都是一个图元,都会被渲染为一个点。我们可以通过OpenGL的 阅读详情

顶点着色器变量

gl_PointSize :可以设置渲染出来点的大小。使用

	glEnable(GL_PROGRAM_POINT_SIZE);`

开始启用点大小设置,点的大小会随着观察者距顶点距离变远而增大。

	void main()
	{
    	gl_Position = projection * view * model * vec4(aPos, 1.0);    
    	gl_PointSize = gl_Position.z;    
	}

gl_VertexID:整型变量gl_VertexID储存了正在绘制顶点的当前ID当(使用glDrawElements)进行索引渲染的时候,这个变量会存储正在绘制顶点的当前索引。当(使用glDrawArrays)不使用索引进行绘制的时候,这个变量会储存从渲染调用开始的已处理顶点数量。

片段着色器变量

gl_FragCoord:因为gl_FragCoord的z分量等于对应片段的深度值。l_FragCoord的x和y分量是片段的窗口空间(Window-space)坐标,其原点为窗口的左下角。
gl_FrontFacing:gl_FrontFacing将会告诉我们当前片段是属于正向面的一部分还是背向面的一部分。
gl_FragDepth:输入变量gl_FragCoord能让我们读取当前片段的窗口空间坐标,并获取它的深度值,但是它是一个只读(Read-only)变量

在写入gl_FragDepth时,你就需要考虑到它所带来的性能影响。然而,从OpenGL 4.2起,我们仍可以对两者进行一定的调和,在片段着色器的顶部使用深度条件(Depth Condition)重新声明gl_FragDepth变量:

layout (depth_) out float gl_FragDepth;
condition可以为下面的值:

条件 描述
any 默认值。提前深度测试是禁用的,你会损失很多性能
greater 你只能让深度值比gl_FragCoord.z更大
less 你只能让深度值比gl_FragCoord.z更小
unchanged 如果你要写入gl_FragDepth,你将只能写入gl_FragCoord.z的值

接口块

到目前为止,每当我们希望从顶点着色器向片段着色器发送数据时,我们都声明了几个对应的输入/输出变量。将它们一个一个声明是着色器间发送数据最简单的方式了,但当程序变得更大时,你希望发送的可能就不只是几个变量了,它还可能包括数组和结构体。

为了帮助我们管理这些变量,GLSL为我们提供了一个叫做接口块(Interface Block)的东西,来方便我们组合这些变量。接口块的声明和struct的声明有点相像,不同的是,现在根据它是一个输入还是输出块(Block),使用in或out关键字来定义的。

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoords;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

out VS_OUT
{
    vec2 TexCoords;
} vs_out;

void main()
{
    gl_Position = projection * view * model * vec4(aPos, 1.0);    
    vs_out.TexCoords = aTexCoords;
}  

这次我们声明了一个叫做vs_out的接口块,它打包了我们希望发送到下一个着色器中的所有输出变量。这只是一个很简单的例子,但你可以想象一下,它能够帮助你管理着色器的输入和输出。当我们希望将着色器的输入或输出打包为数组时,它也会非常有用。之后,我们还需要在下一个着色器,即片段着色器,中定义一个输入接口块。块名(Block Name)应该是和着色器中一样的(VS_OUT),但实例名(Instance Name)(顶点着色器中用的是vs_out)可以是随意的,但要避免使用误导性的名称,比如对实际上包含输入变量的接口块命名为vs_out:

#version 330 core
out vec4 FragColor;

in VS_OUT
{
    vec2 TexCoords;
} fs_in;

uniform sampler2D texture;

void main()
{             
    FragColor = texture(texture, fs_in.TexCoords);   
}

Uniform缓冲对象

OpenGL为我们提供了一个叫做Uniform缓冲对象(Uniform Buffer Object)的工具,它允许我们定义一系列在多个着色器中相同的全局Uniform变量。当使用Uniform缓冲对象的时候,我们只需要设置相关的uniform一次。当然,我们仍需要手动设置每个着色器中不同的uniform。并且创建和配置Uniform缓冲对象会有一点繁琐。

因为Uniform缓冲对象仍是一个缓冲,我们可以使用glGenBuffers来创建它,将它绑定到GL_UNIFORM_BUFFER缓冲目标,并将所有相关的uniform数据存入缓冲。在Uniform缓冲对象中储存数据是有一些规则的,我们将会在之后讨论它。首先,我们将使用一个简单的顶点着色器,将projection和view矩阵存储到所谓的Uniform块(Uniform Block)中:

#version 330 core
layout (location = 0) in vec3 aPos;

layout (std140) uniform Matrices
{
    mat4 projection;
    mat4 view;
};

uniform mat4 model;

void main()
{
    gl_Position = projection * view * model * vec4(aPos, 1.0);
}

在我们大多数的例子中,我们都会在每个渲染迭代中,对每个着色器设置projection和view Uniform矩阵。这是利用Uniform缓冲对象的一个非常完美的例子,因为现在我们只需要存储这些矩阵一次就可以了。这里,我们声明了一个叫做Matrices的Uniform块,它储存了两个4x4矩阵。Uniform块中的变量可以直接访问,不需要加块名作为前缀。接下来,我们在OpenGL代码中将这些矩阵值存入缓冲中,每个声明了这个Uniform块的着色器都能够访问这些矩阵。

Uniform块布局

Uniform块的内容是储存在一个缓冲对象中的,它实际上只是一块预留内存。因为这块内存并不会保存它具体保存的是什么类型的数据,我们还需要告诉OpenGL内存的哪一部分对应着着色器中的哪一个uniform变量。假设着色器中有以下的这个Uniform块:

	layout (std140) uniform ExampleBlock
	{
    	float value;
    	vec3  vector;
    	mat4  matrix;
    	float values[3];
   	 	bool  boolean;
    	int   integer;
	};

我们需要知道的是每个变量的大小(字节)和(从块起始位置的)偏移量,来让我们能够按顺序将它们放进缓冲中。每个元素的大小都是在OpenGL中有清楚地声明的,而且直接对应C++数据类型,其中向量和矩阵都是大的float数组。OpenGL没有声明的是这些变量间的间距(Spacing)。这允许硬件能够在它认为合适的位置放置变量。比如说,一些硬件可能会将一个vec3放置在float边上。不是所有的硬件都能这样处理,可能会在附加这个float之前,先将vec3填充(Pad)为一个4个float的数组。这个特性本身很棒,但是会对我们造成麻烦。

默认情况下,GLSL会使用一个叫做共享(Shared)布局的Uniform内存布局,共享是因为一旦硬件定义了偏移量,它们在多个程序中是共享并一致的。使用共享布局时,GLSL是可以为了优化而对uniform变量的位置进行变动的,只要变量的顺序保持不变。因为我们无法知道每个uniform变量的偏移量,我们也就不知道如何准确地填充我们的Uniform缓冲了。我们能够使用像是glGetUniformIndices这样的函数来查询这个信息,但这超出本节的范围了。
虽然共享布局给了我们很多节省空间的优化,但是我们需要查询每个uniform变量的偏移量,这会产生非常多的工作量。通常的做法是,不使用共享布局,而是使用std140布局。std140布局声明了每个变量的偏移量都是由一系列规则所决定的,这显式地声明了每个变量类型的内存布局。由于这是显式提及的,我们可以手动计算出每个变量的偏移量。每个变量都有一个基准对齐量(Base Alignment),它等于一个变量在Uniform块中所占据的空间(包括填充量(Padding)),这个基准对齐量是使用std140布局的规则计算出来的。接下来,对每个变量,我们再计算它的对齐偏移量(Aligned Offset),它是一个变量从块起始位置的字节偏移量。一个变量的对齐字节偏移量必须等于基准对齐量的倍数。布局规则的原文可以在OpenGL的Uniform缓冲规范这里找到,但我们将会在下面列出最常见的规则。GLSL中的每个变量,比如说int、float和bool,都被定义为4字节量。每4个字节将会用一个N来表示。

类型 布局规则
标量,比如int和bool 每个标量的基准对齐量为N。
向量 2N或者4N。这意味着vec3的基准对齐量为4N。
标量或向量的数组 每个元素的基准对齐量与vec4的相同。
矩阵 储存为列向量的数组,每个向量的基准对齐量与vec4的相同。
结构体 等于所有元素根据规则计算后的大小,但会填充到vec4大小的倍数。
和OpenGL大多数的规范一样,使用例子就能更容易地理解。我们会使用之前引入的那个叫做ExampleBlock的Uniform块,并使用std140布局计算出每个成员的对齐偏移量:

layout (std140) uniform ExampleBlock
{
                     // 基准对齐量       // 对齐偏移量
    float value;     // 4               // 0 
    vec3 vector;     // 16              // 16  (必须是16的倍数,所以 4->16)
    mat4 matrix;     // 16              // 32  (列 0)
                     // 16              // 48  (列 1)
                     // 16              // 64  (列 2)
                     // 16              // 80  (列 3)
    float values[3]; // 16              // 96  (values[0])
                     // 16              // 112 (values[1])
                     // 16              // 128 (values[2])
    bool boolean;    // 4               // 144
    int integer;     // 4               // 148
}; 

知识点总结

关键字总结:
gl_PointSize
gl_VertexID
gl_FragCoord
gl_FrontFacing
gl_FragDepth
接口块:
in或out关键字
Uniform缓冲对象:
全局Uniform变量
Uniform块布局

https://learnopengl-cn.github.io/04%20Advanced%20OpenGL/08%20Advanced%20GLSL/#uniform

openGL之API学习(七十六)GLSL的内置变量 预定义变量 GLSL为不同的渲染阶段定义了一些特定的变量。这些预定义(也叫做内置变量)有特定的属性。所有的预定义变量都以gl_开头。用户定义的变量不能以此开头。 下面分类进行介绍。 (1)顶点着色器输入 inintgl_VertexID; inintgl_InstanceID; gl_VertexID是当前被处理的顶点的索引。对于arrayrendering,它是当前顶点在数组中的索引;... 阅读详情

相关推荐

LearnOpenGL学习笔记

LearnOpenGL学习笔记

qq_42216823的博客 1135

WebGL着色器内置变量gl_PointSize、gl_Position、gl_FragColor、gl_FragCoord、gl_PointCoord

WebGL着色器内置变量 本文是WebGL教程(电子书)的2.7节内容 着色器语言在GPU的着色器单元执行,javascript语言、C语言在CPU上执行,任何一种语言的语法规则,整体设计都和它执行的硬件有一定的关系,GPU和CPU执行程序的硬件单元既有相同点,也有不同点。这里谈到GPU和CPU不是为了讲解硬件,而是为了提醒大家,学习着色器语言有些语法可以参考javascript、C等执行在CPU...

u014291990的博客 3万+

【LearnOpenGL学习笔记】——08.颜色

文章目录1.光照2.创建一个光照场景3.例子实现 1.光照 在现实生活中看到某一物体的颜色并不是这个物体真正拥有的颜色,而是它所反射的(Reflected)颜色 2.创建一个光照场景 (1)被照物体:类似前几次,绘制一个立方体,为了简化,先不做纹理映射 (2)光源:绘制一个立方体模拟光照 需要为光源创建一个VAO? 当然也可以让这个灯和其它物体使用同一个VAO,简单地对它的model(模型)矩阵做一些变换就好了,然而如果频繁地对顶点数据和属性指针做出修改,可能会让这些修改影响到灯,因此有必要为灯创建一

qq_45974407的博客 840

OpenGL.Shader:6-glDrawArraysInstanced / 内置变量gl_VertexID

OpenGL.Shader:6-glDrawArraysInstanced+内置变量gl_VertexID绘制自跟踪的《三块广告牌》 首先可以看看效果。这种效果可以从现在超火的《一起来捉妖》就能观察到。现在我们就来学习其中shader的知识。 首先这次模型和着色器程序的代码组织上和以前稍作一些改变,便于更好的理解学习。我们先来定义那堆绿草的模型代码GreeneryMgr.hpp ...

vx number:zzr_admin,拉入技术交流群。 2945

Three 之 three.js (webgl)着色器材质的一些内置变量的简单说明(gl_PointSize/gl_Position/gl_PointCoord/gl_FragCoord...)

three.js着色器的内置变量,分别是 gl_PointSize:在点渲染模式中,控制方形点区域渲染像素大小(注意这里是像素大小,而不是three.js单位,因此在移动相机是,所看到该点在屏幕中的大小不变) gl_Position:控制顶点选完的位置 gl_FragColor:片元的RGB颜色值 gl_FragCoord:片元的坐标,同样是以像素为单位 gl_PointCoord:在点渲染模式中,对应方形像素坐标 他们或者单个出现在着色器中,或者组团出现在着色器中,是着色器的灵魂 ...

仙魁XAN 2197

LearnOpenGL(三)之GLSL

LearnOpenGL之GLSL

ckg3824278的博客 914

LearnOpenGL学习笔记—高级OpenGL 07-08:高级数据/高级GLSL

LearnOpenGL学习笔记—高级OpenGL 07-08:高级数据/高级GLSL 1 高级数据1.1回顾1.2 分批顶点属性1.3 复制缓冲2 高级GLSL2.1 GLSL的内建变量2.1.1 顶点着色器变量2.1.1.1 gl_PointSize2.1.1.2 gl_VertexID2.1.2 片段着色器变量2.1.2.1 gl_FragCoord2.1.2.2 gl_FrontFacing2.1.2.3 gl_FragDepth2.2 接口块2.3 Uniform缓冲对象2.3.1 Uniform块

清清!的博客 870

大疆C板使用C610电调驱动M2006电机(hal库)

大疆C板使用C610电调驱动M2006电机,以及遇到代码没问题,但是电机死活不转的处理

qq_46210601的博客 6019

LearnOpenGL——高级数据、高级GLSL

当从文件中加载数据时,得到的会是分类好的数据数组,比如会得到三个数组position[]、normal[]、texture[],而不是像我们之前使用的交错的数据数组123123123这样的。目前对于一个个uniform变量,我们还需要一个个来设置,我们可以使用Uniform缓冲对象的工具。我们能够选用的其中一个图元是GL_POINTS,每个顶点都是一个图元,都会被渲染为一个点,我们可以使用float类型的变量gl_PointSize来调整渲染出来的点的大小(可以在顶点着色器中修改这个值)。

weixin_70073176的博客 1287

电商产品组合策略:引流品与利润品的实战方法论

在电商运营中,产品组合策略是提升流量转化与利润增长的核心技术。其基本原理是通过数据化选品构建产品矩阵,利用引流品吸引用户流量,再通过利润品实现商业变现。这种策略不仅能优化广告投放的ROAS(广告投入产出比),还能显著提升客单价。技术实现上需要结合Google Analytics等工具进行归因分析,并运用动态库存管理模型控制风险。该方案特别适用于Amazon、Shopify等电商平台,能有效解决跨境电商业内流量获取与利润创造的平衡难题。通过实战案例可见,合理的产品组合可使客单价提升30-50%,是电商运营必备

weixin_42522009的博客 350

KIBANA可视化管理界面说明

更说明转自https://blog.youkuaiyun.com/IT_ZRS/article/details/125496588 1 主要结构功能 使用浏览器访问 ip:5601 默认端口,进入首页 Discover:日志管理视图 主要进行搜索和查询 Visualize:统计视图 构建可视化的图表 Dashboard:仪表视图 将构建的图表组合形成图表盘 Timelion:时间轴视图 随着时间流逝的数据 APM:性能管理视图 应用程序的性能管理系统 Canvas:大屏展示

tian830937的专栏 7083

LearnOpenGL之高级GLSL

高级GLSL 文章目录高级GLSL一、GLSL的内建变量1.顶点着色器的内建变量(1)gl_PointSize(2)gl_VertexID2.片段着色器的内建变量(1)gl_FragCoord(2)gl_FrontFacing(3)gl_FragDepth二、接口块三、Uniform缓冲对象1.在着色器形式为uniform块:2.Uniform块布局有三种:3.std140布局规则4.使用Uniform缓冲(以绑定投影和观察矩阵为例)(1)定义每个着色器的Uniform块(2)每个着色器的Uniform块绑

Jason_Chen__的博客 775

保姆级教程:用STM32单片机实现国标交流充电桩的CP信号检测(附完整代码)

本文详细介绍了基于STM32单片机实现国标交流充电桩CP信号检测的全流程,包括硬件设计、软件架构和充电控制实现。通过分压电路设计、ADC配置和状态机逻辑,确保充电过程的安全与可靠性,适用于新能源汽车充电桩开发。附完整代码和调试技巧,助力开发者快速掌握关键技术。

weixin_42641998的博客 252

LearnOpenGL学习笔记2-Shaders

这一节介绍了基本的GLSL语法;着色器的输入与输出;全局变量在着色器的使用;颜色属性的添加;着色器类的封装。

LLLawrenceQ的博客 1875

芯片级IO (Pad) Ring &IP Checklist

芯片级IO Ring,PAD Ring 和IP Checklist检查项目

weixin_37584728的博客 3571

计算三维空间中AOA定位的 CRLB(Cramér–Rao 下界,克拉美罗下界)公式与MATLAB例程

摘要:本文介绍了三维空间中基于AOA(到达角度)测量的目标定位CRLB(Cramér–Rao下界)计算方法。通过定义目标位置向量、传感器位置和AOA测量角度(方位角与俯仰角),推导了方向向量和雅可比矩阵的表达式,并构建Fisher信息矩阵计算CRLB。提供了MATLAB例程实现该算法,包括参数设置、CRLB计算和可视化(3σ误差椭球)。实验结果表明,当目标位置偏离传感器阵列时,定位误差显著增大。该方法适用于评估AOA定位系统的理论性能极限,为导航与定位算法设计提供参考。

985工科博士毕业,专攻定位、导航和滤波等算法研究。从业10年,主要使用MATLAB 588

LearnOpenGL——高级OpenGL(八)高级GLSL

本文介绍了GLSL着色器中一些实用的内建变量和接口块功能。重点讲解了顶点着色器的gl_PointSize(控制点大小)和gl_VertexID(获取顶点ID),以及片段着色器的gl_FragCoord(窗口坐标)、gl_FrontFacing(面朝向判断)和gl_FragDepth(深度值写入)等内建变量的使用方法。还介绍了接口块(Interface Block)这一组织着色器输入输出的有效方式,可以更方便地管理多个变量。这些特性虽然不会显著提升视觉效果,但能提供更多控制手段,在特定场景下非常实用,如粒子效

QQ805009795的博客 682

[27] cuda 应用之 核函数实现图像通道变换

[27] cuda 应用之 核函数实现图像通道变换

yohnyang的博客 202

LearnOpenGL学习(高级OpenGL -> 高级GLSL,几何着色器)

float 输出变量,用于控制渲染型图元时,点的大小。可用于粒子系统。将其设置为 gl_Position.z 时,可以使点的距离越远,大小越大。创建出类似近视眼看远处灯光的效果//也是需要开启int 型输入变量(只读),存储了正在绘制顶点的ID(当(使用glDrawElements)进行索引渲染的时候,这个变量会存储正在绘制顶点的当前索引。当(使用glDrawArrays)不使用索引进行绘制的时候,这个变量会储存从渲染调用开始的已处理顶点数量。

zaizai1007的博客 1238

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

LearnOpenGL学习笔记—入门04:Shaders(上)

LearnOpenGL学习笔记—入门03:Shaders(上)0 前言1 GLSL2 GLSL的数据类型3 输入与输出4 给图形上色5 让图形随着时间变色6 绘制一个彩色的图形 0 前言 本节笔记对应的内容 着色器 在入门01中我们配置好了环境 在入门02中我们可以检测输入并出现一个有颜色的窗口 在入门03中我们初步学习了图形渲染管线,尝试用不同方法画出了三角形和四边形 在这一节,我们会开始讲讲着色器(Shader)的内容,以及OpenGL着色器语言(GLSL)。 在入门03的程序中,我们有用过shader

清清!的博客 1347

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

LearnOpenGL-高级OpenGL-8.高级GLSL

我们将会讨论一些有趣的**内建变量**(Built-in Variable),管理着色器输入和输出的新方式以及一个叫做**Uniform缓冲对象**(Uniform Buffer Object)的有用工具。

qq_34060370的博客 1099

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

LearnOpenGL笔记——四、高级OpenGL:“高级数据”与“高级GLSL”

四、高级OpenGL:“高级数据”与“高级GLSL” 4.7 高级数据 除了使用一次函数调用填充整个缓冲之外,我们也可以使用来填充缓冲的特定区域的几个方法。 分批顶点属性:从交错布局123123123123,到分批(Batched)的方式111122223333,可以很容易使用glBufferSubData函数实现 复制缓冲:glCopyBufferSubData能够让我们相对容易地从一个缓冲中复制数据到另一个缓冲中 此部分具体看官网即可。 4.8 高级GLSL 这一节会或多或少涉及GLSL的一些有趣

weixin_44478658的博客 338

(自用)learnOpenGL-高级OpenGL-高级数据、高级glsl

这一节中,我们将讨论一些更有意思的缓冲函数,以及我们该如何使用纹理对象来储存大量的数据(纹理的部分还没有完成)。先来回顾一下之前有关的缓冲内存,OpenGL中的缓冲只是一个管理特定内存块的对象,没有其它更多的功能了。在我们将它绑定到一个缓冲目标(Buffer Target)时,我们才赋予了其意义。当我们绑定一个缓冲到GL_ARRAY_BUFFER时,它就是一个顶点数组缓冲,但我们也可以很容易地将其绑定到GL_ELEMENT_ARRAY_BUFFER。

SHIgaNatsuki的博客 1354

learnopengl——Advanced GLSL

https://learnopengl.com/Advanced-OpenGL/Advanced-GLSL

小孔明的专栏 297

LearnOpenGL 学习笔记 高级 OpenGL

将一个多重采样的纹理图像不进行还原直接传入着色器也是可行的。GLSL提供了这样的选项,让我们能够对纹理图像的每个子样本进行采样,所以我们可以创建我们自己的抗锯齿算法。在大型的图形应用中通常都会这么做。要想获取每个子样本的颜色值,你需要将纹理uniform采样器设置为sampler2DMS,而不是平常使用的sampler2D:使用texelFetch函数就能够获取每个子样本的颜色值了:// 第4个子样本我们不会深入探究自定义抗锯齿技术的细节,这里仅仅是给你一点启发。

hijackedbycsdn的博客 1241
上一篇: LearnOpenGL学习笔记——高级数据
下一篇: LearnOpenGL学习笔记——几何着色器
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值