저는 두 개의 서페이스 (객체의 앞과 뒤)를 통해 빛의 굴절을 계산하는 셰이더를 구현하려고합니다. 이렇게하려면 보통 깊이 테스트 (GL_LESS) 및 역 깊이 테스트 (GL_GREATER)로 굴절 형상을 렌더링해야합니다. 그것은 내가 뒤쪽면에서 앞면까지의 거리를 계산할 수있게 해준다. 불행히도, 나는 한 번에 그 중 하나만 렌더링 할 수 있습니다. 두 깊이 정보를 텍스처로 텍스처 셰이더에 전달하는 방법을 알 수 없습니다.FBO로 여러 깊이 정보 렌더링하기
쉐이더 자체는 문제가되지 않지만, 쉐이더에 필요한 모든 것을 제공 할 수 있도록 OpenGL을 설정하는 데 어려움을 겪고 있습니다!
완벽하게 명확하게하기 위해, 나는 내 쉐이더에 두 개의 텍스처를 제공해야합니다 - 내 객체
의 뒷면의 깊이 정보와 텍스처 - 내 객체 의 정면 얼굴의 깊이 정보와 텍스처를여기 대략 대략 내가 한 것입니다 (코드가 너무 복잡해서 읽기가 쉽지 않습니다). 내가 먼저 초기화 방식을 볼 수 초기화() 함수를 참조하십시오 렌더링 기능이 개 FBO의 외부를 만들 : 여기
void FBO::init() {
initDepthTexture();
initFBO();
}
void FBO::initDepthTexture() {
//32 bit depth texture, mWidth*mHeight
glGenTextures(1, &mDepthTex);
glBindTexture(GL_TEXTURE_2D, mDepthTex);
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);
glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE,
GL_COMPARE_R_TO_TEXTURE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
//NULL means reserve texture memory, but texels are undefined
//You can also try GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT24 for the internal format.
//If GL_DEPTH24_STENCIL8_EXT, go ahead and use it (GL_EXT_packed_depth_stencil)
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, mWidth, mHeight, 0,
GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
}
void FBO::initFBO() {
glGenFramebuffersEXT(1, &mFrameBuffer);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFrameBuffer);
//Attach
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
GL_TEXTURE_2D, mDepthTex, 0);
//-------------------------
//Does the GPU support current FBO configuration?
//Before checking the configuration, you should call these 2 according to the spec.
//At the very least, you need to call glDrawBuffer(GL_NONE)
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
checkFBO();
renderToScreen();
}
void FBO::renderToFBO() {
cout << "Render to FBO: " << mFrameBuffer << endl;
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFrameBuffer); // Bind our frame buffer for rendering
//-------------------------
//----and to render to it, don't forget to call
//At the very least, you need to call glDrawBuffer(GL_NONE)
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
}
/**
* Static
*/
void FBO::renderToScreen() {
cout << "Render to screen " << endl;
// Finish all operations
//glFlush();
//-------------------------
//If you want to render to the back buffer again, you must bind 0 AND THEN CALL glDrawBuffer(GL_BACK)
//else GL_INVALID_OPERATION will be raised
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // Unbind our texture
glDrawBuffer(GL_BACK);
glReadBuffer(GL_BACK);
}
그리고 내가 식 코멘트를 사용하는 방법이다. 첫 번째 FBO에서 앞면에서 기하학적 깊이를 렌더링합니다. 두 번째 FBO에서 뒤쪽에서 기하학적 깊이를 렌더링합니다. 그런 다음 두 텍스처를 전체 화면 쿼드로 렌더링합니다.
void Viewer::onRender() {
FBO::renderToScreen();
// XXX: Need of Z-Depth sorting to get alpha blending right!!
glEnable(GL_DEPTH_TEST);
glClearColor(0., 0., 0.2, 1.);
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glClearDepth(1.);
glDepthFunc(GL_LESS);
// set the projection transformation
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, (GLdouble) m_width/(GLdouble) m_height,
m_scale * 5.0, m_scale * 10000.0);
// set the model transformation
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glm::vec3 pos = mCamera->getPosition();
glm::vec3 view = mCamera->getView();
glm::vec3 up = mCamera->getUp();
gluLookAt(pos.x, pos.y, pos.z, view.x, view.y, view.z, up.x, up.y,
up.z);
static float rotationAngle = 0;
rotationAngle+=5;
static int i = 0;
if(i++ < 200) {
/**
* Render geometry twice to FBOs
*/
mFBO->renderToFBO();
glClear(GL_DEPTH_BUFFER_BIT);
glClearDepth(0.);
glDepthFunc(GL_LESS);
glPushMatrix();
glRotatef(1, 1, 0, 120);
glColor3f(0., 1., 0.);
// Draw teapot
glutSolidTeapot(1.8);
glPopMatrix();
mFBO2->renderToFBO();
glClear(GL_DEPTH_BUFFER_BIT);
glClearDepth(0.);
glDepthFunc(GL_GREATER);
glPushMatrix();
glColor3f(0., 1., 0.);
// Draw teapot
glutSolidTeapot(3.5);
glPopMatrix();
/**
* Render the same geometry to the screen
*/
FBO::renderToScreen();
} else {
mShader->enable();
mShader->setTextureFromId("frontDepth", mFBO->getDepthTextureId());
mShader->setTextureFromId("backDepth", mFBO2->getDepthTextureId());
glBegin(GL_QUADS); // Draw A Quad
glTexCoord2f(0, 1);
glVertex3f(-1.0f, 1.0f, 0.0f); // Top Left
glTexCoord2f(1, 1);
glVertex3f(1.0f, 1.0f, 0.0f); // Top Right
glTexCoord2f(1, 0);
glVertex3f(1.0f, -1.0f, 0.0f); // Bottom Right
glTexCoord2f(0, 0);
glVertex3f(-1.0f, -1.0f, 0.0f); // Bottom Left
glEnd(); // Done Drawing The Quad
mShader->disable();
}
}
FBO로 렌더링 한 다음 쿼드에 렌더링하면 완벽하게 작동합니다. 위 예제에서 FBO에 200 번 렌더링 한 다음 FBO로 렌더링을 중단하고 전체 화면 쿼드에 텍스처를 표시합니다. 여기 이 결과, 예상대로 (표시 목적, I는 먼저보다 작은 제 기하학적 표현)
여기
가 작동 이미지와 거의 동일한 코드이다 (이 있지만 렌더링 나는 식 코멘트로 렌더링 한 다음 모든 프레임에 쿼드를 표시 할 때마다 프레임의 쿼드)
void Viewer::onRender() {
FBO::renderToScreen();
// XXX: Need of Z-Depth sorting to get alpha blending right!!
glEnable(GL_DEPTH_TEST);
glClearColor(0., 0., 0.2, 1.);
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glClearDepth(1.);
glDepthFunc(GL_LESS);
// set the projection transformation
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, (GLdouble) m_width/(GLdouble) m_height,
m_scale * 5.0, m_scale * 10000.0);
// set the model transformation
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glm::vec3 pos = mCamera->getPosition();
glm::vec3 view = mCamera->getView();
glm::vec3 up = mCamera->getUp();
gluLookAt(pos.x, pos.y, pos.z, view.x, view.y, view.z, up.x, up.y,
up.z);
static float rotationAngle = 0;
rotationAngle+=5;
/**
* Render geometry twice to FBOs
*/
mFBO->renderToFBO();
glClear(GL_DEPTH_BUFFER_BIT);
glClearDepth(0.);
glDepthFunc(GL_LESS);
glPushMatrix();
glRotatef(1, 1, 0, 120);
glColor3f(0., 1., 0.);
// Draw teapot
glutSolidTeapot(1.8);
glPopMatrix();
mFBO2->renderToFBO();
glClear(GL_DEPTH_BUFFER_BIT);
glClearDepth(0.);
glDepthFunc(GL_GREATER);
glPushMatrix();
glColor3f(0., 1., 0.);
// Draw teapot
glutSolidTeapot(3.5);
glPopMatrix();
/**
* Render both depth texture on a fullscreen quad
**/
FBO::renderToScreen();
mShader->enable();
mShader->setTextureFromId("frontDepth", mFBO->getDepthTextureId());
mShader->setTextureFromId("backDepth", mFBO2->getDepthTextureId());
glBegin(GL_QUADS); // Draw A Quad
glTexCoord2f(0, 1);
glVertex3f(-1.0f, 1.0f, 0.0f); // Top Left
glTexCoord2f(1, 1);
glVertex3f(1.0f, 1.0f, 0.0f); // Top Right
glTexCoord2f(1, 0);
glVertex3f(1.0f, -1.0f, 0.0f); // Bottom Right
glTexCoord2f(0, 0);
glVertex3f(-1.0f, -1.0f, 0.0f); // Bottom Left
glEnd(); // Done Drawing The Quad
mShader->disable();
}
}
하지만 지금은 내 문제가 발생합니다. 내가 계정으로 형상의 작은 부분을 것으로 보인다 이상한 결과를 얻을 :
이런 일이 왜 알아낼 수 있습니다. 깊이 텍스처에 확실히 렌더링되지만, 어떤 이유로 전체 화면 쿼드를 렌더링하면 FBO 지오메트리의 렌더링이 변경되는 것 같습니다.
[편집] 난 그냥 OpenGL은 상태를 저장하고, 쿼드 후 복원을 시도 ...
FBO::renderToScreen();
glPushAttrib(GL_ALL_ATTRIB_BITS);
mShader->enable();
mShader->setTextureFromId("frontDepth", mFBO->getDepthTextureId());
mShader->setTextureFromId("backDepth", mFBO2->getDepthTextureId());
glBegin(GL_QUADS); // Draw A Quad
glTexCoord2f(0, 1);
glVertex3f(-1.0f, 1.0f, 0.0f); // Top Left
glTexCoord2f(1, 1);
glVertex3f(1.0f, 1.0f, 0.0f); // Top Right
glTexCoord2f(1, 0);
glVertex3f(1.0f, -1.0f, 0.0f); // Bottom Right
glTexCoord2f(0, 0);
glVertex3f(-1.0f, -1.0f, 0.0f); // Bottom Left
glEnd(); // Done Drawing The Quad
mShader->disable();
glPopAttrib();
글쎄, 내가 문제가 어떤 종류없이 객체와 모든게 좋을 꺼를 추가 장면 주위를 이동할 수 있습니다 작품 . 그러나 어떤 상태 변화로 인해 렌더링 프로세스가 너무 많이 실패 할 수 있는지 궁금합니다. 어떤 생각입니까?
감사합니다, 렌더링, 그것은 참으로 그 개념에 매우 가깝다. 코드를 많이 정리하고 두 개의 분리 된 FBO를 사용하여 깊이 버퍼를 렌더링했습니다. 거의 작동하지만 문제에 대해서는 편집 한 첫 번째 메시지에서 설명했습니다. – geenux