跳转到主要内容

Vulkan Shader——几何着色器之法线可视化

demi 提交于

<font size="3" style="line-height: 45px;" color="#c200ff"><strong>几何着色器</strong></font>

我们大部分情况下仅使用顶点着色器(vertex shader)和片元着色器(fragment shader),而实际上vulkan还提供了一个可选的几何着色器(geometry shader)。几何着色器位于顶点和片元着色器之间,如果没有使用时,则顶点着色器输出到片元着色器,在使用几何着色器后,顶点着色器输出组成一个基础图元的顶点信息到几何着色器,经过几何着色器处理后,再输出到片元着色器。几何着色器能够产生0个以上的基础图元(primitive),它能起到一定的裁剪作用、同时也能产生比顶点着色器输入更多的基础图元。

<font size="3" style="line-height: 45px;" color="#c200ff"><strong>法线可视化</strong></font>

首先简述一下我们需要实现的简单效果,在原始模型的基础上我们来实现法线可视化:
1.原始加载模型代码不变;
2.新增一个管线来绘制法线;
3.shader部分新增一个顶点、几何、片元着色器来处理法线;

创建管线等基础部分就不在累述,如果想看具体实现,见最后源码。

那么我来主要说一下新增的shader部分,首先来看片元着色器:

<pre>#version 450
#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shading_language_420pack : enable

layout (location = 0) in vec3 inColor;
layout (location = 0) out vec4 outFragColor;

void main(void){
outFragColor = vec4(inColor, 1.0);
}
</pre>

最简单的片元着色器,无需多说。接下来我们看的是顶点着色器,显然 也无需多说,依旧很简单:
#version 450
<pre>#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shading_language_420pack : enable

layout (location = 0) in vec3 inPos;
layout (location = 1) in vec3 inNormal;

layout (location = 0) out vec3 outNormal;

out gl_PerVertex{
vec4 gl_Position;
};

void main(void){
outNormal = inNormal;
gl_Position = vec4(inPos.xyz, 1.0);
}
</pre>

那么接下来中点来了,我们在以上两个阶段之间添加一个集合着色器normaldebug.geom:
<pre>#version 450

#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shading_language_420pack : enable

layout (triangles) in;
layout (line_strip, max_vertices = 6) out;

layout (binding = 1) uniform UBO
{
mat4 projection;
mat4 model;
} ubo;

layout (location = 0) in vec3 inNormal[];

layout (location = 0) out vec3 outColor;

void main(void)
{
float normalLength = 10;
for(int i=0; i&lt;gl_in.length(); i++)
{
vec3 pos = gl_in[i].gl_Position.xyz;
vec3 normal = inNormal[i].xyz;

gl_Position = ubo.projection * (ubo.model * vec4(pos, 1.0));
outColor = vec3(0.0, 1.0, 0.0);
EmitVertex();

gl_Position = ubo.projection * (ubo.model * vec4(pos + normal * normalLength, 1.0));
outColor = vec3(0.0, 1.0, 1.0);
EmitVertex();

EndPrimitive();
}
}
</pre>

<strong>layout (*) in;输入可以有如下:</strong>

<ul><li>points:绘制GL_POINTS图元时</li>
<lilines:绘制GL_LINES或GL_LINE_STRIP时</li>
<lilines_adjacency:GL_LINES_ADJACENCY或GL_LINE_STRIP_ADJACENCY</li>
<litriangles:GL_TRIANGLES、GL_TRIANGLE_STRIP或GL_TRIANGLE_FAN 即绘制三角面片时使用</li>
<litriangles_adjacency:GL_TRIANGLES_ADJACENCY或GL_TRIANGLE_STRIP_ADJACENCY</li></ul>

<strong>layout (*) out输出如下:</strong>

<ul><li>points 输出的图元是点</li>
<li>line_strip 输出的图元是线</li>
<li>triangle_strip 输出的图元是三角形</li>
<li>max_vertices 代表输出的最大顶点数量,超过这个数量,shader将不再绘制多出的顶点。</li></ul>

注:EmitVertex表示输出一个顶点,而EndPrimitive表示结束一个图元的输出,这是一对命令。只有几何着色器才有的命令。不明白的可以Google其用法

上述shader主要作用是在法线起点和延法线延长normalLength出新增两个点,并对其设置颜色。

运行,可看到如下效果:

<center><img width="600" src="http://imgtec.eetrend.com/files/2021-11/%E5%8D%9A%E5%AE%A2/100555705-22…; alt=""></center><br>

此外几何着色器还有更多效果,有时间我们再来试一下爆炸或者腐蚀消散等效果吧。

<strong>附:main源码</strong>
<iframe src="http://imgtec.eetrend.com/files/2021-11/%E5%8D%9A%E5%AE%A2/100555705-22…; width="100%" height="480"></iframe>

<font color="#9a9a9a">版权声明:本文为CSDN博主 </font><a href="https://blog.csdn.net/qq_35312463"><u>沉默的舞台剧</u></a&gt; <font color="#9a9a9a">原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。</font>
<font color="#9a9a9a">原文链接:</font><a href="https://blog.csdn.net/qq_35312463/article/details/104889100"><font color="#9a9a9a">https://blog.csdn.net/qq_35312463/article/details/104889100</font></a&gt;