如何在OpenGL程序中获取纹理大小限制?

huangapple go评论59阅读模式
英文:

How to get texture size limit in a program on Opengl?

问题

我有一个Qt程序,它在QOpenglWidget中使用了几个VBO(Vertex Buffer Objects)和两个Framebuffer Objects(帧缓冲对象),如下所示:

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

在这里,我没有初始化一些资源,比如PointsTangentstbo_depthtbo_norm,因为这些数据将在小部件类外部重置,所以我选择在paintGL()函数中分配或重新分配这些资源。

initializeGL函数中,我创建和初始化了各种OpenGL资源,如缓冲区、纹理和帧缓冲对象。

paintGL函数中,我使用了一些布尔值来确保某些资源在initializeGL()中没有分配时只分配一次,并且当在该类外部重置时也只重置一次。我还展示了如何在帧缓冲中渲染深度纹理和模式。

以下是一些重置函数的示例,它们用于根据不同条件重置OpenGL资源的大小和数据:

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

void PatternWidget::resetFBO() {
    if (openGLInitialized) {
        // 重新分配帧缓冲相关的资源,例如深度纹理和法线纹理
        frameObjectUpdated = true;
    }
}

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

void PatternWidget::resetBO() {
    if (openGLInitialized) {
        // 重新分配其他缓冲区对象相关的资源
        bufferObjectUpdated = true;
    }
}

您提到如果PointsTangents的大小为75M,那么tbo_depthtbo_norm的大小应小于1024 * 1024,否则阴影映射将无法正常工作。如果PointsTangents的大小减半,那么tbo_depthtbo_norm的大小可以为2048 * 2048。您是否有办法获取在不同条件下纹理的实际最大大小?

您可以使用OpenGL函数glGetIntegerv来查询OpenGL实现的各种参数,以获取不同条件下纹理的最大大小。以下是一种获取纹理大小限制的方法:

GLint maxTextureSize;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);

上述代码将查询OpenGL实现支持的最大纹理尺寸,并将其存储在maxTextureSize变量中。您可以在不同条件下调用这个函数来获取不同条件下的最大纹理尺寸限制。然后,您可以根据这个限制来动态分配和管理纹理资源的大小。

英文:

I have a qt program, which use several VBOs,and two framebuffer objects in QOpenglWidget like this:

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

Here I don't initialize some resources like Points/Tangents/tbo_depth/tbo_norm because these data will be reset outside the widget class,so I choose to allocate or reallocate these resources in paintGL() function.

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

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

glActiveTexture(GL_TEXTURE0);
glGenTextures(1, &amp;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, &amp;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, &amp;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, &amp;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, &amp;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, &amp;rb_colorPattern);
glBindRenderbuffer(GL_RENDERBUFFER, rb_colorPattern);

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

glGenFramebuffers(1, &amp;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);
}

In paintGL,I use several bool value to make sure when some resources not allocated in initialGL() will be set here only once,and when be reset outside this class,will also be reset only once.

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);
}

Here are my reset functions,setFrameSizeaccept window width and height outside the class,then call resetFBO to reset framebuffer size, same way to call resetRenderData and resetBO to reset 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&lt;vec4&gt; *pnts, QVector&lt;vec3&gt; *t){
    points = pnts;
    tangents = t;
    resetBO();
}

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

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

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

I find that if Points and Tangents are 75M big, then the size of tbo_depth and tbo_norm should be smaller than 1024 * 1024,because if the size is bigger than 1024,shadow map won't work. I also copy tbo_norm to default framebuffer by glBlitFramebuffer,there wont be anything if size bigger than 1024.If Points and Tangents are half size then tbo_depth and tbo_norm size can be 2048 * 2048. Is there any way that I can get the actual max size of texture on different condition?

答案1

得分: 0

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

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

但要注意,这是特定于您的驱动程序(可能也与您的GPU有关)。

编辑:

还有其他要检查的事项,尽管您可能已经知道:

  • 看起来您没有在以下位置设置resetFBO(w,h)
void 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的大小很不可能影响阴影贴图纹理的分辨率。

英文:

After creating your context, you can check the max texture size like this:

int value;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &amp;value);
std::cout &lt;&lt; &quot;Max texture: &quot; &lt;&lt; value &lt;&lt; &quot; x &quot; &lt;&lt; value &lt;&lt; std::endl;

but be aware that this is specific to your driver (maybe your GPU as well).

EDIT:

Other things to check, even though you might already know:

  • You don't seem to be setting resetFBO(w,h) in

:

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

for example:

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,...)
...

Which might be important, since drawing to the shadow map requires changing the viewport size:

glViewport(0, 0, shadowMapResolution, shadowMapResolution);

  • bo_renderRotations looks uninitialized, but maybe you didn't include in the original snippet for brevity.

  • You could check if 1024 is hard coded somewhere else, like in the shader.

Because, even though it looks like, its pretty unlikely that the size of the VBO is influencing the resolution of the shadow map texture.

huangapple
  • 本文由 发表于 2023年6月27日 17:25:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/76563435.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定