mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-30 08:44:19 -04:00
Support for stereo FBOs
This commit is contained in:
parent
fd3fb16ec1
commit
eaab45dc9a
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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());
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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));
|
||||
|
Loading…
x
Reference in New Issue
Block a user