1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > OpenGL超级宝典(第7版)笔记8 几何着色器 清单3.9

OpenGL超级宝典(第7版)笔记8 几何着色器 清单3.9

时间:2021-03-23 16:20:48

相关推荐

OpenGL超级宝典(第7版)笔记8 几何着色器 清单3.9

OpenGL超级宝典(第7版)笔记8 几何着色器 清单3.9

文章目录

OpenGL超级宝典(第7版)笔记8 几何着色器 清单3.9几何着色器总结

上一篇我们介绍了曲面细分的各个环节,包括细分曲面控制着色器TCS、细分曲面引擎、细分曲面评估着色器TES。这回我们将学习在光栅化之前最后一个可编程的着色器,结合着色器。并稍微说说基元装配、裁剪、光栅化有关的东西。

首先说说最简单的几何着色器编译:

geometry_shader = glCreateShader(GL_GEOMETRY_SHADER);glShaderSource(geometry_shader, 1, geometry_shader_source2, NULL);glCompileShader(geometry_shader);glGetShaderiv(geometry_shader, GL_COMPILE_STATUS, &shader_success);//检查编译是否成功if (!shader_success){glGetShaderInfoLog(geometry_shader, 512, NULL, infoLog);std::cout << "ERROR::SHADER::GEOMETRY_SHADER::COMPILATION_FAILED\n" << infoLog << std::endl;}

和之前的各种着色器没什么不同,就是注意GL_GEOMETRY_SHADER,还有别忘了在连接着色器程序前把这个着色器attach上(glAttachShader();)

几何着色器

几何着色器可以改变基元的模式,例如输入到几何着色器的是很多的小三角形,而输出可以是很多的顶点,还例如输入是很多的顶点,输出可以在每个顶点位置处生成很多的小三角形。几何着色器十分的灵活(它甚至能在细分着色器之后再对三角形进行细分,见后方我们的试验)

几何着色器的运行十分特殊,它对每个输入基元运行一次,在运行时可以访问该基元所有的顶点信息,且在一次运行中可以通过EmitVertex();进行多次的顶点输出(等下你就会见到),例如清单3.9

清单3.9 我们的第一个几何着色器

#version 450 corelayout (triangles) in;layout (points,max_vertices=3) out;void main(void){int i;for(i=0;i<gl_in.length();i++){gl_Position=gl_in[i].gl_Position;EmitVertex();}}

首先layout (triangles) in;这里指的是我们几何着色器输入的基元是三角形,也就是说每个三角形运行一次,通过gl_in[]来读取当前基元的顶点数据(还记得之前细分着色器的gl_in吗,跟那个也不是同一个价格数组哦)。比如这里for循环中就依次读取三角形的三个顶点位置,然后赋值给gl_Position。(你在这里先不要管为什么要重复地对一个变量赋值,后面会说道)

layout (points,max_vertices=3) out;这里是指我们几何着色器的输出基元是点,且每次运行一次几何着色器,输出的最大的数量是3(输出点的数量)。

在顶点着色器中每运行一次会对gl_Position进行一次赋值,这样OpenGL就知道了该次运行的顶点位置,而几何着色器中你会看到多次对gl_Position进行赋值,但是OpenGL怎么知道哪个是顶点的位置值呢。关键在于EmitVertex();的调用,这里的EmitVertex();就是在结果中生成一个新的顶点,因为在EmitVertex();调用之前对gl_Position进行了赋值,这样新的顶点中就储存了这个信息。这样不断的对gl_Position赋值然后调用EmitVertex();就可以在几何着色器的一次运行中产生很多的顶点。

整体看这个几何着色器,它的功能就是把每个小三角形的线去掉,只留下顶点。

注意在startup();函数中设置glPointSize();,让点的大小稍微大一些,否则这些顶点显示的很小,容易看不见。(这里设置为glPointSize(5.0f);)

下图分别为未启用几何着色器和启用着色器的结果

既然能把输入的小三角形变成很多的点(你可以试试生成更多的顶点,比如max_vertices=4或max_vertices=6等等),那我们能让一个小三角形变成更多的小三角形呢?

于是有了下面的几何着色器:

#version 450 corelayout (triangles) in;layout (triangle_strip,max_vertices=4) out;void main(void){int i;for(i=0;i<gl_in.length();i++){gl_Position=gl_in[i].gl_Position;EmitVertex();}gl_Position=(gl_in[0].gl_Position+gl_in[1].gl_Position+gl_in[2].gl_Position)*0.33333;EmitVertex();}

layout (triangles) in;仍然输入的是小三角形,跟之前是一样的。

layout (triangle_strip,max_vertices=4) out;这里就变了,生成的基元是三角形条(就是一串三角形)输出的顶点数最大是4。这里我们是想在三角形的中心再加一个顶点,让三角形一分为三(见下图,红色为新顶点,蓝色为相比没有几何着色器新生成的线)。

与之对应的是上面的EmitVertex();也被调用了4次,因为一共有四个顶点要输出嘛~

结果如下(上为未启用几何着色器的结果,下为启用几何着色器的结果)

诶,你可能会说了,这和我们想的不一样啊,怎么三角形只分出了一部分,之前的蓝线好像还少一条,而且如果你的顶点顺序不同还可能出现更多的情况,如下图:

还可能是:

当然如果你很幸运,也可能直接得到我们预想的结果:

什么?难不成我们的结果还有要看天意?当然并不是,问题来源于我们的输出基元(triangle_strip)的特点,这个基元意思是我们输出的是三角形条带,但是OpenGL到底是怎么通过生成(EmitVertex();)的顶点来绘制三角形条带呢?甚至到底什么是三角形条带呢?

比如我给出一串顶点(按照标号顺序先后给出),OpenGL会按照顶点的顺序先后取临近的三个顶点绘制一个三角形,比如这里的顺序是先画红色三角形,然后蓝色,黄色,绿色,紫色,以此类推。

所以我们在看一下之前的问题:因为我们输出的是max_vertices=4,所以三角形条带中只会有两个三角形,所以会形成下面三种错误的情况(我这里是示意图,具体可以对应之前的运行结果)

但是我们为什么有时候能得到正确的结果呢?答案在于那一边并不是该三角形条带的边,而是另外三角形条带的边,例如下图(红色为1号条带。蓝色为2号,黄色为3号…)

你仔细观察可以发现,虽然只画了两个三角形,但是配合上周围的三角形条带还是能做到我们预想的效果,当然我还提供了另一个更稳妥的方法,那就是传出5个顶点,我们每个条带绘制3个三角形:

#version 450 corelayout (triangles) in;layout (triangle_strip,max_vertices=5) out;void main(void){int i;for(i=0;i<gl_in.length();i++){gl_Position=gl_in[i].gl_Position;EmitVertex();}gl_Position=(gl_in[0].gl_Position+gl_in[1].gl_Position+gl_in[2].gl_Position)*0.33333;EmitVertex();gl_Position=gl_in[0].gl_Position;EmitVertex();}

其实就是把第一个顶点重新再生成一次,当然大家自己想想为什么就可以必定生成我们想要的结果,这里我就不解释了(其实已经很明显了)

这样我们就在几何着色器下实现了类似于细分着色器的功能(虽然可能没有细分着色器高效),如果你还想看看更多的示例可以浏览:OpenGL学习脚印:几何着色器(geometry shader) 写的很不错,简单易懂,循序渐进。

总结

这一次介绍了几何着色器,它能改变基元的类型,非常灵活,大家一定要弄懂,下一篇我们说说基元装配、裁剪、光栅化,这一篇没有清单,但是我们还是要重视,因为下一篇的内容对之后的三维图形运行结果有很大的影响,让我们能更好的理解OpenGL是怎样把众多顶点转为图形,再转为一个个像素的!

我们下篇见~~

关于书籍的问题

如果你手中没有该书,我还是建议你购买一本,毕竟书本毕竟更加严谨专业,我这里难免遗漏一些细节,主要是提供实例,并做一个消化,将很混乱的流程为大家理清,但这笔记一定是通俗的,是对新手友好的(当然有时候你需要在某些方面自己努努力,比如后面出现的基本线性代数的内容,还有C语言或是c++的基础知识,虽然我可能也不太懂O(∩_∩)O,慢慢来吧)。

别被吓住

刚开始的时候很容易被OpenGL的巨长的函数和超级复杂的流程吓到,其实并没有那么可怕,只要对这样或那样的流程熟悉之后,一切都变得相当简单(当然如果你能提出一个更好的流程那就更好了,当我们把很多基础的工作做完,我们会不断的提出新问题新点子,用新的技术来实现它,最终完成OpenGL的学习)

虽然我也不知道后面将是怎样的道路,但至少努力学习是没错的。

我看过的相关内容

以下并不是全看完了,大部分看了15%就看不下去了,实在是没看懂。(本人没什么计算机编程基础,算是野生程序员吧,很多内容都不能标准表述,望见谅)

如果你对opengl的工作有了一定的了解,我一开始也是从这里开始的,但是仍然有很多的不懂的,最后至今为止,我杂糅了很多的网站内容包括LearnOpenGL、极客学院、哔哩哔哩的闫令琪计算机图形学、哔哩哔哩的傅老师的OpenGL课程、OpenGL编程指南"也称为红宝书"、OpenGL超级宝典"也称为蓝宝书"、当然还有很多的csdn文章O(∩_∩)O这就不介绍了,等用到是时候我在放链接吧O(∩_∩)O

这里面图形学比较易懂也很基础推荐可以作为开始(如果你是学OpenGL需要马上用,应该可以跳过,但是其中的内容很是很重要,这会让后面涉及变换透视的章节更加易懂,推荐大家看看),之后是蓝宝书或是极客学院翻译的教程比较推荐,这两个还是比较适合你我这样的新手的。

这里不推荐看的是红宝书,这本书我看了有点类似于字典那样的工具书,不太适合新手上手学,而且讲的也并不是很通俗易懂(可能是我的书版本比较老吧…)

加油

当然如果你对我有信心,我也会持续更新(虽然前路漫漫),跟大家一同进步(虽然很可能没人看(╥╯^╰╥),无所谓了,当然如有错误还请大家指正∠(°ゝ°),哪里不懂我会尽力解决,哪里说的不好也可以指出我会及时修改~)

我们下篇见~~

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。