diff --git a/panda/src/display/graphicsOutput.cxx b/panda/src/display/graphicsOutput.cxx index 962e0dcf24..e843bab755 100644 --- a/panda/src/display/graphicsOutput.cxx +++ b/panda/src/display/graphicsOutput.cxx @@ -108,6 +108,7 @@ GraphicsOutput(GraphicsEngine *engine, GraphicsPipe *pipe, _flip_ready = false; _cube_map_index = -1; _cube_map_dr = NULL; + _tex_view_offset = -1; _sort = 0; _child_sort = 0; _got_child_sort = false; @@ -1384,6 +1385,29 @@ change_scenes(DisplayRegionPipelineReader *new_dr) { } } } + + int new_tex_view_offset = new_dr->get_tex_view_offset(); + if (new_tex_view_offset != _tex_view_offset) { + int old_tex_view_offset = _tex_view_offset; + //DisplayRegion *old_cube_map_dr = _cube_map_dr; + _tex_view_offset = new_tex_view_offset; + //_cube_map_dr = new_dr->get_object(); + + CDReader cdata(_cycler); + RenderTextures::const_iterator ri; + for (ri = cdata->_textures.begin(); ri != cdata->_textures.end(); ++ri) { + RenderTextureMode rtm_mode = (*ri)._rtm_mode; + Texture *texture = (*ri)._texture; + if (rtm_mode == RTM_bind_or_copy || rtm_mode == RTM_bind_layered) { + // In render-to-texture mode, switch the rendering backend to + // the new view, so that the subsequent frame will be + // rendered to the new view. + + select_tex_view(new_tex_view_offset); + break; + } + } + } } //////////////////////////////////////////////////////////////////// @@ -1399,6 +1423,18 @@ void GraphicsOutput:: select_cube_map(int) { } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsOutput::select_tex_view +// Access: Public, Virtual +// Description: Called internally when the window is in +// render-to-a-texture mode and the DisplayRegion +// requests that we switch rendering to a different +// texture view. +//////////////////////////////////////////////////////////////////// +void GraphicsOutput:: +select_tex_view(int) { +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsOutput::begin_flip // Access: Public, Virtual diff --git a/panda/src/display/graphicsOutput.h b/panda/src/display/graphicsOutput.h index 1d58096195..9574a48015 100644 --- a/panda/src/display/graphicsOutput.h +++ b/panda/src/display/graphicsOutput.h @@ -261,6 +261,7 @@ public: void change_scenes(DisplayRegionPipelineReader *new_dr); virtual void select_cube_map(int cube_map_index); + virtual void select_tex_view(int tex_view_offset); // These methods will be called within the app (main) thread. virtual void begin_flip(); @@ -312,6 +313,7 @@ protected: bool _flip_ready; int _cube_map_index; DisplayRegion *_cube_map_dr; + int _tex_view_offset; PT(Geom) _texture_card; bool _trigger_copy; diff --git a/panda/src/display/stereoDisplayRegion.cxx b/panda/src/display/stereoDisplayRegion.cxx index 044a84035b..ba16b1ce6c 100644 --- a/panda/src/display/stereoDisplayRegion.cxx +++ b/panda/src/display/stereoDisplayRegion.cxx @@ -52,24 +52,9 @@ StereoDisplayRegion:: //////////////////////////////////////////////////////////////////// void StereoDisplayRegion:: set_clear_active(int n, bool clear_active) { - // The clear_active flag gets set only on the parent, stereo display - // region. - DisplayRegion::set_clear_active(n, clear_active); - - // Except for depth and stencil buffers. These also get set on the - // right display region by default, on the assumption that we want - // to clear these buffers between drawing the eyes, and that the - // right eye is the second of the pair. - switch (n) { - case RTP_stencil: - case RTP_depth_stencil: - case RTP_depth: - _right_eye->set_clear_active(n, clear_active); - break; - - default: - break; - } + //DisplayRegion::set_clear_active(n, clear_active); + _left_eye->set_clear_active(n, clear_active); + _right_eye->set_clear_active(n, clear_active); } //////////////////////////////////////////////////////////////////// @@ -79,7 +64,7 @@ set_clear_active(int n, bool clear_active) { //////////////////////////////////////////////////////////////////// void StereoDisplayRegion:: set_clear_value(int n, const LColor &clear_value) { - DisplayRegion::set_clear_value(n, clear_value); + //DisplayRegion::set_clear_value(n, clear_value); _left_eye->set_clear_value(n, clear_value); _right_eye->set_clear_value(n, clear_value); } diff --git a/panda/src/glstuff/glGraphicsBuffer_src.cxx b/panda/src/glstuff/glGraphicsBuffer_src.cxx index 8e42dd8436..7b7ba65bce 100644 --- a/panda/src/glstuff/glGraphicsBuffer_src.cxx +++ b/panda/src/glstuff/glGraphicsBuffer_src.cxx @@ -81,6 +81,7 @@ CLP(GraphicsBuffer)(GraphicsEngine *engine, GraphicsPipe *pipe, _shared_depth_buffer = 0; _active_cube_map_index = -1; + _bound_tex_view = 0; } //////////////////////////////////////////////////////////////////// @@ -304,6 +305,7 @@ rebuild_bitplanes() { for (size_t i = 0; i != cdata->_textures.size(); ++i) { const RenderTexture &rt = cdata->_textures[i]; RenderTextureMode rtm_mode = rt._rtm_mode; + RenderTexturePlane plane = rt._plane; Texture *tex = rt._texture; if (rtm_mode == RTM_bind_layered) { @@ -311,11 +313,13 @@ rebuild_bitplanes() { GLCAT.warning() << "All textures attached to layered FBO should have the same layer count!\n"; } - } else if (tex->get_z_size() > 1) { - num_fbos = max(num_fbos, tex->get_z_size()); + + // Assign the texture to this slot. + attach[plane] = tex; + continue; } - if (rtm_mode != RTM_bind_or_copy && rtm_mode != RTM_bind_layered) { + if (rtm_mode != RTM_bind_or_copy) { continue; } @@ -339,12 +343,15 @@ rebuild_bitplanes() { // If I can't find an appropriate slot, or if there's // already a texture bound to this slot, then punt // this texture. - RenderTexturePlane plane = rt._plane; if (attach[plane]) { ((CData *)cdata.p())->_textures[i]._rtm_mode = RTM_copy_texture; continue; } + if (tex->get_z_size() > 1) { + num_fbos = max(num_fbos, tex->get_z_size()); + } + // Assign the texture to this slot. attach[plane] = tex; } @@ -491,6 +498,7 @@ rebuild_bitplanes() { _fb_properties.set_alpha_bits(0); } + _bound_tex_view = 0; _initial_clear = false; report_my_gl_errors(); @@ -1030,6 +1038,20 @@ end_frame(FrameMode mode, Thread *current_thread) { report_my_gl_errors(); } +//////////////////////////////////////////////////////////////////// +// Function: glGraphicsBuffer::set_size +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void CLP(GraphicsBuffer):: +set_size(int x, int y) { + if (_x_size != x || _y_size != y) { + _needs_rebuild = true; + } + + set_size_and_recalc(x, y); +} + //////////////////////////////////////////////////////////////////// // Function: glGraphicsBuffer::select_cube_map // Access: Public, Virtual @@ -1059,6 +1081,79 @@ select_cube_map(int cube_map_index) { report_my_gl_errors(); } +//////////////////////////////////////////////////////////////////// +// Function: glGraphicsBuffer::select_tex_view +// Access: Public, Virtual +// Description: Called internally when the window is in +// render-to-a-texture mode and the DisplayRegion +// requests that we switch rendering to a different +// texture view. +// +// In the FBO case, we do this by re-binding the +// texture that is attached to the color plane. +//////////////////////////////////////////////////////////////////// +void CLP(GraphicsBuffer):: +select_tex_view(int view) { + CLP(GraphicsStateGuardian) *glgsg; + DCAST_INTO_V(glgsg, _gsg); + + if (view == _bound_tex_view) { + return; + } + + // We assume that we've already configured the texture earlier + // in bind_bitplanes. Therefore, since we can safely assume that + // all texture views have the same format, we can just bind the + // new view here. + + Texture *tex = _tex[RTP_color]; + if (tex != NULL) { + if (view >= tex->get_num_views()) { + tex->set_num_views(view + 1); + } + + GLenum target = glgsg->get_texture_target(tex->get_texture_type()); + if (target == GL_TEXTURE_CUBE_MAP) { + target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + _active_cube_map_index; + } + + // Create the OpenGL texture object. + TextureContext *tc = tex->prepare_now(view, glgsg->get_prepared_objects(), glgsg); + nassertv(tc != (TextureContext *)NULL); + CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc); + glgsg->update_texture(tc, true); + + GLCAT.spam() << "Binding texture " << *tex + << " view " << view << " to color attachment.\n"; + + #ifndef OPENGLES + GLclampf priority = 1.0f; + glPrioritizeTextures(1, >c->_index, &priority); + #endif + glgsg->update_texture(tc, true); + + if (_rb_size_z == 1) { + if (target == GL_TEXTURE_3D) { + glgsg->_glFramebufferTexture3D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, + target, gtc->_index, 0, _active_cube_map_index); + } else if (target == GL_TEXTURE_2D_ARRAY_EXT) { + glgsg->_glFramebufferTextureLayer(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, + gtc->_index, 0, _active_cube_map_index); + } else { + glgsg->_glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, + target, gtc->_index, 0); + } + } else { + glgsg->_glFramebufferTexture(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, + gtc->_index, 0); + } + + report_my_gl_errors(); + } + + _bound_tex_view = view; +} + //////////////////////////////////////////////////////////////////// // Function: glGraphicsBuffer::open_buffer // Access: Protected, Virtual @@ -1139,7 +1234,7 @@ open_buffer() { _fb_properties.set_back_buffers(0); _fb_properties.set_indexed_color(0); _fb_properties.set_rgb_color(1); - _fb_properties.set_stereo(0); + //_fb_properties.set_stereo(0); _fb_properties.set_force_hardware(_host->get_fb_properties().get_force_hardware()); _fb_properties.set_force_software(_host->get_fb_properties().get_force_software()); diff --git a/panda/src/glstuff/glGraphicsBuffer_src.h b/panda/src/glstuff/glGraphicsBuffer_src.h index 8412920bc9..8c6117ec9a 100644 --- a/panda/src/glstuff/glGraphicsBuffer_src.h +++ b/panda/src/glstuff/glGraphicsBuffer_src.h @@ -72,7 +72,10 @@ public: virtual bool begin_frame(FrameMode mode, Thread *current_thread); virtual void end_frame(FrameMode mode, Thread *current_thread); + virtual void set_size(int x, int y); + virtual void select_cube_map(int cube_map_index); + virtual void select_tex_view(int tex_view_offset); virtual bool share_depth_buffer(GraphicsOutput *graphics_output); virtual void unshare_depth_buffer(); @@ -127,6 +130,7 @@ private: // The cube map face we are currently drawing to or have just // finished drawing to, or -1 if we are not drawing to a cube map. int _active_cube_map_index; + int _bound_tex_view; bool _initial_clear; bool _needs_rebuild; diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 3cccc2295f..3dfe65e856 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -1939,6 +1939,16 @@ clear(DrawableRegion *clearable) { } } + // In the past, it was possible to set the draw buffer + // once in prepare_display_region and then forget about it. + // Now, with aux layers, it is necessary to occasionally + // change the draw buffer. In time, I think there will need + // to be a draw buffer attrib. Until then, this little hack + // to put things back the way they were after + // prepare_display_region will do. + + set_draw_buffer(_draw_buffer_type); + if (_current_properties->get_color_bits() > 0) { if (clearable->get_clear_color_active()) { LColor v = clearable->get_clear_color(); @@ -1948,7 +1958,6 @@ clear(DrawableRegion *clearable) { } _state_mask.clear_bit(ColorWriteAttrib::get_class_slot()); mask |= GL_COLOR_BUFFER_BIT; - set_draw_buffer(clearable->get_draw_buffer_type()); } } @@ -1971,18 +1980,8 @@ clear(DrawableRegion *clearable) { GLP(ClearStencil)(clearable->get_clear_stencil()); mask |= GL_STENCIL_BUFFER_BIT; } - + GLP(Clear)(mask); - - // In the past, it was possible to set the draw buffer - // once in prepare_display_region and then forget about it. - // Now, with aux layers, it is necessary to occasionally - // change the draw buffer. In time, I think there will need - // to be a draw buffer attrib. Until then, this little hack - // to put things back the way they were after - // prepare_display_region will do. - - set_draw_buffer(_draw_buffer_type); if (GLCAT.is_spam()) { GLCAT.spam() << "glClear("; @@ -2225,7 +2224,8 @@ end_scene() { GraphicsStateGuardian::end_scene(); #ifndef OPENGLES_1 - if (_vertex_array_shader_context != 0) { + // This breaks shaders across multiple regions. + /*if (_vertex_array_shader_context != 0) { _vertex_array_shader_context->disable_shader_vertex_arrays(this); _vertex_array_shader = (Shader *)NULL; _vertex_array_shader_context = (CLP(ShaderContext) *)NULL; @@ -2239,7 +2239,7 @@ end_scene() { _current_shader_context->unbind(this); _current_shader = (Shader *)NULL; _current_shader_context = (CLP(ShaderContext) *)NULL; - } + }*/ #endif _dlights.clear(); @@ -4648,6 +4648,7 @@ do_issue_shader(bool state_has_changed) { if (!shader) { shader = _default_shader; } + #endif if (shader) { context = (CLP(ShaderContext) *)(shader->prepare_now(get_prepared_objects(), this));