在片段着色器中获取顶点位置
Get vertex positions in fragment shader
出于某些原因,我需要在我的片段着色器中获取构成图元(三角形)的所有顶点的位置。
我可以通过三种方式做到这一点:附加属性、制服和通过几何着色器。
属性:
// vertex shader
in vec3 vPosition;
in vec3 vposA;
in vec3 vposB;
in vec3 vposC;
out vec3 posA;
out vec3 posB;
out vec3 posC;
void main() {
// ....
posA = vposA;
posB = vposB;
posC = vposC;
}
问题是我需要发送额外的属性,这意味着 VBO 中使用了额外的内存。
制服:
// fragment shader
uniform vec3 posA;
uniform vec3 posB;
uniform vec3 posC;
void main() {
// ...
}
主要缺点显然需要为正在绘制的每个三角形绑定制服,因此我每次绘制调用只能绘制一个三角形。
GS:
layout(triangles) in;
layout(triangle_strip, max_vertices = 3) out;
out vec3 posA;
out vec3 posB;
out vec3 posC;
void main()
{
posA = gl_in[0].gl_Position.xyz;
posB = gl_in[1].gl_Position.xyz;
posC = gl_in[2].gl_Position.xyz;
gl_Position = gl_in[0].gl_Position;
EmitVertex();
gl_Position = gl_in[1].gl_Position;
EmitVertex();
gl_Position = gl_in[2].gl_Position;
EmitVertex();
EndPrimitive();
}
有了 GS,我不需要在内存中存储任何东西,我可以绘制任意多的三角形,但问题是正在使用整个新的着色器阶段。
我也考虑过使用 flat
关键字,但这里不行。
问题是,还有其他选择吗?我可能会遗漏一些东西?
谢谢。
几何着色器是最实用的方法,但通常会排除 WebGL。
您可能会考虑从可编程顶点拉取页面,其中您的实际顶点数据存储在缓冲区纹理中,您使用索引来查找位置值。我无法评论性能,但这样做需要 显着 每个顶点的存储空间。
这是您最初基于属性的尝试的修改版本:
// vertex shader
in int vIdxA; // Index of vtx 0 in current triangle
in int vIdxB; // Index of vtx 1 in current triangle
in int vIdxC; // Index of vtx 2 in current triangle
out vec3 posA;
out vec3 posB;
out vec3 posC;
uniform samplerBuffer vtx_buf; // Actual vertex position array, as a buffer texture
void main() {
int vtx = gl_VertexID % 3;
// ....
posA = texelFetch (vtx_buf, vIdxA);
posB = texelFetch (vtx_buf, vIdxB);
posC = texelFetch (vtx_buf, vIdxC);
if (vtx == 0)
gl_Position = posA;
else if (vtx == 1)
gl_Position = posB;
else
gl_Position = posC;
}
实施时,这也将排除 WebGL,但与基于几何着色器的方法相比,将此方法应用于 OpenGL ES 应该更容易。
出于某些原因,我需要在我的片段着色器中获取构成图元(三角形)的所有顶点的位置。
我可以通过三种方式做到这一点:附加属性、制服和通过几何着色器。
属性:
// vertex shader
in vec3 vPosition;
in vec3 vposA;
in vec3 vposB;
in vec3 vposC;
out vec3 posA;
out vec3 posB;
out vec3 posC;
void main() {
// ....
posA = vposA;
posB = vposB;
posC = vposC;
}
问题是我需要发送额外的属性,这意味着 VBO 中使用了额外的内存。
制服:
// fragment shader
uniform vec3 posA;
uniform vec3 posB;
uniform vec3 posC;
void main() {
// ...
}
主要缺点显然需要为正在绘制的每个三角形绑定制服,因此我每次绘制调用只能绘制一个三角形。
GS:
layout(triangles) in;
layout(triangle_strip, max_vertices = 3) out;
out vec3 posA;
out vec3 posB;
out vec3 posC;
void main()
{
posA = gl_in[0].gl_Position.xyz;
posB = gl_in[1].gl_Position.xyz;
posC = gl_in[2].gl_Position.xyz;
gl_Position = gl_in[0].gl_Position;
EmitVertex();
gl_Position = gl_in[1].gl_Position;
EmitVertex();
gl_Position = gl_in[2].gl_Position;
EmitVertex();
EndPrimitive();
}
有了 GS,我不需要在内存中存储任何东西,我可以绘制任意多的三角形,但问题是正在使用整个新的着色器阶段。
我也考虑过使用 flat
关键字,但这里不行。
问题是,还有其他选择吗?我可能会遗漏一些东西?
谢谢。
几何着色器是最实用的方法,但通常会排除 WebGL。
您可能会考虑从可编程顶点拉取页面,其中您的实际顶点数据存储在缓冲区纹理中,您使用索引来查找位置值。我无法评论性能,但这样做需要 显着 每个顶点的存储空间。
这是您最初基于属性的尝试的修改版本:
// vertex shader
in int vIdxA; // Index of vtx 0 in current triangle
in int vIdxB; // Index of vtx 1 in current triangle
in int vIdxC; // Index of vtx 2 in current triangle
out vec3 posA;
out vec3 posB;
out vec3 posC;
uniform samplerBuffer vtx_buf; // Actual vertex position array, as a buffer texture
void main() {
int vtx = gl_VertexID % 3;
// ....
posA = texelFetch (vtx_buf, vIdxA);
posB = texelFetch (vtx_buf, vIdxB);
posC = texelFetch (vtx_buf, vIdxC);
if (vtx == 0)
gl_Position = posA;
else if (vtx == 1)
gl_Position = posB;
else
gl_Position = posC;
}
实施时,这也将排除 WebGL,但与基于几何着色器的方法相比,将此方法应用于 OpenGL ES 应该更容易。