Tessellation Shader(细分曲面着色器)

2024-04-21 17:32

本文主要是介绍Tessellation Shader(细分曲面着色器),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Tessellation Shader)是OpenGLES4.0引入的,处于顶点着色器阶段的下一个阶段,它是由ATI在2001年率先设计出来的。

 

细分曲面着色器


直到这个阶段,对于操作几何图元而言,只有顶点着色器对我们可用。尽管使用顶点着色器可以使用不少图形技术,不过顶点着色器也确实存在一些限制。一个就是它们在执行过程中无法创建额外的几何图形。它们仅仅更新与它们当前所处理的顶点相关的数据。而且,它们甚至无法访问在当前图元中其它顶点的数据。

为了解决那些问题,OpenGL流水线含有几个其它着色器阶段来打破这些限制。我们这里所要介绍的细分曲面着色器可以使用一个新的几何图元类型,称为patch(斑点、碎片),来生成一个三角形网格。

细分曲面着色器在OpenGL流水线中增添了两个着色器阶段来生成一个几何图元的网格。比起在使用顶点着色器时不得不指定所有线与三角形来形成自己的模型,在使用细分曲面时,一开始指定一个patch,它是一列排好序的顶点。当一个patch被渲染时,细分曲面控制着色器先执行,对patch顶点进行操作,并指定从patch中应该生成多少几何图形。细分曲面控制着色器是可选的,我们后面会看到,如果不用它的话需要使用哪些条件。在细分曲面控制着色器完成之后,第二个着色器——细分曲面计算着色器使用细分曲面坐标来放置所生成的顶点,并且将它们发送到光栅化器,或发送到几何着色器做进一步处理。


细分曲面Patch


细分曲面过程并不对OpenGL典型的几何图元(点、线和三角形)进行操作,而是使用一个新的图元(在OpenGL 4.0版本中新增的),称为patch。patch由流水线中所有活动的着色阶段处理。相比起来,其它图元类型仅仅被顶点、片段和几何着色器处理,而旁通细分曲面阶段。实际上,如果有任一细分曲面着色器是活跃的,那么传递任何其它几何类型会产生一个GL_INVALID_OPERATION错误。相反地,如果企图渲染一个patch而没有任何细分曲面着色器(明确地说是一个细分曲面计算着色器;我们会看到细分曲面控制着色器是可选的),那么将也会得到一个GL_INVALID_OPERATION错误。

patch仅仅是传入到OpenGL的一列顶点列表,该列表在处理期间保存它们的次序。当用细分曲面与patch进行渲染时,使用像glDrawArrays()这样的渲染命令,并指定从绑定的顶点缓存对象(VBO)将被读出的顶点的总数,然后为该绘制调用进行处理。当用其它的OpenGL图元进行渲染时,OpenGL基于在绘制调用中所指定的图元类型而隐式地知道要使用多少顶点,比如使用三个顶点来绘制一个三角形。然后,当使用一个patch时,需要告诉OpenGL顶点数组中要使用多少个顶点来组成一个patch,而这可以通过使用glPatchParameteri()进行指定。由同一个绘制调用所处理的patch,它们的尺寸(即每个patch的顶点个数)将是相同的。

void glPatchParameteri(GLenum pname, GLint value);
/*** 使用value来指定一个patch中的顶点个数。pname必须设置为GL_PATCH_VERTICES。* 如果value小于零或大于GL_MAX_PATCH_VERTICES,将会产一个GL_INVALID_ENUM的错误。* 一个patch的默认顶点个数是三。如果一个patch的顶点个数小于参数value值,那么该patch将被忽略,从而不会有几何图形产生。
*/

要指定一个patch,使用类型GL_PATCHES输入到任一OpenGL绘制命令。以下代码描述了发射两个patch,每个patch含有四个顶点,然后通过glDrawArrays绘制命令进行渲染。

GLfloat vertices[][2] = {{-0.75f, -0.25f}, {-0.25f, -0.25f}, {-0.25f, 0.25f}, {-0.75f, 0.25f},{0.25f, -0.25f}, {0.75f, -0.25f}, {0.75f, -0.25f}, {0.75f, 0.25f}, {0.25f, 0.25f}
};glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(vPos, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
glPatchParameteri(GL_PATCH_VERTICES, 4);
glDrawArrays(GL_PATCHES, 0, 8);

每个patch的顶点首先由当前绑定的顶点着色器处理,然后用于初始化数组gl_in,这个变量在细分曲面控制着色器中被隐式地声明。gl_in中的元素个数与由glPatchParameteri()所指定的patch大小相同。在一个细分曲面着色器内部,变量gl_PatchVerticesIn提供了gl_in中的元素个数(就好比使用sizeof(gl_in) / sizeof(gl_in[0])进行查询)。


细分曲面控制着色器


一旦应用发射了一个patch,细分曲面控制着色器就会被调用(如果有所绑定的话)并且负责完成以下行动:

a.生成细分曲面输出patch顶点,传递到细分曲面计算着色器,以及更新任一每个顶点的,或每个patch的属性值,若有必要的话。

 b.指定细分曲面程度因子,控制图元生成器的操作。这些是特殊的细分曲面控制着色器变量,称为gl_TessLevelInner和gl_TessLevelOuter,并在细分曲面控制着色器中隐式声明。

我们将依次讨论这些行动的每一个。


生成输出patch顶点


细分曲面控制器使用由应用所指定的顶点——这些顶点我们称为输入patch顶点(作为顶点着色器的输出)——来生成一组新的顶点,这些新的顶点为输出patch顶点。它们存放在细分曲面控制着色器的gl_out数组中。细分曲面控制着色器在产出输出patch顶点时,可以修改传递自应用的值(比如顶点属性),也可以创建或移除来自输入patch顶点中的顶点。

使用一个layout构造在细分曲面控制着色器中指定输出patch顶点的个数。下面语句描述了设置输出patch顶点的个数为16。

layout (vertices = 16) out;

layout指示符中的vertices参数所设置的值做了两件事情:它设置了输出patch顶点gl_out的大小;并且指定了细分曲面控制着色器将被执行多少次:对每个输出patch顶点执行一次。

为了确定正在处理哪个输出顶点,细分曲面控制着色器可以使用gl_InvocationID变量。该变量最经常被用作为gl_out数组的一个索引。当一个细分曲面控制着色器在执行时,它具有对所有patch顶点数据的访问,包括输入顶点和输出顶点。这可能会导致发射一次着色器调用,该调用需要使用来自另一个着色器调用的数据值,但是那个着色器调用尚未发生。细分曲面控制着色器可以使用GLSL的barrier()函数,该函数使得对于一个输入patch的所有控制着色器执行并等待所有这些着色器的执行到达那个函数的调用点,从而确保了可能要设置的所有数据值将被计算。

细分曲面控制着色器的一个普遍的习惯用法仅仅是将输入patch顶点输出到此着色器的外面。下面的例子描述了带有四个顶点的一个输出patch。

#version 410 corelayout (vertices = 4) out;void main(void)
{gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;// 下面设置细分曲面程度
}


细分曲面控制着色器变量


gl_in数组实际上是一个结构体的数组,每个元素被定义为:

in gl_PerVertex {vec4 gl_Position;float gl_PointSize;float gl_ClipDistance[];}gl_in[gl_PatchVerticesIn];

并且对于每个需要向下一个阶段传递的值(比如,向下传递到细分曲面计算着色器),需要进行相应地赋值。如上述代码片段所述,传递了gl_Position变量。

gl_out数组具有相同的结构体成员,不过数组大小与gl_in不同,它是由gl_PatchVerticesOut来指定的。而这个值则是在细分曲面控制器中的out这一layout限定符中设置。此外,以下标量值用于确定正在被着色的图元和输出顶点:

gl_InvocationID:当前细分曲面着色器的输出顶点的调用索引

gl_PrimitiveID:当前输入patch的图元索引

gl_PatchVerticesIn:输入patch中的顶点个数,它作为gl_in数组变量中的元素个数

gl_PatchVerticesOut:输出patch中的顶点个数,它作为gl_out数组变量中的元素个数

如果我们需要额外的基于每个顶点的属性值,或为输入或为输出,那么这需要在我们的细分曲面控制着色器中将它们声明为in或out数组。一个输入数组的大小需要与输入patch大小相同,或者可以被声明为缺省大小的,这样OpenGL将会为其所有值适当地分配空间。类似地,每个顶点的输出属性需要与输出patch中的顶点个数相一致,也可以为输出属性声明为缺省大小的。输出属性值将会被传递到细分曲面计算着色器,作为其输入属性值。

比如:

#version 410 corelayout (vertices = 4) out;in vec4 vertexCoeffs1[4];    // 我们假定指定一个输入patch含有4个顶点
in vec4 vertexCoeffs2[];     // 这里使用缺省大小的数组变量,OpenGL将会自动为其分配大小out vec2 vertexTexCoord1[4];    // 这里需要用上面out的layout (vertices)值一致
out vec2 vertexTexCoord2[];     // 这里使用缺省大小的数组变量,OpenGL将会自动为其分配大小void main(void)
{// Do something here
}

上面给出的是基于逐个顶点的属性值,它们可以用gl_InvocationID作为索引,不过要注意的是,gl_InvocationID标识的是当前细分曲面着色器的输出顶点的调用索引。我们可以使用patch限定符来声明每个patch的输出变量。每个patch的变量不是以数组方式定义而是以普通单实例变量的方式来定义。当然,我们也可以将它们定义为数组。所有细分曲面控制着色器的调用看到的都是同一个patch变量。比如:

#version 410 corepatch out vec4 data;layout (vertices = 4) out;void main(void)
{// Do something heredata = vec4(1.0, 0.0, 0.0, 1.0);
}

这里,我们定义了一个标识符为data的patch输出变量。对于每次细分曲面控制着色器的调用,data的值都被写为vec4(1.0, 0.0, 0.0, 1.0)。因此,任一细分曲面控制着色器可以写基于每个patch的输出变量;实际上,所有细分曲面控制着色器的调用一般都将写到一个基于每个patch的变量。只要它们都写相同的值,那么一切都是良好的。


控制细分曲面


一个细分曲面控制着色器的另一个功能是指定对输出patch细分多少。然而我们还没详细地讨论细分曲面计算着色器,它们控制用于渲染的输出patch的类型,结果也就是细分曲面所发生的域。OpenGL支持三种细分曲面域:四边形,三角形,和等值线集合。这些通过细分曲面计算着色器中的in的layout进行指定。

细分曲面的数量通过指定两组值:内部和外部细分曲面程度来控制的。外部细分曲面的值控制域的周边是如何划分的,然后存放在一个隐式声明的名为gl_TessLevelOuter的含有四个元素的数组中。而内部细分曲面程度指定了域的内部如何进行划分,然后存放在一个名为gl_TessLevelInner的含有两个元素的数组中。所有细分曲面程度因子是浮点值,并且我们将会看到浮点值在细分曲面上以一个比特的效果。最后一点是,尽管隐式声明的细分曲面程度因子数组的维度是固定的,不过从那些数组所使用的值的个数依赖于细分曲面域的类型。下面来看看这两个OpenGL内建的细分曲面输出patch变量的声明:

patch out float gl_TessLevelOuter[4];
patch out float gl_TessLevelInner[2];

理解外部与内部细分曲面程度如何操作是让细分曲面做我们想要做的事情的关键。每个细分曲面程度因子指定了对一个区域划分多少条“线段”,以及生成多少细分曲面坐标与几何图元。这种划分如何完成根据不同域类型而有所不同。我们将依次讨论域的每种类型。


四边形细分曲面


使用四边形域可能是最直观的,因此我们先介绍这种类型。当输入patch形状为矩形时,这很有用,当我们可能使用二维的样条曲面时,比如Bézier曲面。四边形域使用所有内部和外部细分曲面程度来划分单位正方形。比如,如果我们用以下代码来设置细分曲面程度因子,那么OpenGL将会把四边形域细分为如下图所示的样子。

#version 410 corelayout (vertices = 4) out;void main(void)
{gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;// 下面设置细分曲面程度gl_TessLevelInner[0] = 3.0;     // 内部划分3条垂直区域,即内部新增2列顶点gl_TessLevelInner[1] = 4.0;     // 内部划分4条水平区域,即内部新增3行顶点gl_TessLevelOuter[0] = 2.0;     // 左边2条线段gl_TessLevelOuter[1] = 3.0;     // 下边3条线段gl_TessLevelOuter[2] = 4.0;     // 右边4条线段gl_TessLevelOuter[3] = 5.0;     // 上边5条线段
}

下图为上述细分曲面控制着色器可能会得到的几何图形样子。

          

 

上图中,三条黄色线条表示三条垂直区域;四条绿色线条表示四条水平区域。

注意,外部细分曲面程度值对应于围绕周边的每条边的线段个数,而内部细分曲面程度指定了域的内部空间中水平与垂直方向上有多少个“区域”。使用虚线则是将整个域用三角形进行划分。域的三角形划分是依赖于实现的。实心圆点表示细分曲面坐标,每个坐标都会提供给细分曲面计算着色器,作为其输入。在四边形域的情况下,细分曲面坐标有两个坐标值(u, v),两者值的范围都在[0, 1]范围内,并且每个细分曲面坐标将传递到细分曲面计算着色器中,作为它的一次调用。


等值线细分曲面


类似于四边形域,等值线域也生成(u, v)对作为给细分曲面计算着色器的细分曲面坐标。然而,等值线仅仅使用外部细分曲面程度的两个元素值来判定划分量(这里没有用到内部细分曲面程度)。

下面是设置等值线域的细分曲面程度:

gl_TessLevelOuter[0] = 6;      // 6条等值线
gl_TessLevelOuter[1] = 8;      // 每条等值线被划分为8条线段

下图为可能的结果图形:

 

 

旁通细分曲面控制着色器


正如我们所提到过的,细分曲面着色器往往只是一个直通着色器,将数据从输入直接到输出。在这种情况下,我们实际上可以使一个细分曲面着色器进行旁通,仅仅使用主机端OpenGL API来设置细分曲面程度因子。使用glPatchParameterfv()函数来设置内部与外部细分曲面程度。

void glPatchParameterfv(GLenum pname, const GLfloat *values);/*** 当没有细分曲面控制着色器时,设置内部与外部细分曲面程度。* 参数pname要么是GL_PATCH_DEFAULT_OUTER_LEVEL,要么是GL_PATCH_DEFAULT_INNER_LEVEL。* 当pname是GL_PATCH_DEFAULT_OUTER_LEVEL时,参数values必须是含有四个单精度浮点值的数组,指定四个外部细分曲面程度。* 类似地,当pname是GL_PATCH_DEFAULT_INNER_LEVEL时,values必须是含有两个单精度浮点值的数组,指定两个内部细分曲面程度。
*/


细分曲面图元生成


图元生成是一个固定功能阶段,负责从输入patch来创建一组新的图元。此阶段仅当一个细分曲面计算着色器在当前程序或程序流水线中活动时才会执行。图元生成受以下因素影响:

�9�9 细分曲面程度

�9�9 被细分的顶点的空间划分,这个由细分曲面计算着色器阶段进行定义。它可以是equal_spacing、fractional_even_spacing或fractional_odd_spacing。

�9�9 由后续细分曲面着色器所定义的图元类型,即triangles、quads或isolines。细分曲面计算着色器也可以迫使细分曲面的生成作为一系列的点,而不是三角形或线。这个可以通过point_mode来指定。

�9�9 由后续细分曲面计算着色器所定义的图元生成次序,比如cw(顺时针)或ccw(逆时针)。


抽象patch


注意,图元生成不受细分曲面控制着色器中用户定义的输出影响(或当没有细分曲面控制着色器时,也不受顶点着色器的影响),不受细分曲面控制着色器的输出patch大小影响,也不受任一每个patch的细分曲面控制着色器输出的影响,而只受细分曲面程度的影响。细分曲面阶段的图元生成部分完全对实际的顶点坐标与其它patch数据是不可见的。

图元生成系统的目的是确定要生成多少个顶点,用哪个次序来生成它们,以及用哪种图元来构造它们。实际为这些顶点的每个顶点的数据,诸如位置、颜色等等,是通过细分曲面计算着色器来生成的,基于图元生成器所提供的信息。

因为这种对分,图元生成器对可以被认为是一个“抽象patch”的东东进行操作。它并不从细分曲面控制器的输出来看patch;它仅考虑一个抽象四边形、三角形或等值线块的细分曲面。

依赖于抽象patch类型,图元生成器计算不同数量的细分曲面程度并应用不同的细分曲面算法。每个所生成的顶点在一个抽象patch内具有一个规格化的位置(即,坐标范围在[0, 1]之内)。这个位置具有两个或三个分量,依赖于patch的类型。这些坐标通过内建的

in vec3 gl_TessCoord;

输入提供给细分曲面计算着色器。


细分曲面计算着色器


OpenGL细分曲面流水线的最后一个阶段就是细分曲面计算着色器执行。绑定的细分曲面计算着色器对图元生成器发射的每个细分曲面坐标逐个执行,并负责确定从细分曲面坐标所得到的顶点的位置。我们将看到,细分曲面计算着色器看上去与顶点着色器类似,将顶点变换到屏幕位置(除非细分曲面着色器的数据将被进一步由几何着色器来处理)。

配置一个细分曲面计算着色器的第一步是配置图元生成器,这通过使用一个layout指示符来完成。其参数指定了细分曲面域与后续所生成的图元的类型;实体图元的面部朝向(用于做面剔除);以及在图元生成期间如何应用细分曲面程度。


指定图元生成域


我们现在将描述细分曲面计算着色器的in这个layout的参数。首先,我们先谈论指定细分曲面域。我们之前已经提及过,一共有三种类型的域来生成细分曲面坐标:

�9�9 quads——单位正方形中的一个矩形域;域坐标:带有范围在[0, 1]内的u, v值的一个个坐标对(u, v)。

�9�9 triangles——使用重心坐标的一个三角形域;域坐标:带有范围在[0, 1]内的a、b、c三个值的坐标(a, b, c),这里a+b+c=1。

�9�9 isolines——跨单位正方形的一组线;域坐标:u值范围在[0, 1],v值范围在[0, 1)范围的(u, v)坐标对。


指定生成图元的面部朝向


与OpenGL中任何填充的图元一样,所发射的顶点的次序决定了图元的脸部朝向。由于我们在这种情况下不直接发射顶点,而只是让图元生成器为我们来做,不过我们需要告诉图元生成器我们图元的右手旋转方向。在layout指示符中,指定cw为顺时针旋转,ccw为逆时针。


指定细分曲面坐标的空间


此外,我们可以控制外部细分曲面程度的浮点值如何用在确定周边的细分曲面坐标生成上。(内部细分曲面程度受这些选项影响。)

�9�9 equal_spacing——细分曲面程度被裁减到[1, max]范围内,然后取整到下一个最大整数值。

�9�9 fractional_even_spacing——值被裁减到[2, max]范围内,然后取整到下一个最大偶整数值n。边然后被划分为n-2条等长部分,以及两个剩余部分,每个在一端,剩余部分长度可能比其它长度要短。

�9�9 fractional_odd_spacing——值被裁减到[1, max-1]范围内,然后取整到下一个最大奇整数值n。边然后被划分为n-2条等长部分,以及两个剩余部分,每个在一端,剩余部分长度可能比其它长度要短。


额外的细分曲面计算着色器layout选项


最后,如果我们想输出点,而不是等值线或填充区域的话,我们可以应用point_mode选项。该选项将为每个由细分曲面计算着色器所处理的顶点渲染一单个点。

在layout指示符内的选项的次序不重要。下面例子描述的是一个生成三角形域的图元,使用相等空间,逆时针方向的三角形,但只渲染点,而不是互联的图元。

layout (triangles, equal_spacing, ccw, point_mode) in;


指定一个顶点的位置


从细分曲面控制着色器输出的顶点(即,在gl_out数组中的gl_Position的值)在计算着色器中的gl_in变量中可用。当它们与细分曲面坐标相结合时,可以用于生成输出顶点的位置。

细分曲面坐标在变量gl_TessCoord中提供给计算着色器。在下面例子中我们使用相等空间划分的四边形来渲染一个简单的patch。在这个例子中,细分曲面坐标用于对表面进行上色,然后此例子也描述了如何计算顶点坐标。我们这里要注意的是,gl_in中的gl_Position相当于原始的patch每个顶点的坐标,而gl_TessCoord则是经过细分曲面之后的新增细分曲面顶点,这些顶点的坐标值是被规格化在[0, 1]范围内的。我们通过以原patch的顶点坐标与当前处理的细分曲面顶点坐标做相应的插值计算来获得此细分曲面顶点最后输出的坐标值。我们在细分曲面计算着色器中可以访问所有gl_in数组的元素,即每次调用可以访问当前patch所有输入的顶点坐标。

#version 410 corelayout (quads, equal_spacing, ccw) in;out vec4 color;void main(void)
{float u = gl_TessCoord.x;float omu = 1 - u;    // omu为1减去"u"float v = gl_TessCoord.y;float omv = 1 - v;    // omv为1减去"v"color = gl_TessCoord; // color最后给到片段着色器时,值为(gl_TessCoord.x, gl_TessCoord.y, 0.0, 1.0)gl_Position = omu * omv * gl_in[0].gl_Position +u * omv * gl_in[1].gl_Position +u * v * gl_in[2].gl_Position +omu * v * gl_in[3].gl_Position;
}


细分曲面计算着色器变量


与细分曲面控制着色器类似,细分曲面计算着色器也有gl_in数组,它是一个结构体数组,每个元素如下定义:

in gl_PerVertex {vec4 gl_Position;float gl_PointSize;float gl_ClipDistance[];
} gl_in[gl_PatchVerticesIn];

输出顶点的数据被存放在一个接口块中,如下定义:

out gl_PerVertex {vec4 gl_Position;float gl_PointSize;float gl_ClipDistance[];
};

这篇关于Tessellation Shader(细分曲面着色器)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/923650

相关文章

OpenGL——着色器画一个点

一、 绘制 在窗口中间画一个像素点: #include <GL/glew.h>#include <GLFW/glfw3.h>#include <iostream>using namespace std;#define numVAOs 1GLuint renderingProgram;GLuint vao[numVAOs];GLuintcreateShaderProgram (){c

Unity3D Shader详解:只画顶点或只画线框

在Unity3D开发中,Shader是控制渲染过程的关键组件,它允许开发者自定义物体的渲染方式。有时,为了特定的视觉效果,我们可能需要只渲染模型的顶点或者只显示其线框。下面,我们将详细探讨这两种效果的技术实现,并给出相应的代码示例。 对惹,这里有一个游戏开发交流小组,大家可以点击进来一起交流一下开发经验呀! 只画顶点 在Unity中直接“只画顶点”的概念可能不是非常直观,因为顶点本身只是模型

学习使用RenderDoc查看着色器代码

0. 准备 首先,我想要一个相对简单的程序来学习。因此,我选择了 DX11官方范例(包含在DirectX11官方SDK中)里的【Tutorial 07: Texture Mapping and Constant 】 需要安装工程,编译出exe,然后将着色器文件(Tutorial07.fx)和贴图文件(seafloor.dds)放到exe的同级目录。随后应该可以打开exe: 1. 截一帧

glsl着色器学习(九)屏幕像素空间和设置颜色

在上一篇文章中,使用的是裁剪空间进行绘制,这篇文章使用屏幕像素空间的坐标进行绘制。 上一篇的顶点着色器大概是这样子的 回归一下顶点着色的主要任务:  通常情况下,顶点着色器会进行一系列的矩阵变换操作,将输入的顶点坐标从模型空间依次经过世界空间,视图空间,最终转换到裁剪空间。 将顶点着色器改成下面这样: <script id="vertex-shader-2d" type="x-sh

unity shader实现一个移动的箭头

Shader "Unlit/LT_Arrow" {     Properties     {         _MainTex ("Texture", 2D) = "white" {}         _MSpeed("MoveSpeed", Range(1, 3)) = 2 //移动速度     }     SubShader     {         //贴图带透明通道 ,半透明效果设置如下

glsl着色器学习(十)缩放

对二维图形进行缩放,需要用到顶点着色器,顶点着色器经过矩阵变换,会将模型空间最终转换成裁剪空间。下面就来操作矩阵 这里需要用到一个库glMatrix。 首先修改顶点着色器 <script id="vertex-shader-2d" type="x-shader/x-vertex">attribute vec4 a_position;uniform mat4 u_matrix;void m

nurbs曲面和贝塞尔曲面的区别是什么

NURBS曲面和贝塞尔曲面的主要区别如下:   定义与理论基础:   NURBS曲面:全称非均匀有理B样条曲面,是NURBS曲线在二维空间上的扩展。它结合了非均匀性、有理性和B样条的特性,能够更灵活地表示复杂曲面。 贝塞尔曲面:通过Bernstein基函数的张量积为加权系数对控制顶点进行线性组合所构造的参数曲面。它具有良好的连续性和插值性质。   控制点的灵活性与局部性:   N

glsl着色器学习(六点五)顶点和片元的处理顺序

在WebGL中,顶点和片元的处理顺序遵循着图形渲染管线的流程。 顶点处理阶段 顶点处理阶段是图形渲染管线的起点,在这一阶段,所有与顶点相关的操作都会被执行。 顶点着色器(Vertex Shader) 顶点着色器接收每个顶点的数据,例如顶点坐标,法线,纹理坐标等。将顶点数据上传到图形硬件的缓冲区。在顶点着色器中,对这些顶点数据进行变换和运算,例如将顶点从模型空间转换到世界空间、视图空间和

Shader学习笔记

1. 渲染管线概述 定义:渲染管线(流水线)就是将数据分阶段的变为屏幕图像的过程 数据就是我们在游戏场景中放置的模型、光源、摄像机等等内容的数据 阶段就是渲染管线中的三个阶段:应用阶段一>几何阶段一>光栅化阶段 通过这三个阶段对数据的处理,最终我们就能够在屏幕上看见最终的图像 2. 应用阶段 应用阶段的大部分内容都和渲染无关(游戏逻辑处理、动画更新、物理模拟)几何阶段和光栅化阶段将开始处理

我如何选择自己的AI细分方向和第一个入门项目

思维导图 下图展示了我的思考和分析过程 目录 思维导图大纲1. **确定兴趣和技能方向**2. **寻找合适的开源项目**3. **评估项目的活跃度**4. **开始贡献**5. **展示你的贡献**6. **推荐开源项目**总结 选择一个细分领域1. **了解各个领域的基本概念**2. **考虑你的兴趣和背景**3. **评估市场需求**4. **尝试小项目和实践**5. *