OpenGL 4.3或4.5转换反馈不起作用

时间:2016-10-18 16:13:52

标签: opengl transform-feedback

有两个调试printf段。第一个打印出正确的数据,但第二个不打印。我哪里做错了? 哦,我使用相同的顶点和片段着色器来获取顶点数据并再次绘制它们。

#include "Dependencies\glew\glew.h"
#include "Dependencies\freeglut\freeglut.h"
#include <cstdio>

GLuint program;
GLuint VAOs[2];
GLuint VBOs[2];
GLuint TFBs[1];

char *vertSrc =
"#version 450 core\n"
"in vec4 vPosition;"
"in vec4 vColor;"
"out vec4 fColor;"
"uniform mat4 vMatrix;"
"void main(void)"
"{"
"gl_Position = vMatrix * vPosition;"
"fColor = vColor;"
"}";

char *fragSrc =
"#version 450 core\n"
"in vec4 fColor;"
"out vec4 color;"
"void main(void)"
"{"
"color = vec4(1.0, 0, 0, 1.0);"
"}";

GLfloat vPosition[6][4] = {
    { 0.25, -0.25, -0.7, 1.0 },
    { -0.25, -0.25, -0.7, 1.0 },
    { 0.25, 0.25, -0.7, 1.0 },
    { 0.1, -0.1, -0.8, 1.0 },
    { -0.1, -0.1, -0.8, 1.0 },
    { 0.1, 0.1, -0.8, 1.0 }
};

GLfloat vColor[6][4] = {
    { 1.0, 0, 0, 1.0 },
    { 0, 1.0, 0, 1.0 },
    { 0, 0, 1.0, 1.0 },
    { 1.0, 1.0, 0, 1.0 },
    { 0, 1.0, 1.0, 1.0 },
    { 1.0, 0, 1.0, 1.0 }
};

GLfloat vMatrix[16] = {
    1.0, 0, 0, 0,
    0, 1.0, 0, 0,
    0, 0, 1.0, 0,
    0, 0, 0, 1.0
};


void renderScene(void)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    float q[48];
    glBindBuffer(GL_ARRAY_BUFFER, VBOs[0]);
    glGetBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vPosition) + sizeof(vColor), q);
    for (int i = 0; i < 48; i++)
    {
        printf("%f\n", q[i]);
    }
    printf("\n");

    glEnable(GL_RASTERIZER_DISCARD);
    glBindVertexArray(VAOs[0]);
    glBindVertexBuffer(0, VBOs[0], 0, 4 * sizeof(GL_FLOAT));
    glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, TFBs[0]);
    glBeginTransformFeedback(GL_TRIANGLES);
    glDrawArrays(GL_TRIANGLES, 3, 3);
    glDrawArrays(GL_TRIANGLES, 0, 3);
    glEndTransformFeedback();
    glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
    glBindVertexArray(0);

    float p[48];
    glBindBuffer(GL_ARRAY_BUFFER, VBOs[1]);
    glGetBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vPosition) + sizeof(vColor), p);
    for (int i = 0; i < 48; i++)
    {
        printf("%f\n", p[i]);
    }

    glDisable(GL_RASTERIZER_DISCARD);
    glBindVertexArray(VAOs[1]);
    glBindVertexBuffer(0, VBOs[1], 0, 8 * sizeof(GL_FLOAT));
    //glDrawArrays(GL_TRIANGLES, 3, 3);
    //glDrawArrays(GL_TRIANGLES, 0, 3);
    glDrawTransformFeedback(GL_TRIANGLES, TFBs[0]);
    glBindVertexArray(0);

    glutSwapBuffers();
    //glutPostRedisplay();
}

void Init()
{
    glEnable(GL_DEPTH_TEST);

    GLuint vert = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vert, 1, &vertSrc, 0);
    glCompileShader(vert);

    GLuint frag = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(frag, 1, &fragSrc, 0);
    glCompileShader(frag);

    GLuint program = glCreateProgram();
    glAttachShader(program, vert);
    glAttachShader(program, frag);
    glLinkProgram(program);
    glUseProgram(program);


    GLint matrix = glGetUniformLocation(program, "vMatrix");
    glUniformMatrix4fv(matrix, 1, GL_TRUE, vMatrix);//second parameter indicates the number of matrices

    GLint position = glGetAttribLocation(program, "vPosition");
    GLint color = glGetAttribLocation(program, "vColor");

    glGenVertexArrays(2, VAOs);

    glBindVertexArray(VAOs[0]);
    glVertexAttribFormat(position, 4, GL_FLOAT, GL_FALSE, 0);
    glVertexAttribBinding(position, 0);
    glVertexAttribFormat(color, 4, GL_FLOAT, GL_FALSE, sizeof(vPosition));
    glVertexAttribBinding(color, 0);
    glEnableVertexAttribArray(position);
    glEnableVertexAttribArray(color);
    glBindVertexArray(0);

    glBindVertexArray(VAOs[1]);
    glVertexAttribFormat(position, 4, GL_FLOAT, GL_FALSE, 0);
    glVertexAttribBinding(position, 0);
    glVertexAttribFormat(color, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GL_FLOAT));
    glVertexAttribBinding(color, 0);
    glEnableVertexAttribArray(position);
    glEnableVertexAttribArray(color);
    glBindVertexArray(0);


    glGenBuffers(2, VBOs);

    glBindBuffer(GL_ARRAY_BUFFER, VBOs[0]);
    //glBufferStorage(GL_ARRAY_BUFFER, sizeof(vPosition) + sizeof(vColor), 0, 0);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vPosition) + sizeof(vColor), 0, GL_STATIC_DRAW);
    glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vPosition), vPosition);
    glBufferSubData(GL_ARRAY_BUFFER, sizeof(vPosition), sizeof(vColor), vColor);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    glBindBuffer(GL_ARRAY_BUFFER, VBOs[1]);
    //glBufferStorage(GL_ARRAY_BUFFER, sizeof(vPosition) + sizeof(vColor), 0, 0);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vPosition) + sizeof(vColor), 0, GL_STREAM_READ);
    glBindBuffer(GL_ARRAY_BUFFER, 0);


    glGenTransformFeedbacks(1, TFBs);

    glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, TFBs[0]);
    glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, VBOs[1]);
    glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);


    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}

int main(int argc, char **argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
    glutInitWindowPosition(400, 300);
    glutInitWindowSize(800, 600);
    glutInitContextVersion(4, 5);
    glutInitContextProfile(GLUT_CORE_PROFILE);
    glutCreateWindow("Drawing my first triangle");
    glewInit();

    GLubyte const *v = glGetString(GL_VERSION);
    printf("%s\n", v);

    Init();

    // register callbacks
    glutDisplayFunc(renderScene);
    glutMainLoop();
    glDeleteProgram(program);
    return 0;
}

1 个答案:

答案 0 :(得分:1)

转换反馈不会仅仅因为绑定了反馈对象而发生。您的着色器必须明确告诉OpenGL哪些输出转到反馈缓冲区。有a variety of mechanisms for doing this。就个人而言,因为您使用的是GLSL 4.50,所以我会去in-shader setup

考虑到VAOs[1]和反馈缓冲区的布局,以下着色器代码应该有效:

#version 450 core

in vec4 vPosition;
in vec4 vColor;

//Use buffer 0 by default.
layout(xfb_buffer = 0) out;

//Must redeclare `gl_PerVertex` to apply TF to it.
out gl_PerVertex
{
    layout(xfb_offset = 0) vec4 gl_Position;
};

//4 floats after gl_Position
layout(xfb_offset = 16) out vec4 fColor;

uniform mat4 vMatrix;

void main(void)
{
    gl_Position = vMatrix * vPosition;
    fColor = vColor;
};

您的代码的另一个小问题。这样:

glVertexAttribFormat(color, 4, GL_FLOAT, GL_FALSE, sizeof(vPosition));

不会一直有效。缓冲区中属性的偏移量限制为GL_MAX_VERTEX_ATTRIB_STRIDE。该实现定义的值至少为2048,因此您当前的代码是安全的。但这只是安全的,因为vPosition太小了。它不会使vPosition太大而无法抵消。

属性格式的偏移量是从缓冲区的起点到第一个顶点信息所在的偏移量。它并不意味着用于跳过整个属性数组的数据,这就是你在这里所做的。格式的偏移量用于交错顶点的偏移。

当你有两个这样的非交错数组时,处理这个问题的最好方法是使用两个缓冲区绑定。也就是说,positioncolor应该使用不同的缓冲区绑定。

请注意,我没有说不同的缓冲区对象。您可以在两个绑定中使用相同的缓冲区;您只需使用提供给glBindVertexBuffer的偏移量来为颜色数组的开头提供偏移量。与格式偏移不同,该偏移没有限制。