如何在OpenGL上的程序中获得纹理大小限制?

4nkexdtk  于 2023-06-29  发布在  其他
关注(0)|答案(1)|浏览(168)

我有一个qt程序,它使用了几个VBO,以及QOpenglWidget中的两个framebuffer对象,如下所示:

class PatternWidget: public QOpenGLWidget,protected QOpenGLFunctions_4_3_Core {...}

这里我没有初始化一些资源,如Points/Tangents/tbo_depth/tbo_norm,因为这些数据将在widget类之外重置,所以我选择在paintGL()函数中分配或重新分配这些资源。

void PatternWidget::initializeGL(){
...
glGenBuffers(1, &Points);
glBindBuffer(GL_ARRAY_BUFFER,Points);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(0);

glGenBuffers(1, &Tangents);
glBindBuffer(GL_ARRAY_BUFFER,Tangents);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(1);

glActiveTexture(GL_TEXTURE0);
glGenTextures(1, &tbo_radiance);
glBindTexture(GL_TEXTURE_2D_ARRAY, tbo_radiance);
glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32F, 100, 100, 32);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

glActiveTexture(GL_TEXTURE1);
glGenTextures(1, &tbo_density);
glBindTexture(GL_TEXTURE_2D_ARRAY, tbo_density);
glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R32F, 100, 100, 32);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

glActiveTexture(GL_TEXTURE2);
glGenTextures(1, &tbo_depth);
glBindTexture(GL_TEXTURE_2D, tbo_depth);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);

glActiveTexture(GL_TEXTURE3);
glGenTextures(1, &tbo_norm);
glBindTexture(GL_TEXTURE_2D, tbo_norm);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

glGenFramebuffers(1, &depthFrame);
glBindFramebuffer(GL_FRAMEBUFFER, depthFrame);
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, tbo_depth, 0);
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tbo_norm, 0);
glDrawBuffer(GL_COLOR_ATTACHMENT0);

glGenRenderbuffers(1, &rb_colorPattern);
glBindRenderbuffer(GL_RENDERBUFFER, rb_colorPattern);

glGenRenderbuffers(1, &rb_depthPattern);
glBindRenderbuffer(GL_RENDERBUFFER, rb_depthPattern);

glGenFramebuffers(1, &patternFrame);
glBindFramebuffer(GL_FRAMEBUFFER, patternFrame);
glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_RENDERBUFFER, rb_colorPattern);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rb_depthPattern);
glDrawBuffer(GL_COLOR_ATTACHMENT0);
}

paintGL中,我使用了几个bool值来确保当一些没有在initialGL()中分配的资源在这里只被设置一次,当在这个类之外被重置时,也只被重置一次。

void PatternWidget::paintGL(){
    if(!frameObjectUpdated){//frameObjectUpdated bool value,to make sure reset framebuffer only once
        resetFBO();
    }
    if(!bufferObjectUpdated){//bufferObjectUpdated same as frameObjectUpdated
        resetBO();
    }
    if(!crossTextureUpdated){//crossTextureUpdatedsame as frameObjectUpdated
        resetCrossData();
    }
    //render depth texture for shadow map   
    glUseProgram(shadowProgram);
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, depthFrame);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    ...//some basic matrix set
    glDrawArrays(GL_POINTS, 0, renderSize);
    //render pattern in framebuffer 
    glUseProgram(renderProgram);
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, patternFrame);
    ...//some basic matrix set
    glBindVertexArray(vao_render);
    glDrawArrays(GL_POINTS, 0, renderSize);
    //copy framebuffer to default framebuffer
    glBindFramebuffer(GL_READ_FRAMEBUFFER, patternFrame);
    glReadBuffer(GL_COLOR_ATTACHMENT0);
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, defaultFramebufferObject());
    glBlitFramebuffer(0,0,winWid, winHei,0,0, winWid, winHei,GL_COLOR_BUFFER_BIT,GL_NEAREST);
}

这里是我的重置函数,setFrameSize接受类外的窗口宽度和高度,然后调用resetFBO重置帧缓冲区大小,同样的方式调用resetRenderDataresetBO重置vbo。

void PatternWidget::setFrameSize(int w,int h){
    winWid = w;
    winHei = h;
    resetFBO();
}
void PatternWidget::resetFBO(){
    if(openGLInitialized){
        glBindTexture(GL_TEXTURE_2D, tbo_depth);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, 1024, 1024, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);

        glBindTexture(GL_TEXTURE_2D, tbo_norm);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1024, 1024, 0, GL_RGBA, GL_FLOAT, NULL);

        glBindRenderbuffer(GL_RENDERBUFFER, rb_colorPattern);
        glRenderbufferStorage(GL_RENDERBUFFER,GL_RGBA,winWid, winHei);

        glBindRenderbuffer(GL_RENDERBUFFER, rb_depthPattern);
        glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT32F, winWid, winHei);

        frameObjectUpdated = true;
    }
}

void PatternWidget::resetRenderData(QVector<vec4> *pnts, QVector<vec3> *t){
    points = pnts;
    tangents = t;
    resetBO();
}

void PatternWidget::resetBO(){
    if(openGLInitialized){
        renderSize = points->size();
        int nBytes = renderSize * sizeof(vec4);
        glBindBuffer(GL_ARRAY_BUFFER,bo_renderPoints);
        glBufferData(GL_ARRAY_BUFFER,nBytes,&(*points)[0].x,GL_DYNAMIC_DRAW);

        nBytes = renderSize * sizeof(vec3);
        glBindBuffer(GL_ARRAY_BUFFER,bo_renderTangents);
        glBufferData(GL_ARRAY_BUFFER,nBytes,&(*tangents)[0].x,GL_DYNAMIC_DRAW);

        nBytes = renderSize * sizeof(float);
        glBindBuffer(GL_ARRAY_BUFFER,bo_renderRotations);
        glBufferData(GL_ARRAY_BUFFER,nBytes,&(*rotations)[0],GL_DYNAMIC_DRAW);
        bufferObjectUpdated = true;
    }
}

我发现如果PointsTangents的大小是75 M,那么tbo_depthtbo_norm的大小应该小于1024 * 1024,因为如果大小大于1024,阴影贴图将无法工作。我也复制tbo_norm到默认的帧缓冲区的glBlitFramebuffer,没有什么,如果大小大于1024.如果PointsTangents是一半的大小,那么tbo_depthtbo_norm的大小可以是2048 * 2048.有没有什么方法可以让我在不同的条件下得到纹理的实际最大尺寸?

fnx2tebb

fnx2tebb1#

创建上下文后,您可以像这样检查最大纹理大小:

int value;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
std::cout << "Max texture: " << value << " x " << value << std::endl;

但要注意,这是特定于您的驱动程序(也许您的GPU以及)。
编辑:
其他需要检查的事项,即使您可能已经知道:

  • 您似乎没有将resetFBO(w,h)设置为

PatternWidget::setFrameSize(int w,int h){
    winWid = w;
    winHei = h;
    resetFBO();
}

例如:

void PatternWidget::resetFBO(int w, int h){
    if(openGLInitialized){
        glBindTexture(GL_TEXTURE_2D, tbo_depth);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, w, h,...)
...

这可能很重要,因为绘制阴影贴图需要更改视口大小:
glViewport(0, 0, shadowMapResolution, shadowMapResolution);

  • bo_renderRotations看起来未初始化,但可能为了简洁,您没有在原始代码段中包含它。
  • 您可以检查1024是否在其他地方硬编码,例如在着色器中。

因为,即使看起来像,它的VBO的大小是不太可能影响的阴影贴图纹理的分辨率。

相关问题