OpenGL:如何将顶点位置从几何着色器传递到片段着色器?
OpenGL: how to pass vertex pos from Geometry shader to fragment shader?
我目前正在学习 OpenGL 中的着色器,并完成了我的“drawText”几何着色器的编写,因此我可以绘制动态文本(每帧内容都会更改),而无需每帧重新创建 VBO。
它运行良好,但限制为 28 个字符,因为 GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 限制等于 1024。
ATM 每个顶点有 6 个组件发出 vec4 pos 和 vec2 texCoord。
这给我 1024/6 = 170 个顶点用于我的三角形带。
我需要每个字符 6 个顶点(而不是第一个和最后一个字符)来显示每个字符的四边形和 2 个顶点以移动到具有退化三角形的下一个字符。
这给了我 170/6 = 28 个字符。
所以当我有一个长文本时,我将它分成 28 个字符的文本。
所以现在我尝试优化它并让我的几何着色器绘制超过 28 个字符。
所以因为我在 2D 中,所以我试图找到一种方法将 texCoord 存储在片段着色器的 pos.zw 中。并在我的几何着色器中删除 out vec2 texCoord。这将使我每个顶点仅发出 4 个组件,这将使我达到 42 个字符。
但是在阅读片段着色器文档和片段系统输入时,我不知道该由谁执行此操作。
那么,有什么办法可以实现吗?
我的代码供参考
顶点着色器
#version 330 core
layout (location = 0) in vec2 aPos;
uniform vec2 textPosition;
void main()
{
gl_Position = vec4(aPos ,0, 1) + vec4(textPosition, 0, 0);
}
片段着色器
#version 330 core
out vec4 fragColor;
in vec2 texCoord;
uniform vec4 textColor;
uniform sampler2D outTexture;
void main()
{
fragColor = texture(outTexture, texCoord) * textColor;
}
几何着色器
#version 330 core
layout (points) in;
layout (triangle_strip, max_vertices = 170) out;
// max components and vertices are 1024
// vec4 pos and vec2 text coord per vertex, that 6 components per vertex, 1024 / 6 = 170
out vec2 texCoord;
uniform float screenRatio = 1;
uniform float fontRatio = 1;
uniform float fontInterval = 0; // distance between letters
uniform float fontSize = 0.025f; // default value, screen coord range is -1f , 1f
uniform int textString[8]; // limited to 28 chars . 170 vertices / 6 = 28, 28 / 4 = 7 ints.
void main()
{
vec4 position = gl_in[0].gl_Position;
float fsx = fontSize * fontRatio * screenRatio;
float fsy = fontSize;
float tsy = 1.0f / 16.0f; // fixed in a 16x16 chars bitmap
float tsx = tsy;
float tw = tsx * fontRatio;
float to = ( tsx - tw ) * 0.5f;
vec4 ptl = position + vec4(0,0,0,0); // top left
vec4 ptr = position + vec4(fsx,0,0,0); // top right
vec4 pbl = position + vec4(0,fsy,0,0); // bottom left
vec4 pbr = position + vec4(fsx,fsy,0,0); // bottom right
vec2 tt; // tex coord top
vec2 tb; // tex coord bottom
fsx += fontInterval;
int i = 0; // index in int array
int si = 0; // sub index in int
int ti = textString[0];
int ch = 0;
do
{
// unpack a char, 4 chars per int
ch = (ti >> si) & (0xFF);
// string ends with [=12=] or end of array
if ( ch == 0 || i >= 8)
break;
// compute row and col of char in bitmaps 16x16 chars
int r = ch >> 4;
int c = ch - ( r << 4 );
// compute tex coord from row and column
tb = vec2(c * tsx + to, 1.0f - r * tsy);
tt = vec2(tb.x , tb.y - tsy);
texCoord = tt;
gl_Position = ptl;
EmitVertex();
EmitVertex();
texCoord = tb;
gl_Position = pbl;
EmitVertex();
tt.x += tw;
tb.x += tw;
texCoord = tt;
gl_Position = ptr;
EmitVertex();
texCoord = tb;
gl_Position = pbr;
EmitVertex();
EmitVertex();
// advance of 1 char
ptl.x += fsx;
ptr.x += fsx;
pbl.x += fsx;
pbr.x += fsx;
si += 8;
if ( si >= 32 )
{
si = 0;
++i;
ti = textString[i];
}
}
while ( true );
EndPrimitive();
}
要发送到光栅器的顶点位置,如通过 gl_Position
定义的,包含 4 个分量。总是。而这些组件的含义由光栅器和 OpenGL 渲染系统定义。
您无法绕过或绕过它。输出位置有 4 个分量,您不能在其中隐藏纹理坐标或其他任意数据。
如果您需要从 GS 输出更多内容,那么您需要更有效地使用 GS 的顶点输出。按照目前的情况,您在每个四边形之间输出退化条带。这意味着对于每 6 个顶点,只有 4 个是有意义的。您正在使用退化条带拆分四边形。
而不是这样做,你应该使用 EndPrimitive
来分割你的四边形。这将删除所有顶点输出的 1/3,从而为您提供更多组件以供实际使用。
我目前正在学习 OpenGL 中的着色器,并完成了我的“drawText”几何着色器的编写,因此我可以绘制动态文本(每帧内容都会更改),而无需每帧重新创建 VBO。
它运行良好,但限制为 28 个字符,因为 GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 限制等于 1024。
ATM 每个顶点有 6 个组件发出 vec4 pos 和 vec2 texCoord。 这给我 1024/6 = 170 个顶点用于我的三角形带。
我需要每个字符 6 个顶点(而不是第一个和最后一个字符)来显示每个字符的四边形和 2 个顶点以移动到具有退化三角形的下一个字符。 这给了我 170/6 = 28 个字符。
所以当我有一个长文本时,我将它分成 28 个字符的文本。
所以现在我尝试优化它并让我的几何着色器绘制超过 28 个字符。 所以因为我在 2D 中,所以我试图找到一种方法将 texCoord 存储在片段着色器的 pos.zw 中。并在我的几何着色器中删除 out vec2 texCoord。这将使我每个顶点仅发出 4 个组件,这将使我达到 42 个字符。
但是在阅读片段着色器文档和片段系统输入时,我不知道该由谁执行此操作。 那么,有什么办法可以实现吗?
我的代码供参考
顶点着色器
#version 330 core
layout (location = 0) in vec2 aPos;
uniform vec2 textPosition;
void main()
{
gl_Position = vec4(aPos ,0, 1) + vec4(textPosition, 0, 0);
}
片段着色器
#version 330 core
out vec4 fragColor;
in vec2 texCoord;
uniform vec4 textColor;
uniform sampler2D outTexture;
void main()
{
fragColor = texture(outTexture, texCoord) * textColor;
}
几何着色器
#version 330 core
layout (points) in;
layout (triangle_strip, max_vertices = 170) out;
// max components and vertices are 1024
// vec4 pos and vec2 text coord per vertex, that 6 components per vertex, 1024 / 6 = 170
out vec2 texCoord;
uniform float screenRatio = 1;
uniform float fontRatio = 1;
uniform float fontInterval = 0; // distance between letters
uniform float fontSize = 0.025f; // default value, screen coord range is -1f , 1f
uniform int textString[8]; // limited to 28 chars . 170 vertices / 6 = 28, 28 / 4 = 7 ints.
void main()
{
vec4 position = gl_in[0].gl_Position;
float fsx = fontSize * fontRatio * screenRatio;
float fsy = fontSize;
float tsy = 1.0f / 16.0f; // fixed in a 16x16 chars bitmap
float tsx = tsy;
float tw = tsx * fontRatio;
float to = ( tsx - tw ) * 0.5f;
vec4 ptl = position + vec4(0,0,0,0); // top left
vec4 ptr = position + vec4(fsx,0,0,0); // top right
vec4 pbl = position + vec4(0,fsy,0,0); // bottom left
vec4 pbr = position + vec4(fsx,fsy,0,0); // bottom right
vec2 tt; // tex coord top
vec2 tb; // tex coord bottom
fsx += fontInterval;
int i = 0; // index in int array
int si = 0; // sub index in int
int ti = textString[0];
int ch = 0;
do
{
// unpack a char, 4 chars per int
ch = (ti >> si) & (0xFF);
// string ends with [=12=] or end of array
if ( ch == 0 || i >= 8)
break;
// compute row and col of char in bitmaps 16x16 chars
int r = ch >> 4;
int c = ch - ( r << 4 );
// compute tex coord from row and column
tb = vec2(c * tsx + to, 1.0f - r * tsy);
tt = vec2(tb.x , tb.y - tsy);
texCoord = tt;
gl_Position = ptl;
EmitVertex();
EmitVertex();
texCoord = tb;
gl_Position = pbl;
EmitVertex();
tt.x += tw;
tb.x += tw;
texCoord = tt;
gl_Position = ptr;
EmitVertex();
texCoord = tb;
gl_Position = pbr;
EmitVertex();
EmitVertex();
// advance of 1 char
ptl.x += fsx;
ptr.x += fsx;
pbl.x += fsx;
pbr.x += fsx;
si += 8;
if ( si >= 32 )
{
si = 0;
++i;
ti = textString[i];
}
}
while ( true );
EndPrimitive();
}
要发送到光栅器的顶点位置,如通过 gl_Position
定义的,包含 4 个分量。总是。而这些组件的含义由光栅器和 OpenGL 渲染系统定义。
您无法绕过或绕过它。输出位置有 4 个分量,您不能在其中隐藏纹理坐标或其他任意数据。
如果您需要从 GS 输出更多内容,那么您需要更有效地使用 GS 的顶点输出。按照目前的情况,您在每个四边形之间输出退化条带。这意味着对于每 6 个顶点,只有 4 个是有意义的。您正在使用退化条带拆分四边形。
而不是这样做,你应该使用 EndPrimitive
来分割你的四边形。这将删除所有顶点输出的 1/3,从而为您提供更多组件以供实际使用。