DYTSrouce/src/viewer/RenderStageEx.cpp

279 lines
10 KiB
C++
Raw Normal View History

2025-01-04 04:12:51 +00:00
#include "viewer/RenderStageEx.h"
#include "viewer/StateEx.h"
void RenderStageEx::drawInner(osg::RenderInfo& renderInfo,
osgUtil::RenderLeaf*& previous, bool& doCopyTexture)
{
#if 0
// **************************************************************
// Code from RenderStage class
struct SubFunc
{
static void applyReadFBO(bool& apply_read_fbo,
const osg::FrameBufferObject* read_fbo, osg::State& state)
{
if(read_fbo->isMultisample())
{
OSG_WARN << "Attempting to read from a"
" multisampled framebuffer object. Set a resolve"
" framebuffer on the RenderStage to fix this." << std::endl;
}
if(apply_read_fbo)
{
// Bind the monosampled FBO to read from
read_fbo->apply(state, osg::FrameBufferObject::READ_FRAMEBUFFER);
apply_read_fbo = false;
}
}
};
// **************************************************************
// New code
osg::State& state = *renderInfo.getState();
//osg::FBOExtensions* fbo_ext = osg::FBOExtensions::instance(state.getContextID(), true);
osg::GLExtensions* fbo_ext = state.get<osg::GLExtensions>();
bool using_multiple_render_targets = false;
if(fbo_ext)
{
if(_fbo.valid())
{
using_multiple_render_targets = _fbo->hasMultipleRenderingTargets();
if(!using_multiple_render_targets)
{
#if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE)
if(getDrawBufferApplyMask())
glDrawBuffer(_drawBuffer);
if(getReadBufferApplyMask())
glReadBuffer(_readBuffer);
#endif
}
}
else
fbo_ext->glBindFramebuffer(osg::FrameBufferObject::READ_DRAW_FRAMEBUFFER,
static_cast<StateEx*>(&state)->getDefaultFbo());
}
RenderBin::draw(renderInfo, previous);
// **************************************************************
// Code from RenderStage class
if(state.getCheckForGLErrors() != osg::State::NEVER_CHECK_GL_ERRORS)
{
if(state.checkGLErrors("after RenderBin::draw(..)"))
{
if(fbo_ext)
{
GLenum fbstatus = fbo_ext->glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT);
if(fbstatus != GL_FRAMEBUFFER_COMPLETE_EXT)
{
OSG_NOTICE << "RenderStage::drawInner(,) FBO status = 0x" << std::hex <<
fbstatus << std::dec << std::endl;
}
}
}
}
const osg::FrameBufferObject* read_fbo = fbo_ext ? _fbo.get() : 0;
bool apply_read_fbo = false;
if(fbo_ext && _resolveFbo.valid() && fbo_ext->glBlitFramebuffer)
{
GLbitfield blitMask = 0;
bool needToBlitColorBuffers = false;
//find which buffer types should be copied
for(osg::FrameBufferObject::AttachmentMap::const_iterator
it = _resolveFbo->getAttachmentMap().begin(),
end = _resolveFbo->getAttachmentMap().end(); it != end; ++it)
{
switch(it->first)
{
case osg::Camera::DEPTH_BUFFER:
blitMask |= GL_DEPTH_BUFFER_BIT;
break;
case osg::Camera::STENCIL_BUFFER:
blitMask |= GL_STENCIL_BUFFER_BIT;
break;
case osg::Camera::PACKED_DEPTH_STENCIL_BUFFER:
blitMask |= GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
break;
case osg::Camera::COLOR_BUFFER:
blitMask |= GL_COLOR_BUFFER_BIT;
break;
default:
needToBlitColorBuffers = true;
break;
}
}
// Bind the resolve framebuffer to blit into.
_fbo->apply(state, osg::FrameBufferObject::READ_FRAMEBUFFER);
_resolveFbo->apply(state, osg::FrameBufferObject::DRAW_FRAMEBUFFER);
if(blitMask)
{
// Blit to the resolve framebuffer.
// Note that (with nvidia 175.16 windows drivers at least) if the read
// framebuffer is multisampled then the dimension arguments are ignored
// and the whole framebuffer is always copied.
fbo_ext->glBlitFramebuffer(
static_cast<GLint>(_viewport->x()), static_cast<GLint>(_viewport->y()),
static_cast<GLint>(_viewport->x() + _viewport->width()),
static_cast<GLint>(_viewport->y() + _viewport->height()),
static_cast<GLint>(_viewport->x()), static_cast<GLint>(_viewport->y()),
static_cast<GLint>(_viewport->x() + _viewport->width()),
static_cast<GLint>(_viewport->y() + _viewport->height()),
blitMask, GL_NEAREST);
}
#if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE)
if(needToBlitColorBuffers)
{
for(osg::FrameBufferObject::AttachmentMap::const_iterator
it = _resolveFbo->getAttachmentMap().begin(),
end = _resolveFbo->getAttachmentMap().end(); it != end; ++it)
{
osg::Camera::BufferComponent attachment = it->first;
if(attachment >= osg::Camera::COLOR_BUFFER0)
{
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + (attachment -
osg::Camera::COLOR_BUFFER0));
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT + (attachment -
osg::Camera::COLOR_BUFFER0));
fbo_ext->glBlitFramebuffer(
static_cast<GLint>(_viewport->x()), static_cast<GLint>(_viewport->y()),
static_cast<GLint>(_viewport->x() + _viewport->width()),
static_cast<GLint>(_viewport->y() + _viewport->height()),
static_cast<GLint>(_viewport->x()), static_cast<GLint>(_viewport->y()),
static_cast<GLint>(_viewport->x() + _viewport->width()),
static_cast<GLint>(_viewport->y() + _viewport->height()),
GL_COLOR_BUFFER_BIT, GL_NEAREST);
}
}
// reset the read and draw buffers? will comment out for now with the assumption that
// the buffers will be set explicitly when needed elsewhere.
// glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
// glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
}
#endif
apply_read_fbo = true;
read_fbo = _resolveFbo.get();
using_multiple_render_targets = read_fbo->hasMultipleRenderingTargets();
}
// now copy the rendered image to attached texture.
if(doCopyTexture)
{
if(read_fbo) SubFunc::applyReadFBO(apply_read_fbo, read_fbo, state);
copyTexture(renderInfo);
}
std::map< osg::Camera::BufferComponent, Attachment>::const_iterator itr;
for(itr = _bufferAttachmentMap.begin();
itr != _bufferAttachmentMap.end();
++itr)
{
if(itr->second._image.valid())
{
if(read_fbo) SubFunc::applyReadFBO(apply_read_fbo, read_fbo, state);
#if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE)
if(using_multiple_render_targets)
{
int attachment = itr->first;
if(attachment == osg::Camera::DEPTH_BUFFER
|| attachment == osg::Camera::STENCIL_BUFFER)
{
// assume first buffer rendered to is the one we want
glReadBuffer(read_fbo->getMultipleRenderingTargets()[0]);
}
else
{
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + (attachment -
osg::Camera::COLOR_BUFFER0));
}
}
else
{
if(_readBuffer != GL_NONE)
{
glReadBuffer(_readBuffer);
}
}
#endif
GLenum pixelFormat = itr->second._image->getPixelFormat();
if(pixelFormat == 0) pixelFormat = _imageReadPixelFormat;
if(pixelFormat == 0) pixelFormat = GL_RGB;
GLenum dataType = itr->second._image->getDataType();
if(dataType == 0) dataType = _imageReadPixelDataType;
if(dataType == 0) dataType = GL_UNSIGNED_BYTE;
itr->second._image->readPixels(static_cast<int>(_viewport->x()),
static_cast<int>(_viewport->y()),
static_cast<int>(_viewport->width()),
static_cast<int>(_viewport->height()),
pixelFormat, dataType);
}
}
if(fbo_ext)
{
if(getDisableFboAfterRender())
{
// switch off the frame buffer object
GLuint fboId = state.getGraphicsContext() ?
state.getGraphicsContext()->getDefaultFboId() : 0;
fbo_ext->glBindFramebuffer(GL_FRAMEBUFFER_EXT, fboId);
}
doCopyTexture = true;
}
if(fbo_ext && _camera.valid())
{
// now generate mipmaps if they are required.
const osg::Camera::BufferAttachmentMap& bufferAttachments =
_camera->getBufferAttachmentMap();
for(osg::Camera::BufferAttachmentMap::const_iterator itr =
bufferAttachments.begin();
itr != bufferAttachments.end();
++itr)
{
if(itr->second._texture.valid() && itr->second._mipMapGeneration)
{
state.setActiveTextureUnit(0);
state.applyTextureAttribute(0, itr->second._texture.get());
fbo_ext->glGenerateMipmap(itr->second._texture->getTextureTarget());
}
}
}
#endif
}