プログラム可能なパイプライン (glsl を使用) を使用し、固定パイプラインを使用せずにボリューム レンダリングを実行したいと考えています。2 つのシェーダー プログラムを使用して 2 つのパスで実装しexitPointProg
ますrayCastProg
。最初のパスは、レイキャスティングを行う次のパスでテクスチャとして使用されるキューブ バウンディング ボックスの出口ポイント (つまり背面) を取得することです。レイキャスティング ボリューム レンダリングを行うというアイデアは、ここから生まれました。プログラム可能なパイプラインと組み合わせた固定パイプラインでこれを実装したので、ほとんどのことを正しく行ったと思います。私を混乱させたのは、最初のフレームで結果を達成し、フラッシュで画面上の表示が完全に白くなったことです(glClearColor(1.0f, 1.0f, 1.0f, 1.0f)
. シェーダープログラムやFBOの切り替えに問題があるのではないかと思います。render() 関数で行うことは次のとおりです。
- 最初のパスでは、テクスチャがバインドされた fbo にレンダリングして、
exitPoints
シェーダー プログラムを使用してキューブ バウンディング ボックスの出口ポイントを取得しますexitPointProg
。 2ed パスで、シェーダーで使用される均一な sampler2D 変数として、
exitPoints
テクスチャー (にバインドGL_TEXTURE1
) をシェーダー プログラムにマップしました。rayCastProg
ここにsetupFBO
andrender
と 2 つのサブルーチンがあり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シェーダープログラムを使用する方法を示すデモまたはチュートリアルはありますか?