본문으로 바로가기

예를 들어.. OpenGL 랜더링시 특정 지정한 위치가 화면에(사람눈에) 보이는지 체크하는 방법은 다음과 같음..

참고로 메인 버퍼 오브젝트가 멀티 샘플일 때는 depth를 뽑을 수 없으므로 샘플수를 반드시 0으로 해야 함.

(테스트한 코드는 메인 버퍼 오브젝트의 샘플이 32비트 일 경우 blit으로 복사하여 depth를 취득.)

glReadPixels의 과도한 사용은 랜더링 퍼포먼스를 떨어트리므로 주의해서 사용할 것..

QOpenGLFramebufferObject* m_depthBuffer = nullptr;
...

resizeGL()
{
	if(m_depthBuffer) delete m_depthBuffer;
	QOpenGLFramebufferObjectFormat format;
	format.setSamples(0);
	format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
	m_depthBuffer = new QOpenGLFramebufferObject(size(), format);
}

void paintGL()
{
	....
	/* rendering here */
	....
	glBindFramebuffer(GL_READ_FRAMEBUFFER, defaultFramebufferObject());
	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_depthBuffer->handle());
	glBlitFramebuffer(0, 0, width(), height(), 
		0, 0, m_depthBuffer->width(), m_depthBuffer->height(), 
		GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT, GL_NEAREST);
	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, defaultFramebufferObject());
}

void depthCheck(glm::vec3 pos)
{
	m_depthBuffer->bind(); 
	float depth = 1.f;
	glm::vec3 screenPos = worldToScreenPosition(pos);
	glReadPixels(screenPos[0], screenPos[1], 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);

	if (depth < 1.0 && screenPos[2] < 1.0 && std::fabs(depth - screenPos[2]) < 0.001) {
		// visible on the screen.
	}
    
	m_depthBuffer->release();
}