openGL 概念学习(二)

lutianfei 发表于 2022/05/30 21:33:14 2022/05/30
【摘要】 一、高级数据处理 1.1 定点数据拷贝(glBufferSubData)必须在绑定Buffer之后才能使用,从内存中将数据拷贝至指定的显存。使用问题: 多次修改数据会造成性能浪费,因为每次都要从内存将数据拷贝至显存。 1.2 虚拟指针(glMapBuffer)必须在VBO构造并且分配空间完毕后使用其优点在于拷贝了整个显存数据到达内存,修改完毕后再全部同步回显存,适合一个Pass中对数据进行...

一、高级数据处理

1.1 定点数据拷贝(glBufferSubData)

必须在绑定Buffer之后才能使用,从内存中将数据拷贝至指定的显存。

image.png

使用问题: 多次修改数据会造成性能浪费,因为每次都要从内存将数据拷贝至显存。

1.2 虚拟指针(glMapBuffer)

必须在VBO构造并且分配空间完毕后使用
其优点在于拷贝了整个显存数据到达内存,修改完毕后再全部同步回显存,适合一个Pass中对数据进行多阶段修改的场景中使用。
image.png

二、全局数据块(Uniform Buffer Object)

在编写shader的时候,会发现有很多数据比如VP矩阵是几乎每个shader都可以用到的,但还是需要每次都给各个shader设置,因此引出了Uniform Buffer Object来进行不同shader之间的数据共享,即UBO。

Binding point(绑定点)

在创建Uniform缓冲之后,我们将它绑定到其中一个绑定点上,并将着色器中的Uniform块绑定到相同的绑定点,把它们连接到一起。
image.png

如上图所示,可以绑定多个Uniform缓冲到不同的绑定点上。因为着色器A和着色器B都有一个链接到绑定点0的Uniform块,它们的Uniform块将会共享相同的uniform数据,uboMatrices,前提条件是两个着色器都定义了相同的Matrices Uniform块。

为了将Uniform块绑定到一个特定的绑定点中,需要调用glUniformBlockBinding函数,它的第一个参数是一个程序对象,之后是一个Uniform块索引和链接到的绑定点。Uniform块索引(Uniform Block Index)是着色器中已定义Uniform块的位置值索引。这可以通过调用glGetUniformBlockIndex来获取,它接受一个程序对象和Uniform块的名称。我们可以用以下方式将图示中的Lights Uniform块链接到绑定点2

unsigned int lights_index = glGetUniformBlockIndex(shaderA.ID, "Lights");
glUniformBlockBinding(shaderA.ID, lights_index, 2);

注意:这里需要对每个着色器重复这一步骤。

接下来,我们还需要绑定Uniform缓冲对象到相同的绑定点上,这可以使用glBindBufferBase或glBindBufferRange来完成。

glBindBufferBase(GL_UNIFORM_BUFFER, 2, uboExampleBlock); 
// 或
glBindBufferRange(GL_UNIFORM_BUFFER, 2, uboExampleBlock, 0, 152);

三、几何着色器

3.1 几何输入方式

点输入方式
图元装配部分不用做任何工作直接将顶点传递给对应的GeometryShader
image.png

三角形输入方式
每三个顶点构成一个三角形通过gl_in[]将顶点数组送入GeometryShader
image.png

3.2 几何输出方式

可以输出points, lines, triangles
image.png

#version 330 core
layout (points) in;
layout (line_strip, max_vertices = 2) out;

void main() {    
    gl_Position = gl_in[0].gl_Position + vec4(-0.1, 0.0, 0.0, 0.0); 
    EmitVertex(); //gl_Position中的向量会被添加到图元中来

    gl_Position = gl_in[0].gl_Position + vec4( 0.1, 0.0, 0.0, 0.0);
    EmitVertex(); 所有发射出的(Emitted)顶点都会合成为指定的输出渲染图元。

    EndPrimitive();
}

3.3 法向量可视化

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

shader.use();
DrawScene();
normalDisplayShader.use();
DrawScene();

为了适配(观察和模型矩阵的)缩放和旋转,我们在将法线变换到裁剪空间坐标之前,先使用法线矩阵变换一次。

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;

out VS_OUT {
    vec3 normal;
} vs_out;

uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;

void main()
{
    gl_Position = projection * view * model * vec4(aPos, 1.0); 
    mat3 normalMatrix = mat3(transpose(inverse(view * model)));
    vs_out.normal = normalize(vec3(projection * vec4(normalMatrix * aNormal, 0.0)));
}

关于法线矩阵为何是由MV求逆转置而来的说明:https://blog.csdn.net/Qinhaifu/article/details/102476692

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请发送邮件至:cloudbbs@huaweicloud.com;如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。