opengl ---几何着色器

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了opengl ---几何着色器相关的知识,希望对你有一定的参考价值。

参考技术A 这是我第一次写博客,格式和内容难免存在很多纰漏,忘指正

下面我将从以下纪录我所学到的

1.创建和使用几何着色器

2.使用//几个着色器创建额外的几何图元

3.使用集合着色器与transform feedback 共同生成多组几何数据流

4.在一个单独的渲染流程中渲染到多个视口

一.创建和使用几何着色器

1.创建

    几何着色器的创建和其他的着色器是完全相同的

a).GLuint glCreateShader (GLenu mtype);   mtype传 GL_GEOMETRY_SHADER 来创建

b).void glCompileShader (GLuint shader) shader 为glCreateShader 返回的shader的id, 使用此函数来编译着色器程序

c).void glAttachShader (GLuint program,GLuin tshader); 将shader 附着到program里面

几何着色器是Opengl的一个可选阶段,你的程序对象不一样非要包含这个阶段,它位于光栅化和片元着色器之前。当不需要几何着色器的时候,我们可以通过GLEnable 传入GL_RASTERIZER_DISCARD来关闭光栅化阶段,并且通过transform feedback 来获取顶点数据

2.输入和输出

几何着色器的输入来自于顶点着色器或如果开启了细分着色器则来自于细分着色器,几何着色器对于每个输入的图元,输入的数据以数组的形式出现,每一项是一个接口块的形式,隐式的定义为gl_in

in gl_Pervertex

vec4 gl_Position;      

float gl_PointSize;

float fl_ClipDistance[];



数组的长度由输入的图元类型决定并且由.length()方法获取。

支持的图元类型包括:

类型                            数组大小

points                         1

lines                            2

triangles                        3

lines_adjacency            4

triangles_adjacency            6

这里比较特别的事lines_adjacency 和 triangles_anjacency 这两种邻接图元类型,它们不能作为几何着色器的输出,后面会讲到。

我们也可以自定义接口块的数据结构,定义的方式如下:

out VS_GS_INTERFACE



    out vec4 position;

    out vec4 normal;

    out vec4 color;

    out vec2 tex_coord[4]

vs_out;

并且在几何着色器中作如下声明

in VS_GS_INTERFACE 



  out vec4 position;

    out vec4 normal;

    out vec4 color;

    out vec2 tex_coord[4];



接口块的匹配是通过块名称(这里是VS_GS_INTERFACE)来实现的。

特殊的输入:

    除了内置的gl_in[] 成员和用户自定义的输入之外,几何着色器还有gl_PrimitiveIDin和gl_InvocationID。

第一个等价于片元着色器中的gl_primitiveID,后缀用于区分是在几何着色器或者是片元着色器,若想偏远着色器的gl_primitiveID生效必须指定gl_primitiveIDIn。

第二个输入gl_InvocationID用于实现几何着色器的实例化。这一块还不清楚,后面的博客会提到。

特殊的几何着色器图元lines_adjacency  和 triangles_adjacency 这两种图元分别是4个和6个顶点,并且支持邻接信息——也就是有关邻接图元或者边界的信息传入几个着色器中。带有邻接信息的线可以通过glDrawArrays()等绘制命令中传入GL_LINES_ADJACENCY 或者 GL_LINES_STRIP_ADJACENCY图元模式来设置,如果没有几何着色器,这些图元也可以使用,但是它们会被解析成普通的线段或者三角形儿多余的顶点信息将会被抛弃。

lines_adjacency 图元作为几何着色器的输入,表示一个4顶点的图元形式,包含两种子类型

GL_LINES_ADJACENCY    

        1)    a ...>b--->c...>d        2) e...>f--->g...>h

    图元装配的时候每次总是4个顶点的数量,如上所示,第一次是a,b,c,d  实际上真正绘制的点是b和c用 --->表示,其他的点是提供邻接关系的点。

GL_LINES_STRIP_ADJACENCY

        2)    a ...>b--->c--->d---> e--->f--->g...>h

    这种类型第一次取a,b,c,d,下一次取b,c,d,e...依此类推

triangles_adjacency 作为图元输入时,每个图元由6个顶点组成,opengl 可以通过绘制命令传入GL_TRIANGLES_ADJACENCY和GL_TRIANGLES_STRIP_ADJACENCY来控制,为了说明怎么工作的盗两张图

GL_TRIANGLES_ADJACENCY图元类型第一个点由a-f6个点构成,第二个从g-l ,图中黄色三角形的三个顶点将保留,其余的二GL_LINES_ADJACENCY的类似也是邻接信息的点,输出的时候将被丢弃

GL_TRIANGLES_STRIP_ADJACENCY 图元类型理解费劲。

第一个图元由0-5个6个顶点构成,三角形顶点为0,2,4附加的信息是1,3,5

下一个图元通过后记的1个顶点加上之前的顶点构成,顶点为4,2,6,附加信息为0,5,8。

可以发现,第一个,奇数,偶数,和最后一个画的线是有相同规律的,通过划线很容易就知道那三个顶点是需要输出的,那几个提供邻接信息。

几何着色器的输出

几何着色器的输出将送入图元装配引擎,光栅化器,进而进入片元着色器,没有几何着色器输出则和顶点着色器相同,几何着色器的输出也是逐顶点输出的接口块定义。隐式定义如下:

out gl_PerVertext 



    vec4 gl_Position;

    float gl_PositionSIze;

    float gl_ClipDistance[];



用户可以自定义输出接口块的结构,并且它们会跟内置的接口块成员一块传递到片元着色器。因为每个几个着色器的请求都可以创建多个输出顶点,所以我们必须现实地通过EmitVertex() 函数来产生顶点,调用EmitVertex()之后多有的当前值都会被记录下来,就是这个当前数组的中的当前顶点。当调用完EmitVertex()之后,我们必须写出信息,哪怕输出和输入完全一致。

唯一例外的是flat关键字,此时唯有用于provoking vertex的顶点才会后继阶段,我们可以调用glProvokingVertex()并且设置所需的模式,默认的模式是GL_LAST_VERTEX_CONVENTION,即每个图元的最后一个顶点用作扁平的着色的插值。当然provoking vertex 不仅依赖于glProvokingVertex 也依赖于具体的图元类型。

我的理解:当在片元着色器需要插值的时候,GL_LAST_VERTEX_CONVENTION表示最后一个顶点的颜色用于多边形

除了内置和用户自定义的顶点输出之外,几何着色器还有三个特殊的内置变量类型,它们是gl_PrimitiveID、gl_Layer、gl_Viewportindex

gl_PrimitiveID用于片元着色器判断片元属于哪个图元,后面两个后面提到

3.产生图元

几何着色器的图元通过两个特殊的内置函数生成的,即EmitVertex()和EndPrimitive() ,每个着色器请求都必须调用EmitVertex(),以及必须必要的时候使用EndPrimitive()来产生图元,如果没有调用这些函数,那么就不会输出几何体,也就是剪裁的意思。如果多次调用那么就产生比输入更多的数据

1)、剪裁

    如上所说不调用EmitVertex和EndPrimitive就可以达到剪裁的目的,可以根据条件剪裁

2)、几何体的扩充

    产生的图元比输入的图元多叫做扩充,可以实现诸如毛发或者适度的细分等算法(当然最好使用固定的戏份硬件来实现细分的要求)

qt opengl的图形怎么刷新

参考技术A qglwidget 用updategl
qopenglwidget用update

以上是关于opengl ---几何着色器的主要内容,如果未能解决你的问题,请参考以下文章

glfw 包含了opengl吗

OpenGL ES 与 OpenGL [关闭]

qt opengl的图形怎么刷新

OpenGL是啥?

我的OpenGL学习进阶之旅OpenGL ES命令语法

我的OpenGL学习进阶之旅OpenGL ES命令语法