深圳公司网站,wordpress女性主题,网页编辑面试知识,php 网站目录结构完整代码见#xff1a;zaizai77/Cherno-OpenGL: OpenGL 小白学习之路
高级GLSL
内建变量
顶点着色器
gl_PointSoze : float 输出变量#xff0c;用于控制渲染 GL_POINTS 型图元时#xff0c;点的大小。可用于粒子系统。将其设置为 gl_Position.z 时#xff0c;可以使点…完整代码见zaizai77/Cherno-OpenGL: OpenGL 小白学习之路
高级GLSL
内建变量
顶点着色器
gl_PointSoze : float 输出变量用于控制渲染 GL_POINTS 型图元时点的大小。可用于粒子系统。将其设置为 gl_Position.z 时可以使点的距离越远大小越大。创建出类似近视眼看远处灯光的效果 glEnable(GL_PROGRAM_POINT_SIZE); //也是需要开启 void main()
{gl_Position projection * view * model * vec4(aPos, 1.0); gl_PointSize gl_Position.z;
}
gl_vertexID: int 型输入变量只读存储了正在绘制顶点的ID当使用glDrawElements进行索引渲染的时候这个变量会存储正在绘制顶点的当前索引。当使用glDrawArrays不使用索引进行绘制的时候这个变量会储存从渲染调用开始的已处理顶点数量。
片段着色器
gl_FragCoord: vec4型输出变量。存储了屏幕空间坐标x,y 以窗口左下角为原点和图元深度值z0 - 1.常用来获取深度值。
我们已经使用glViewport设定了一个800x600的窗口了所以片段窗口空间坐标的x分量将在0到800之间y分量在0到600之间。
void main()
{ if(gl_FragCoord.x 400)FragColor vec4(1.0, 0.0, 0.0, 1.0);elseFragColor vec4(0.0, 1.0, 0.0, 1.0);
} gl_FrontFacing: bool 型输入变量。标记了当前图元是否为正面
#version 330 core
out vec4 FragColor;in vec2 TexCoords;uniform sampler2D frontTexture;
uniform sampler2D backTexture;void main()
{ if(gl_FrontFacing)FragColor texture(frontTexture, TexCoords);elseFragColor texture(backTexture, TexCoords);
}
给立方体里外使用不同的纹理 gl_FragDepth float 型输出变量。用于手动设置片段的深度值。在片段着色器中出现后Early-Z 将被禁用
gl_FragDepth 0.0; // 这个片段现在的深度值为 0.0
//如果着色器没有写入值到gl_FragDepth它会自动取用gl_FragCoord.z的值。
从OpenGL 4.2起我们仍可以对两者进行一定的调和在片段着色器的顶部使用深度条件(Depth Condition)重新声明gl_FragDepth变量 layout (depth_condition) out float gl_FragDepth; 这样子的话当深度值比片段的深度值要小的时候OpenGL仍是能够进行提前深度测试的。
接口块
但当程序变得更大时你希望发送的可能就不只是几个变量了它还可能包括数组和结构体。
接口块的声明和struct的声明有点相像不同的是现在根据它是一个输入还是输出块(Block)使用in或out关键字来定义的。
#version 330 core
layout (location 0) in vec3 aPos;
layout (location 1) in vec2 aTexCoords;uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;out VS_OUT
{vec2 TexCoords;
} vs_out;void main()
{gl_Position projection * view * model * vec4(aPos, 1.0); vs_out.TexCoords aTexCoords;
}
这次我们声明了一个叫做vs_out的接口块它打包了我们希望发送到下一个着色器中的所有输出变量
之后我们还需要在下一个着色器即片段着色器中定义一个输入接口块。
#version 330 core
out vec4 FragColor;in VS_OUT
{vec2 TexCoords;
} fs_in;uniform sampler2D texture;void main()
{ FragColor texture(texture, fs_in.TexCoords);
}
只要两个接口块的名字一样它们对应的输入和输出将会匹配起来。这是帮助你管理代码的又一个有用特性它在几何着色器这样穿插特定着色器阶段的场景下会很有用。
Uniform 缓冲对象
OpenGL为我们提供了一个叫做Uniform缓冲对象(Uniform Buffer Object)的工具它允许我们定义一系列在多个着色器程序中相同的全局Uniform变量。当使用Uniform缓冲对象的时候我们只需要设置相关的uniform一次。
因为Uniform缓冲对象仍是一个缓冲我们可以使用glGenBuffers来创建它将它绑定到GL_UNIFORM_BUFFER缓冲目标并将所有相关的uniform数据存入缓冲。在Uniform缓冲对象中储存数据是有一些规则的
#version 330 core
layout (location 0) in vec3 aPos;layout (std140) uniform Matrices
{mat4 projection;mat4 view;
};uniform mat4 model;void main()
{gl_Position projection * view * model * vec4(aPos, 1.0);
}
这里我们声明了一个叫做Matrices的Uniform块它储存了两个4x4矩阵。Uniform块中的变量可以直接访问不需要加块名作为前缀。
接下来我们在OpenGL代码中将这些矩阵值存入缓冲中每个声明了这个Uniform块的着色器都能够访问这些矩阵。
其中layout(std140) 指定了Uniform块布局。默认情况下Uniform块布局是Shared型这类布局的各变量偏移量会随设备和系统的不同而变化。但我们希望Uniform块中各变量的偏移量能被手工计算出以便让块内各变量能与UBO中各变量相对应。std140布局便是我们需要的。
在std140布局中每个变量都有一个基准对齐量Base Alignment它是一个变量在Uniform块中占据的空间。每个变量还有一个对齐偏移量Aligned Offset它是一个变量从块起始位置的偏移量它必须是Base Alignment的倍数。简而言之前者是size后者是offset。
Uniform 块布局
Uniform块的内容是储存在一个缓冲对象中的它实际上只是一块预留内存。因为这块内存并不会保存它具体保存的是什么类型的数据我们还需要告诉OpenGL内存的哪一部分对应着着色器中的哪一个uniform变量。
假设着色器中有以下的这个Uniform块
layout (std140) uniform ExampleBlock
{float value;vec3 vector;mat4 matrix;float values[3];bool boolean;int integer;
}; 4 字节是 1 N
layout (std140) uniform ExampleBlock
{// 基准对齐量 // 对齐偏移量float value; // 4 // 0 vec3 vector; // 16 // 16 (必须是16的倍数所以 4-16)mat4 matrix; // 16 // 32 (列 0)// 16 // 48 (列 1)// 16 // 64 (列 2)// 16 // 80 (列 3)float values[3]; // 16 // 96 (values[0])// 16 // 112 (values[1])// 16 // 128 (values[2])bool boolean; // 4 // 144int integer; // 4 // 148
};
使用 Uniform 缓冲
我们已经讨论了如何在着色器中定义Uniform块并设定它们的内存布局了但我们还没有讨论该如何使用它们。
首先我们需要调用glGenBuffers创建一个Uniform缓冲对象。一旦我们有了一个缓冲对象我们需要将它绑定到GL_UNIFORM_BUFFER目标并调用glBufferData分配足够的内存。
unsigned int uboExampleBlock;
glGenBuffers(1, uboExampleBlock);
glBindBuffer(GL_UNIFORM_BUFFER, uboExampleBlock);
glBufferData(GL_UNIFORM_BUFFER, 152, NULL, GL_STATIC_DRAW); // 分配152字节的内存
glBindBuffer(GL_UNIFORM_BUFFER, 0);
在OpenGL上下文中定义了一些绑定点(Binding Point)我们可以将一个Uniform缓冲链接至它。在创建Uniform缓冲之后我们将它绑定到其中一个绑定点上并将着色器中的Uniform块绑定到相同的绑定点把它们连接到一起。下面的这个图示展示了这个 我们可以绑定多个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);
//glBindBufferRange函数它需要一个附加的偏移量和大小参数
//这样子你可以绑定Uniform缓冲的特定一部分到绑定点中。
使用
//创建UBO
unsigned int UBO;
glGenBuffers(1,UBO);
glBindBuffer(GL_UNIFORM_BUFFER,UBO);
glBufferData(GL_UNIFORM_BUFFER,152,NULL,GL_STATIC_DRAW);
//获取Uniform块索引
unsigned int UBI glGetUniformBlockIndex(shader.ID,Matrices);
//绑定块索引至绑定点
glUniformBlockBinding(shader.ID,UBI,0);
//绑定UBO到绑定点
glBindBufferBase(GL_UNIFORM_BUFFER,0,UBO);
//传输数据
glBufferSubData(GL_UNIFORM_BUFFER,0,sizeof(glm::mat4),value_ptr(projection));
//解绑
glBindBuffer(GL_UNIFORM_BUFFER,0); 使用UBO的好处主要在于设置一个UBO改变所有绑定的着色器中的块提高着色器中允许存在的uniform数量。 //shader#version 330 core
layout (location 0) in vec3 aPos;layout (std140) uniform Matrices
{mat4 projection;mat4 view;
};
uniform mat4 model;void main()
{gl_Position projection * view * model * vec4(aPos, 1.0);
}//.cpp//首先我们将顶点着色器的Uniform块设置为绑定点0。注意我们需要对每个着色器都设置一遍。
unsigned int uniformBlockIndexRed glGetUniformBlockIndex(shaderRed.ID, Matrices);
unsigned int uniformBlockIndexGreen glGetUniformBlockIndex(shaderGreen.ID, Matrices);
unsigned int uniformBlockIndexBlue glGetUniformBlockIndex(shaderBlue.ID, Matrices);
unsigned int uniformBlockIndexYellow glGetUniformBlockIndex(shaderYellow.ID, Matrices); glUniformBlockBinding(shaderRed.ID, uniformBlockIndexRed, 0);
glUniformBlockBinding(shaderGreen.ID, uniformBlockIndexGreen, 0);
glUniformBlockBinding(shaderBlue.ID, uniformBlockIndexBlue, 0);
glUniformBlockBinding(shaderYellow.ID, uniformBlockIndexYellow, 0);//接下来我们创建Uniform缓冲对象本身并将其绑定到绑定点0
unsigned int uboMatrices
glGenBuffers(1, uboMatrices);glBindBuffer(GL_UNIFORM_BUFFER, uboMatrices);
glBufferData(GL_UNIFORM_BUFFER, 2 * sizeof(glm::mat4), NULL, GL_STATIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, 0);glBindBufferRange(GL_UNIFORM_BUFFER, 0, uboMatrices, 0, 2 * sizeof(glm::mat4));//填充数据
glm::mat4 projection glm::perspective(glm::radians(45.0f), (float)width/(float)height, 0.1f, 100.0f);
glBindBuffer(GL_UNIFORM_BUFFER, uboMatrices);
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(glm::mat4), glm::value_ptr(projection));
glBindBuffer(GL_UNIFORM_BUFFER, 0);glm::mat4 view camera.GetViewMatrix();
glBindBuffer(GL_UNIFORM_BUFFER, uboMatrices);
glBufferSubData(GL_UNIFORM_BUFFER, sizeof(glm::mat4), sizeof(glm::mat4), glm::value_ptr(view));
glBindBuffer(GL_UNIFORM_BUFFER, 0);//绘制
glBindVertexArray(cubeVAO);
shaderRed.use();
glm::mat4 model;
model glm::translate(model, glm::vec3(-0.75f, 0.75f, 0.0f)); // 移动到左上角
shaderRed.setMat4(model, model);
glDrawArrays(GL_TRIANGLES, 0, 36);
// ... 绘制绿色立方体
// ... 绘制蓝色立方体
// ... 绘制黄色立方体
几何着色器
几何着色器Geometry Shader位于顶点着色器和片段着色器之间它的输入是一个图元的一组顶点用于在将其发送到下一个着色器阶段前对其进行变换。几何着色器可以把一组顶点变化为不同的图元也可以生成更多的顶点。
例子
#version 330 core
//声明从顶点着色器传入的图元类型
//图元类型包括points(GL_POINTS)、lines(GL_LINES/GL_LINES_STRIP)、
//lines_adjacency(GL_LINES_ADJACENCY/GL_LINE_STRIP_ADJACENCY)、
//triangles(GL_TRIANGLES/GL_TRIANGLE_STRIP/GL_TRIANGLE_FAN)、
//triangless_adjacency(GL_TRIANGLES_ADJACENCY/GL_TRIANGLE_STRIP_ADJACENCY)
layout (points) in;
//声明输出的图元类型。可接受points、line_strip、triangle_strip
//同时需要声明输出的最大顶点数
layout (line_strip, max_vertices 2) out;void main() { //gl_in是一个内建接口块数组因为图元不止一个顶点
//其中包含gl_Position、gl_PointSize和gl_CLipDistance[]。//这里的gl_Position作为一个临时变量用于存储新顶点的位置。gl_Position gl_in[0].gl_Position vec4(-0.1, 0.0, 0.0, 0.0); //调用EmitVertex后,将在gl_Position所处的位置生成一个新顶点EmitVertex();gl_Position gl_in[0].gl_Position vec4( 0.1, 0.0, 0.0, 0.0);EmitVertex();//调用EndPrimitive后Emit的顶点将被合成为指定的图元。EndPrimitive();
}
为了生成更有意义的结果我们需要某种方式来获取前一着色器阶段的输出。GLSL提供给我们一个内建(Built-in)变量在内部看起来可能是这样的
in gl_Vertex
{vec4 gl_Position;float gl_PointSize;float gl_ClipDistance[];
} gl_in[];
它被声明为一个数组因为大多数的渲染图元包含多于1个的顶点而几何着色器的输入是一个图元的所有顶点。
有了之前顶点着色器阶段的顶点数据我们就可以使用2个几何着色器函数EmitVertex和EndPrimitive来生成新的数据了。几何着色器希望你能够生成并输出至少一个定义为输出的图元。在我们的例子中我们需要至少生成一个线条图元。
void main() {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();
}
每次我们调用EmitVertex时gl_Position中的向量会被添加到图元中来。当EndPrimitive被调用时所有发射出的(Emitted)顶点都会合成为指定的输出渲染图元。在一个或多个EmitVertex调用之后重复调用EndPrimitive能够生成多个图元。
在这个例子中我们发射了两个顶点它们从原始顶点位置平移了一段距离之后调用了EndPrimitive将这两个顶点合成为一个包含两个顶点的线条。 //本来的绘制函数 glDrawArrays(GL_POINTS, 0, 4); 使用几何着色器
创建几何着色器
geometryShader glCreateShader(GL_GEOMETRY_SHADER);
glShaderSource(geometryShader, 1, gShaderCode, NULL);
glCompileShader(geometryShader);
...
glAttachShader(program, geometryShader);
glLinkProgram(program);
利用点创造房子
通过使用三角形带作为几何着色器的输出我们可以很容易创建出需要的房子形状只需要以正确的顺序生成3个相连的三角形就行了。下面这幅图展示了顶点绘制的顺序蓝点代表的是输入点 几何着色器
#version 330 core
layout (points) in;
layout (triangle_strip, max_vertices 5) out;void build_house(vec4 position)
{ gl_Position position vec4(-0.2, -0.2, 0.0, 0.0); // 1:左下EmitVertex(); gl_Position position vec4( 0.2, -0.2, 0.0, 0.0); // 2:右下EmitVertex();gl_Position position vec4(-0.2, 0.2, 0.0, 0.0); // 3:左上EmitVertex();gl_Position position vec4( 0.2, 0.2, 0.0, 0.0); // 4:右上EmitVertex();gl_Position position vec4( 0.0, 0.4, 0.0, 0.0); // 5:顶部EmitVertex();EndPrimitive();
}void main() { build_house(gl_in[0].gl_Position);
}
这个几何着色器生成了5个顶点每个顶点都是原始点的位置加上一个偏移量来组成一个大的三角形带。最终的图元会被光栅化然后片段着色器会处理整个三角形带最终在每个绘制的点处生成一个绿色房子 还可以设置颜色
fColor gs_in[0].color;
gl_Position position vec4(-0.2, -0.2, 0.0, 0.0); // 1:左下
EmitVertex();
gl_Position position vec4( 0.2, -0.2, 0.0, 0.0); // 2:右下
EmitVertex();
gl_Position position vec4(-0.2, 0.2, 0.0, 0.0); // 3:左上
EmitVertex();
gl_Position position vec4( 0.2, 0.2, 0.0, 0.0); // 4:右上
EmitVertex();
gl_Position position vec4( 0.0, 0.4, 0.0, 0.0); // 5:顶部
fColor vec3(1.0, 1.0, 1.0);
EmitVertex();
EndPrimitive(); 爆破物体 参考高级GLSL - LearnOpenGL CN
LearnOpenGL学习笔记十 - 高级GLSL、几何着色器、实例化与抗锯齿 - Yois Home 文章转载自: http://www.morning.grynb.cn.gov.cn.grynb.cn http://www.morning.xhkgl.cn.gov.cn.xhkgl.cn http://www.morning.dnhdp.cn.gov.cn.dnhdp.cn http://www.morning.gmmyn.cn.gov.cn.gmmyn.cn http://www.morning.srnhk.cn.gov.cn.srnhk.cn http://www.morning.qbjrf.cn.gov.cn.qbjrf.cn http://www.morning.yhywx.cn.gov.cn.yhywx.cn http://www.morning.mqffm.cn.gov.cn.mqffm.cn http://www.morning.hxwrs.cn.gov.cn.hxwrs.cn http://www.morning.fdhwh.cn.gov.cn.fdhwh.cn http://www.morning.qyllw.cn.gov.cn.qyllw.cn http://www.morning.zzhqs.cn.gov.cn.zzhqs.cn http://www.morning.mbqyl.cn.gov.cn.mbqyl.cn http://www.morning.ymbqr.cn.gov.cn.ymbqr.cn http://www.morning.ydgzj.cn.gov.cn.ydgzj.cn http://www.morning.zfhwm.cn.gov.cn.zfhwm.cn http://www.morning.kvzvoew.cn.gov.cn.kvzvoew.cn http://www.morning.qbjrl.cn.gov.cn.qbjrl.cn http://www.morning.schwr.cn.gov.cn.schwr.cn http://www.morning.yhdqq.cn.gov.cn.yhdqq.cn http://www.morning.pltbd.cn.gov.cn.pltbd.cn http://www.morning.nypgb.cn.gov.cn.nypgb.cn http://www.morning.rzmkl.cn.gov.cn.rzmkl.cn http://www.morning.gwsdt.cn.gov.cn.gwsdt.cn http://www.morning.rgqnt.cn.gov.cn.rgqnt.cn http://www.morning.sggzr.cn.gov.cn.sggzr.cn http://www.morning.qznkn.cn.gov.cn.qznkn.cn http://www.morning.ffydh.cn.gov.cn.ffydh.cn http://www.morning.rzmzm.cn.gov.cn.rzmzm.cn http://www.morning.frpfk.cn.gov.cn.frpfk.cn http://www.morning.cbvlus.cn.gov.cn.cbvlus.cn http://www.morning.zczkm.cn.gov.cn.zczkm.cn http://www.morning.lxctl.cn.gov.cn.lxctl.cn http://www.morning.dskmq.cn.gov.cn.dskmq.cn http://www.morning.qpnmd.cn.gov.cn.qpnmd.cn http://www.morning.bndkf.cn.gov.cn.bndkf.cn http://www.morning.bqdgr.cn.gov.cn.bqdgr.cn http://www.morning.tpnx.cn.gov.cn.tpnx.cn http://www.morning.ptwzy.cn.gov.cn.ptwzy.cn http://www.morning.jyknk.cn.gov.cn.jyknk.cn http://www.morning.rttkl.cn.gov.cn.rttkl.cn http://www.morning.lwyqd.cn.gov.cn.lwyqd.cn http://www.morning.pszw.cn.gov.cn.pszw.cn http://www.morning.rjrz.cn.gov.cn.rjrz.cn http://www.morning.ycnqk.cn.gov.cn.ycnqk.cn http://www.morning.mmplj.cn.gov.cn.mmplj.cn http://www.morning.gcrlb.cn.gov.cn.gcrlb.cn http://www.morning.jllnh.cn.gov.cn.jllnh.cn http://www.morning.mqwdh.cn.gov.cn.mqwdh.cn http://www.morning.pslzp.cn.gov.cn.pslzp.cn http://www.morning.cwznh.cn.gov.cn.cwznh.cn http://www.morning.mwns.cn.gov.cn.mwns.cn http://www.morning.kpcjl.cn.gov.cn.kpcjl.cn http://www.morning.qflwp.cn.gov.cn.qflwp.cn http://www.morning.dzfwb.cn.gov.cn.dzfwb.cn http://www.morning.zztkt.cn.gov.cn.zztkt.cn http://www.morning.ygbq.cn.gov.cn.ygbq.cn http://www.morning.zmyhn.cn.gov.cn.zmyhn.cn http://www.morning.fycjx.cn.gov.cn.fycjx.cn http://www.morning.qynnw.cn.gov.cn.qynnw.cn http://www.morning.qwlml.cn.gov.cn.qwlml.cn http://www.morning.sbrxm.cn.gov.cn.sbrxm.cn http://www.morning.qkrz.cn.gov.cn.qkrz.cn http://www.morning.npxcc.cn.gov.cn.npxcc.cn http://www.morning.czlzn.cn.gov.cn.czlzn.cn http://www.morning.yqpzl.cn.gov.cn.yqpzl.cn http://www.morning.pctql.cn.gov.cn.pctql.cn http://www.morning.fwkjp.cn.gov.cn.fwkjp.cn http://www.morning.mfmrg.cn.gov.cn.mfmrg.cn http://www.morning.kxryg.cn.gov.cn.kxryg.cn http://www.morning.ywpwg.cn.gov.cn.ywpwg.cn http://www.morning.smry.cn.gov.cn.smry.cn http://www.morning.ttshf.cn.gov.cn.ttshf.cn http://www.morning.qdscb.cn.gov.cn.qdscb.cn http://www.morning.qfdyt.cn.gov.cn.qfdyt.cn http://www.morning.ywqsk.cn.gov.cn.ywqsk.cn http://www.morning.fkwp.cn.gov.cn.fkwp.cn http://www.morning.sooong.com.gov.cn.sooong.com http://www.morning.bmmyx.cn.gov.cn.bmmyx.cn http://www.morning.drwpn.cn.gov.cn.drwpn.cn