我是OpenGL的新手。我以为我了解FBO,但是我很难使它们起作用。
我的程序绘制了多次采样的fbo基本图形信息(colorFbo)。 从colorFbo我将blit到postprocessFbo。 然后是带有无符号int值的counterFbo,我在其中简单地用对象的ID填充每个对象的轮廓。
我想对postprocessFbo和counterFbo进行后处理,但是,我看不到counterFbo的任何作用...请问问题出在哪里? 这是我的代码的一部分:
初始化:
colorFbo = new Framebuffer(true, false); //multisampled, rgba
counterFbo = new Framebuffer(false, true); //not MS, red
...seting polygonmode, viewport, depthtest, blending...
modelProgram = loadProgram("model");
counterProgram = loadProgram("counter");
...
postprocessProgram = loadProgram("postprocess");
...
postprocessFbo = new Framebuffer(false, false); //not MS, rgba
渲染循环:
glBindFramebuffer(GL_FRAMEBUFFER, colorBuffer.fbo());
Main.clear(0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glEnable(GL_MULTISAMPLE);
drawing objects using model program...
glBindFramebuffer(GL_FRAMEBUFFER, counterBuffer.fbo());
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDisable(GL_MULTISAMPLE);
drawing objects using counter program...
blit colorFbo to postprocessFbo...
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClear(GL_COLOR_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
glUseProgram(postprocessProgram);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, postprocessFbo.fboColorTexture());
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, counterFbo.fboColorTexture());
glBindVertexArray(screenQuadArray);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
计数器片段着色器:
#version 330
out uint counter;
in vec3 vPosition;
uniform uint id;
void main() {
counter = id;
}
后处理片段着色器:
#version 330
uniform sampler2D colorTex;
uniform usampler2D counterTex;
out vec4 finalColor;
in vec2 texCoord;
void main() {
finalColor = texture(colorTex, vec2(tex));
uint id = texture(counterTex, vec2(tex)).s;
if (id > 0) {
finalColor = black;
}
}
帧缓冲构造函数:
public Framebuffer(boolean multisampled, boolean redOnly) {
int internalFormat = redOnly ? GL_R32UI : GL_RGBA;
int format = redOnly ? GL_RED_INTEGER : GL_RGBA;
int dataType = redOnly ? GL_UNSIGNED_INT : GL_UNSIGNED_BYTE;
int interpolation = redOnly ? GL_NEAREST : GL_LINEAR;
int textureType = multisampled ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D;
// Prepare FBO textures
fboColorTexture = glGenTextures();
fboDepthStencilTexture = glGenTextures();
if (multisampled) {
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, fboColorTexture);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, SAMPLES, internalFormat, Main.width(), Main.height(), false);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, fboDepthStencilTexture);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, SAMPLES, GL_DEPTH24_STENCIL8, Main.width(), Main.height(), false);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
} else {
glBindTexture(GL_TEXTURE_2D, fboColorTexture);
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, Main.width(), Main.height(), 0, format, dataType, (float[]) null);
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_MIN_FILTER, interpolation);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, interpolation);
glBindTexture(GL_TEXTURE_2D, fboDepthStencilTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, Main.width(), Main.height(), 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, (float[]) null);
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_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D, 0);
}
fbo = glGenFramebuffers();
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, textureType, fboColorTexture, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, textureType, fboDepthStencilTexture, 0);
glDrawBuffers(GL_COLOR_ATTACHMENT0);
int status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
System.err.println("Framebuffer not complete.");
System.exit(1);
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
答案 0 :(得分:1)
您似乎缺少将纹理单位分配给纹理名称的想法。因此,当我加载纹理时,通常在初始化时执行此操作...
uColorTex = glGetUniformLocation(shaders.shaderProgram, "colorTex");
uCounterTex = glGetUniformLocation(shaders.shaderProgram, "counterTex");
...以及绘图时...
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, postprocessFbo.fboColorTexture());
glUniform1i(uColourTex, 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, counterFbo.fboColorTexture());
glUniform1i(uCounterTex, 1);
答案 1 :(得分:0)
问题出在计数器程序本身(在glVertexAttribPointer
中),我没有写过。
我只需要在计数器程序中定位即可,所以我这样写:
glVertexAttribPointer(positionAttribLoc, 3, GL_FLOAT, false, FLOAT_VEC3_SIZE, 0);
但是我忘记了,数据始终位于同一位置,所以我不能“节省空间”,因为我只是绑定,所以顶点数据保持不变:
glVertexAttribPointer(positionAttribLoc, 3, GL_FLOAT, false, SIZEOF_MODEL_VERTEX, 0);
感谢您的回答,对不起,我没有显示更多代码,我认为问题可能出在任何地方,不想让阅读过多代码的人不知所措。