RenderStage::runCameraSetUp
文章目录
- RTT
- osg::Camera::_bufferAttachmentMap
- RenderStage::BufferComponent和RenderStage::_bufferAttachmentMap
- Camera::attach(BufferComponent buffer, GLenum internalFormat)
- Camera::attach(BufferComponent buffer, osg::Texture* texture.....
- Camera::attach(BufferComponent buffer, osg::Image* image.......
- RenderStage::runCameraSetUp
RTT
- RenderStage::runCameraSetUp实现了一个场景渲染过程中可能非常重要的功能,即纹理烘焙(Render To Texture,RTT),或者称之为“渲染到纹理”。RTT技术意味着我们可以将后台实时绘制得到的场景图像直接作为另一个场景中对象的纹理,从而实现更加丰富的场景表达效果。
- ogl中rtt的基本步骤:
1.首先创建一个“渲染纹理”(Render Texture),可以是例如FBO帧缓存对象,像素缓存对象等;
2.设置“渲染纹理”为图形设备的渲染目标(Render Target),即渲染输出所在地;
3.将“渲染纹理”绑定到一个纹理或图片对象上(添加附件方式);
4.此时图形设备的渲染将在后台进行,其结果将直接体现在所绑定的纹理或图片对象上。
- osg中rtt基本步骤在osg::Camera中,并对camera的renderStage产生影响,在每一帧中使用
osg::Texture2D* texture = new osg::Texture2D;
camera->setRenderTargetImplementation( osg::Camera::FRAME_BUFFER_OBJECT);
camera->attach( osg::Camera::COLOR_BUFFER, texture );
我们既可以将texture的内容保存成图片,作为场景的截图;也可以将纹理绑定到某个物体上,实现纹理烘焙的效果。这里osgprerender是一个很好的例子,使用附加参数–fb,–fbo,–pbuffer,–window等可以充分了解不同渲染目标实现的过程及其差异。
- 绑定到摄像机的实际纹理或者图片,在Camera类中均使用struct Camera::Attachment来保存
- 更多纹理细节参考
osg::Camera::_bufferAttachmentMap
//osg::camera中
typedef std::map< BufferComponent, Attachment> BufferAttachmentMap;
BufferAttachmentMap _bufferAttachmentMap;enum BufferComponent{DEPTH_BUFFER,STENCIL_BUFFER,PACKED_DEPTH_STENCIL_BUFFER,COLOR_BUFFER,COLOR_BUFFER0,COLOR_BUFFER1 = COLOR_BUFFER0+1,COLOR_BUFFER2 = COLOR_BUFFER0+2,COLOR_BUFFER3 = COLOR_BUFFER0+3,COLOR_BUFFER4 = COLOR_BUFFER0+4,COLOR_BUFFER5 = COLOR_BUFFER0+5,COLOR_BUFFER6 = COLOR_BUFFER0+6,COLOR_BUFFER7 = COLOR_BUFFER0+7,COLOR_BUFFER8 = COLOR_BUFFER0+8,COLOR_BUFFER9 = COLOR_BUFFER0+9,COLOR_BUFFER10 = COLOR_BUFFER0+10,COLOR_BUFFER11 = COLOR_BUFFER0+11,COLOR_BUFFER12 = COLOR_BUFFER0+12,COLOR_BUFFER13 = COLOR_BUFFER0+13,COLOR_BUFFER14 = COLOR_BUFFER0+14,COLOR_BUFFER15 = COLOR_BUFFER0+15};struct Attachment{Attachment():_internalFormat(GL_NONE),_level(0),_face(0),_mipMapGeneration(false),_multisampleSamples(0),_multisampleColorSamples(0) {}int width() const{if (_texture.valid()) return _texture->getTextureWidth();if (_image.valid()) return _image->s();return 0;};int height() const{if (_texture.valid()) return _texture->getTextureHeight();if (_image.valid()) return _image->t();return 0;};int depth() const{if (_texture.valid()) return _texture->getTextureDepth();if (_image.valid()) return _image->r();return 0;};GLenum _internalFormat;ref_ptr<Image> _image;ref_ptr<Texture> _texture;unsigned int _level;unsigned int _face;bool _mipMapGeneration;unsigned int _multisampleSamples;unsigned int _multisampleColorSamples;};
RenderStage::BufferComponent和RenderStage::_bufferAttachmentMap
std::map< osg::Camera::BufferComponent, Attachment> _bufferAttachmentMap;
enum BufferComponent{DEPTH_BUFFER,STENCIL_BUFFER,PACKED_DEPTH_STENCIL_BUFFER,COLOR_BUFFER,COLOR_BUFFER0,COLOR_BUFFER1 = COLOR_BUFFER0+1,COLOR_BUFFER2 = COLOR_BUFFER0+2,COLOR_BUFFER3 = COLOR_BUFFER0+3,COLOR_BUFFER4 = COLOR_BUFFER0+4,COLOR_BUFFER5 = COLOR_BUFFER0+5,COLOR_BUFFER6 = COLOR_BUFFER0+6,COLOR_BUFFER7 = COLOR_BUFFER0+7,COLOR_BUFFER8 = COLOR_BUFFER0+8,COLOR_BUFFER9 = COLOR_BUFFER0+9,COLOR_BUFFER10 = COLOR_BUFFER0+10,COLOR_BUFFER11 = COLOR_BUFFER0+11,COLOR_BUFFER12 = COLOR_BUFFER0+12,COLOR_BUFFER13 = COLOR_BUFFER0+13,COLOR_BUFFER14 = COLOR_BUFFER0+14,COLOR_BUFFER15 = COLOR_BUFFER0+15};
struct Attachment {osg::ref_ptr<osg::Image> _image;GLenum _imageReadPixelFormat;GLenum _imageReadPixelDataType;};
Camera::attach(BufferComponent buffer, GLenum internalFormat)
- 设定指定BufferComponent 的internalFormat
void Camera::attach(BufferComponent buffer, GLenum internalFormat)
{switch(buffer){case DEPTH_BUFFER:if(_bufferAttachmentMap.find(PACKED_DEPTH_STENCIL_BUFFER) != _bufferAttachmentMap.end()){OSG_WARN << "Camera: DEPTH_BUFFER already attached as PACKED_DEPTH_STENCIL_BUFFER !" << std::endl;}break;case STENCIL_BUFFER:if(_bufferAttachmentMap.find(PACKED_DEPTH_STENCIL_BUFFER) != _bufferAttachmentMap.end()){OSG_WARN << "Camera: STENCIL_BUFFER already attached as PACKED_DEPTH_STENCIL_BUFFER !" << std::endl;}break;case PACKED_DEPTH_STENCIL_BUFFER:if(_bufferAttachmentMap.find(DEPTH_BUFFER) != _bufferAttachmentMap.end()){OSG_WARN << "Camera: DEPTH_BUFFER already attached !" << std::endl;}if(_bufferAttachmentMap.find(STENCIL_BUFFER) != _bufferAttachmentMap.end()){OSG_WARN << "Camera: STENCIL_BUFFER already attached !" << std::endl;}break;default:break;}_bufferAttachmentMap[buffer]._internalFormat = internalFormat;
}
Camera::attach(BufferComponent buffer, osg::Texture* texture…
/** Attach a Texture to specified buffer component.* The level parameter controls the mip map level of the texture that is attached.* The face parameter controls the face of texture cube map or z level of 3d texture.* The mipMapGeneration flag controls whether mipmap generation should be done for texture.*/void attach(BufferComponent buffer, osg::Texture* texture, unsigned int level = 0, unsigned int face=0, bool mipMapGeneration=false,unsigned int multisampleSamples = 0,unsigned int multisampleColorSamples = 0);
void Camera::attach(BufferComponent buffer, osg::Texture* texture, unsigned int level, unsigned int face, bool mipMapGeneration,unsigned int multisampleSamples,unsigned int multisampleColorSamples)
{_bufferAttachmentMap[buffer]._texture = texture;_bufferAttachmentMap[buffer]._level = level;_bufferAttachmentMap[buffer]._face = face;_bufferAttachmentMap[buffer]._mipMapGeneration = mipMapGeneration;_bufferAttachmentMap[buffer]._multisampleSamples = multisampleSamples;_bufferAttachmentMap[buffer]._multisampleColorSamples = multisampleColorSamples;
}
Camera::attach(BufferComponent buffer, osg::Image* image…
/** Attach a Image to specified buffer component.*/void attach(BufferComponent buffer, osg::Image* image,unsigned int multisampleSamples = 0,unsigned int multisampleColorSamples = 0);
void Camera::attach(BufferComponent buffer, osg::Image* image,unsigned int multisampleSamples,unsigned int multisampleColorSamples)
{_bufferAttachmentMap[buffer]._image = image;_bufferAttachmentMap[buffer]._multisampleSamples = multisampleSamples;_bufferAttachmentMap[buffer]._multisampleColorSamples = multisampleColorSamples;
}
RenderStage::runCameraSetUp
-
RenderStage::runCameraSetUp则反复遍历Camera::BufferAttachmentMap _bufferAttachmentMap的映射表,检索并设置那些与颜色缓存(COLOR_BUFFER),深度缓存(DEPTH_BUFFER)等相对应的Attachment对象 到renderStage中。
-
renderTargetImplementation==osg::Camera::FRAME_BUFFER_OBJECT
void RenderStage::runCameraSetUp(osg::RenderInfo& renderInfo)
{_cameraRequiresSetUp = false;if (!_camera) return;OSG_INFO<<"RenderStage::runCameraSetUp(osg::RenderInfo& renderInfo) "<<this<<std::endl;_cameraAttachmentMapModifiedCount = _camera->getAttachmentMapModifiedCount();osg::State& state = *renderInfo.getState();osg::Camera::RenderTargetImplementation renderTargetImplementation = _camera->getRenderTargetImplementation();osg::Camera::RenderTargetImplementation renderTargetFallback = _camera->getRenderTargetFallback();osg::Camera::BufferAttachmentMap& bufferAttachments = _camera->getBufferAttachmentMap();// 将camera的设置到这里_bufferAttachmentMap.clear();// compute the required dimensionsint width = static_cast<int>(_viewport->x() + _viewport->width());int height = static_cast<int>(_viewport->y() + _viewport->height());int depth = 1;for(osg::Camera::BufferAttachmentMap::iterator itr = bufferAttachments.begin();itr != bufferAttachments.end();++itr){width = osg::maximum(width,itr->second.width());height = osg::maximum(height,itr->second.height());depth = osg::maximum(depth,itr->second.depth());}// OSG_NOTICE<<"RenderStage::runCameraSetUp viewport "<<_viewport->x()<<" "<<_viewport->y()<<" "<<_viewport->width()<<" "<<_viewport->height()<<std::endl;// OSG_NOTICE<<"RenderStage::runCameraSetUp computed "<<width<<" "<<height<<" "<<depth<<std::endl;// attach images that need to be copied after the stage is drawn.for(osg::Camera::BufferAttachmentMap::iterator itr = bufferAttachments.begin();itr != bufferAttachments.end();++itr){// if one exist attach image to the RenderStage.if (itr->second._image.valid()){osg::Image* image = itr->second._image.get();GLenum pixelFormat = image->getPixelFormat();GLenum dataType = image->getDataType();if (image->data()==0){if (pixelFormat==0) pixelFormat = itr->second._internalFormat;if (pixelFormat==0) pixelFormat = _imageReadPixelFormat;if (pixelFormat==0) pixelFormat = GL_RGBA;if (dataType==0) dataType = _imageReadPixelDataType;if (dataType==0) dataType = GL_UNSIGNED_BYTE;}_bufferAttachmentMap[itr->first]._imageReadPixelFormat = pixelFormat;_bufferAttachmentMap[itr->first]._imageReadPixelDataType = dataType;_bufferAttachmentMap[itr->first]._image = image;}if (itr->second._texture.valid()){osg::Texture* texture = itr->second._texture.get();osg::Texture1D* texture1D = 0;osg::Texture2D* texture2D = 0;osg::Texture2DMultisample* texture2DMS = 0;osg::Texture3D* texture3D = 0;osg::TextureCubeMap* textureCubeMap = 0;osg::TextureRectangle* textureRectangle = 0;if (0 != (texture1D=dynamic_cast<osg::Texture1D*>(texture))){if (texture1D->getTextureWidth()==0){texture1D->setTextureWidth(width);}}else if (0 != (texture2D = dynamic_cast<osg::Texture2D*>(texture))){if (texture2D->getTextureWidth()==0 || texture2D->getTextureHeight()==0){texture2D->setTextureSize(width,height);}}else if (0 != (texture2DMS = dynamic_cast<osg::Texture2DMultisample*>(texture))){if (texture2DMS->getTextureWidth()==0 || texture2DMS->getTextureHeight()==0){texture2DMS->setTextureSize(width,height);}}else if (0 != (texture3D = dynamic_cast<osg::Texture3D*>(texture))){if (texture3D->getTextureWidth()==0 || texture3D->getTextureHeight()==0 || texture3D->getTextureDepth()==0 ){// note we dont' have the depth here, so we'll heave to assume that height and depth are the same..texture3D->setTextureSize(width,height,height);}}else if (0 != (textureCubeMap = dynamic_cast<osg::TextureCubeMap*>(texture))){if (textureCubeMap->getTextureWidth()==0 || textureCubeMap->getTextureHeight()==0){textureCubeMap->setTextureSize(width,height);}}else if (0 != (textureRectangle = dynamic_cast<osg::TextureRectangle*>(texture))){if (textureRectangle->getTextureWidth()==0 || textureRectangle->getTextureHeight()==0){textureRectangle->setTextureSize(width,height);}}}}if (renderTargetImplementation==osg::Camera::FRAME_BUFFER_OBJECT){osg::GLExtensions* ext = state.get<osg::GLExtensions>();bool fbo_supported = ext->isFrameBufferObjectSupported;//一系列gl函数能使用if (fbo_supported){OSG_INFO<<"Setting up osg::Camera::FRAME_BUFFER_OBJECT"<<std::endl;OpenThreads::ScopedLock<OpenThreads::Mutex> lock(*(_camera->getDataChangeMutex()));osg::ref_ptr<osg::FrameBufferObject> fbo = new osg::FrameBufferObject;osg::ref_ptr<osg::FrameBufferObject> fbo_multisample;bool colorAttached = false;bool depthAttached = false;bool stencilAttached = false;unsigned samples = 0;unsigned colorSamples = 0;// This is not a cut and paste error. Set BOTH local masks// to the value of the Camera's use render buffers mask.// We'll change this if and only if we decide we're doing MSFBO(Multi-Sample Framebuffer Object).// true代表从_displaySettings或DisplaySettings::instance()获得隐式BufferAttachmentRenderMaskunsigned int renderBuffersMask = _camera->getImplicitBufferAttachmentRenderMask(true);unsigned int resolveBuffersMask = _camera->getImplicitBufferAttachmentRenderMask(true);if (ext->isRenderbufferMultisampleSupported()){for(osg::Camera::BufferAttachmentMap::iterator itr = bufferAttachments.begin();itr != bufferAttachments.end();++itr){osg::Camera::Attachment& attachment = itr->second;samples = maximum(samples, attachment._multisampleSamples);colorSamples = maximum(colorSamples, attachment._multisampleColorSamples);}if (colorSamples > samples){OSG_NOTIFY(WARN) << "Multisample color samples must be less than or ""equal to samples. Setting color samples equal to samples." << std::endl;colorSamples = samples;}if (samples){fbo_multisample = new osg::FrameBufferObject;// Use the value of the Camera's use resolve buffers mask as the// resolve mask.// 可以自定义,也可以从camera._displaySettings中获得resolveBuffersMask = _camera->getImplicitBufferAttachmentResolveMask(true);}}for(osg::Camera::BufferAttachmentMap::iterator itr = bufferAttachments.begin();itr != bufferAttachments.end();++itr){osg::Camera::BufferComponent buffer = itr->first;osg::Camera::Attachment& attachment = itr->second;// 往帧缓冲对象中设置完整的attachment// 可是设置自定义有效的texture或image,也可以使用默认新建的if (attachment._texture.valid() || attachment._image.valid())fbo->setAttachment(buffer, osg::FrameBufferAttachment(attachment));elsefbo->setAttachment(buffer, osg::FrameBufferAttachment(new osg::RenderBuffer(width, height, attachment._internalFormat)));if (fbo_multisample.valid()){GLenum internalFormat = attachment._internalFormat;if (!internalFormat){switch (buffer){case Camera::DEPTH_BUFFER:internalFormat = GL_DEPTH_COMPONENT24;break;case Camera::STENCIL_BUFFER:internalFormat = GL_STENCIL_INDEX8_EXT;break;case Camera::PACKED_DEPTH_STENCIL_BUFFER:internalFormat = GL_DEPTH_STENCIL_EXT;break;// all other buffers are color buffersdefault:// setup the internal format based on attached texture if such exists, otherwise just default formatif (attachment._texture)internalFormat = attachment._texture->getInternalFormat();elseinternalFormat = GL_RGBA;break;}}fbo_multisample->setAttachment(buffer,osg::FrameBufferAttachment(new osg::RenderBuffer(width, height, internalFormat,samples, colorSamples)));}if (buffer==osg::Camera::DEPTH_BUFFER) depthAttached = true;else if (buffer==osg::Camera::STENCIL_BUFFER) stencilAttached = true;else if (buffer==osg::Camera::PACKED_DEPTH_STENCIL_BUFFER){depthAttached = true;stencilAttached = true;}else if (buffer>=osg::Camera::COLOR_BUFFER) colorAttached = true;}// 根据resolveBuffersMask 的需求,完善fbo中的附件if (!depthAttached){// If doing MSFBO (and therefore need two FBOs, one for multisampled rendering and one for// final resolve), then configure "fbo" as the resolve FBO, and When done// configuring, swap it into "_resolveFbo" (see line 554),然后_fbo = fbo_multisample. // But, if not using MSFBO, then "fbo" is just the render fbo.// If using MSFBO, then resolveBuffersMask// is the value set by the app for the resolve buffers. But if not using// MSFBO, then resolveBuffersMask is the value set by the app for render// buffers. In both cases, resolveBuffersMask is used to configure "fbo".if( resolveBuffersMask & osg::Camera::IMPLICIT_DEPTH_BUFFER_ATTACHMENT ){fbo->setAttachment(osg::Camera::DEPTH_BUFFER, osg::FrameBufferAttachment(new osg::RenderBuffer(width, height, GL_DEPTH_COMPONENT24)));depthAttached = true;}if (fbo_multisample.valid() &&( renderBuffersMask & osg::Camera::IMPLICIT_DEPTH_BUFFER_ATTACHMENT ) ){fbo_multisample->setAttachment(osg::Camera::DEPTH_BUFFER,osg::FrameBufferAttachment(new osg::RenderBuffer(width,height, GL_DEPTH_COMPONENT24, samples, colorSamples)));}}if (!stencilAttached){if( resolveBuffersMask & osg::Camera::IMPLICIT_STENCIL_BUFFER_ATTACHMENT ){fbo->setAttachment(osg::Camera::STENCIL_BUFFER, osg::FrameBufferAttachment(new osg::RenderBuffer(width, height, GL_STENCIL_INDEX8_EXT)));stencilAttached = true;}if (fbo_multisample.valid() &&( renderBuffersMask & osg::Camera::IMPLICIT_STENCIL_BUFFER_ATTACHMENT ) ){fbo_multisample->setAttachment(osg::Camera::STENCIL_BUFFER,osg::FrameBufferAttachment(new osg::RenderBuffer(width,height, GL_STENCIL_INDEX8_EXT, samples, colorSamples)));}}if (!colorAttached){if( resolveBuffersMask & osg::Camera::IMPLICIT_COLOR_BUFFER_ATTACHMENT ){fbo->setAttachment(osg::Camera::COLOR_BUFFER, osg::FrameBufferAttachment(new osg::RenderBuffer(width, height, GL_RGB)));colorAttached = true;}if (fbo_multisample.valid() &&( renderBuffersMask & osg::Camera::IMPLICIT_COLOR_BUFFER_ATTACHMENT ) ){fbo_multisample->setAttachment(osg::Camera::COLOR_BUFFER,osg::FrameBufferAttachment(new osg::RenderBuffer(width,height, GL_RGB, samples, colorSamples)));}}// ogl操作://创建一个新的fbo//遍历设置的_attachments,编译纹理//ext->glBindFramebuffer(READ_DRAW_FRAMEBUFFER, fboID);//调用glDrawBuffers(GLsizei n, const GLenum *bufs);,指定在一个渲染操作中输出到多个颜色缓冲区的目标//遍历设置的_attachments,添加附件fbo->apply(state);// If no color attachment make sure to set glDrawBuffer/glReadBuffer to none// otherwise glCheckFramebufferStatus will fail// It has to be done after call to glBindFramebuffer (fbo->apply)// and before call to glCheckFramebufferStatusif ( !colorAttached ){#if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE) && !defined(OSG_GLES3_AVAILABLE)setDrawBuffer( GL_NONE, true );//true代表glDrawBuffer is called at each frame draw.state.glDrawBuffer( GL_NONE );#endif}//检查fbo是否完整GLenum status = ext->glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT);if (status != GL_FRAMEBUFFER_COMPLETE_EXT){OSG_NOTICE<<"RenderStage::runCameraSetUp(), FBO setup failed, FBO status= 0x"<<std::hex<<status<<std::dec<<std::endl;fbo_supported = false;GLuint fboId = state.getGraphicsContext() ? state.getGraphicsContext()->getDefaultFboId() : 0;ext->glBindFramebuffer(GL_FRAMEBUFFER_EXT, fboId);fbo = 0;// clean up.osg::get<osg::GLRenderBufferManager>(state.getContextID())->flushAllDeletedGLObjects();osg::get<osg::GLFrameBufferObjectManager>(state.getContextID())->flushAllDeletedGLObjects();}else{//false代表glDrawBuffer is not called at each frame draw.setDrawBuffer(GL_NONE, false );setReadBuffer(GL_NONE, false );// 当前渲染台的帧缓冲替换为自定义帧缓冲_fbo = fbo;if (fbo_multisample.valid()){// glBindFrameBufferfbo_multisample->apply(state);status = ext->glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT);if (status != GL_FRAMEBUFFER_COMPLETE_EXT){OSG_NOTICE << "RenderStage::runCameraSetUp(), ""multisample FBO setup failed, FBO status = 0x"<< std::hex << status << std::dec << std::endl;// 绑定回自定义的帧缓冲fbo->apply(state);fbo_multisample = 0;_resolveFbo = 0;// clean up.osg::get<osg::GLRenderBufferManager>(state.getContextID())->flushAllDeletedGLObjects();osg::get<osg::GLFrameBufferObjectManager>(state.getContextID())->flushAllDeletedGLObjects();}else{_resolveFbo.swap(_fbo);_fbo = fbo_multisample;}}else{_resolveFbo = 0;}}}if (!fbo_supported){if (renderTargetImplementation<renderTargetFallback)renderTargetImplementation = renderTargetFallback;elserenderTargetImplementation = osg::Camera::PIXEL_BUFFER_RTT;}}// check whether PBuffer-RTT is supported or notif (renderTargetImplementation==osg::Camera::PIXEL_BUFFER_RTT &&!osg::isGLExtensionSupported(state.getContextID(), "WGL_ARB_render_texture")){if (renderTargetImplementation<renderTargetFallback)renderTargetImplementation = renderTargetFallback;elserenderTargetImplementation = osg::Camera::PIXEL_BUFFER;}
}
。。。。。。
- 需要单独图形设备的,例如osg::Camera::PIXEL_BUFFER_RTT || PIXEL_BUFFER || SEPARATE_WINDOW
。。。。。。
while (!getGraphicsContext() &&(renderTargetImplementation==osg::Camera::PIXEL_BUFFER_RTT ||renderTargetImplementation==osg::Camera::PIXEL_BUFFER ||renderTargetImplementation==osg::Camera::SEPARATE_WINDOW) ){osg::ref_ptr<osg::GraphicsContext> context = getGraphicsContext();if (!context){// set up the traits of the graphics context that we wantosg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;traits->width = width;// viewport和纹理二者间的maxtraits->height = height;// OSG_NOTICE<<"traits = "<<traits->width<<" "<<traits->height<<std::endl;traits->pbuffer = (renderTargetImplementation==osg::Camera::PIXEL_BUFFER || renderTargetImplementation==osg::Camera::PIXEL_BUFFER_RTT);traits->windowDecoration = (renderTargetImplementation==osg::Camera::SEPARATE_WINDOW);traits->doubleBuffer = (renderTargetImplementation==osg::Camera::SEPARATE_WINDOW);osg::Texture* pBufferTexture = 0;GLenum bufferFormat = GL_NONE;unsigned int level = 0;unsigned int face = 0;bool colorAttached = false;bool depthAttached = false;for(osg::Camera::BufferAttachmentMap::iterator itr = bufferAttachments.begin();itr != bufferAttachments.end();++itr){osg::Camera::BufferComponent buffer = itr->first;osg::Camera::Attachment& attachment = itr->second;switch(buffer){case(osg::Camera::DEPTH_BUFFER):{traits->depth = 24;depthAttached = true;break;}case(osg::Camera::STENCIL_BUFFER):{traits->stencil = 8;break;}case(osg::Camera::PACKED_DEPTH_STENCIL_BUFFER):{traits->depth = 24;depthAttached = true;traits->stencil = 8;break;}case(osg::Camera::COLOR_BUFFER):{if (attachment._internalFormat!=GL_NONE){bufferFormat = attachment._internalFormat;}else{if (attachment._texture.valid()){pBufferTexture = attachment._texture.get();bufferFormat = attachment._texture->getInternalFormat();}else if (attachment._image.valid()){bufferFormat = attachment._image->getInternalTextureFormat();}else{bufferFormat = GL_RGBA;}}level = attachment._level;face = attachment._face;if (renderTargetImplementation==osg::Camera::PIXEL_BUFFER_RTT){traits->target = attachment._texture.valid() ? attachment._texture->getTextureTarget() : 0;traits->format = bufferFormat;traits->level = level;traits->face = face;traits->mipMapGeneration = attachment._mipMapGeneration;}break;}default:{if (renderTargetImplementation==osg::Camera::SEPARATE_WINDOW){OSG_NOTICE<<"Warning: RenderStage::runCameraSetUp(State&) Window ";}else{OSG_NOTICE<<"Warning: RenderStage::runCameraSetUp(State&) Pbuffer ";}OSG_NOTICE<<"does not support multiple color outputs."<<std::endl;break;}}}if (!depthAttached){traits->depth = 24;}if (!colorAttached){if (bufferFormat == GL_NONE) bufferFormat = GL_RGB;traits->red = 8;traits->green = 8;traits->blue = 8;traits->alpha = (bufferFormat==GL_RGBA) ? 8 : 0;}// share OpenGL objects if possible...if (state.getGraphicsContext()){traits->sharedContext = state.getGraphicsContext();const osg::GraphicsContext::Traits* sharedTraits = traits->sharedContext->getTraits();if (sharedTraits){traits->hostName = sharedTraits->hostName;traits->displayNum = sharedTraits->displayNum;traits->screenNum = sharedTraits->screenNum;}}// create the graphics context according to these traits.context = osg::GraphicsContext::createGraphicsContext(traits.get());if (context.valid() && context->realize()){OSG_INFO<<"RenderStage::runCameraSetUp(State&) Context has been realized "<<std::endl;// successfully set up graphics context as requested,// will assign this graphics context to the RenderStage and// associated parameters. Setting the graphics context will// single this while loop to exit successful.setGraphicsContext(context.get());// how to do we detect that an attempt to set up RTT has failed??setDrawBuffer(GL_FRONT);setReadBuffer(GL_FRONT);if (pBufferTexture && renderTargetImplementation==osg::Camera::PIXEL_BUFFER_RTT){OSG_INFO<<"RenderStage::runCameraSetUp(State&) Assign graphics context to Texture"<<std::endl;pBufferTexture->setReadPBuffer(context.get());}else{OSG_INFO<<"RenderStage::runCameraSetUp(State&) Assigning texture to RenderStage so that it does the copy"<<std::endl;setTexture(pBufferTexture, level, face);}}else{OSG_INFO<<"Failed to acquire Graphics Context"<<std::endl;if (renderTargetImplementation==osg::Camera::PIXEL_BUFFER_RTT){// fallback to using standard PBuffer, this will allow this while loop to continueif (renderTargetImplementation<renderTargetFallback)renderTargetImplementation = renderTargetFallback;elserenderTargetImplementation = osg::Camera::PIXEL_BUFFER;}else{renderTargetImplementation = osg::Camera::FRAME_BUFFER;}}}}
。。。。。。
- 别的都失败了,回退,renderTargetImplementation==osg::Camera::FRAME_BUFFER
// finally if all else has failed, then the frame buffer fallback will come in to play.if (renderTargetImplementation==osg::Camera::FRAME_BUFFER){OSG_INFO<<"Setting up osg::Camera::FRAME_BUFFER"<<std::endl;for(osg::Camera::BufferAttachmentMap::iterator itr = bufferAttachments.begin();itr != bufferAttachments.end();++itr){// assign the texture...if (itr->second._texture.valid()) setTexture(itr->second._texture.get(), itr->second._level, itr->second._face);}}
相关文章:
RenderStage::runCameraSetUp
文章目录 RTTosg::Camera::_bufferAttachmentMapRenderStage::BufferComponent和RenderStage::_bufferAttachmentMapCamera::attach(BufferComponent buffer, GLenum internalFormat)Camera::attach(BufferComponent buffer, osg::Texture* texture.....Camera::attach(BufferC…...
突破速率瓶颈:毫米波技术如何推动 5G 网络迈向极限?
突破速率瓶颈:毫米波技术如何推动 5G 网络迈向极限? 引言 5G 网络的普及,已经让我们告别了“加载中”时代,实现了更快的数据传输、更低的延迟和更高的设备连接密度。而在 5G 技术的核心中,毫米波(mmWave&…...
前端面试真题集合(一)
一、Vue的响应式原理 Vue的响应式系统通过数据劫持和依赖追踪实现,核心流程如下: 数据劫持 • Vue 2.x:使用Object.defineProperty递归遍历数据对象,将属性转换为getter/setter,拦截属性的读取和修改操作。 • Vue 3.x:改用Proxy代理对象,支持动态属性添加和数组变化监听…...
聊聊Spring AI Alibaba的ElasticsearchDocumentReader
序 本文主要研究一下Spring AI Alibaba的ElasticsearchDocumentReader ElasticsearchDocumentReader community/document-readers/spring-ai-alibaba-starter-document-reader-elasticsearch/src/main/java/com/alibaba/cloud/ai/document/reader/es/ElasticsearchDocumentR…...
【网络技术_域名解析DNS】三、DNS 中间件实践应用与优化策略
一、DNS 中间件在典型行业的实践应用 1.1 金融行业:保障交易安全与服务稳定 金融行业对网络服务的安全性和稳定性要求极高,DNS 中间件在此领域发挥着不可替代的作用。以某银行线上支付系统为例,在 CentOS 7 环境下部署 DNS 中间件时&…...
Node.js 异步I/O与事件循环深度优化
Node.js 的核心魅力在于其异步、非阻塞I/O模型,这使得它在处理高并发、I/O密集型应用(如Web服务器、API网关、实时通信服务)时表现出色。然而,这种强大的能力并非凭空而来,它深深植根于其独特的**事件循环(…...
npm 常用操作和配置
一、npm 核心操作 1. 初始化项目 npm init # 交互式创建 package.json npm init -y # 跳过提问,直接生成默认 package.json2. 安装依赖 npm install <package> # 安装包到本地 node_modules(生产依赖) npm in…...
嵌入式芯片中的 低功耗模式 内容细讲
电源域与运行级别概述 电源域(Power Domain) 核心域(Core Domain):包括 CPU 核心和关键架构模块(如 NVIC、CPU 内核寄存器)。 外设域(Peripheral Domain):…...
React-请勿在循环或者条件语句中使用hooks
这是React Hooks的首要规则,这是因为React Hooks 是以单向循环链表的形式存储,即是有序的。循环是为了从最后一个节点移到一个节点的时候,只需通过next一步就可以拿到第一个节点,而不需要一层层回溯。React Hooks的执行࿰…...
React-memo (useMemo, useCallback)
在react中,当我们setState之后,若值发生变化,则会重新render当前组件以及其子组件 (默认情况下),在必要的时候,我可使用memo (class组件则对应shouldComponentUpdate、PureComponent)进行优化,来减少无效渲…...
点云数据处理开源C++方案
一、主流开源库对比 库名称特点适用场景开源协议活跃度PCL功能最全,算法丰富科研、工业级应用BSD★★★★★Open3D现代API,支持Python绑定快速开发、深度学习MIT★★★★☆CGAL计算几何算法强大网格处理、高级几何运算GPL/LGPL★★★☆☆PDAL专注于点云…...
android测试依赖
Android 项目中常用的测试相关库 1. androidx.arch.core:core-testing:2.2.0 作用: 提供与 Android Architecture Components(如 LiveData、ViewModel)相关的测试工具。主要用于测试基于 LiveData 的异步操作。 常见功能: 即时…...
Gradle与Idea整合
文章目录 1. Groovy 简介2. Groovy 安装[非必须]3. 在idea中创建java工程 1. Groovy 简介 在某种程度上,Groovy可以被视为Java的一种脚本化改良版,Groovy也是运行在JVM上,它可以很好地与Java代码及其相关库进行交互操作。它是一种成熟的面向对象编程语言…...
【数据结构】励志大厂版·初阶(复习+刷题)单链表
前引:此篇文章作为小编复习的记录,将快速回忆单链表的知识点,讲解单链表增删查找的实现,每个细节之处要注意的地方,解释为何这样设计。文章末尾包含了单链表算法题, 同样解释详细,借助题目再次巩…...
前端面试宝典---参数解构+默认值的面试题
重点要义 对于函数参数要解构,且参数有默认值的,一律用Object.assign的思路去合并参。 看不懂这句话没关系,看下面的例子\ 例子1 function fn ({ x 1, y } { y: 10 }) {console.log(x, y) } fn() // 1 10没有传递实参,你就把{ …...
【开发心得】筑梦上海:项目风云录(16)
目录 代码反面案例 李青与诺基亚的兴衰 并行项目下的利益纠葛与团队协作 未完待续。。。 今天分享的是一个反面案例,也算是一个避坑指南了。 代码反面案例 今天分享的代码是一个反面案例,当时由于项目人员变动频繁,经常是新人看不太懂旧…...
Neovim插件深度解析:mcphub.nvim如何用MCP协议重构开发体验
在AI与工具链深度融合的今天,Neovim 作为现代开发者的生产力工具,正通过插件生态不断突破边界。mcphub.nvim 作为一款基于 MCP(Model Context Protocol) 协议的插件,重新定义了Neovim与智能工具的交互方式。它不仅简化了MCP服务器的集成与管理,更通过直观的UI和生态整合,…...
Qt UDP 通信的详细实现步骤和示例代码
在 Qt 中实现 UDP 通信主要使用 QUdpSocket 类。以下是 UDP 通信的详细实现步骤和示例代码: 一、UDP 通信基础 无连接协议:不需要建立持久连接数据报模式:以独立数据包(datagram)形式发送适用场景:实时性要…...
(二)Trae 配置C++ 编译
Trae配置c编译 零 CMake 编译C0.1 下载安装0.2 安装设置0.3 三种编译方式(见 下文 一 二 三)0.4 调试 (见 下文四) 一 使用MSVC方式编译1.1 安装编译环境1.2安装插件1.3 设置文件 二 使用GCC方式2.1 安装编译环境2.1.1下载:[MinGw](https://gcc-mcf.lhmouse.com/)2.1.2安装:(以…...
动态规划算法的欢乐密码(一):斐波那契数模型
专栏:算法的魔法世界 个人主页:手握风云 目录 一、动态规划 二、例题讲解 2.1. 第 N 个泰波那契数 2.2. 三步问题 2.3. 使用最小花费爬楼梯 2.4. 解码方法 一、动态规划 动态规划是一种将复杂问题分解为更小的子问题,并利用子问题的解来…...
【FreeRTOS进阶】优先级翻转现象详解及解决方案
【FreeRTOS进阶】优先级翻转现象详解及解决方案 接下来我们聊聊优先级翻转这个经典问题。这个问题在实时系统中经常出现,尤其是在任务较多的场景下,而且问题定位起来比较麻烦。 什么是优先级翻转? 优先级翻转的核心定义很简单:…...
解决 IntelliJ IDEA 项目启动时端口冲突问题
1.问题 Description: The Tomcat connector configured to listen on port 8082 failed to start. The port may already be in use or the connector may be misconfigured. Action: Verify the connectors configuration, identify and stop any process thats listening…...
笔试专题(十一)
文章目录 添加字符(暴力枚举)题解代码 城市群数量(dfs)题解代码 判断是不是平衡二叉树(递归)题解代码 最大子矩阵(二维前缀和)题解代码 小葱的01串 (固定区间大小的滑动窗…...
C++11新增语法:列表初始化
前言: 接下来我们将要讲解,相较于c98,c11中新增的语法以及如何使用~。我们首先来讲解:列表初始化。 下文预告:右值引用和移动语义 C98中传统的{} 在c98中的{},仅能初始化数组和结构体 #include<iostrea…...
Linux:基础IO---动静态库
文章目录 1. 动静态库前置知识1.1 动静态库知识回顾1.2 什么是动静态库 2. 动静态库2.1 站在库的制作者的角度2.2 站在库的使用者的角度2.3 动态库是怎么被加载的(原理) 序:上一篇文章我们从认识到理解,从理解到实现场景ÿ…...
从裸仓库到GitLab全解析
Git服务器搭建与使用指南:从裸仓库到GitLab全解析 前言 在团队协作开发中,版本控制系统是必不可少的工具。虽然GitHub提供了优秀的代码托管服务,但企业级项目往往需要更安全的私有化部署方案。本文将手把手教你两种主流的Git服务器搭建方式…...
OzGIS:地理信息分析与处理软件
大家好,今天为大家介绍的软件是OzGIS:一款地理信息分析与处理软件。下面,我们将从软件的主要功能、支持的系统、软件官网等方面对其进行简单的介绍。 OzGIS官网网址为:https://ozgis.sourceforge.io/。 OzGIS是一款开源软件&#…...
PHP异常处理__Throwable
在 PHP 里,Throwable 是一个极为关键的接口,自 PHP 7 起被引入。它为错误和异常处理构建了一个统一的框架。下面会详细介绍 Throwable 的相关内容。 1. 基本概念 Throwable 是 Exception 和 Error 的父接口。在 PHP 7 之前,异常(…...
PHP异常处理__Exception类
以下是对 PHP 中 Exception 类的详细解释: 一、Exception 类概述 Exception 是 PHP 中所有异常类的基类。它提供了一个通用的异常处理机制,用于处理程序执行过程中可能出现的错误情况。当程序中出现异常时,可以创建 Exception 的实例并将其…...
C++中动态多态类别浅析
非抽象类继承和虚函数 #include <iostream> using namespace std;class Base { public:virtual void func() { // 虚函数,支持动态绑定cout << "Base::func()" << endl;} };class Derived : public Base { public:void func() overrid…...
游戏引擎学习第234天:实现基数排序
回顾并为今天的内容设定背景 我们今天继续进行排序的相关,虽然基本已经完成了,但还是想收尾一下,让整个流程更完整。其实这次排序只是个借口,主要是想顺便聊一聊一些计算机科学的知识点,这些内容在我们项目中平时不会…...
系分架构论文《论高并发场景的架构设计和开发方法》
系统分析师论文范文系列 【摘要】 2022年8月,我司承接了某知名电商平台“秒杀系统架构优化”项目,我作为系统分析师主导了整体架构设计与技术选型工作。该平台在促销活动中面临瞬时流量超过50万QPS的挑战,原有架构存在数据库崩溃、服务响应延…...
最新得物小程序sign签名加密,请求参数解密,响应数据解密逆向分析
点击精选,出现https://app.dewu.com/api/v1/h5/index/fire/index 这个请求 直接搜索sign的话不容易定位 直接搜newAdvForH5就一个,进去再搜sign,打上断点 可以看到t.params就是没有sign的请求参数, 经过Object(a.default)该函数…...
jangow靶机笔记(Vulnhub)
环境准备: 靶机下载地址: https://download.vulnhub.com/jangow/jangow-01-1.0.1.ova kali地址:192.168.144.128 靶机(jangow)地址:192.168.144.180 一.信息收集 1.主机探测 使用arp-scan进行主机探…...
Spring Boot + Caffeine:打造高性能缓存解决方案
1. 引言 1.1 缓存的重要性 缓存是提升系统性能的关键技术之一,通过将频繁访问的数据存储在内存中,减少对数据库或其他外部系统的访问次数,从而降低延迟并提高吞吐量。 缓存的基本概念:缓存是一种临时存储机制,用于快速访问常用数据。缓存在提升系统性能中的作用:减少数…...
C++入门小馆: 深入string类
嘿,各位技术潮人!好久不见甚是想念。生活就像一场奇妙冒险,而编程就是那把超酷的万能钥匙。此刻,阳光洒在键盘上,灵感在指尖跳跃,让我们抛开一切束缚,给平淡日子加点料,注入满满的pa…...
命令行基础
学习目标 掌握VRP命令行的基础知识 利用VRP命令行进行基本的配置 VRP命令行的基础知识 一、VRP 命令行基本架构 1. 用户视图(User View) 进入方式:设备启动后默认进入,提示符为 <HUAWEI>。功能&#…...
10-DevOps-Jenkins参数化构建实现多版本发布
在之前的Jenkins配置中,固定写死了程序的版本号,实际情况是随着版本的不断迭代,版本号也是不断变化的,版本号由代码仓库(GitLab)设置。 当前Jenkins配置是固定写的1.0,本节我们要把它改成动态的…...
C++游戏服务器开发之⑦redis的使用
目录 1.当前进度 2.守护进程 3.进程监控 4.玩家姓名添加文件 5.文件删除玩家姓名 6.redis安装 7.redis存取命令 8.redis链表存取 9.redis程序结构 10.hiredisAPI使用 11.基于redis查找玩家姓名 12.MAKEFILE编写 13.游戏业务实现总结 1.当前进度 2.守护进程 3.进程监…...
二进制裁剪命令mips-linux-gnu-strip 命令的使用
-s 或者--strip-all:移除所有符号和调试信息 -g 或者--strip-debug:仅移除调试信息 -d 或者--strip-unneeded:移除不需要的符号 默认不传任何参数 也是移除所有符号和调试 应用:把文件系统所有二进制镜像使用一遍,缩小文件系统大小 79K Apr 19 15:47 fat.ko //使用前 mips-l…...
【Bluedroid】蓝牙存储模块配置管理:启动、读写、加密与保存流程解析
本文围绕蓝牙存储模块展开,主要解析了蓝牙存储模块(StorageModule)的初始化流程,重点围绕配置文件校验、读取、设备类型修复及加密处理展开。通过工厂重置检测、校验和验证、多源配置加载、设备类型推断修正等步骤,确保…...
SpringBoot启动后初始化的几种方式
目录 一、静态代码块 二、构造方法 三、PostConstruct 四、InitializingBean 接口 五、 Bean 注解中的 initMethod 六、 CommandLineRunner 接口 七、ApplicationRunner 接口 八、EventListener事件 九、SmartInitializingSingleton接口 十、ApplicationListener接口…...
asp.net core webapi+efcore
简洁的restfull风格 目前c#提供了多种风格的web编程,因为微软有自己的前端,所以集成了很多内容,不过基于现在编程前后端分离的模式,webapi是合适的。 webapi 目前网络上有很多介绍,不反复说这个了。在建立控制器时&…...
java怎么完善注册,如果邮箱中途更换,能否判断
解析在下面 附赠代码 private static class CodeInfo {String code;long timestamp;CodeInfo(String code, long timestamp) {this.code code;this.timestamp timestamp;}}// 存储验证码(邮箱 -> 验证码信息)(保证线程安全) 以免中途更改邮箱pri…...
实战设计模式之备忘录模式
概述 与解释器模式、迭代器模式一样,备忘录模式也是一种行为设计模式。备忘录模式允许我们保存一个对象的状态,并在稍后恢复到这个状态。该模式非常适合于需要回滚、撤销或历史记录等功能的应用场景。通过使用备忘录模式,开发者可以轻松添加诸…...
数据库表设计
一对一关系 共享主键 两个表的主键是相同的 唯一外键 从表中记录主表的id 一对多关系 从表(多的表)存储主表的id 多对多关系 设计一个中间表(关联表),它有两列分别记录两个主表(A 和 B)…...
Linux 桌面环境 LXQt 2.2 发布
Linux 桌面环境 LXQt 2.2 于 2025 年 4 月 17 日正式发布。这是该轻量级开源 Qt 桌面环境的最新稳定版本,带来了诸多改进,特别是在 Wayland 支持方面。以下是一些主要的更新内容: Wayland 支持增强: 提升了多屏支持,使…...
多人五子棋联机对战平台 测试报告
目录 项目介绍 测试用例设计 部分功能测试示例 自动化测试 测试范围 排除范围 自动化测试目录编辑 执行全部自动化测试用例 性能说明 总结 性能测试 结果分析 测试总结 项目介绍 该项目基于WebSocket实现实时通信,采用SSM框架构建在线五子棋多人联机…...
探索 .bat 文件:自动化任务的利器
在现代计算机操作中,批处理文件(.bat 文件)是一种简单而强大的工具,它可以帮助我们自动化重复性任务,工作效率提高。尽管随着编程语言和脚本工具的发展,.bat 文件的使用频率有所下降,但它依然是…...
240419 leetcode exercises
240419 leetcode exercises jarringslee 文章目录 240419 leetcode exercises[19. 删除链表的倒数第 N 个结点](https://leetcode.cn/problems/remove-nth-node-from-end-of-list/)🔁 经典方法:两次遍历暴力求解🔁 双指针法 :快慢…...