OpenGL学习-----高级OpenGL:几何着色器

目录

简述:

输入输出:

输入:

输出:

几何着色器的样例解析:

样例代码:

线段(Line Strip):

gl_in:

EmitVertex():

EndPrimitive():

实例尝试:

爆破物体:

简述:

获取法向量:

爆破:

当前完整的几何着色器代码:

法线可视化:

简述:

顶点着色器:

几何着色器:

像素着色器:

学习资料:


简述:

几何着色器在顶点着色器(以及曲面细分着色器)之后,专门处理场景里的几何图形,可以将创建或销毁几何图元,可以根据顶点的信息批量处理几何图形,对顶点附近的数据进行函数的处理,快速创造出新的多边形(Vertex Shader是专门处理多边形顶点的,而Geometry shader就是专门用来处理场景中的几何图形)

输入输出:

输入:

图元—顶点,边,三角形等

points:GL_POINTS (1)

lines:GL_LINES, GL_LINE_STRIP, GL_LINE_LIST (2)

lines_adjacency:GL_LINES_ADJACENCY, GL_LINE_STRIP_ADJACENCY (4)

triangles:GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN(3)

triangles_adjacency:GL_TRIANGLES_ADJACENCY, GL_TRIANGLE_STRIP_ADJACENCY (6)

输出:

图元(输出图元类型跟输入图元类型完全不同,而且输出图元的数量和输入图元数量也没有关系)

points

line_strip

triangle_strip

几何着色器的样例解析:

样例代码:

#version330 core

//表明输入的数据,并且类型是points

layout (points) in;

//表明输出的数据,并且类型是线段,允许的最大顶点数为2

layout (line_strip, max_vertices =2) out;

void main() {

//gl_in是一个包含了前一个阶段的输出的结构体

gl_Position = gl_in[0].gl_Position +vec4(-0.1, 0.0, 0.0, 0.0);

//生成(输出)一个顶点

EmitVertex();

gl_Position = gl_in[0].gl_Position +vec4( 0.1, 0.0, 0.0, 0.0);

EmitVertex();

//结束一个图元的输出

EndPrimitive();

}

线段(Line Strip):

线段连接了一组点,形成一条连续的线,它最少要由两个点来组成。

gl_in:

GLSL提供给我们一个内建(Built-in)变量,来获取前一着色器阶段的输出,在内部看起来(可能)是这样的:

要注意的是,gl_Position其实应该被声明为一个数组,因为大多数的渲染图元包含多于1个的顶点,而几何着色器的输入是一个图元的所有顶点。

EmitVertex():

生成(输出)一个顶点。每次我们调用EmitVertex时,gl_Position中的向量会被添加到图元中来。

EndPrimitive():

结束一个图元的输出。

当EndPrimitive被调用时,所有发射出的(Emitted)顶点都会合成为指定的输出渲染图元。在一个或多个EmitVertex调用之后重复调用EndPrimitive能够生成多个图元。

实例尝试:

爆破物体:

简述:

当我们说爆破一个物体时,我们并不是指要将宝贵的顶点集给炸掉,我们是要将每个三角形沿着法向量的方向移动一小段时间。效果就是,整个物体看起来像是沿着每个三角形的法线向量爆炸一样。

获取法向量:

vec3 GetNormal()

{

vec3 a =vec3(gl_in[0].gl_Position) -vec3(gl_in[1].gl_Position);

vec3 b =vec3(gl_in[2].gl_Position) -vec3(gl_in[1].gl_Position);

return normalize(cross(a, b));

}

爆破:

vec4 explode(vec4 position, vec3 normal)

{

float magnitude =2.0;

vec3 direction = normal * ((sin(time) +1.0) /2.0) * magnitude;

return position +vec4(direction, 0.0);

}

它使用法向量和顶点位置向量作为参数。这个函数会返回一个新的向量,它是位置向量沿着法线向量进行位移之后的结果

当前完整的几何着色器代码:

#version330 core





 

layout (triangles) in;

layout (triangle_strip, max_vertices =3) out;

in VS_OUT {

vec2 texCoords;

} gs_in[];

outvec2 TexCoords;

uniformfloat time;

vec4 explode(vec4 position, vec3 normal)

{

float magnitude =2.0;

vec3 direction = normal * ((sin(time) +1.0) /2.0) * magnitude;

return position +vec4(direction, 0.0);

}

vec3 GetNormal()

{

vec3 a =vec3(gl_in[0].gl_Position) -vec3(gl_in[1].gl_Position);

vec3 b =vec3(gl_in[2].gl_Position) -vec3(gl_in[1].gl_Position);

returnnormalize(cross(a, b));

}

void main() {

vec3 normal = GetNormal();

gl_Position = explode(gl_in[0].gl_Position, normal);

TexCoords = gs_in[0].texCoords;

EmitVertex();

gl_Position = explode(gl_in[1].gl_Position, normal);

TexCoords = gs_in[1].texCoords;

EmitVertex();

gl_Position = explode(gl_in[2].gl_Position, normal);

TexCoords = gs_in[2].texCoords;

EmitVertex();

EndPrimitive();

}

法线可视化:

简述:

我们首先不使用几何着色器正常绘制场景。然后再次绘制场景,但这次只显示通过几何着色器生成法向量。几何着色器接收一个三角形图元,并沿着法向量生成三条线——每个顶点一个法向量。伪代码看起来会像是这样:

顶点着色器:

为了使用导入模型的法线,我们在将法线变换到裁剪空间坐标之前,先使用法线矩阵变换一次(几何着色器接受的位置向量是剪裁空间坐标,所以我们应该将法向量变换到相同的空间中)

#version330 core



 

layout (location =0) invec3 aPos;

layout (location =1) invec3 aNormal;

out VS_OUT {

vec3 normal;

} vs_out;

uniformmat4 view;

uniformmat4 model;

void main()

{

mat3 normalMatrix =mat3(transpose(inverse(view * model)));

vs_out.normal =vec3(vec4(normalMatrix * aNormal, 0.0));

gl_Position = view * model *vec4(aPos, 1.0);

}

几何着色器:

这个很好理解,就在顶点处根据法线延长,得一个点,这样就能根据顶点和延长点画出一根线。

#version330 core





 

layout (triangles) in;

layout (line_strip, max_vertices =6) out;

in VS_OUT {

vec3 normal;

} gs_in[];

constfloat MAGNITUDE =0.002;

uniformmat4 projection;

void GenerateLine(int index)

{

gl_Position = projection * gl_in[index].gl_Position;

EmitVertex();

gl_Position = projection * (gl_in[index].gl_Position +vec4(gs_in[index].normal, 0.0) * MAGNITUDE);

EmitVertex();

EndPrimitive();

}

void main()

{

GenerateLine(0); // first vertex normal

GenerateLine(1); // second vertex normal

GenerateLine(2); // third vertex normal

}

像素着色器:

#version330 core


 

outvec4 FragColor;

void main()

{

FragColor =vec4(1.0, 1.0, 0.0, 1.0);

}

学习资料:

1.几何着色器 - LearnOpenGL CN

2.Shader入门---曲面细分着色器和几何着色器_m0_56399931的博客-CSDN博客_曲面细分着色器

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值