我想使用可编程管道(使用glsl)进行体积渲染,并且没有固定的管道。我使用2个着色器程序exitPointProg
和rayCastProg
实现了2次传递。第一遍是获得立方体边界框的出口点(即背面),该边界框将用作进行光线投射的下一遍中的纹理。进行光线投射体绘制的想法来自here。我认为我已经完成了大部分工作,因为我已经使用固定管道和可编程管道实现了这一点。让我感到困惑的是我用第一帧获得了结果,然后用闪光灯将屏幕上的显示变为白色(我设置glClearColor(1.0f, 1.0f, 1.0f, 1.0f)
。我认为切换时可能有些错误着色器程序或FBO。这是我在render()函数中所做的。
exitPoints
渲染到绑定了exitPointProg
纹理的fbo以获取立方体边界框的出口点。 2ed pass,将exitPoints
纹理(绑定到GL_TEXTURE1
)映射到着色器程序rayCastProg
,作为将在着色器中使用的统一sampler2D变量。
这是setupFBO
和render
以及两个子程序:
setupFBO()
函数:
void SimpleRayCasting::setupFBO()
{
GLuint textureHandles[1];
glGenTextures(1, textureHandles);
entryPoints = textureHandles[0];
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, exitPoints);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, NULL);
GLuint depthRenderBuffer;
glGenRenderbuffers(1, &depthRenderBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, depthRenderBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
glGenFramebuffers(1, &frameBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
exitPoints, 0/* level */);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
depthRenderBuffer);
checkFramebufferState(__FILE__, __LINE__);
GLenum drawbufs[] = {GL_COLOR_ATTACHMENT0};
glDrawBuffers(1, drawbufs);
glBindFramebuffer(GL_FRAMEBUFFER,0);
}
render()
函数:
void SimpleRayCasting::render()
{
getExitPoints();
GLUtils::checkForOpenGLError(__FILE__,__LINE__);
rayCasting();
GLUtils::checkForOpenGLError(__FILE__,__LINE__);
}
getExitPoints()
函数:
void SimpleRayCasting::getExitPoints()
{
// render to the texture
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
glEnable(GL_DEPTH_TEST);
glViewport(0, 0, width, height);
// checkFramebufferState(__FILE__, __LINE__);
glClearColor(0.2f, 0.2f, 0.2f, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
exitPointsProg.use();
// note that the model will recalculated.
model = mat4(1.0f);
model *= glm::rotate(angle , vec3(0.0f,1.0f,0.0f));
model *= glm::rotate(90.0f, vec3(1.0f, 0.0f, 0.0f));
model *= glm::translate(vec3(-0.5f, -0.5f, -0.5f));
view = glm::lookAt(vec3(0.0f,0.0f,2.0f), vec3(0.0f,0.0f,0.0f), vec3(0.0f,1.0f,0.0f));
projection = mat4(1.0f);
projection = glm::perspective(60.0f, (float)width/(float)height,0.01f, 400.0f);
setMatrices(exitPointsProg);
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
drawBoundBox();
glDisable(GL_CULL_FACE);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
rayCasting
函数:
void SimpleRayCasting::rayCasting()
{
// Directly render to the screen
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glEnable(GL_DEPTH_TEST);
glViewport(0, 0, width, height);
glClearColor(1.0f, 1.0f, 1.0f, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
rayCastProg.use();
model = mat4(1.0f);
model *= glm::rotate(angle, vec3(0.0f,1.0f,0.0f));
model *= glm::rotate(90.0f, vec3(1.0f, 0.0f, 0.0f));
model *= glm::translate(vec3(-0.5f, -0.5f, -0.5f));
view = glm::lookAt(vec3(0.0f,0.0f,2.0f), vec3(0.0f,0.0f,0.0f), vec3(0.0f,1.0f,0.0f));
projection = mat4(1.0f);
projection = glm::perspective(60.0f, (float)width/(float)height,0.01f, 400.0f);
setMatrices(rayCastProg);
rayCastProg.setUniform("StepSize", stepSize);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, exitPoints);
rayCastProg.setUniform("ExitPoints", 1);
glActiveTexture(GL_TEXTURE4);
glBindTexture(GL_TEXTURE_3D, volume_to);
rayCastProg.setUniform("VolumeTex", 4);
glActiveTexture(GL_TEXTURE5);
glBindTexture(GL_TEXTURE_1D, transferFunc_to);
rayCastProg.setUniform("TransferFunc", 5);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
drawBoundBox();
glDisable(GL_CULL_FACE);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
我在Qt中使用从QGLWidget继承的类。正如我早些时候提到的那样,我在第一帧时得到了正确的结果,很快它就会闪现并变成白色。我不知道这有什么问题,着色器程序或FBO事件的切换是否有问题?我一直在研究这个问题,无法弄明白,任何帮助都将不胜感激!
编辑询问 是否有任何演示或教程演示如何在FBO中使用多个glsl着色器程序?