我有一个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
重置帧缓冲区大小,同样的方式调用resetRenderData
和resetBO
重置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;
}
}
我发现如果Points
和Tangents
的大小是75 M,那么tbo_depth
和tbo_norm
的大小应该小于1024 * 1024,因为如果大小大于1024,阴影贴图将无法工作。我也复制tbo_norm
到默认的帧缓冲区的glBlitFramebuffer
,没有什么,如果大小大于1024.如果Points
和Tangents
是一半的大小,那么tbo_depth
和tbo_norm
的大小可以是2048 * 2048.有没有什么方法可以让我在不同的条件下得到纹理的实际最大尺寸?
1条答案
按热度按时间fnx2tebb1#
创建上下文后,您可以像这样检查最大纹理大小:
但要注意,这是特定于您的驱动程序(也许您的GPU以及)。
编辑:
其他需要检查的事项,即使您可能已经知道:
resetFBO(w,h)
设置为:
例如:
这可能很重要,因为绘制阴影贴图需要更改视口大小:
glViewport(0, 0, shadowMapResolution, shadowMapResolution);
bo_renderRotations
看起来未初始化,但可能为了简洁,您没有在原始代码段中包含它。因为,即使看起来像,它的VBO的大小是不太可能影响的阴影贴图纹理的分辨率。