OpenGL 4.4变换反馈布局说明符

OpenGL 4.4 transform feedback layout specifier

本文关键字:布局 说明符 变换 OpenGL      更新时间:2023-10-16

我在使用OpenGL 4.4版本的转换反馈缓冲区时遇到了问题。

我使用几何着色器输出捕获和绘制三角形。

三角形将被几何着色器中的一些算法剔除,我想捕获生成的三角形。

所以结果三角形计数应该小于输入计数。

当我指定in-shader布局说明符(xfb_buffer等)时,没有捕获原语。

我把它改回gltransformfeedbackvardings,现在原语正在被捕获,但不是每个三角形3个顶点(9个浮点数)它捕获较少,因为结果缓冲区的大小不能被3整除

初始化:

// ---------------
// VERTEX BUFFER
// ---------------
glGenBuffers(1, &vertexBufferObjectId_);
// Init vertex data
unsigned int numVerts = width * height;
size_t vertexSize = (3 + 2) * sizeof(GLfloat); // position, texcoord
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObjectId_);
glBufferData(GL_ARRAY_BUFFER, numVerts * vertexSize, 0, GL_STATIC_DRAW);
uint8_t* vertices = (uint8_t*)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
for (unsigned int y = 0; y < height; ++y)
{
    for (unsigned int x = 0; x < width; ++x)
    {
        *(float*)(vertices+0) = x; // x
        *(float*)(vertices+4) = y; // y
        *(float*)(vertices+8) = 0; // z
        *(float*)(vertices+12) = (float)x / (width - 1);  // u
        *(float*)(vertices+16) = (float)y / (height - 1); // v
        vertices += vertexSize;
    }
}
glUnmapBuffer(GL_ARRAY_BUFFER);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// ---------------
// INDEX BUFFER
// ---------------
glGenBuffers(1, &indexBufferObjectId_);
glEnable(GL_PRIMITIVE_RESTART);
glPrimitiveRestartIndex(-1); // accepts GLuint, so this will be the largest possible value
// Init index data
unsigned int numPolys = 2 * (width - 1) * (height - 1) * 2;
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferObjectId_);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, numPolys * 3 * sizeof(GLuint), 0, GL_STATIC_DRAW);
GLuint* indices = (GLuint*)glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY);
for (unsigned int y = 0; y < height-1; ++y)
{
    for (unsigned int x = 0; x < width-1; ++x)
    {
        // i11 is at (x,y)
        //         i20
        //     i11 i21 i31
        // i02 i12 i22
        //     i13
        uint32_t i20 = get_index(width,height,x+1,y-1);
        uint32_t i11 = get_index(width,height,x,y);
        uint32_t i21 = get_index(width,height,x+1,y);
        uint32_t i31 = get_index(width,height,x+2,y);
        uint32_t i02 = get_index(width,height,x-1,y+1);
        uint32_t i12 = get_index(width,height,x,y+1);
        uint32_t i22 = get_index(width,height,x+1,y+1);
        uint32_t i13 = get_index(width,height,x,y+2);
        // first triangle: i12,i22,i21
        //         i21
        //     i12 i22
        // with adjacency: i12,i13,i22,i31,i21,i11
        //     i11 i21 i31
        //     i12 i22
        //     i13
        *(indices++) = i12;
        *(indices++) = i13;
        *(indices++) = i22;
        *(indices++) = i31;
        *(indices++) = i21;
        *(indices++) = i11;
        // second triangle: i12,i21,i11
        //     i11 i21
        //     i12
        // with adjacency: i12,i22,i21,i20,i11,i02
        //         i20
        //     i11 i21
        // i02 i12 i22
        *(indices++) = i12;
        *(indices++) = i22;
        *(indices++) = i21;
        *(indices++) = i20;
        *(indices++) = i11;
        *(indices++) = i02;
    }
}
glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
// ---------------
// TRANSFORM FEEDBACK BUFFER
// ---------------
if (feedbackVertexBufferObjectId_)
    glDeleteBuffers(1, &feedbackVertexBufferObjectId_);
glGenBuffers(1, &feedbackVertexBufferObjectId_);
glBindBuffer(GL_ARRAY_BUFFER, feedbackVertexBufferObjectId_);
glBufferData(GL_ARRAY_BUFFER, numPolys * 3 * 3 * sizeof(GLfloat), 0, GL_STREAM_READ);

呈现:

meshRenderShader_.enable();
// Set to write to the framebuffer.
glBindFramebuffer(GL_FRAMEBUFFER, camData.framebuffer_.framebufferId_);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// ----------------------------------
// Render projected mesh
// Binding vertex buffer
size_t vertexSize = (3 + 2) * sizeof(GLfloat);
glBindBuffer(GL_ARRAY_BUFFER, camData.mesh_.vertexBufferObjectId_);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, vertexSize, (const GLvoid*)0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, vertexSize, (const GLvoid*)(sizeof(GLfloat) * 3));
// Binding index buffer
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, camData.mesh_.indexBufferObjectId_);
// Bind transform feedback and target buffer
glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, camData.mesh_.feedbackVertexBufferObjectId_);
GLuint query;
glGenQueries(1, &query);
//      glEnable(GL_RASTERIZER_DISCARD);
// Begin transform feedback
glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, query);
glBeginTransformFeedback(GL_TRIANGLES);
// Set shader uniforms
meshRenderShader_.setUniformMat4("ModelViewProjection", (viewProjMatrix * camData.transform_).data());
// Binding texture
meshRenderShader_.setUniformTexture("colorTexture", camData.mesh_.textureId_, 0);
meshRenderShader_.setUniformTexture("depthTexture", camData.mesh_.depthTextureId_, 1);
meshRenderShader_.setUniform2f("depthSize", camData.intrinsic_.width, camData.intrinsic_.height);
meshRenderShader_.setUniform2f("intrinsic_f", camData.intrinsic_.fx, camData.intrinsic_.fy);
meshRenderShader_.setUniform2f("intrinsic_c", camData.intrinsic_.cx, camData.intrinsic_.cy);
// Drawing elements to textures
glDrawElements(GL_TRIANGLES_ADJACENCY, camData.mesh_.numPolys_ * 3, GL_UNSIGNED_INT, (const GLvoid*) 0);
// End transform feedback
glEndTransformFeedback();
glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
//      glDisable(GL_RASTERIZER_DISCARD);
//      glFlush();

glGetQueryObjectuiv(query, GL_QUERY_RESULT, &camData.mesh_.primitivesWritten_);
//      glDrawTransformFeedback(GL_TRIANGLES_ADJACENCY, camData.mesh_.feedbackbufferId_);
glDeleteQueries(1, &query);
// Unbinding buffers
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindFramebuffer(GL_FRAMEBUFFER,0);
// Disable shader
meshRenderShader_.disable();

GLSL几何着色器的相关部分:

layout(xfb_buffer = 0) out vec3 xPosition;
    
if (cull)
{
    gl_Position = ModelViewProjection * gl_in[0].gl_Position;
    fTexCoord = gTexCoord[0];
    xPosition = gl_Position.xyz;
    EmitVertex();
    gl_Position = ModelViewProjection * gl_in[2].gl_Position;
    fTexCoord = gTexCoord[2];
    xPosition = gl_Position.xyz;
    EmitVertex();
    gl_Position = ModelViewProjection * gl_in[4].gl_Position;
    fTexCoord = gTexCoord[4];
    xPosition = gl_Position.xyz;
    EmitVertex();
    EndPrimitive();
}

解决方案是什么?

当您指定转换反馈限定符时,xfb_buffer需要伴随xfb_offset。来自OpenGL Wiki:

变量可以不使用xfb_offset而将xfb_buffer赋值给它们。

简而言之,将您的着色器更改为以下内容应该可以避免调用glTransformFeedbackVaryings():

layout(xfb_buffer = 0, xfb_offset = 0) out vec3 xPosition;