为啥 glreadpixels 仅在某些情况下有效?

Posted

技术标签:

【中文标题】为啥 glreadpixels 仅在某些情况下有效?【英文标题】:Why is glreadpixels only working in certain cases?为什么 glreadpixels 仅在某些情况下有效? 【发布时间】:2018-12-03 03:13:17 【问题描述】:

如果我尝试使用glreadpixels 读取屏幕,然后使用gldrawpixels 再次绘制相同的东西,它可以工作,但当且仅当我使用除gldrawarraysgldrawelements 之外的任何其他东西来绘制时(@987654325 @工作就好)。我正在尝试将对象绘制到屏幕上并将像素保存在数组中。

我尝试读/写前/后缓冲区,交换缓冲区后读取,都无济于事。

这是我用来绘制对象的代码:(请注意,我不使用此范围之外的任何类型的缓冲区)。

 void CCssample5View::DrawCylinder(Model obj)
    
    GLuint VertexArrayID;
    glGenVertexArrays(1, &VertexArrayID);
    glBindVertexArray(VertexArrayID);

    Shader castingShader("casting.vs", "casting.fs");
    Shader lightShader("light.vs", "light.fs");

    GLuint MatrixID = glGetUniformLocation(castingShader.ID, "MVP");
    GLuint ViewMatrixID = glGetUniformLocation(castingShader.ID, "V");
    GLuint ModelMatrixID = glGetUniformLocation(castingShader.ID, "M");

    GLuint textur = loadBMP_custom("flower.bmp");
    GLuint TextureID = glGetUniformLocation(castingShader.ID , "myTextureSampler");


    indexVBO(obj.vertices, obj.uvs, obj.normals, obj.indices, obj.indexed_vertices, obj.indexed_uvs, obj.indexed_normals);

    GLuint vertexbuffer;
    glGenBuffers(1, &vertexbuffer);
    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
    glBufferData(GL_ARRAY_BUFFER, obj.indexed_vertices.size() * sizeof(glm::vec3), &obj.indexed_vertices[0], GL_STATIC_DRAW);

    GLuint uvbuffer;
    glGenBuffers(1, &uvbuffer);
    glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
    glBufferData(GL_ARRAY_BUFFER, obj.indexed_uvs.size() * sizeof(glm::vec2), &obj.indexed_uvs[0], GL_STATIC_DRAW);

    GLuint normalbuffer;
    glGenBuffers(1, &normalbuffer);
    glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
    glBufferData(GL_ARRAY_BUFFER, obj.indexed_normals.size() * sizeof(glm::vec3), &obj.indexed_normals[0], GL_STATIC_DRAW);

    GLuint elementbuffer;
    glGenBuffers(1, &elementbuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, obj.indices.size() * sizeof(unsigned short), &obj.indices[0], GL_STATIC_DRAW);



    castingShader.use();

    GLuint LightID = glGetUniformLocation(castingShader.ID, "LightPosition_worldspace");
    computeMatricesFromInputs();
    GLfloat gProjectionMatrix[16];
    glGetFloatv(GL_PROJECTION_MATRIX, gProjectionMatrix);
    glm::mat4 ProjectionMatrix = glm::make_mat4(gProjectionMatrix);// = glm::mat4(gProjectionMatrix);   

    GLfloat gViewMatrix[16];
    glGetFloatv(GL_MODELVIEW_MATRIX, gViewMatrix);
    glm::mat4 ViewMatrix = glm::make_mat4(gViewMatrix);// = glm::mat4(gProjectionMatrix);

    glm::vec3 lightPos = glm::vec3(4, 4, 4);
    glUniform3f(LightID, lightPos.x, lightPos.y, lightPos.z);
    glUniformMatrix4fv(ViewMatrixID, 1, GL_FALSE, &ViewMatrix[0][0]);

    glm::mat4 ModelMatrix1 = glm::mat4(1.0);
    glm::mat4 MVP1 = ProjectionMatrix * ViewMatrix * ModelMatrix1;


    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, textur);

    glUniform1i(TextureID, 0);
    // Send our transformation to the currently bound shader, 
    // in the "MVP" uniform
    glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP1[0][0]);
    glUniformMatrix4fv(ModelMatrixID, 1, GL_FALSE, &ModelMatrix1[0][0]);
    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
    glVertexAttribPointer(
        0,                  // attribute
        3,                  // size
        GL_FLOAT,           // type
        GL_FALSE,           // normalized?
        0,                  // stride
        (void*)0            // array buffer offset
    );

    // 2nd attribute buffer : UVs
    glEnableVertexAttribArray(1);
    glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
    glVertexAttribPointer(
        1,                                // attribute
        2,                                // size
        GL_FLOAT,                         // type
        GL_FALSE,                         // normalized?
        0,                                // stride
        (void*)0                          // array buffer offset
    );

    // 3rd attribute buffer : normals
    glEnableVertexAttribArray(2);
    glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
    glVertexAttribPointer(
        2,                                // attribute
        3,                                // size
        GL_FLOAT,                         // type
        GL_FALSE,                         // normalized?
        0,                                // stride
        (void*)0                          // array buffer offset
    );

    // Index buffer
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);

    // Draw the triangles !
    glDrawElements(
        GL_TRIANGLES,      // mode
        obj.indices.size(),    // count
        GL_UNSIGNED_SHORT,   // type
        (void*)0           // element array buffer offset
    );

    //glFlush(); glFinish(); readScreen(screen, GL_RGB, true);

    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(1);
    glDisableVertexAttribArray(2);

    glDeleteBuffers(1, &vertexbuffer);
    glDeleteBuffers(1, &uvbuffer);
    glDeleteBuffers(1, &normalbuffer);
    glDeleteBuffers(1, &elementbuffer);
    glDeleteProgram(castingShader.ID);
    glDeleteTextures(1, &textur);
    glDeleteVertexArrays(1, &VertexArrayID);

这些是我的阅读和绘制屏幕功能:

void CCssample5View::readScreen(GLubyte* screen, GLenum format, bool back)

    check();


    if (format == GL_RGB) 


        check();
        if (back) 
            glReadBuffer(GL_BACK);
            check();
        
        else 
            glReadBuffer(GL_FRONT);
            check();
        

    
    //glRasterPos2i(00, 00);
    //glDisable(GL_DEPTH_TEST);
    glPixelStorei(GL_PACK_ALIGNMENT, 1);
    glReadPixels(0, 0, w, h, format, GL_UNSIGNED_BYTE, screen);


    glFlush();
    glFinish();
    bool found = false;
    for (size_t u = 0; u <= w * h * 4; u++) 
        if (screen[u] != 0) 
            found = true;
            break;
        
    
    assert(found);
    check();



void CCssample5View::drawScreen(GLubyte *screen, GLenum format, bool back)



    glClear(GL_COLOR_BUFFER_BIT);
    //glGetIntegerv(GL_CURRENT_RASTER_POSITION, rasterpos);
    if (back) 
        glDrawBuffer(GL_BACK);
    
    else 
        glDrawBuffer(GL_FRONT);
        

    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glDrawPixels(w, h, format, GL_UNSIGNED_BYTE, screen);
    check();

    glFlush();
    glFinish();

除了阅读屏幕部分之外,绘图完美时似乎无法弄清楚有什么问题..

【问题讨论】:

只是为了排除:我认为,glReadPixels 在您的第一个代码 sn-p 中被注释掉是格式错误,对吧? 是的,这是我拼命尝试阅读屏幕的一部分。这不是我通常尝试读取屏幕的地方。 【参考方案1】:

我想通了。我所要做的就是在拉缸功能的最后添加glUseProgram(0)。经过 3 多周的调查。

【讨论】:

以上是关于为啥 glreadpixels 仅在某些情况下有效?的主要内容,如果未能解决你的问题,请参考以下文章

如何仅在某些情况下禁用 Django 的 csrf 保护?

Pyspark es.query 仅在默认情况下有效

设计模式 - 如何仅在某些情况下强制执行对象属性(构建器模式,依赖注入)

为啥 KeyListener 仅在未按下按钮时才起作用?

解析 JWT 令牌以仅在 C# 或 Blazor 中没有外部库的情况下获取有效负载内容

Grails:println 仅在某些时候有效